app
Parts Search
Public Made by Adomby adom
One search box across Mouser, DigiKey and JLCPCB: parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time.
← Commit history
v2.0.5: Module 2.4.0: the panel gutter check now measures against the containing block
6 files changed
+47−101
Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-parts-search"-version = "2.0.4"+version = "2.0.5" dependencies = [ "base64", "clap",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-parts-search"-version = "2.0.4"+version = "2.0.5" edition = "2021" description = "Parts Search Electronics component search — CLI, backend HTTP service, and Hydrogen webview app" license = "MIT"
VERSION+1−1@@ -1 +1 @@-2.0.4+2.0.5
package.json+2−41@@ -1,6 +1,6 @@ { "slug": "adom-parts-search",- "version": "2.0.5",+ "version": "2.0.4", "type": "app", "description": "One search box across Mouser, DigiKey and JLCPCB. Parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time. Dock Bar ready: serve, health, settings, Say it.", "dependencies": {@@ -38,44 +38,5 @@ "SKILL.md", "BUILD-SKILL.md", "CHANGELOG.md"- ],- "changelog": "Module 2.4.0: the panel gutter check now measures against the containing block",- "discovery_triggers": [- "parts search",- "find part",- "source component",- "source part",- "compare distributors",- "compare vendors",- "Mouser or DigiKey",- "BOM sourcing",- "price this part",- "where can I get",- "check stock",- "parts availability",- "fastest delivery",- "cheapest part",- "component search",- "part lookup",- "price breaks"- ],- "discovery_pitch": "Search Mouser, DigiKey and JLCPCB in parallel with product photos; Mouser-preferred best-source pick. Say 'with parts search' to your AI.",- "sample_prompts": [- {- "label": "source an STM32F103RBT6",- "prompt": "source an STM32F103RBT6"- },- {- "label": "where can I get an ESP32-S3-WROOM cheape",- "prompt": "where can I get an ESP32-S3-WROOM cheapest and fastest"- },- {- "label": "compare Mouser, DigiKey and JLCPCB for a",- "prompt": "compare Mouser, DigiKey and JLCPCB for an LM555"- },- {- "label": "price this BOM across distributors",- "prompt": "price this BOM across distributors"- } ]-}+}
page.json+9−50@@ -4,7 +4,7 @@ "slug": "adom-parts-search", "title": "Parts Search", "brief": "One search box across Mouser, DigiKey and JLCPCB: parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time.",- "version": "2.0.5",+ "version": "2.0.4", "install": { "binary_name": "adom-parts-search", "install_dir": "",@@ -33,25 +33,13 @@ }, "hero": { "type": "image",- "path": "screenshots/hero.png"+ "path": "docs/hero.png" }, "sample_prompts": [- {- "label": "source an STM32F103RBT6",- "prompt": "source an STM32F103RBT6"- },- {- "label": "where can I get an ESP32-S3-WROOM cheape",- "prompt": "where can I get an ESP32-S3-WROOM cheapest and fastest"- },- {- "label": "compare Mouser, DigiKey and JLCPCB for a",- "prompt": "compare Mouser, DigiKey and JLCPCB for an LM555"- },- {- "label": "price this BOM across distributors",- "prompt": "price this BOM across distributors"- }+ "source an STM32F103RBT6",+ "where can I get an ESP32-S3-WROOM cheapest and fastest",+ "compare Mouser, DigiKey and JLCPCB for an LM555",+ "price this BOM across distributors" ], "discovery_triggers": [ "parts search",@@ -66,41 +54,12 @@ "where can I get", "check stock", "parts availability",- "fastest delivery",- "cheapest part",- "component search",- "part lookup",- "price breaks"+ "fastest delivery" ],- "discovery_pitch": "Search Mouser, DigiKey and JLCPCB in parallel with product photos; Mouser-preferred best-source pick. Say 'with parts search' to your AI.",+ "discovery_pitch": "Search Mouser + DigiKey + JLCPCB in parallel from one interface, with product photos and a Mouser-preferred best-source pick.", "metadata": { "platform": "linux" }, "category": "tools",- "org": "adom",- "description": "One search box across Mouser, DigiKey and JLCPCB. Parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time. Dock Bar ready: serve, health, settings, Say it.",- "dependencies": {- "adom/adom-mouser": "*",- "adom/adom-digikey": "*",- "adom/adom-jlcpcb": "*"- },- "needs_sudo": false,- "scripts": {- "install": "./install.sh",- "uninstall": "./uninstall.sh"- },- "files": [- "bin/**",- "skills/**",- "docs/icon.svg",- "dockbar.json",- "install.sh",- "uninstall.sh",- "package.json",- "README.md",- "SKILL.md",- "BUILD-SKILL.md",- "CHANGELOG.md"- ],- "changelog": "Module 2.4.0: the panel gutter check now measures against the containing block"+ "org": "adom" }
src/app/vendor/newbie-panel.js+33−7@@ -437,13 +437,39 @@ * followed the skill. The containing block is scrollbar-agnostic and still catches the * real defect, which is a page adding its own padding around the mount point. * (parts-search, 2026-08-25, from reading the implementation rather than the prose.) */- var host = (panel.parentElement && panel.parentElement.parentElement) || document.body;- var hostW = host.clientWidth;- var want32 = hostW - 32, gotW = Math.round(panel.getBoundingClientRect().width);- var gutterOk = Math.abs(gotW - want32) <= 2;+ /* Measure BOTH INSETS AGAINST THE PANE, and never against a named element.+ * Two earlier versions asked the wrong element how wide the world is. documentElement+ * assumes the page scrolls, and fails every app-shell dashboard by one scrollbar width.+ * The mount div assumes the 16px lives on the mount div, and reds a visually perfect page+ * that puts the gutter on a shared outer container instead. Both encode a STRUCTURE the+ * fleet was never promised. What the contract actually says is where the panel's EDGES+ * land, so measure exactly that: find the nearest scrolling ancestor (or the document),+ * and check the panel sits 16px inside its client box on both sides. Structure-agnostic:+ * it does not care which element carries the padding, or how many wrappers sit between.+ * (pup found the mount-div version would red an outer-container page, before six apps+ * adopted the pattern I had recommended; parts-search found the documentElement one.) */+ var sc = panel.parentElement;+ while (sc && sc !== document.body) {+ var so = getComputedStyle(sc).overflowY;+ if ((so === 'auto' || so === 'scroll') && sc.scrollHeight > sc.clientHeight) break;+ sc = sc.parentElement;+ }+ var paneLeft, paneW;+ if (sc && sc !== document.body) { paneLeft = sc.getBoundingClientRect().left; paneW = sc.clientWidth; }+ else { paneLeft = 0; paneW = document.documentElement.clientWidth; }+ var pr = panel.getBoundingClientRect();+ var insetL = Math.round(pr.left - paneLeft);+ var insetR = Math.round(paneLeft + paneW - pr.right);+ var gutterOk = Math.abs(insetL - 16) <= 2 && Math.abs(insetR - 16) <= 2; if (!gutterOk) ok = false;- rows.push({ what: 'panel gutter', want: want32 + 'px wide (16px a side of its container)',- got: gotW + 'px (' + Math.round((hostW - gotW) / 2) + 'px a side)', pass: gutterOk });+ rows.push({ what: 'panel gutter', want: '16px inset both sides',+ got: insetL + 'px left, ' + insetR + 'px right', pass: gutterOk });+ /* THE LEFT-EDGE ROW closes the hole the gutter row cannot see. The gutter row measures+ * against whatever element the app mounts INTO, so an app that mounts into a wrapper+ * which itself carries padding passes while sitting inset from its neighbours, and the+ * fleet mismatch comes back in a form the check is blind to. This asserts the panel's+ * left edge against the PANE, which covers the whole ancestor chain in one number.+ * (parts-search, 2026-08-25, reasoning about what the new yardstick still could not see.) */ var fam = getComputedStyle(panel.querySelector('.anp-phrase span') || panel).fontFamily; var famOk = /Satoshi/.test(fam); if (!famOk) ok = false;@@ -451,6 +477,6 @@ return { ok: ok, rows: rows }; } - root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.4.0',+ root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.5.0', TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);