← Commit history

v0.13.4: newbie-panel module 2.6.0 (sha256 a83af07, 110211 bytes, node --check passes) and page gutter unified at 16px — the module's new rule requires the panel to sit 16px inside its pane (|inset-16|<=2) and my container was at 22px, which would have red-lined; the app's own content gutters moved with it so every region still shares the panel's edge

John Lauer ·855b96e7eb ·1mo ago ·parent 28bf7af
6 files changed +67−10
Cargo.lock+1−1
@@ -4,7 +4,7 @@ version = 4  [[package]] name = "adom-project-manager"-version = "0.13.2"+version = "0.13.4" dependencies = [  "altium-codec",  "anyhow",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-project-manager"-version = "0.13.2"+version = "0.13.4" edition = "2021" description = "Adom Project Manager — the central hub for navigating wiki boards, molecules, and libraries into Hydrogen: browse your wiki boards/projects, view symbol + footprint + 3D and the footprint layer stackup, add components to your KiCad/Altium libraries, and deliver self-contained KiCad projects. Built on adom-lbr." 
bin/adom-project-manager
⋯ 1 unchanged line ⋯
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-project-manager",-  "version": "0.13.2",+  "version": "0.13.4",   "type": "app",   "description": "Adom Project Manager — the central hub for navigating wiki boards, molecules and libraries into Hydrogen: browse your wiki boards/projects (Personal / Organization / Public), view symbol + footprint + 3D and the per-EDA footprint layer stackup, explore the board and schematic in INTERACTIVE cross-probing viewers (click a net, hover a part for stock and price), add components to your KiCad/Altium libraries, and deliver self-contained KiCad projects. Built on adom-lbr. (Formerly Adom Project Manager / adom-project-manager.)",   "dependencies": {
src/manage.html+6−6
@@ -39,7 +39,7 @@   #home{flex:1;min-height:0;display:none;flex-direction:column;background:var(--bg)}   #workspace.home #home{display:flex}   #workspace.home #list,#workspace.home #view{display:none}-  .home-bar{display:flex;align-items:center;gap:16px;padding:16px 22px 12px;flex-wrap:wrap;width:100%}+  .home-bar{display:flex;align-items:center;gap:16px;padding:16px 16px 12px;flex-wrap:wrap;width:100%}   .seg{display:inline-flex;background:var(--elevated);border:1px solid var(--edge);border-radius:9px;padding:3px;gap:2px}   .seg .segbtn{background:none;border:none;color:var(--mut);font:inherit;font-size:12.5px;font-weight:500;padding:6px 15px;border-radius:6px;cursor:pointer;white-space:nowrap;display:inline-flex;align-items:center;gap:7px;transition:color .12s,background .12s}   .seg .segbtn:hover{color:var(--ink)}@@ -55,9 +55,9 @@   .home-sort{font-size:12px;color:var(--mut);display:flex;align-items:center;gap:7px;white-space:nowrap}   .home-sort select{background:var(--elevated);color:var(--ink);border:1px solid var(--edge);border-radius:8px;font-size:12px;padding:7px 26px 7px 10px;font-family:inherit;cursor:pointer;-webkit-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%238b93a3' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 9px center}   .home-sort select:focus{outline:none;border-color:var(--acc)}-  .home-chips{display:flex;flex-wrap:wrap;gap:6px;padding:0 22px 12px;width:100%}+  .home-chips{display:flex;flex-wrap:wrap;gap:6px;padding:0 16px 12px;width:100%}   /* Clear breathing room between the filter chips and the first row/section header. */-  #home-scroll{flex:1;min-height:0;overflow:auto;padding:14px 22px 34px}+  #home-scroll{flex:1;min-height:0;overflow:auto;padding:14px 16px 34px}   /* Fixed 3-wide wall. A centered max-width keeps cards a consistent (bigger) size once      the window is wide enough — past ~1240px the grid stops growing instead of stretching.      Narrower viewports gracefully drop to 2 then 1 column. */@@ -100,7 +100,7 @@   .g-userbanner .g-clearuser:hover{border-color:var(--acc);color:var(--ink)}   .gcard .g-when{font-size:10.5px;color:#6d7686;white-space:nowrap;flex:none;font-variant-numeric:tabular-nums}   .g-empty{grid-column:1/-1;color:#8b93a3;text-align:center;padding:64px 20px;line-height:1.7}-  @media (max-width:600px){ .home-bar{padding:12px 14px 8px} .home-tools{width:100%;margin-left:0} .home-search,.home-search:focus{width:100%;flex:1} .home-chips,#home-scroll{padding-left:14px;padding-right:14px} }+  @media (max-width:600px){ .home-bar{padding:12px 16px 8px} .home-tools{width:100%;margin-left:0} .home-search,.home-search:focus{width:100%;flex:1} .home-chips,#home-scroll{padding-left:16px;padding-right:16px} }   /* ── Tools menu (top-right): Chip Fetcher + Library Manager(EDA) ── */   .tools-wrap{position:relative}   /* "update available" badge — hidden until the update check confirms a newer wiki version */@@ -482,7 +482,7 @@      this page never slices prose to make one. Prose appears on tap only, and a red      pill always carries its next step. */   :root{--led-green:var(--green);--led-amber:var(--yellow);--led-red:var(--red)}-  #dash-top{flex:0 0 auto;padding:0 22px}+  #dash-top{flex:0 0 auto;padding:0 16px}   #dash-top:empty{display:none}   #leds{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 16px}   #leds:empty{display:none}@@ -742,7 +742,7 @@ function nbInit(){    // Set LAST, and record what failed, so a diagnosis never has to be inferred   // from which regions happen to be painted.-  window.__pmBoot={complete:true,failed:fails,version:'0.13.2',+  window.__pmBoot={complete:true,failed:fails,version:'0.13.4',                    panelMounted:!!window.__pmPanelMounted,ledTimer:!!window.__pmLedTimer};   if(fails.length) toast('Part of this dashboard failed to start: '+fails.join('; '),'error'); }
src/newbie-panel.js+58−1
@@ -421,6 +421,63 @@     var cols = cs.gridTemplateColumns.split(' ').filter(Boolean).length;     rows.push({ what: 'columns at this width', want: panel.getBoundingClientRect().width >= TWO_COL_MIN ? '2' : '1',                 got: String(cols), pass: true });+    /* THE GUTTER ROW. Four apps measured at the SAME 744px pane reported panel widths of+     * 734, 735, 702 and 694, because each page put a different amount of its own padding+     * around the mount point. 694 is under the 700 threshold, so that app rendered ONE+     * column while the other three rendered TWO, at an identical pane width. The panel was+     * conformant in all four; the PAGE around it was not. The fleet gutter is 16px a side,+     * so the panel's border box is the pane minus 32. */+    /* Measure against the panel's OWN CONTAINING BLOCK, never documentElement.+     * The first version compared to documentElement.clientWidth, which silently assumes the+     * PAGE scrolls. An app-shell dashboard (position:fixed shell, 44px header, scroller on an+     * inner .app-body) has no document scrollbar, so clientWidth is the full pane and the+     * inner scrollbar is charged to content instead: a correctly built app-shell page fails+     * by exactly one scrollbar width, and only pages that happen to scroll at document level+     * pass. Since app-shell is the prescribed structure, the check was failing the apps that+     * 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.) */+    /* 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) {+      /* A DECLARED scroller is the pane whether or not it is scrolling RIGHT NOW. Requiring+       * it to overflow was a bug with a nastier shape than the two before it: with+       * scrollbar-gutter:stable (which this pack mandates, so results arriving cause no+       * reflow) the track is reserved even when nothing overflows, so the loop walked PAST+       * the real pane, fell back to documentElement, and reported the right inset over by+       * one scrollbar width. The SAME PAGE passed when populated and failed when empty, and+       * empty is a dashboard's first-load state. Predicted from a code read by parts-search+       * and confirmed here: 16 left / 31 right, exact. */+      var so = getComputedStyle(sc).overflowY;+      if (so === 'auto' || so === 'scroll') 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: '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;@@ -428,6 +485,6 @@     return { ok: ok, rows: rows };   } -  root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.1.2',+  root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.6.0',                            TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);