@wafertools/wafermap 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -22,6 +22,31 @@ under `### Breaking`.
22
22
 
23
23
  ---
24
24
 
25
+ ## [0.26.0] — 2026-08-28
26
+
27
+ ### Breaking
28
+
29
+ - **The die-list table/CSV's single `Position` column (`"(x, y)"`) is now two separate `X`/`Y` columns.** A bracketed pair reads fine on screen but forces an extra parsing step (or breaks outright) when the CSV is opened in Excel, pandas, or any other tool expecting one number per cell. Any code reading the die-list CSV/table by column name or position needs to read `X`/`Y` instead of `Position`.
30
+
31
+ ### Added
32
+
33
+ - **`Ring`/`Quadrant` die-list columns**, via new `DieListOptions.getWafer`/`ringCount`. Wired up automatically through `renderWaferMap`/`renderWaferGallery` — a direct `buildDieListSection` call supplies `getWafer` itself. Appear only when `getWafer` resolves at least one die to a `Wafer` (omitted entirely, not shown empty, otherwise), and use the same `classifyDie`/`ringCount` the rest of that wafer/lot's analysis uses, so "Ring 2" here always names the same region a Ring finding does.
34
+ - **`Edge excluded` die-list column**, shown only when at least one die in the export has `edgeExcluded: true` (an included die is never stamped `false`, so "no die is excluded" and "the feature was never configured" are indistinguishable from `Die[]` alone — omitting the column in that case is the closest available approximation).
35
+ - **`openReportModal`** (`/render`) — opens report HTML (from `renderFindingsReportHtml`/`renderSummaryReportHtml`/`renderLotSummaryReportHtml`) in an in-app modal, with a Print/Save-as-PDF header button and an "Open as full page ↗" fallback to `openHtmlReport`/`setReportOpener`. The Summary panel's "Summary report" button now calls this automatically — **no `setReportOpener` wiring is required just to view a report anymore**, in a plain browser tab or an embedded host (Tauri, Electron, WebView2) alike.
36
+ - **`openWaferMapGuide`** (`/render`) — opens the built-in guide window with no live `WaferMapController`/`GalleryController` required, for a host whose help entry point must also work before anything has rendered (an empty-state "Help" menu). `WaferMapController.openUserGuide()`/`GalleryController.openUserGuide()` are now thin wrappers around this same call.
37
+ - **`ICONS`** (`/render`) — the toolbar's own icon set, now public so a host rendering its own chrome alongside wmap's can match its iconography instead of copy-pasting SVGs that drift on the next redesign.
38
+ - **Combined "Contents" navigation and Print/Save-as-PDF in the guide window.** A sticky bar lists every `<h2 id>` across the host's `extension.html` and wmap's own guide content as one flat, unnumbered list (see `UserGuideExtension`'s doc for why it's deliberately not split by source), flowing top-to-bottom in columns. A Print/Save-as-PDF header button covers the in-page overlay case (`window.open` blocked/unavailable); a real popup needs none, since native Ctrl+P already scopes to just that window.
39
+ - **Find-in-page search in the guide window** — but only for the in-page overlay case, next to the Contents toggle. A real popup window gets no search box: it's an actual OS window, so native Ctrl+F/Cmd+F already searches it, and a custom box there would just be redundant chrome. Matches highlight via plain `<mark>` elements (no invented highlight colour), Enter/Shift+Enter step through them, Escape clears.
40
+ - **`LotStatsSummary.mixedIdentityFields`** — identity keys (lot, product, testProgram, temperature, etc.) where the pooled wafers passed to `analyzeWaferLot` do *not* all agree, e.g. items pooled from more than one lot/program. `lot` now only includes a key when every wafer with identity data agrees on its value; a disagreeing key is omitted from `lot` and named here instead of silently taking the first wafer's value.
41
+ - **`WaferWarning` code `'edge-exclusion-exceeds-radius'`** (severity `'warning'`) — raised when `waferConfig.edgeExclusion` exceeds the resolved wafer radius (most likely with an under-inferred diameter); see the Fixed entry below for the behaviour this replaces.
42
+ - The gallery's toolbar and legend are now `position: sticky` in every one of the library's own demo pages, given a proper scrolling ancestor.
43
+
44
+ ### Fixed
45
+
46
+ - **CSV export was vulnerable to formula injection from untrusted die/wafer metadata.** A cell value beginning with `=`, `+`, `-`, or `@` is read as a formula by Excel/Sheets/LibreOffice on open — a real risk when the source is a host's own MES/LIMS metadata or operator free text, not data this library originated. `csvField` (shared by every CSV export, including the die list) now prefixes such a value with `'` before quoting — but only when it doesn't parse as a plain number, so a genuine negative/signed test value (offsets, leakage, deltas — routine in test data) round-trips unchanged.
47
+ - **An edge-exclusion width exceeding the resolved wafer radius silently produced a smaller, wrong excluded band** instead of excluding the whole wafer — squaring the resulting negative "inner radius" flipped its sign back positive, so the comparison it fed just picked the wrong dies. Now clamped to 0 and reported via the new `'edge-exclusion-exceeds-radius'` warning.
48
+ - **`analyzeWaferLot`'s lot identity (`LotStatsSummary.lot`) was silently derived from the first wafer only**, not verified shared — pooling wafers from two different lots/products into one call could report the first one's identity as if it applied to the whole batch. See `mixedIdentityFields` above.
49
+
25
50
  ## [0.25.0] — 2026-08-25
26
51
 
27
52
  ### Added
@@ -29,7 +54,7 @@ under `### Breaking`.
29
54
  - `WaferViewOptions.showLegend` (`renderWaferMap`) — hide the legend/colorbar entirely, for a host that provides its own equivalent control. Default `true`, matching prior behaviour.
30
55
  - `WaferViewOptions.markFailingDies` / `ToCanvasOptions.markFailingDies` — draws a diagonal hatch on dies whose bin is not a pass bin, giving pass/fail a second channel that isn't hue. Bin modes only; opt in from the Colour scheme menu. Default `false`.
31
56
  - `GalleryOptions.perCardLegend` — lets a gallery card grow its own legend again (its distinct value: highlighting a bin on one card independently of the rest, e.g. after changing that card's plot mode). Default `false`; the toolbar shows the toggle disabled with a stated reason where it genuinely cannot apply — a data-ranged value-mode gallery, where each card is normalised to its own min/max and no shared bar could describe them.
32
- - `ViewOptions.passBins` (`buildView`) / `ViewRect.binFail` — which bins count as passing, consulted only to set the new failing-die marker above, never to colour anything (bin colour always comes from the colour scheme). Default `[1]`. Any bin can be a pass bin or a fail bin, bin 1 included — this must never be derived from the bin number.
57
+ - `ViewOptions.passBins` (`buildView`) / `ViewRect.binFail` — internal plumbing for the failing-die marker above, relevant only to a caller using the low-level `buildView` directly (bypassing `renderWaferMap`/`renderWaferGallery`). It is **not** a new option for the normal `renderWaferMap`/`renderWaferGallery` path: both already required `passBins` before this release (for the summary panel's yield figure), and that existing value now also flows down into `buildView` automatically for the marker — nothing new to set, no second place to keep in sync. A direct `buildView` caller does need to pass it explicitly, matching whatever they already pass to `buildWaferMap`/`analyzeWaferMap`, or the marker will disagree with the yield figure beside it. Default `[1]`. Any bin can be a pass bin or a fail bin, bin 1 included — this must never be derived from the bin number.
33
58
 
34
59
  ### Fixed
35
60
 
@@ -1,4 +1,5 @@
1
1
  import type { Die } from '../core/dies.js';
2
+ import { type Wafer } from '../core/index.js';
2
3
  import { type MetadataFieldDef, type TestDef } from '../renderer/buildWaferMap.js';
3
4
  import type { WaferMetadata } from '../core/metadata.js';
4
5
  import { type MetadataKeySelection } from '../stats/metadataColumns.js';
@@ -94,6 +95,22 @@ export interface DieListOptions extends DieListDisplayOptions {
94
95
  label: string;
95
96
  get: (die: Die) => string | undefined;
96
97
  };
98
+ /**
99
+ * Per-die wafer lookup for Ring/Quadrant classification. A single-wafer
100
+ * caller passes a constant `() => wafer`; the lot-pooled combined list
101
+ * (multiple wafers in one export) passes a per-die lookup, since a die
102
+ * carries no wafer identity of its own — see `renderLotSummaryContent`'s
103
+ * `waferByDie`. Omitted or returning `undefined` for a die (unpositioned,
104
+ * or wafer unknown) leaves that die's Ring/Quadrant cells blank. If no die
105
+ * in the export resolves a wafer, the columns are omitted entirely rather
106
+ * than shown empty.
107
+ */
108
+ getWafer?: (die: Die) => Wafer | undefined;
109
+ /** Ring count for classification — must match the value the rest of this
110
+ * wafer/lot's analysis used (`analyzeWaferMap`/`analyzeWaferLot`'s
111
+ * `ringCount`), so a die's "Ring 2" here always means the same region a
112
+ * Ring finding elsewhere names. Default `4`, matching that default. */
113
+ ringCount?: number;
97
114
  /** Wafer-level metadata for this population, e.g. `WaferMapResult.metadata`. */
98
115
  waferMetadata?: WaferMetadata;
99
116
  /** Label/order hints for die metadata columns, e.g. `WaferMapResult.metadataFields`. */
@@ -1,13 +1,13 @@
1
- import{hasPosition as H}from"../core/dies.js";import{isParametricTest as R}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as E}from"../stats/metadataColumns.js";import{CLR as o,saveTextFile as M}from"./toolbar.js";import{csvField as $}from"./summaryPanel.js";import{fmt as T}from"../renderer/fmt.js";const B=5e4,N=new WeakSet;function F(n){if(N.has(n))return;N.add(n);const s=n.createElement("style");s.textContent=`
1
+ import{hasPosition as E,isPositionedDie as H}from"../core/dies.js";import{classifyDie as M}from"../core/index.js";import{isParametricTest as T}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as B}from"../stats/metadataColumns.js";import{CLR as r,saveTextFile as F}from"./toolbar.js";import{csvField as N}from"./summaryPanel.js";import{fmt as z}from"../renderer/fmt.js";const O=5e4,L=new WeakSet;function P(n){if(L.has(n))return;L.add(n);const o=n.createElement("style");o.textContent=`
2
2
  .wmap-dielist-table { width: 100%; border-collapse: collapse; font-size: 11px; }
3
3
  .wmap-dielist-th {
4
4
  text-align: left; padding: 4px 8px; position: sticky; top: 0;
5
- background: ${o.panelBg}; color: ${o.label}; font-weight: 600;
6
- border-bottom: 1px solid ${o.menuBorder}; white-space: nowrap;
5
+ background: ${r.panelBg}; color: ${r.label}; font-weight: 600;
6
+ border-bottom: 1px solid ${r.menuBorder}; white-space: nowrap;
7
7
  }
8
8
  .wmap-dielist-td {
9
- padding: 3px 8px; color: ${o.text};
10
- border-bottom: 1px solid ${o.menuBorder}; white-space: nowrap;
9
+ padding: 3px 8px; color: ${r.text};
10
+ border-bottom: 1px solid ${r.menuBorder}; white-space: nowrap;
11
11
  }
12
- `,n.head.appendChild(s)}function i(n,s,t,l){const r=n.createElement(s);return t&&Object.assign(r.style,t),l!==void 0&&(r.textContent=l),r}function P(n){return H(n)?`(${n.x}, ${n.y})`:"\u2014"}function D(n,s){if(s?.length)return s.filter(R);const t=new Map;for(const l of n)for(const r of Object.keys(l.testValues??{})){const d=Number(r);t.has(d)||t.set(d,{testNumber:d,name:`Test ${d}`})}return[...t.values()].sort((l,r)=>l.testNumber-r.testNumber)}export function buildDieListSection(n,s,t={}){if(!n.length)return null;const l=t.ownerDocument??document;F(l);const r=D(n,s),d=t.maxRows??B,h=Math.max(0,n.length-d),k=h>0?n.slice(0,d):n,u=i(l,"div",{display:"flex",flexDirection:"column",gap:"8px",flex:"1",minHeight:"0",minWidth:"0"}),b=i(l,"div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});b.appendChild(i(l,"div",{fontSize:"10px",fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:o.label},t.title??`Die list (${n.length})`));const x=i(l,"button",{fontSize:"11px",padding:"3px 8px",borderRadius:"4px",border:`1px solid ${o.menuBorder}`,background:o.menuBg,color:o.text,cursor:"pointer"},"Export CSV");x.type="button",b.appendChild(x),u.appendChild(b),t.note&&u.appendChild(i(l,"div",{fontSize:"11px",color:o.label,lineHeight:"1.4",flexShrink:"0"},t.note));const L=[...t.extraColumn?[t.extraColumn.label]:[],"Position","Site","Hard bin","Soft bin",...r.map(e=>e.name)],{columns:j,truncatedKeys:f}=E({dies:n,waferMetadata:t.waferMetadata,metadataFields:t.metadataFields,dieKeys:t.metadataColumns,waferKeys:t.waferMetadataColumns==="none"?"none":void 0,waferPlacement:t.waferMetadataColumns??"csv",reservedLabels:L}),g=[...t.extraColumn?[{label:t.extraColumn.label,get:e=>t.extraColumn.get(e)??""}]:[],{label:"Position",get:P},{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...r.map(e=>({label:e.name,get:a=>{const c=a.testValues?.[e.testNumber];if(c!==void 0)return T(c,e.unit);const m=a.testPass?.[e.testNumber];return m===void 0?"":m?"PASS":"FAIL"}})),...j.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],C=g.filter(e=>!e.csvOnly),w=i(l,"div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${o.menuBorder}`,borderRadius:"4px",...t.maxHeight?{maxHeight:t.maxHeight}:{}}),p=l.createElement("table");p.className="wmap-dielist-table",p.setAttribute("aria-label",t.title??`Die list (${n.length} dies)`);const S=i(l,"thead"),v=i(l,"tr");for(const e of C){const a=l.createElement("th");a.className="wmap-dielist-th",a.scope="col",a.textContent=e.label,v.appendChild(a)}S.appendChild(v),p.appendChild(S);const y=i(l,"tbody");for(const e of k){const a=i(l,"tr");for(const c of C){const m=l.createElement("td");m.className="wmap-dielist-td",m.textContent=c.get(e),a.appendChild(m)}y.appendChild(a)}if(p.appendChild(y),w.appendChild(p),u.appendChild(w),h>0||f.length>0){const e=[];h>0&&e.push(`Showing the first ${d.toLocaleString()} of ${n.length.toLocaleString()} dies. The CSV export contains all ${n.length.toLocaleString()}.`),f.length>0&&e.push(`${f.length} further metadata field${f.length===1?"":"s"} not shown.`),u.appendChild(i(l,"div",{fontSize:"11px",color:o.label,lineHeight:"1.4",flexShrink:"0"},e.join(" ")))}return x.addEventListener("click",()=>{const e=[g.map(a=>$(a.label)).join(",")];for(const a of n)e.push(g.map(c=>$(c.get(a))).join(","));M(e.join(`
13
- `),t.csvFilename??"dies.csv","text/csv",t.onSaveText)}),u}
12
+ `,n.head.appendChild(o)}function d(n,o,t,l){const i=n.createElement(o);return t&&Object.assign(i.style,t),l!==void 0&&(i.textContent=l),i}function W(n){return E(n)?String(n.x):""}function A(n){return E(n)?String(n.y):""}function I(n,o){if(o?.length)return o.filter(T);const t=new Map;for(const l of n)for(const i of Object.keys(l.testValues??{})){const s=Number(i);t.has(s)||t.set(s,{testNumber:s,name:`Test ${s}`})}return[...t.values()].sort((l,i)=>l.testNumber-i.testNumber)}function V(n,o,t){if(!o)return;const l=new Map;for(const i of n){if(!H(i))continue;const s=o(i);s&&l.set(i,M(i,s,{ringCount:t}))}return l.size>0?l:void 0}export function buildDieListSection(n,o,t={}){if(!n.length)return null;const l=t.ownerDocument??document;P(l);const i=I(n,o),s=t.maxRows??O,g=Math.max(0,n.length-s),R=g>0?n.slice(0,s):n,m=d(l,"div",{display:"flex",flexDirection:"column",gap:"8px",flex:"1",minHeight:"0",minWidth:"0"}),h=d(l,"div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});h.appendChild(d(l,"div",{fontSize:"10px",fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:r.label},t.title??`Die list (${n.length})`));const b=d(l,"button",{fontSize:"11px",padding:"3px 8px",borderRadius:"4px",border:`1px solid ${r.menuBorder}`,background:r.menuBg,color:r.text,cursor:"pointer"},"Export CSV");b.type="button",h.appendChild(b),m.appendChild(h),t.note&&m.appendChild(d(l,"div",{fontSize:"11px",color:r.label,lineHeight:"1.4",flexShrink:"0"},t.note));const x=V(n,t.getWafer,t.ringCount??4),k=n.some(e=>e.edgeExcluded===!0),j=[...t.extraColumn?[t.extraColumn.label]:[],"X","Y","Ring","Quadrant","Edge excluded","Site","Hard bin","Soft bin",...i.map(e=>e.name)],{columns:D,truncatedKeys:p}=B({dies:n,waferMetadata:t.waferMetadata,metadataFields:t.metadataFields,dieKeys:t.metadataColumns,waferKeys:t.waferMetadataColumns==="none"?"none":void 0,waferPlacement:t.waferMetadataColumns??"csv",reservedLabels:j}),C=[...t.extraColumn?[{label:t.extraColumn.label,get:e=>t.extraColumn.get(e)??""}]:[],{label:"X",get:W},{label:"Y",get:A},...x?[{label:"Ring",get:e=>{const a=x.get(e);return a?String(a.ring):""}},{label:"Quadrant",get:e=>x.get(e)?.quadrant??""}]:[],...k?[{label:"Edge excluded",get:e=>e.edgeExcluded?"Yes":"No"}]:[],{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...i.map(e=>({label:e.name,get:a=>{const c=a.testValues?.[e.testNumber];if(c!==void 0)return z(c,e.unit);const u=a.testPass?.[e.testNumber];return u===void 0?"":u?"PASS":"FAIL"}})),...D.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],w=C.filter(e=>!e.csvOnly),S=d(l,"div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${r.menuBorder}`,borderRadius:"4px",...t.maxHeight?{maxHeight:t.maxHeight}:{}}),f=l.createElement("table");f.className="wmap-dielist-table",f.setAttribute("aria-label",t.title??`Die list (${n.length} dies)`);const v=d(l,"thead"),y=d(l,"tr");for(const e of w){const a=l.createElement("th");a.className="wmap-dielist-th",a.scope="col",a.textContent=e.label,y.appendChild(a)}v.appendChild(y),f.appendChild(v);const $=d(l,"tbody");for(const e of R){const a=d(l,"tr");for(const c of w){const u=l.createElement("td");u.className="wmap-dielist-td",u.textContent=c.get(e),a.appendChild(u)}$.appendChild(a)}if(f.appendChild($),S.appendChild(f),m.appendChild(S),g>0||p.length>0){const e=[];g>0&&e.push(`Showing the first ${s.toLocaleString()} of ${n.length.toLocaleString()} dies. The CSV export contains all ${n.length.toLocaleString()}.`),p.length>0&&e.push(`${p.length} further metadata field${p.length===1?"":"s"} not shown.`),m.appendChild(d(l,"div",{fontSize:"11px",color:r.label,lineHeight:"1.4",flexShrink:"0"},e.join(" ")))}return b.addEventListener("click",()=>{const e=[C.map(a=>N(a.label)).join(",")];for(const a of n)e.push(C.map(c=>N(c.get(a))).join(","));F(e.join(`
13
+ `),t.csvFilename??"dies.csv","text/csv",t.onSaveText)}),m}
@@ -13,7 +13,7 @@ export const ICONS={aggr:'<svg viewBox="0 0 24 24" width="16" height="16" fill="
13
13
  <path d="M3 12 c0 2.5 4 4 9 4 s9-1.5 9-4" />
14
14
 
15
15
  <path d="M3 17 c0 2.5 4 4 9 4 s9-1.5 9-4" />
16
- </svg>`,orient:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" fill="currentColor" stroke="none"/></svg>',overlays:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></svg>',palette:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m14.622 17.897-10.68-2.913"/><path d="M18.376 2.622a1 1 0 1 1 3.002 3.002L17.36 9.643a.5.5 0 0 0 0 .707l.944.944a2.41 2.41 0 0 1 0 3.408l-.944.944a.5.5 0 0 1-.707 0L8.354 7.348a.5.5 0 0 1 0-.707l.944-.944a2.41 2.41 0 0 1 3.408 0l.944.944a.5.5 0 0 0 .707 0z"/><path d="M9 8c-1.804 2.71-3.97 3.46-6.583 3.948a.507.507 0 0 0-.302.819l7.32 8.883a1 1 0 0 0 1.185.204C12.735 20.405 16 16.792 16 15"/></svg>',pan:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20"/><path d="m15 19-3 3-3-3"/><path d="m19 9 3 3-3 3"/><path d="M2 12h20"/><path d="m5 9-3 3 3 3"/><path d="m9 5 3-3 3 3"/></svg>',quadrants:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><line x1="12" y1="3" x2="12" y2="21"/><line x1="3" y1="12" x2="21" y2="12"/></svg>',reset:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>',reticle:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="6" rx="0.5"/><rect x="13" y="3" width="8" height="6" rx="0.5"/><rect x="3" y="11" width="8" height="6" rx="0.5"/><rect x="13" y="11" width="8" height="6" rx="0.5"/><rect x="3" y="19" width="8" height="2" rx="0.5" stroke-dasharray="2 1"/><rect x="13" y="19" width="8" height="2" rx="0.5" stroke-dasharray="2 1"/></svg>',rings:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5.5"/><circle cx="12" cy="12" r="2" fill="currentColor" stroke="none"/></svg>',rotateCW:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>',specRange:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4 L5 20"/><path d="M5 4 L8 4"/><path d="M5 20 L8 20"/><path d="M19 4 L19 20"/><path d="M19 4 L16 4"/><path d="M19 20 L16 20"/><path d="M5 12 L19 12" stroke-dasharray="3 2"/></svg>',wafer:`<svg
16
+ </svg>`,orient:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" fill="currentColor" stroke="none"/></svg>',overlays:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></svg>',palette:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m14.622 17.897-10.68-2.913"/><path d="M18.376 2.622a1 1 0 1 1 3.002 3.002L17.36 9.643a.5.5 0 0 0 0 .707l.944.944a2.41 2.41 0 0 1 0 3.408l-.944.944a.5.5 0 0 1-.707 0L8.354 7.348a.5.5 0 0 1 0-.707l.944-.944a2.41 2.41 0 0 1 3.408 0l.944.944a.5.5 0 0 0 .707 0z"/><path d="M9 8c-1.804 2.71-3.97 3.46-6.583 3.948a.507.507 0 0 0-.302.819l7.32 8.883a1 1 0 0 0 1.185.204C12.735 20.405 16 16.792 16 15"/></svg>',pan:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20"/><path d="m15 19-3 3-3-3"/><path d="m19 9 3 3-3 3"/><path d="M2 12h20"/><path d="m5 9-3 3 3 3"/><path d="m9 5 3-3 3 3"/></svg>',print:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><path d="M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6"/><rect x="6" y="14" width="12" height="8" rx="1"/></svg>',quadrants:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><line x1="12" y1="3" x2="12" y2="21"/><line x1="3" y1="12" x2="21" y2="12"/></svg>',reset:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>',reticle:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="6" rx="0.5"/><rect x="13" y="3" width="8" height="6" rx="0.5"/><rect x="3" y="11" width="8" height="6" rx="0.5"/><rect x="13" y="11" width="8" height="6" rx="0.5"/><rect x="3" y="19" width="8" height="2" rx="0.5" stroke-dasharray="2 1"/><rect x="13" y="19" width="8" height="2" rx="0.5" stroke-dasharray="2 1"/></svg>',rings:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5.5"/><circle cx="12" cy="12" r="2" fill="currentColor" stroke="none"/></svg>',rotateCW:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>',specRange:'<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4 L5 20"/><path d="M5 4 L8 4"/><path d="M5 20 L8 20"/><path d="M19 4 L19 20"/><path d="M19 4 L16 4"/><path d="M19 20 L16 20"/><path d="M5 12 L19 12" stroke-dasharray="3 2"/></svg>',wafer:`<svg
17
17
  viewBox="0 0 24 24"
18
18
  width="16"
19
19
  height="16"
@@ -13,4 +13,8 @@ export type { InsightsOptions, InsightsView } from './insightsTab.js';
13
13
  export { setDetachWindowOpener } from './toolbar.js';
14
14
  export type { DetachWindowOpener } from './toolbar.js';
15
15
  export type { UserGuideExtension } from './toolbar.js';
16
+ export { openWaferMapGuide } from './toolbar.js';
17
+ export { ICONS } from './icons.js';
18
+ export { openReportModal } from './toolbar.js';
19
+ export type { OverlayHandle } from './toolbar.js';
16
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- export{toCanvas}from"./toCanvas.js";export{renderWaferMap}from"./renderWaferMap.js";export{renderWaferGallery}from"./renderWaferGallery.js";export{buildDieListSection}from"./dieList.js";export{collectWarnings,severityOf}from"./warnings.js";export{setDetachWindowOpener}from"./toolbar.js";
1
+ export{toCanvas}from"./toCanvas.js";export{renderWaferMap}from"./renderWaferMap.js";export{renderWaferGallery}from"./renderWaferGallery.js";export{buildDieListSection}from"./dieList.js";export{collectWarnings,severityOf}from"./warnings.js";export{setDetachWindowOpener}from"./toolbar.js";export{openWaferMapGuide}from"./toolbar.js";export{ICONS}from"./icons.js";export{openReportModal}from"./toolbar.js";
@@ -1,4 +1,4 @@
1
- import{getUniqueTestNumbers as kn,resolveTestNumber as Dn,findTestDef as Bn}from"../renderer/buildView.js";import{getColorScheme as En}from"../renderer/colorSchemes.js";import{metadataValueColor as On}from"../renderer/colorMap.js";import{resolveCanvasTheme as Tn}from"./canvasTheme.js";import{ICONS as ge}from"./icons.js";import{CLR as g,sevColor as Tt,BIN_LEGEND_MODES as Lt,STACKED_MODES as he,Z_ABOVE as Wt,applyOverlayZ as Ln,getTooltip as Wn,hideTooltip as Rt,createToolbarHelpers as Rn,buildModeMenuEl as In,openDetachWindow as $n,openFloatingWindow as Pn,openModal as Fn,copyWmapThemeTokens as An,syncWmapPopupTheme as Hn,openUserGuideWindow as jn,makePaletteBtn as zn,makeLogScaleBtn as Vn,makeLegendStyleBtn as Nn,makeOverlaysBtn as _n,makeOrientationBtn as Gn,menuLayerFor as It,saveImageBlob as Kn,markMenuTrigger as be,wireMenuA11y as $t,wireExpandToggle as Pt,passFailMenuRows as qn,requestedPassFailDisplay as Ue,logWmapVersionOnce as Xn,buildDataModeEntries as Un,metadataKeyHasData as Qn,metadataModeEntry as Yn}from"./toolbar.js";import{aggregateValues as Zn,aggregateBinCounts as Ft}from"../core/aggregates.js";import{renderWaferMap as Qe}from"./renderWaferMap.js";import{classifyChanged as Jn}from"./renderWaferMap.js";import{buildWaferMap as eo,getTestPassStatus as to,isParametricTest as At}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Le}from"../stats/analyzeWaferMap.js";import{collectWarnings as no,buildWarningsMenuEl as oo,severityOf as io}from"./warnings.js";import{compareNatural as ao}from"../core/utils.js";import{createSummaryPanelEl as Ye,buildMetadataStripRow as lo,buildCompactMetadataRows as Ht,metadataEntries as jt,renderLotSummaryContent as so}from"./summaryPanel.js";import"../stats/facets.js";import{openHtmlReport as ro}from"../stats/renderFindingsReport.js";import{escHtml as ye,renderSection as co,renderSeverityBadge as uo,reportStyles as fo}from"../stats/reportHtml.js";import{createInsightsTab as po}from"./insightsTab.js";import{getDieKey as mo,hasPosition as go}from"../core/dies.js";function We(f){const D=new Set;return f.filter(p=>D.has(p.bin)?!1:(D.add(p.bin),!0))}function zt(f,D){const p=f.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:"2px 4px",borderRadius:"3px"});const Q=f.ownerDocument.createElement("span");Object.assign(Q.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:D.color,border:D.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:"2px",boxSizing:"border-box"});const ne=f.ownerDocument.createElement("span");ne.textContent=D.label,Object.assign(ne.style,{fontWeight:D.isActive?"700":"400",color:D.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),p.appendChild(Q),p.appendChild(ne),p.setAttribute("role","button"),p.setAttribute("aria-pressed",D.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=g.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=g.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",D.onClick),p.addEventListener("keydown",W=>{(W.key==="Enter"||W.key===" ")&&(W.preventDefault(),D.onClick())}),f.appendChild(p)}export function renderWaferGallery(f,D,p={}){Xn();const Q=p.cardPadding??6,ne=p.downloadFilename??"wafer-gallery";let W=p.columns;const Vt=p.showPlotModeSelector??!0,Nt=p.showHelpButton??!1,_t=p.userGuideExtension,Ze=p.insights?.enabled??!1,Gt=Ln(p.zIndex),Y=p.summaryPanel,Je=p.passBins??[1];let we=p.fallbackFormat,E=p.lotStatsSummary,oe=p.legendPosition??"default",xe=p.perCardLegend??!1;function ie(){const e=r.plotMode??"hardBin";return Lt.has(e)?null:r.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"This lot has no shared colour bar for value mode, so each map keeps its own"}function et(){const e=xe||ie()!==null;for(const t of v)t&&t.setOptions({showLegend:e})}let r={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},v=[],q=[],Z=[],k=[],w=D.map(e=>typeof e=="function"?null:e),Re=0,ve=0;const I=new Map;let Kt=0,O=null,ae=null,tt=new Set,m=null,le="lot",qt={};function nt(e){return w[e]?.statsSummary??E?.perWafer.find(t=>t.waferIndex===e)?.summary}function Ce(){return!!(w.some(e=>e?.statsSummary?.findings.length)||E?.perWafer.some(e=>e.summary.findings.length))}const Xt=Wn(),J=Rn(Xt),{makeBtn:N,setActive:se,makeSep:$,makeMenuRow:Ut,makeMenuSection:Qt,makeDropdown:ot,makeCheckMenuBtn:ho,closeOpenMenu:Se,getOpenMenu:re,setOpenMenu:de}=J;f.ownerDocument.addEventListener("click",Se,!0);const it=()=>Rt();window.addEventListener("blur",it);function Ie(e){tt=new Set(e);const t=[...B.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,s)=>{const c=tt.has(s);o.style.outline=c?`3px solid ${g.findingHighlight}`:"",o.style.outlineOffset=c?"-3px":"",c&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function $e(){Ie([])}function Pe(){for(const e of v)e&&e.clearSelection()}function Fe(e,t){const n=new Set(e),o=t??v.map((s,c)=>c);for(const s of o){const c=k[s],i=v[s];if(!c||!i)continue;const d=c.dies.filter(l=>n.has(mo(l)));i.setSelection(d)}}function at(){const e=f.ownerDocument.createElement("div");Object.assign(e.style,{display:"flex",gap:"4px",marginBottom:"10px",borderBottom:`1px solid ${g.menuBorder}`,paddingBottom:"8px"});for(const t of["lot","wafers"]){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent=t==="lot"?"Lot":"Findings";const o=le===t;Object.assign(n.style,{border:"none",borderRadius:"4px",padding:"2px 8px",fontSize:"11px",cursor:"pointer",fontWeight:o?"600":"400",background:o?g.bgActive:"transparent",color:o?g.iconHover:g.icon}),n.addEventListener("click",()=>{le=t,$e(),Pe(),R()}),e.appendChild(n)}return e}function Yt(){if(!m)return;m.innerHTML="",E&&m.appendChild(at());const e=[];for(let n=0;n<w.length;n++){const o=w[n];if(!o)continue;const s=nt(n)?.findings??[];if(!s.length)continue;const c=s.filter(d=>d.severity==="unusual").length,i=s.filter(d=>d.severity==="notable").length;e.push({index:n,item:o,unusualCount:c,notableCount:i,totalCount:s.length})}if(w.length>0){const n=f.ownerDocument.createElement("div"),o=e.length,s=w.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${s} wafers`:`${o} of ${s} wafer${s===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:"11px",color:g.label,marginBottom:"8px"}),m.appendChild(n)}if(e.length>0){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent="Findings report",Object.assign(n.style,{border:`1px solid ${g.menuBorder}`,borderRadius:"4px",padding:"3px 8px",marginBottom:"10px",fontSize:"10px",color:g.iconHover,background:"none",cursor:"pointer",display:"block",width:"100%",textAlign:"left"}),n.addEventListener("click",()=>{const o=`Findings report \u2014 ${e.length} wafer${e.length>1?"s":""}`,s=new Date().toLocaleString(),c=e.map(({item:d,index:l})=>{const a=nt(l),u=d.label??`W${l+1}`,h=a.findings.map(b=>`<li>${uo(b.severity)} ${ye(b.summary)}</li>`).join("");return co(ye(u),`<ul style="margin:0;padding-left:18px;list-style:none">${h}</ul>`)}).join(`
1
+ import{getUniqueTestNumbers as kn,resolveTestNumber as Dn,findTestDef as Bn}from"../renderer/buildView.js";import{getColorScheme as En}from"../renderer/colorSchemes.js";import{metadataValueColor as On}from"../renderer/colorMap.js";import{resolveCanvasTheme as Tn}from"./canvasTheme.js";import{ICONS as ge}from"./icons.js";import{CLR as g,sevColor as Tt,BIN_LEGEND_MODES as Lt,STACKED_MODES as he,Z_ABOVE as Wt,applyOverlayZ as Ln,getTooltip as Wn,hideTooltip as Rt,createToolbarHelpers as Rn,buildModeMenuEl as In,openDetachWindow as $n,openFloatingWindow as Pn,openModal as Fn,openReportModal as An,copyWmapThemeTokens as Hn,syncWmapPopupTheme as jn,openUserGuideWindow as zn,makePaletteBtn as Vn,makeLogScaleBtn as Nn,makeLegendStyleBtn as _n,makeOverlaysBtn as Gn,makeOrientationBtn as Kn,menuLayerFor as It,saveImageBlob as qn,markMenuTrigger as be,wireMenuA11y as $t,wireExpandToggle as Pt,passFailMenuRows as Xn,requestedPassFailDisplay as Ue,logWmapVersionOnce as Un,buildDataModeEntries as Qn,metadataKeyHasData as Yn,metadataModeEntry as Zn}from"./toolbar.js";import{aggregateValues as Jn,aggregateBinCounts as Ft}from"../core/aggregates.js";import{renderWaferMap as Qe}from"./renderWaferMap.js";import{classifyChanged as eo}from"./renderWaferMap.js";import{buildWaferMap as to,getTestPassStatus as no,isParametricTest as At}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Le}from"../stats/analyzeWaferMap.js";import{collectWarnings as oo,buildWarningsMenuEl as io,severityOf as ao}from"./warnings.js";import{compareNatural as lo}from"../core/utils.js";import{createSummaryPanelEl as Ye,buildMetadataStripRow as so,buildCompactMetadataRows as Ht,metadataEntries as jt,renderLotSummaryContent as ro}from"./summaryPanel.js";import"../stats/facets.js";import{escHtml as ye,renderSection as co,renderSeverityBadge as uo,reportStyles as fo}from"../stats/reportHtml.js";import{createInsightsTab as po}from"./insightsTab.js";import{getDieKey as mo,hasPosition as go}from"../core/dies.js";function We(f){const D=new Set;return f.filter(p=>D.has(p.bin)?!1:(D.add(p.bin),!0))}function zt(f,D){const p=f.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:"2px 4px",borderRadius:"3px"});const Q=f.ownerDocument.createElement("span");Object.assign(Q.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:D.color,border:D.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:"2px",boxSizing:"border-box"});const ne=f.ownerDocument.createElement("span");ne.textContent=D.label,Object.assign(ne.style,{fontWeight:D.isActive?"700":"400",color:D.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),p.appendChild(Q),p.appendChild(ne),p.setAttribute("role","button"),p.setAttribute("aria-pressed",D.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=g.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=g.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",D.onClick),p.addEventListener("keydown",W=>{(W.key==="Enter"||W.key===" ")&&(W.preventDefault(),D.onClick())}),f.appendChild(p)}export function renderWaferGallery(f,D,p={}){Un();const Q=p.cardPadding??6,ne=p.downloadFilename??"wafer-gallery";let W=p.columns;const Vt=p.showPlotModeSelector??!0,Nt=p.showHelpButton??!1,_t=p.userGuideExtension,Ze=p.insights?.enabled??!1,Gt=Ln(p.zIndex),Y=p.summaryPanel,Je=p.passBins??[1];let we=p.fallbackFormat,E=p.lotStatsSummary,oe=p.legendPosition??"default",xe=p.perCardLegend??!1;function ie(){const e=r.plotMode??"hardBin";return Lt.has(e)?null:r.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"This lot has no shared colour bar for value mode, so each map keeps its own"}function et(){const e=xe||ie()!==null;for(const t of v)t&&t.setOptions({showLegend:e})}let r={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},v=[],q=[],Z=[],k=[],w=D.map(e=>typeof e=="function"?null:e),Re=0,ve=0;const I=new Map;let Kt=0,O=null,ae=null,tt=new Set,m=null,le="lot",qt={};function nt(e){return w[e]?.statsSummary??E?.perWafer.find(t=>t.waferIndex===e)?.summary}function Ce(){return!!(w.some(e=>e?.statsSummary?.findings.length)||E?.perWafer.some(e=>e.summary.findings.length))}const Xt=Wn(),J=Rn(Xt),{makeBtn:N,setActive:se,makeSep:$,makeMenuRow:Ut,makeMenuSection:Qt,makeDropdown:ot,makeCheckMenuBtn:ho,closeOpenMenu:Se,getOpenMenu:re,setOpenMenu:de}=J;f.ownerDocument.addEventListener("click",Se,!0);const it=()=>Rt();window.addEventListener("blur",it);function Ie(e){tt=new Set(e);const t=[...B.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,s)=>{const c=tt.has(s);o.style.outline=c?`3px solid ${g.findingHighlight}`:"",o.style.outlineOffset=c?"-3px":"",c&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function $e(){Ie([])}function Pe(){for(const e of v)e&&e.clearSelection()}function Fe(e,t){const n=new Set(e),o=t??v.map((s,c)=>c);for(const s of o){const c=k[s],i=v[s];if(!c||!i)continue;const d=c.dies.filter(l=>n.has(mo(l)));i.setSelection(d)}}function at(){const e=f.ownerDocument.createElement("div");Object.assign(e.style,{display:"flex",gap:"4px",marginBottom:"10px",borderBottom:`1px solid ${g.menuBorder}`,paddingBottom:"8px"});for(const t of["lot","wafers"]){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent=t==="lot"?"Lot":"Findings";const o=le===t;Object.assign(n.style,{border:"none",borderRadius:"4px",padding:"2px 8px",fontSize:"11px",cursor:"pointer",fontWeight:o?"600":"400",background:o?g.bgActive:"transparent",color:o?g.iconHover:g.icon}),n.addEventListener("click",()=>{le=t,$e(),Pe(),R()}),e.appendChild(n)}return e}function Yt(){if(!m)return;m.innerHTML="",E&&m.appendChild(at());const e=[];for(let n=0;n<w.length;n++){const o=w[n];if(!o)continue;const s=nt(n)?.findings??[];if(!s.length)continue;const c=s.filter(d=>d.severity==="unusual").length,i=s.filter(d=>d.severity==="notable").length;e.push({index:n,item:o,unusualCount:c,notableCount:i,totalCount:s.length})}if(w.length>0){const n=f.ownerDocument.createElement("div"),o=e.length,s=w.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${s} wafers`:`${o} of ${s} wafer${s===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:"11px",color:g.label,marginBottom:"8px"}),m.appendChild(n)}if(e.length>0){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent="Findings report",Object.assign(n.style,{border:`1px solid ${g.menuBorder}`,borderRadius:"4px",padding:"3px 8px",marginBottom:"10px",fontSize:"10px",color:g.iconHover,background:"none",cursor:"pointer",display:"block",width:"100%",textAlign:"left"}),n.addEventListener("click",()=>{const o=`Findings report \u2014 ${e.length} wafer${e.length>1?"s":""}`,s=new Date().toLocaleString(),c=e.map(({item:d,index:l})=>{const a=nt(l),u=d.label??`W${l+1}`,h=a.findings.map(b=>`<li>${uo(b.severity)} ${ye(b.summary)}</li>`).join("");return co(ye(u),`<ul style="margin:0;padding-left:18px;list-style:none">${h}</ul>`)}).join(`
2
2
  `),i=`<!DOCTYPE html>
3
3
  <html lang="en">
4
4
  <head>
@@ -17,4 +17,4 @@ ${fo()}
17
17
  ${c}
18
18
  </main>
19
19
  </body>
20
- </html>`;ro(i)}),m.appendChild(n)}if(e.length===0){const n=f.ownerDocument.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:"11px",padding:"4px 0"}),n.textContent="No findings on any wafer.",m.appendChild(n)}else for(const{index:n,item:o,unusualCount:s,notableCount:c,totalCount:i}of e){const d=s?"unusual":c?"notable":"info",l=s+c||i,a=f.ownerDocument.createElement("button");a.type="button",Object.assign(a.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:"4px",border:"none",borderLeft:`3px solid ${Tt(d)}`,borderRadius:"3px",background:g.bgHover,cursor:"pointer",fontSize:"11px",textAlign:"left",boxSizing:"border-box"}),a.addEventListener("mouseover",()=>{a.style.background=g.bgActive}),a.addEventListener("mouseout",()=>{a.style.background=g.bgHover});const u=f.ownerDocument.createElement("span");u.textContent=o.label??`W${n+1}`,Object.assign(u.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const h=f.ownerDocument.createElement("span");h.textContent=String(l),a.setAttribute("aria-label",`${o.label??`W${n+1}`} \u2014 ${l} finding${l===1?"":"s"}${s?`, ${s} unusual`:""} \u2014 view wafer`),Object.assign(h.style,{marginLeft:"6px",flexShrink:"0",background:Tt(d),color:"#fff",borderRadius:"8px",padding:"1px 5px",fontSize:"10px",fontWeight:"600"}),a.appendChild(u),a.appendChild(h),a.addEventListener("click",()=>Oe(n,o)),m.appendChild(a)}const t=f.ownerDocument.createElement("div");t.style.height="12px",m.appendChild(t)}function R(){if(m)if(le==="lot"&&E){const e=We(w.flatMap(n=>n?.hbinDefs??[])),t=We(w.flatMap(n=>n?.sbinDefs??[]));so(m,{lotSummary:E,items:w,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:w.find(n=>n?.testDefs?.length)?.testDefs,passBins:Je,ringCount:r.ringCount,colorScheme:r.colorScheme,fallbackFormat:we,activeFindingId:ae,warnings:p.warnings?.display??!0?_:[],findingsFilter:qt,onFindingsFilterChange:R,onSaveText:p.onSaveText,onFindingClick:(n,o)=>{ae===n.id?Ae():Zt(n,o),R()},onWaferClick:n=>{Ie([n])},dieListOptions:p.dieList}),Ce()&&m.insertBefore(at(),m.firstChild)}else Yt()}function lt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}function Ae(){ae=null,$e(),Pe(),C({highlightBin:void 0},{fireCallback:!1})}function Zt(e,t){if(ae===e.id){Ae();return}ae=e.id,t.style.background=g.bgActive,t.style.fontWeight="600";const{kind:n,index:o}=e.variable;n==="test"?C({plotMode:"value",activeTest:o??0,highlightBin:void 0},{fireCallback:!1}):n==="softBin"?C({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):C({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1}),$e(),Pe();const s=e.highlight;if(s.kind==="wafer"){Ie(s.waferIndices);const c=lt(e);for(const i of s.waferIndices){const a=k[i]?.statsSummary?.findings.find(u=>lt(u)===c)?.highlight?.dieKeys;a?.length&&Fe(a,[i])}}else s.kind==="bin"?s.dieKeys?.length&&Fe(s.dieKeys):(s.kind==="region"||s.kind==="dies")&&s.dieKeys?.length&&Fe(s.dieKeys)}function X(){if(!O)return;const e=!!m;O.style.display=(E||Ce())&&e&&!je?"flex":"none";const t=m?m.style.display!=="none":!1;(E?.hasNotableFindings||w.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?O.style.color=g.findingIndicator:O.dataset.active||(O.style.color=g.icon)}const T=f.ownerDocument.createElement("div");T.dataset.wmapToolbar="gallery",Object.assign(T.style,{display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"3px 4px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const st=()=>{const e=re();e&&(e.remove(),de(null)),be(j,!1)},j=N("mode","Plot mode",()=>{if(re()){st();return}const e=w.flatMap(b=>b?.dies??[]),t=w.find(b=>b?.testDefs?.length)?.testDefs,{testEntries:n,binEntries:o,stackedEntries:s}=Un(e,t,{includeStacked:!0}),c=r.plotMode??"hardBin",i=r.activeTest??0;function d(b){return b.plotMode!==c?!1:b.plotMode==="value"?i===(b.activeTest??0):b.plotMode==="metadata"?r.activeMetadataKey===b.activeMetadataKey:!0}function l(b,S){b.activeTest!==void 0?C({plotMode:"value",activeTest:b.activeTest,activeMetadataKey:void 0,logScale:b.logScale}):b.activeMetadataKey!==void 0?C({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:b.activeMetadataKey,passFailDisplay:"off"}):C({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),S.remove(),de(null),be(j,!1)}const a=new Set,u=w.flatMap(b=>b?.metadataFields??[]).filter(b=>!a.has(b.key)&&a.add(b.key)).filter(b=>Qn(e,b.key)).map(Yn),h=In(j.getBoundingClientRect(),n,o,s,d,l,{makeMenuRow:Ut,makeMenuSection:Qt},c,j.ownerDocument.defaultView??window,u);It(j).appendChild(h),de(h),be(j,!0),$t(h,j,st)});be(j,!1);const Jt=()=>k.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:en,sync:rt}=zn(J,()=>r.plotMode??"hardBin",()=>r.colorScheme??"default",Jt,e=>C({colorScheme:e}),{get:()=>r.markFailingDies??!1,set:e=>C({markFailingDies:e})});rt();const tn=D.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function He(){const e=w.find(n=>n?.testDefs?.length)?.testDefs,{testNumber:t}=Dn(r.activeTest??0,e);return{testNumber:t,td:Bn(e,t)}}function dt(){if((r.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function ce(){if((r.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&!At(e)}function nn(){if((r.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=He();return w.some(n=>n?.dies?.some(o=>to(o,e,t)!==void 0))}const on=_n(J,()=>[{label:"Ring boundaries",active:!!r.showRingBoundaries,onClick:()=>C({showRingBoundaries:!r.showRingBoundaries})},{label:"Quadrant lines",active:!!r.showQuadrantBoundaries,onClick:()=>C({showQuadrantBoundaries:!r.showQuadrantBoundaries})},{label:"Die labels",active:!!r.showDieLabels,onClick:()=>C({showDieLabels:!r.showDieLabels})},{label:"Reticle grid",active:!!r.showReticle,enabled:tn,onClick:()=>C({showReticle:!r.showReticle})},{label:"XY indicator",active:!!r.showXYIndicator,onClick:()=>C({showXYIndicator:!r.showXYIndicator})},...qn({functionalActive:ce(),hasLimits:dt()&&!ce(),hasRecorded:nn()&&!ce(),display:Ue(r)},e=>C({passFailDisplay:e}))],()=>!!(r.showRingBoundaries||r.showQuadrantBoundaries||r.showDieLabels||r.showReticle||r.showXYIndicator||Ue(r)!=="off")),{btn:an,sync:ct}=Nn(J,()=>({plotMode:r.plotMode,legendPosition:oe}),e=>{oe=e;for(const t of v)t&&t.setOptions({legendPosition:oe})},{get:()=>xe,set:e=>{xe=e,et()},blockedReason:ie});ct();const ln=[{value:"mean",label:"Mean"},{value:"median",label:"Median"},{value:"stddev",label:"Std Dev"},{value:"min",label:"Min"},{value:"max",label:"Max"},{value:"count",label:"Count"}],ut=ot("aggr","Aggregation method",()=>ln,()=>r.aggregationMethod??"mean",e=>C({aggregationMethod:e}));function ft(){const e=r.plotMode==="stackedValues";ut.style.display=e?"":"none"}ft();const{btn:sn,sync:pt}=Vn(J,()=>({...r,functionalActive:ce()}),e=>C(e));pt();const Me=N("specRange","Colorbar range: spec limits",()=>{const e=r.colorbarRangeMode==="data"?"spec":"data";C({colorbarRangeMode:e})});function mt(){const e=(r.plotMode??"hardBin")==="value"&&dt()&&Ue(r)==="off"&&!ce();Me.style.display=e?"":"none";const t=(r.colorbarRangeMode??"spec")==="spec";se(Me,t),Me.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}mt();const rn=Gn(J,()=>r,e=>C(e)),dn=N("downloadAll","Download gallery PNG",Sn),cn=ot("columns","Columns",()=>[{value:"auto",label:"Auto"},{value:"1",label:"1 column"},{value:"2",label:"2 columns"},{value:"3",label:"3 columns"},{value:"4",label:"4 columns"},{value:"5",label:"5 columns"}],()=>W!=null?String(W):"auto",e=>Mt(e==="auto"?void 0:Number(e))),M=f.ownerDocument.createElement("div");Object.assign(M.style,{display:"inline-flex",alignItems:"center",gap:"0"}),T.appendChild(M),Vt&&M.appendChild(j),M.appendChild(en),M.appendChild(ut),M.appendChild(sn),M.appendChild(Me),M.appendChild($()),M.appendChild(on),M.appendChild($()),M.appendChild(an),M.appendChild($()),M.appendChild(rn),M.appendChild($()),M.appendChild(cn),M.appendChild($()),M.appendChild(dn),(E||Ce())&&(O=N("findings","Summary panel",()=>{if(!m)return;const e=m.style.display!=="none";e||R(),m.style.display=e?"none":"flex",se(O,!e),X()}),T.appendChild($()),T.appendChild(O));let P=null,ke=null,_=[],gt=!1;function ht(){const e=no({lotStatsSummary:E,result:{warnings:w.flatMap(n=>n?.warnings??[])}}),t=e.length!==_.length||e.some((n,o)=>n.code!==_[o]?.code||n.message!==_[o]?.message);_=e,(t||!gt)&&(gt=!0,p.warnings?.onWarning?.(e)),un()}function un(){if(!P||!ke)return;const e=_.length,t=e>0;if(P.style.display=t?"flex":"none",ke.style.display=t?"":"none",!t)return;const n=io(_[0]),o=`${e} data ${e===1?"warning":"warnings"}`;P.style.color=n==="error"?g.errText:g.warnText,P.ariaLabel=n==="error"?`${o} \u2014 wafers in this lot may be positionally wrong`:o}(p.warnings?.display??!0)&&(ke=$(),P=N("warning","Data warnings",()=>{const e=re();if(Se(new MouseEvent("click")),e)return;const t=oo(P.getBoundingClientRect(),_,P.ownerDocument.defaultView??window);It(f).appendChild(t),de(t),$t(t,P,()=>Se(new MouseEvent("click")))}),be(P,!1),T.appendChild(ke),T.appendChild(P)),ht();let U=null;Ze&&(U=N("analysis","Insights",()=>{const e=ee?.style.display!=="none";yt(!e)}),U.dataset.wmapInsightsBtn="1",T.appendChild($()),T.appendChild(U));function bt(){import("./userGuideHtml.js").then(e=>jn({buildWaferMap:eo,renderWaferMap:Qe,renderWaferGallery,analyzeWaferMap:Le},e.USER_GUIDE_HTML,_t,f))}Nt&&(T.appendChild($()),T.appendChild(N("help","User guide",()=>bt())));const G=f.ownerDocument.createElement("div");G.dataset.wmapGalleryLegend="1",Object.assign(G.style,{display:"flex",flexDirection:"column",gap:"6px",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"6px 10px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"});const F=f.ownerDocument.createElement("div");Object.assign(F.style,{display:"flex",flexDirection:"row",gap:"12px",alignItems:"flex-start"});let ue=null,ee=null;Ze&&(ue=po({getItems:()=>w,getLotStats:()=>E,getColorSchemeName:()=>r.colorScheme??"default",passBins:Je,getRingCount:()=>r.ringCount??4,defaultView:p.insights?.defaultView,backTab:{label:"Gallery",onBack:()=>yt(!1)},showMetadataStrip:!1,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,ownerDocument:f.ownerDocument,openWafer:(e,t,n)=>{const o=w[e];if(!o)return;let s=null;const c=Fn({title:t,onClose:()=>s?.destroy(),anchor:f});Bt(c,t,o.wafer.metadata??void 0),s=Ge(c.contentWrap,o,n)}}),ee=ue.el);let je=!1;function yt(e){!ue||!ee||(je=e,ee.style.display=e?"flex":"none",F.style.display=e?"none":"flex",M.style.display=e?"none":"inline-flex",U&&(se(U,e),U.innerHTML=e?ge.wafer:ge.analysis,U.ariaLabel=e?"Back to gallery view":"Insights"),X(),Ee(),e&&ue.render())}const fn=4,ze=240,wt=480,pn=720,mn=1.25,xt=p.maxSize;let z=xt??wt;function vt(e){const t=Q*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const s=o.dies[0].width;if(!(s>0))continue;const c=o.wafer.radius*2*(fn/s),i=Math.ceil(c+t);(n==null||i>n)&&(n=i)}return n}function gn(e){const t=vt(e);return t==null?ze:Math.min(z,Math.max(ze,t))}function hn(e){if(xt!=null)return!1;const t=vt(e);if(t==null)return!1;const n=Math.min(pn,Math.max(wt,t));return n<=z?!1:(z=n,!0)}function bn(){for(const e of Array.from(B.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${z}px`,e.style.maxHeight=`${z}px`)}let De=ze,Ct=0;function St(e){const t=hn(e);if(t&&bn(),W!=null){t&&Be();return}const n=gn(e);n>De&&(De=n),Be()}function Mt(e){W=e,Be()}function Ve(e){return`repeat(${e}, minmax(0, ${z}px))`}function kt(e){B.style.gridTemplateColumns!==e&&(B.style.gridTemplateColumns=e)}function Be(){if(W!=null){kt(Ve(W));return}const e=Math.max(1,Ct),t=12,n=B.clientWidth||0,o=c=>(n-t*(c-1))/c;let s=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const c=Math.min(z,De*mn),i=d=>{let l=0;for(;l<e&&o(l+1)>=d;)l++;return l};s=i(c)||i(De)||1}kt(Ve(s))}const B=f.ownerDocument.createElement("div");if(Object.assign(B.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:Ve(1),gap:"12px",justifyContent:"start",alignContent:"start",isolation:"isolate"}),le=E?"lot":"wafers",Y?.placement){const e=Y.placement;m=Ye(e,f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.display="flex",m.style.flexDirection="column"}else if(E||Ce()){const e=!!Y?.defaultOpen;m=Ye("right",f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.flexDirection="column",m.style.display=e?"flex":"none",R()}X(),m?.style.display!=="none"&&O&&se(O,!0),(Y?.placement??"right")==="left"?(m&&F.appendChild(m),F.appendChild(B)):(F.appendChild(B),m&&F.appendChild(m));const fe=f.ownerDocument.createElement("div");Object.assign(fe.style,{position:"sticky",top:"0",zIndex:"1",background:g.menuBg}),fe.appendChild(T),fe.appendChild(G),f.appendChild(fe),f.appendChild(F),ee&&f.appendChild(ee);function Ee(){G.innerHTML="";const e=r.plotMode??"hardBin",t=!je&&Lt.has(e),n=k.filter(y=>y!=null),o=n.find(y=>y.isLotStack),s=lo(n.map(y=>({metadata:y.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),c=e==="metadata",i=r.activeMetadataKey,d=new Set;if(t&&!c)for(const y of n)for(const L of y.dies){if(L.partial)continue;const x=e==="softBin"?L.sbin:L.hbin;x!=null&&d.add(x)}const l=t&&!c?[...d].sort((y,L)=>y-L):[],a=new Set;if(t&&c&&i)for(const y of n)for(const L of y.dies){if(L.partial)continue;const x=L.metadata?.[i];x!=null&&(typeof x=="string"||typeof x=="number"||typeof x=="boolean")&&a.add(String(x))}const u=t&&c?[...a].sort(ao):[];if(!s&&!l.length&&!u.length){G.style.display="none";return}if(G.style.display="flex",s&&G.appendChild(s),!l.length&&!u.length)return;const h=f.ownerDocument.createElement("div");Object.assign(h.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"6px 14px"}),s&&Object.assign(h.style,{borderTop:`1px solid ${g.separator}`,paddingTop:"6px"}),G.appendChild(h);const b=En(r.colorScheme),S=r.highlightBin;if(c){const y=r.highlightMetadataValue,L=k.flatMap(x=>x?.metadataFields??[]).find(x=>x.key===i);u.forEach((x,Ke)=>{const qe=y===x,Ot=L?.values?.find(Xe=>Xe.value===x),Mn=Ot?.color??On(Ke);zt(h,{color:Mn,isActive:qe,label:Ot?.label??x,onClick:()=>{const Xe=r.highlightMetadataValue===x?void 0:x;C({highlightMetadataValue:Xe})}})});return}const A=e==="softBin"?k.flatMap(y=>y?.sbinDefs??[]):k.flatMap(y=>y?.hbinDefs??[]),H=new Set,K=[];for(const y of A)H.has(y.bin)||(H.add(y.bin),K.push(y));const me=K.length>0?new Map(K.map(y=>[y.bin,y])):null;for(const y of l){const L=S===y,x=me?.get(y),Ke=(r.colorScheme==="custom"?x?.color:void 0)??b.forBin(y);zt(h,{color:Ke,isActive:L,label:x?.name?`${y} \xB7 ${x.name}`:`Bin ${y}`,onClick:()=>{const qe=r.highlightBin===y?void 0:y;C({highlightBin:qe})}})}}function pe(e){const t=w.filter(d=>d!==null);if(!t.length)return[];const n=t.map(d=>d.dies.filter(go)),o=t[0].wafer,s=t.length,c=o.metadata?{...o,metadata:(({wafer:d,waferId:l,...a})=>a)(o.metadata)}:o;function i(d,l){return{...d,stats:{...d.stats,isLotStack:!0,aggregationMethod:l,lotSize:s}}}if(e==="stackedValues"){const d=t.find(u=>u.testDefs?.length)?.testDefs;let l=d?.filter(At);if(d?.length||(l=kn(t.flatMap(h=>h.dies)).map(h=>({testNumber:h,name:`Test ${h}`}))),!l?.length)return[];const a=r.aggregationMethod??"mean";return l.map(u=>{const h=Zn(n,a,u.testNumber),b={testNumber:0,name:u.name,unit:u.unit};return{wafer:c,dies:h,testDefs:[b],label:`${u.name} \xB7 ${a}`,isLotStack:!0,aggrMethod:a,lotSize:s,statsSummary:i(Le({wafer:c,dies:h,testDefs:[b]},{testNumbers:[0]}),a)}})}if(e==="stackedBins"){let d=We(t.flatMap(l=>l.hbinDefs??[]));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.hbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(l=>{const a=Ft(n,l.bin,"hard"),u=[{bin:l.bin,name:l.name}];return{wafer:c,dies:a,hbinDefs:u,label:`${l.bin} \xB7 ${l.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Le({wafer:c,dies:a,hbinDefs:u}),"countBin")}})}if(e==="stackedSoftBins"){let d=We(t.flatMap(l=>l.sbinDefs??[]));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.sbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(l=>{const a=Ft(n,l.bin,"soft"),u=[{bin:l.bin,name:l.name}];return{wafer:c,dies:a,sbinDefs:u,label:`${l.bin} \xB7 ${l.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Le({wafer:c,dies:a,sbinDefs:u}),"countBin")}})}return t}function Ne(e){const t=w.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:r.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const yn=new Set(["default","accessible","custom"]);function C(e,{fireCallback:t=!0}={}){const n=r.plotMode,o=ie()!==null;r={...r,...e};const s=r.plotMode,c=he.has(s),i=n!==void 0&&he.has(n),d=ve>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(s==="hardBin"||s==="softBin")&&!yn.has(r.colorScheme??"")&&(r={...r,colorScheme:"default"}),e.plotMode!==void 0)if(c){const a=Ne(s);if(r={...r,...a},d)for(const u of v)u&&u.setOptions(e);else V(pe(s))}else if(i){const{valueRange:a,lotSize:u,aggregationMethod:h,...b}=r;if(r=b,d)for(const S of v)S&&S.setOptions(e);else V(w.filter(S=>S!==null))}else for(const a of v)a&&a.setOptions(e);else if(e.aggregationMethod!==void 0&&s==="stackedValues")if(d)for(const a of v)a&&a.setOptions(e);else V(pe("stackedValues"));else for(const a of v)a&&a.setOptions(e);ie()!==null!==o&&et(),Ee(),ft(),ct(),rt();const l=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||l)&&R(),pt(),mt(),t){const a=Object.keys(e);p.onViewOptionsChange?.(r,a,Jn(a))}}function Dt(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0"});const s=e.createElement("span");s.textContent=t,Object.assign(s.style,{fontWeight:"700",fontSize:"13px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(s);const c=jt(n??{});let i=null;if(c.length>0){const d=e.createElement("span");Object.assign(d.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),d.textContent="\u25BE",o.appendChild(d),Object.assign(o.style,{cursor:"pointer"}),i=e.createElement("div"),i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Wt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const l=Ht(n??{});l&&i.appendChild(l),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Pt(o,a=>{d.textContent=a?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(a)),i&&(i.style.display=a?"block":"none")})}return{wrap:o,metaPanel:i}}function Bt(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),s=jt(n??{});if(!o||s.length===0)return;const c=o.parentElement,i=f.ownerDocument.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0",cursor:"pointer"}),c?.insertBefore(i,o),i.appendChild(o);const d=f.ownerDocument.createElement("span");Object.assign(d.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),d.textContent="\u25BE",i.appendChild(d);const l=f.ownerDocument.createElement("div");l.dataset.wmapCardMetaPanel="1",Object.assign(l.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Wt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const a=Ht(n??{});a&&l.appendChild(a),e.contentWrap.style.position="relative",e.contentWrap.appendChild(l),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Pt(i,u=>{d.textContent=u?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(u)),l.style.display=u?"block":"none"})}function _e(e,t,n){const o=f.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${z}px`,maxHeight:`${z}px`});const s=f.ownerDocument.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"});const{wrap:c,metaPanel:i}=Dt(document,e.label??"",e.wafer.metadata??void 0);s.appendChild(c);const d=f.ownerDocument.createElement("button");d.dataset.wmapExpandBtn="1",d.title="Open full view",d.innerHTML=ge.expand,Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${g.menuBorder}`,borderRadius:"4px",background:g.panelBg,color:g.label,padding:"2px",cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),s.appendChild(d),o.appendChild(s);const l=f.ownerDocument.createElement("div");Object.assign(l.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(l),i&&l.appendChild(i),B.appendChild(o);const a=xe||ie()!==null,u=e.viewOptions?{...r,...e.viewOptions}:r,h=Qe(l,e,{viewOptions:{...u,showLegend:a},toolbarControls:"full",showTooltip:!0,padding:Q,legendPosition:oe,fallbackFormat:we,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>Oe(t,e),showMetadataBadge:!1});return h.setViewControlsVisible(!1),h.setSummaryVisible(!1),d.onclick=()=>Oe(t,e),{card:o,ctrl:h,canvasWrapper:l,expandBtn:d}}function wn(e){const t=Z[e];if(!t)return;const n=[...I.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=ge.minimize,t.title="Reattach to gallery",t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>vn(n.id)):(t.innerHTML=ge.expand,t.title="Open full view",t.setAttribute("aria-label","Open full view"),t.onclick=()=>Oe(e,k[e]))}function V(e){Cn(),re()?.remove(),de(null),Ae(),k=[];for(const i of v)i&&i.destroy();v=[],q=[],Z=[],ve=0,B.innerHTML="",Ct=e.length,St(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const d=e[i];if(typeof d=="function"){const l=f.ownerDocument.createElement("div");l.className="wmap-gallery-card",Object.assign(l.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const a=f.ownerDocument.createElement("span");a.textContent="\u2026",Object.assign(a.style,{color:g.label,fontSize:"18px"}),l.appendChild(a),B.appendChild(l),k.push(null),v.push(null),q.push(null),Z.push(null),t.push({index:i,factory:d,placeholder:l}),ve++}else{const{ctrl:l,canvasWrapper:a,expandBtn:u}=_e(d,i,e.length);k.push(d),v.push(l),q.push(a),Z.push(u)}}k.flatMap(i=>i?[...i.hbinDefs??[],...i.sbinDefs??[]]:[]).some(i=>i.color)&&!p.viewOptions?.colorScheme&&(r={...r,colorScheme:"custom"}),Ee();const o=++Re;let s=0;function c(){if(o!==Re)return;if(s>=t.length){if(he.has(r.plotMode)){const A=r.plotMode;V(pe(A))}return}const{index:i,factory:d,placeholder:l}=t[s++],a=d();k[i]=a,w[i]=a,St([a]);const{card:u,ctrl:h,canvasWrapper:b,expandBtn:S}=_e(a,i,e.length);v[i]=h,q[i]=b,Z[i]=S,ve--,l.replaceWith(u),Ee(),!m&&!Y?.placement&&a.statsSummary?.findings.length?(E||(le="wafers"),m=Ye("right",f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.flexDirection="column",m.style.display="none",(Y?.placement??"right")==="left"?F.insertBefore(m,B):F.appendChild(m),R(),O||(O=N("findings","Summary panel",()=>{if(!m)return;const H=m.style.display!=="none";H||R(),m.style.display=H?"none":"flex",se(O,!H),X()}),T.appendChild($()),T.appendChild(O)),X()):m&&m.style.display!=="none"&&R(),X(),setTimeout(c,0)}t.length>0&&setTimeout(c,0)}if(he.has(r.plotMode)&&w.length>0){const e=Ne(r.plotMode);r={...r,...e},V(pe(r.plotMode))}else V(D);let te=0;const Et=new(f.ownerDocument.defaultView??window).ResizeObserver(()=>{if(te)return;te=(f.ownerDocument.defaultView??window).requestAnimationFrame(()=>{te=0,W==null&&Be()})});Et.observe(B),m&&R();function xn(e,t){const n=q[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=f.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:g.label,fontSize:"12px",textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Oe(e,t){for(const i of I.values())if(i.cardIndex===e)return;const n=t.label??"Wafer map",o=Kt++,s=v[e]?.getOptions(),c=$n(n);if(c){const i=c.document;i.title=n,Object.assign(i.documentElement.style,{height:"100%"}),Object.assign(i.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),An(f,i.documentElement);const d=Hn(f,i.documentElement,()=>A.setOptions({})),l=i.createElement("div");l.dataset.wmapWindowBanner="1",l.textContent=n,Object.assign(l.style,{display:"none",padding:"6px 12px",fontSize:"12px",fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),i.body.appendChild(l);const a=i.createElement("div");Object.assign(a.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),i.body.appendChild(a);const{wrap:u,metaPanel:h}=Dt(i,n,t.wafer.metadata??void 0),b=i.createElement("div");Object.assign(b.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"}),b.appendChild(u),a.appendChild(b);const S=i.createElement("div");Object.assign(S.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),h&&S.appendChild(h),a.appendChild(S);const A=Ge(S,t,void 0,s),H=setInterval(()=>{c.closed&&Te(o)},400);c.addEventListener("pagehide",()=>Te(o)),I.set(o,{id:o,ctrl:A,cardIndex:e,label:n,closePollId:H,stopThemeSync:d,close:()=>{c.closed||c.close()},setTitle:K=>{i.title=K,l.textContent=K,l.style.display="block"}})}else{const i=Pn({title:n,onClose:()=>Te(o),anchor:f});i.contentWrap.style.flexDirection="column",Bt(i,n,t.wafer.metadata??void 0);const d=Ge(i.contentWrap,t,void 0,s);I.set(o,{id:o,ctrl:d,cardIndex:e,label:n,closePollId:null,close:()=>i.close(),setTitle:l=>{const a=i.box.querySelector("[data-wmap-window-title]");a&&(a.textContent=l,a.title=l)}})}v[e]?.destroy(),v[e]=null,xn(e,c!==null),wn(e)}function Ge(e,t,n,o){const s=t.viewOptions?{...r,...t.viewOptions}:r,c=o?{...s,...o}:s,d={...n!==void 0?{...c,plotMode:"value",activeTest:n}:c,showLegend:!0},l=Qe(e,t,{viewOptions:d,toolbarControls:"full",showTooltip:!0,padding:Q,legendPosition:oe,fallbackFormat:we,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showMetadataBadge:!1});return l.setViewControlsVisible(!0),l.setSummaryVisible(!0),l.setExpandVisible(!1),l}function Te(e){const t=I.get(e);if(!t)return;I.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const o=t.cardIndex,s=k[o];if(!s)return;const c={...s,viewOptions:n};k[o]=c;const{card:i,ctrl:d,canvasWrapper:l,expandBtn:a}=_e(c,o,k.length);q[o]?.parentElement?.replaceWith(i),v[o]=d,q[o]=l,Z[o]=a}function vn(e){const t=I.get(e);t&&(t.close(),Te(e))}function Cn(){for(const e of I.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function Sn(){const e=[...B.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),s=e[0].width,c=e[0].height,i=8,d=window.devicePixelRatio||1,l=Math.round(26*d),a=Math.round(12*d),u=f.ownerDocument.createElement("canvas");u.width=n*s+(n-1)*i,u.height=o*(c+l)+(o-1)*i;const h=u.getContext("2d"),b=Tn(B);h.fillStyle=b.background,h.fillRect(0,0,u.width,u.height),e.forEach((S,A)=>{const H=A%n,K=Math.floor(A/n),me=H*(s+i),y=K*(c+l+i),L=S.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";h.fillStyle=b.surface,h.fillRect(me,y,s,l),h.fillStyle=b.text,h.font=`700 ${a}px system-ui, sans-serif`,h.textAlign="left",h.textBaseline="middle",h.fillText(L,me+Math.round(10*d),y+l/2,s-Math.round(20*d)),h.drawImage(S,me,y+l)}),u.toBlob(S=>{S&&Kn(S,ne,p.onSaveImage)})}return{setItems(e){w=e.map(n=>typeof n=="function"?null:n);const t=r.plotMode;if(he.has(t))if(e.some(o=>typeof o=="function"))V(e);else{const o=Ne(t);r={...r,...o},V(pe(t))}else V(e)},setOptions(e){C(e,{fireCallback:!1})},getOptions(){return{...r}},setFallbackFormat(e){we=e;for(const t of v)t&&t.setFallbackFormat(e)},setLotStatsSummary(e){E=e,ht(),m&&R(),X()},setColumns(e){Mt(e)},openUserGuide:bt,destroy(){Re++;for(const e of[...I.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();I.clear();for(const e of v)e&&e.destroy();v=[],re()?.remove(),Et.disconnect(),te&&((f.ownerDocument.defaultView??window).cancelAnimationFrame(te),te=0),f.ownerDocument.removeEventListener("click",Se,!0),window.removeEventListener("blur",it),Gt(),Rt(),fe.remove(),F.remove(),m?.remove(),ue?.destroy()}}}
20
+ </html>`;An(i,{anchor:f})}),m.appendChild(n)}if(e.length===0){const n=f.ownerDocument.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:"11px",padding:"4px 0"}),n.textContent="No findings on any wafer.",m.appendChild(n)}else for(const{index:n,item:o,unusualCount:s,notableCount:c,totalCount:i}of e){const d=s?"unusual":c?"notable":"info",l=s+c||i,a=f.ownerDocument.createElement("button");a.type="button",Object.assign(a.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:"4px",border:"none",borderLeft:`3px solid ${Tt(d)}`,borderRadius:"3px",background:g.bgHover,cursor:"pointer",fontSize:"11px",textAlign:"left",boxSizing:"border-box"}),a.addEventListener("mouseover",()=>{a.style.background=g.bgActive}),a.addEventListener("mouseout",()=>{a.style.background=g.bgHover});const u=f.ownerDocument.createElement("span");u.textContent=o.label??`W${n+1}`,Object.assign(u.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const h=f.ownerDocument.createElement("span");h.textContent=String(l),a.setAttribute("aria-label",`${o.label??`W${n+1}`} \u2014 ${l} finding${l===1?"":"s"}${s?`, ${s} unusual`:""} \u2014 view wafer`),Object.assign(h.style,{marginLeft:"6px",flexShrink:"0",background:Tt(d),color:"#fff",borderRadius:"8px",padding:"1px 5px",fontSize:"10px",fontWeight:"600"}),a.appendChild(u),a.appendChild(h),a.addEventListener("click",()=>Oe(n,o)),m.appendChild(a)}const t=f.ownerDocument.createElement("div");t.style.height="12px",m.appendChild(t)}function R(){if(m)if(le==="lot"&&E){const e=We(w.flatMap(n=>n?.hbinDefs??[])),t=We(w.flatMap(n=>n?.sbinDefs??[]));ro(m,{lotSummary:E,items:w,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:w.find(n=>n?.testDefs?.length)?.testDefs,passBins:Je,ringCount:r.ringCount,colorScheme:r.colorScheme,fallbackFormat:we,activeFindingId:ae,warnings:p.warnings?.display??!0?_:[],findingsFilter:qt,onFindingsFilterChange:R,onSaveText:p.onSaveText,onFindingClick:(n,o)=>{ae===n.id?Ae():Zt(n,o),R()},onWaferClick:n=>{Ie([n])},dieListOptions:p.dieList}),Ce()&&m.insertBefore(at(),m.firstChild)}else Yt()}function lt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}function Ae(){ae=null,$e(),Pe(),C({highlightBin:void 0},{fireCallback:!1})}function Zt(e,t){if(ae===e.id){Ae();return}ae=e.id,t.style.background=g.bgActive,t.style.fontWeight="600";const{kind:n,index:o}=e.variable;n==="test"?C({plotMode:"value",activeTest:o??0,highlightBin:void 0},{fireCallback:!1}):n==="softBin"?C({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):C({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1}),$e(),Pe();const s=e.highlight;if(s.kind==="wafer"){Ie(s.waferIndices);const c=lt(e);for(const i of s.waferIndices){const a=k[i]?.statsSummary?.findings.find(u=>lt(u)===c)?.highlight?.dieKeys;a?.length&&Fe(a,[i])}}else s.kind==="bin"?s.dieKeys?.length&&Fe(s.dieKeys):(s.kind==="region"||s.kind==="dies")&&s.dieKeys?.length&&Fe(s.dieKeys)}function X(){if(!O)return;const e=!!m;O.style.display=(E||Ce())&&e&&!je?"flex":"none";const t=m?m.style.display!=="none":!1;(E?.hasNotableFindings||w.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?O.style.color=g.findingIndicator:O.dataset.active||(O.style.color=g.icon)}const T=f.ownerDocument.createElement("div");T.dataset.wmapToolbar="gallery",Object.assign(T.style,{display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"3px 4px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const st=()=>{const e=re();e&&(e.remove(),de(null)),be(j,!1)},j=N("mode","Plot mode",()=>{if(re()){st();return}const e=w.flatMap(b=>b?.dies??[]),t=w.find(b=>b?.testDefs?.length)?.testDefs,{testEntries:n,binEntries:o,stackedEntries:s}=Qn(e,t,{includeStacked:!0}),c=r.plotMode??"hardBin",i=r.activeTest??0;function d(b){return b.plotMode!==c?!1:b.plotMode==="value"?i===(b.activeTest??0):b.plotMode==="metadata"?r.activeMetadataKey===b.activeMetadataKey:!0}function l(b,S){b.activeTest!==void 0?C({plotMode:"value",activeTest:b.activeTest,activeMetadataKey:void 0,logScale:b.logScale}):b.activeMetadataKey!==void 0?C({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:b.activeMetadataKey,passFailDisplay:"off"}):C({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),S.remove(),de(null),be(j,!1)}const a=new Set,u=w.flatMap(b=>b?.metadataFields??[]).filter(b=>!a.has(b.key)&&a.add(b.key)).filter(b=>Yn(e,b.key)).map(Zn),h=In(j.getBoundingClientRect(),n,o,s,d,l,{makeMenuRow:Ut,makeMenuSection:Qt},c,j.ownerDocument.defaultView??window,u);It(j).appendChild(h),de(h),be(j,!0),$t(h,j,st)});be(j,!1);const Jt=()=>k.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:en,sync:rt}=Vn(J,()=>r.plotMode??"hardBin",()=>r.colorScheme??"default",Jt,e=>C({colorScheme:e}),{get:()=>r.markFailingDies??!1,set:e=>C({markFailingDies:e})});rt();const tn=D.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function He(){const e=w.find(n=>n?.testDefs?.length)?.testDefs,{testNumber:t}=Dn(r.activeTest??0,e);return{testNumber:t,td:Bn(e,t)}}function dt(){if((r.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function ce(){if((r.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&!At(e)}function nn(){if((r.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=He();return w.some(n=>n?.dies?.some(o=>no(o,e,t)!==void 0))}const on=Gn(J,()=>[{label:"Ring boundaries",active:!!r.showRingBoundaries,onClick:()=>C({showRingBoundaries:!r.showRingBoundaries})},{label:"Quadrant lines",active:!!r.showQuadrantBoundaries,onClick:()=>C({showQuadrantBoundaries:!r.showQuadrantBoundaries})},{label:"Die labels",active:!!r.showDieLabels,onClick:()=>C({showDieLabels:!r.showDieLabels})},{label:"Reticle grid",active:!!r.showReticle,enabled:tn,onClick:()=>C({showReticle:!r.showReticle})},{label:"XY indicator",active:!!r.showXYIndicator,onClick:()=>C({showXYIndicator:!r.showXYIndicator})},...Xn({functionalActive:ce(),hasLimits:dt()&&!ce(),hasRecorded:nn()&&!ce(),display:Ue(r)},e=>C({passFailDisplay:e}))],()=>!!(r.showRingBoundaries||r.showQuadrantBoundaries||r.showDieLabels||r.showReticle||r.showXYIndicator||Ue(r)!=="off")),{btn:an,sync:ct}=_n(J,()=>({plotMode:r.plotMode,legendPosition:oe}),e=>{oe=e;for(const t of v)t&&t.setOptions({legendPosition:oe})},{get:()=>xe,set:e=>{xe=e,et()},blockedReason:ie});ct();const ln=[{value:"mean",label:"Mean"},{value:"median",label:"Median"},{value:"stddev",label:"Std Dev"},{value:"min",label:"Min"},{value:"max",label:"Max"},{value:"count",label:"Count"}],ut=ot("aggr","Aggregation method",()=>ln,()=>r.aggregationMethod??"mean",e=>C({aggregationMethod:e}));function ft(){const e=r.plotMode==="stackedValues";ut.style.display=e?"":"none"}ft();const{btn:sn,sync:pt}=Nn(J,()=>({...r,functionalActive:ce()}),e=>C(e));pt();const Me=N("specRange","Colorbar range: spec limits",()=>{const e=r.colorbarRangeMode==="data"?"spec":"data";C({colorbarRangeMode:e})});function mt(){const e=(r.plotMode??"hardBin")==="value"&&dt()&&Ue(r)==="off"&&!ce();Me.style.display=e?"":"none";const t=(r.colorbarRangeMode??"spec")==="spec";se(Me,t),Me.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}mt();const rn=Kn(J,()=>r,e=>C(e)),dn=N("downloadAll","Download gallery PNG",Sn),cn=ot("columns","Columns",()=>[{value:"auto",label:"Auto"},{value:"1",label:"1 column"},{value:"2",label:"2 columns"},{value:"3",label:"3 columns"},{value:"4",label:"4 columns"},{value:"5",label:"5 columns"}],()=>W!=null?String(W):"auto",e=>Mt(e==="auto"?void 0:Number(e))),M=f.ownerDocument.createElement("div");Object.assign(M.style,{display:"inline-flex",alignItems:"center",gap:"0"}),T.appendChild(M),Vt&&M.appendChild(j),M.appendChild(en),M.appendChild(ut),M.appendChild(sn),M.appendChild(Me),M.appendChild($()),M.appendChild(on),M.appendChild($()),M.appendChild(an),M.appendChild($()),M.appendChild(rn),M.appendChild($()),M.appendChild(cn),M.appendChild($()),M.appendChild(dn),(E||Ce())&&(O=N("findings","Summary panel",()=>{if(!m)return;const e=m.style.display!=="none";e||R(),m.style.display=e?"none":"flex",se(O,!e),X()}),T.appendChild($()),T.appendChild(O));let P=null,ke=null,_=[],gt=!1;function ht(){const e=oo({lotStatsSummary:E,result:{warnings:w.flatMap(n=>n?.warnings??[])}}),t=e.length!==_.length||e.some((n,o)=>n.code!==_[o]?.code||n.message!==_[o]?.message);_=e,(t||!gt)&&(gt=!0,p.warnings?.onWarning?.(e)),un()}function un(){if(!P||!ke)return;const e=_.length,t=e>0;if(P.style.display=t?"flex":"none",ke.style.display=t?"":"none",!t)return;const n=ao(_[0]),o=`${e} data ${e===1?"warning":"warnings"}`;P.style.color=n==="error"?g.errText:g.warnText,P.ariaLabel=n==="error"?`${o} \u2014 wafers in this lot may be positionally wrong`:o}(p.warnings?.display??!0)&&(ke=$(),P=N("warning","Data warnings",()=>{const e=re();if(Se(new MouseEvent("click")),e)return;const t=io(P.getBoundingClientRect(),_,P.ownerDocument.defaultView??window);It(f).appendChild(t),de(t),$t(t,P,()=>Se(new MouseEvent("click")))}),be(P,!1),T.appendChild(ke),T.appendChild(P)),ht();let U=null;Ze&&(U=N("analysis","Insights",()=>{const e=ee?.style.display!=="none";yt(!e)}),U.dataset.wmapInsightsBtn="1",T.appendChild($()),T.appendChild(U));function bt(){import("./userGuideHtml.js").then(e=>zn({buildWaferMap:to,renderWaferMap:Qe,renderWaferGallery,analyzeWaferMap:Le},e.USER_GUIDE_HTML,_t,f))}Nt&&(T.appendChild($()),T.appendChild(N("help","User guide",()=>bt())));const G=f.ownerDocument.createElement("div");G.dataset.wmapGalleryLegend="1",Object.assign(G.style,{display:"flex",flexDirection:"column",gap:"6px",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"6px 10px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"});const F=f.ownerDocument.createElement("div");Object.assign(F.style,{display:"flex",flexDirection:"row",gap:"12px",alignItems:"flex-start"});let ue=null,ee=null;Ze&&(ue=po({getItems:()=>w,getLotStats:()=>E,getColorSchemeName:()=>r.colorScheme??"default",passBins:Je,getRingCount:()=>r.ringCount??4,defaultView:p.insights?.defaultView,backTab:{label:"Gallery",onBack:()=>yt(!1)},showMetadataStrip:!1,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,ownerDocument:f.ownerDocument,openWafer:(e,t,n)=>{const o=w[e];if(!o)return;let s=null;const c=Fn({title:t,onClose:()=>s?.destroy(),anchor:f});Bt(c,t,o.wafer.metadata??void 0),s=Ge(c.contentWrap,o,n)}}),ee=ue.el);let je=!1;function yt(e){!ue||!ee||(je=e,ee.style.display=e?"flex":"none",F.style.display=e?"none":"flex",M.style.display=e?"none":"inline-flex",U&&(se(U,e),U.innerHTML=e?ge.wafer:ge.analysis,U.ariaLabel=e?"Back to gallery view":"Insights"),X(),Ee(),e&&ue.render())}const fn=4,ze=240,wt=480,pn=720,mn=1.25,xt=p.maxSize;let z=xt??wt;function vt(e){const t=Q*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const s=o.dies[0].width;if(!(s>0))continue;const c=o.wafer.radius*2*(fn/s),i=Math.ceil(c+t);(n==null||i>n)&&(n=i)}return n}function gn(e){const t=vt(e);return t==null?ze:Math.min(z,Math.max(ze,t))}function hn(e){if(xt!=null)return!1;const t=vt(e);if(t==null)return!1;const n=Math.min(pn,Math.max(wt,t));return n<=z?!1:(z=n,!0)}function bn(){for(const e of Array.from(B.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${z}px`,e.style.maxHeight=`${z}px`)}let De=ze,Ct=0;function St(e){const t=hn(e);if(t&&bn(),W!=null){t&&Be();return}const n=gn(e);n>De&&(De=n),Be()}function Mt(e){W=e,Be()}function Ve(e){return`repeat(${e}, minmax(0, ${z}px))`}function kt(e){B.style.gridTemplateColumns!==e&&(B.style.gridTemplateColumns=e)}function Be(){if(W!=null){kt(Ve(W));return}const e=Math.max(1,Ct),t=12,n=B.clientWidth||0,o=c=>(n-t*(c-1))/c;let s=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const c=Math.min(z,De*mn),i=d=>{let l=0;for(;l<e&&o(l+1)>=d;)l++;return l};s=i(c)||i(De)||1}kt(Ve(s))}const B=f.ownerDocument.createElement("div");if(Object.assign(B.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:Ve(1),gap:"12px",justifyContent:"start",alignContent:"start",isolation:"isolate"}),le=E?"lot":"wafers",Y?.placement){const e=Y.placement;m=Ye(e,f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.display="flex",m.style.flexDirection="column"}else if(E||Ce()){const e=!!Y?.defaultOpen;m=Ye("right",f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.flexDirection="column",m.style.display=e?"flex":"none",R()}X(),m?.style.display!=="none"&&O&&se(O,!0),(Y?.placement??"right")==="left"?(m&&F.appendChild(m),F.appendChild(B)):(F.appendChild(B),m&&F.appendChild(m));const fe=f.ownerDocument.createElement("div");Object.assign(fe.style,{position:"sticky",top:"0",zIndex:"1",background:g.menuBg}),fe.appendChild(T),fe.appendChild(G),f.appendChild(fe),f.appendChild(F),ee&&f.appendChild(ee);function Ee(){G.innerHTML="";const e=r.plotMode??"hardBin",t=!je&&Lt.has(e),n=k.filter(y=>y!=null),o=n.find(y=>y.isLotStack),s=so(n.map(y=>({metadata:y.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),c=e==="metadata",i=r.activeMetadataKey,d=new Set;if(t&&!c)for(const y of n)for(const L of y.dies){if(L.partial)continue;const x=e==="softBin"?L.sbin:L.hbin;x!=null&&d.add(x)}const l=t&&!c?[...d].sort((y,L)=>y-L):[],a=new Set;if(t&&c&&i)for(const y of n)for(const L of y.dies){if(L.partial)continue;const x=L.metadata?.[i];x!=null&&(typeof x=="string"||typeof x=="number"||typeof x=="boolean")&&a.add(String(x))}const u=t&&c?[...a].sort(lo):[];if(!s&&!l.length&&!u.length){G.style.display="none";return}if(G.style.display="flex",s&&G.appendChild(s),!l.length&&!u.length)return;const h=f.ownerDocument.createElement("div");Object.assign(h.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"6px 14px"}),s&&Object.assign(h.style,{borderTop:`1px solid ${g.separator}`,paddingTop:"6px"}),G.appendChild(h);const b=En(r.colorScheme),S=r.highlightBin;if(c){const y=r.highlightMetadataValue,L=k.flatMap(x=>x?.metadataFields??[]).find(x=>x.key===i);u.forEach((x,Ke)=>{const qe=y===x,Ot=L?.values?.find(Xe=>Xe.value===x),Mn=Ot?.color??On(Ke);zt(h,{color:Mn,isActive:qe,label:Ot?.label??x,onClick:()=>{const Xe=r.highlightMetadataValue===x?void 0:x;C({highlightMetadataValue:Xe})}})});return}const A=e==="softBin"?k.flatMap(y=>y?.sbinDefs??[]):k.flatMap(y=>y?.hbinDefs??[]),H=new Set,K=[];for(const y of A)H.has(y.bin)||(H.add(y.bin),K.push(y));const me=K.length>0?new Map(K.map(y=>[y.bin,y])):null;for(const y of l){const L=S===y,x=me?.get(y),Ke=(r.colorScheme==="custom"?x?.color:void 0)??b.forBin(y);zt(h,{color:Ke,isActive:L,label:x?.name?`${y} \xB7 ${x.name}`:`Bin ${y}`,onClick:()=>{const qe=r.highlightBin===y?void 0:y;C({highlightBin:qe})}})}}function pe(e){const t=w.filter(d=>d!==null);if(!t.length)return[];const n=t.map(d=>d.dies.filter(go)),o=t[0].wafer,s=t.length,c=o.metadata?{...o,metadata:(({wafer:d,waferId:l,...a})=>a)(o.metadata)}:o;function i(d,l){return{...d,stats:{...d.stats,isLotStack:!0,aggregationMethod:l,lotSize:s}}}if(e==="stackedValues"){const d=t.find(u=>u.testDefs?.length)?.testDefs;let l=d?.filter(At);if(d?.length||(l=kn(t.flatMap(h=>h.dies)).map(h=>({testNumber:h,name:`Test ${h}`}))),!l?.length)return[];const a=r.aggregationMethod??"mean";return l.map(u=>{const h=Jn(n,a,u.testNumber),b={testNumber:0,name:u.name,unit:u.unit};return{wafer:c,dies:h,testDefs:[b],label:`${u.name} \xB7 ${a}`,isLotStack:!0,aggrMethod:a,lotSize:s,statsSummary:i(Le({wafer:c,dies:h,testDefs:[b]},{testNumbers:[0]}),a)}})}if(e==="stackedBins"){let d=We(t.flatMap(l=>l.hbinDefs??[]));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.hbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(l=>{const a=Ft(n,l.bin,"hard"),u=[{bin:l.bin,name:l.name}];return{wafer:c,dies:a,hbinDefs:u,label:`${l.bin} \xB7 ${l.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Le({wafer:c,dies:a,hbinDefs:u}),"countBin")}})}if(e==="stackedSoftBins"){let d=We(t.flatMap(l=>l.sbinDefs??[]));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.sbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(l=>{const a=Ft(n,l.bin,"soft"),u=[{bin:l.bin,name:l.name}];return{wafer:c,dies:a,sbinDefs:u,label:`${l.bin} \xB7 ${l.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Le({wafer:c,dies:a,sbinDefs:u}),"countBin")}})}return t}function Ne(e){const t=w.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:r.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const yn=new Set(["default","accessible","custom"]);function C(e,{fireCallback:t=!0}={}){const n=r.plotMode,o=ie()!==null;r={...r,...e};const s=r.plotMode,c=he.has(s),i=n!==void 0&&he.has(n),d=ve>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(s==="hardBin"||s==="softBin")&&!yn.has(r.colorScheme??"")&&(r={...r,colorScheme:"default"}),e.plotMode!==void 0)if(c){const a=Ne(s);if(r={...r,...a},d)for(const u of v)u&&u.setOptions(e);else V(pe(s))}else if(i){const{valueRange:a,lotSize:u,aggregationMethod:h,...b}=r;if(r=b,d)for(const S of v)S&&S.setOptions(e);else V(w.filter(S=>S!==null))}else for(const a of v)a&&a.setOptions(e);else if(e.aggregationMethod!==void 0&&s==="stackedValues")if(d)for(const a of v)a&&a.setOptions(e);else V(pe("stackedValues"));else for(const a of v)a&&a.setOptions(e);ie()!==null!==o&&et(),Ee(),ft(),ct(),rt();const l=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||l)&&R(),pt(),mt(),t){const a=Object.keys(e);p.onViewOptionsChange?.(r,a,eo(a))}}function Dt(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0"});const s=e.createElement("span");s.textContent=t,Object.assign(s.style,{fontWeight:"700",fontSize:"13px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(s);const c=jt(n??{});let i=null;if(c.length>0){const d=e.createElement("span");Object.assign(d.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),d.textContent="\u25BE",o.appendChild(d),Object.assign(o.style,{cursor:"pointer"}),i=e.createElement("div"),i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Wt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const l=Ht(n??{});l&&i.appendChild(l),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Pt(o,a=>{d.textContent=a?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(a)),i&&(i.style.display=a?"block":"none")})}return{wrap:o,metaPanel:i}}function Bt(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),s=jt(n??{});if(!o||s.length===0)return;const c=o.parentElement,i=f.ownerDocument.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0",cursor:"pointer"}),c?.insertBefore(i,o),i.appendChild(o);const d=f.ownerDocument.createElement("span");Object.assign(d.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),d.textContent="\u25BE",i.appendChild(d);const l=f.ownerDocument.createElement("div");l.dataset.wmapCardMetaPanel="1",Object.assign(l.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Wt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const a=Ht(n??{});a&&l.appendChild(a),e.contentWrap.style.position="relative",e.contentWrap.appendChild(l),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Pt(i,u=>{d.textContent=u?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(u)),l.style.display=u?"block":"none"})}function _e(e,t,n){const o=f.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${z}px`,maxHeight:`${z}px`});const s=f.ownerDocument.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"});const{wrap:c,metaPanel:i}=Dt(document,e.label??"",e.wafer.metadata??void 0);s.appendChild(c);const d=f.ownerDocument.createElement("button");d.dataset.wmapExpandBtn="1",d.title="Open full view",d.innerHTML=ge.expand,Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${g.menuBorder}`,borderRadius:"4px",background:g.panelBg,color:g.label,padding:"2px",cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),s.appendChild(d),o.appendChild(s);const l=f.ownerDocument.createElement("div");Object.assign(l.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(l),i&&l.appendChild(i),B.appendChild(o);const a=xe||ie()!==null,u=e.viewOptions?{...r,...e.viewOptions}:r,h=Qe(l,e,{viewOptions:{...u,showLegend:a},toolbarControls:"full",showTooltip:!0,padding:Q,legendPosition:oe,fallbackFormat:we,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>Oe(t,e),showMetadataBadge:!1});return h.setViewControlsVisible(!1),h.setSummaryVisible(!1),d.onclick=()=>Oe(t,e),{card:o,ctrl:h,canvasWrapper:l,expandBtn:d}}function wn(e){const t=Z[e];if(!t)return;const n=[...I.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=ge.minimize,t.title="Reattach to gallery",t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>vn(n.id)):(t.innerHTML=ge.expand,t.title="Open full view",t.setAttribute("aria-label","Open full view"),t.onclick=()=>Oe(e,k[e]))}function V(e){Cn(),re()?.remove(),de(null),Ae(),k=[];for(const i of v)i&&i.destroy();v=[],q=[],Z=[],ve=0,B.innerHTML="",Ct=e.length,St(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const d=e[i];if(typeof d=="function"){const l=f.ownerDocument.createElement("div");l.className="wmap-gallery-card",Object.assign(l.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const a=f.ownerDocument.createElement("span");a.textContent="\u2026",Object.assign(a.style,{color:g.label,fontSize:"18px"}),l.appendChild(a),B.appendChild(l),k.push(null),v.push(null),q.push(null),Z.push(null),t.push({index:i,factory:d,placeholder:l}),ve++}else{const{ctrl:l,canvasWrapper:a,expandBtn:u}=_e(d,i,e.length);k.push(d),v.push(l),q.push(a),Z.push(u)}}k.flatMap(i=>i?[...i.hbinDefs??[],...i.sbinDefs??[]]:[]).some(i=>i.color)&&!p.viewOptions?.colorScheme&&(r={...r,colorScheme:"custom"}),Ee();const o=++Re;let s=0;function c(){if(o!==Re)return;if(s>=t.length){if(he.has(r.plotMode)){const A=r.plotMode;V(pe(A))}return}const{index:i,factory:d,placeholder:l}=t[s++],a=d();k[i]=a,w[i]=a,St([a]);const{card:u,ctrl:h,canvasWrapper:b,expandBtn:S}=_e(a,i,e.length);v[i]=h,q[i]=b,Z[i]=S,ve--,l.replaceWith(u),Ee(),!m&&!Y?.placement&&a.statsSummary?.findings.length?(E||(le="wafers"),m=Ye("right",f.ownerDocument),m.style.maxHeight="calc(100vh - 80px)",m.style.position="sticky",m.style.top="8px",m.style.flexDirection="column",m.style.display="none",(Y?.placement??"right")==="left"?F.insertBefore(m,B):F.appendChild(m),R(),O||(O=N("findings","Summary panel",()=>{if(!m)return;const H=m.style.display!=="none";H||R(),m.style.display=H?"none":"flex",se(O,!H),X()}),T.appendChild($()),T.appendChild(O)),X()):m&&m.style.display!=="none"&&R(),X(),setTimeout(c,0)}t.length>0&&setTimeout(c,0)}if(he.has(r.plotMode)&&w.length>0){const e=Ne(r.plotMode);r={...r,...e},V(pe(r.plotMode))}else V(D);let te=0;const Et=new(f.ownerDocument.defaultView??window).ResizeObserver(()=>{if(te)return;te=(f.ownerDocument.defaultView??window).requestAnimationFrame(()=>{te=0,W==null&&Be()})});Et.observe(B),m&&R();function xn(e,t){const n=q[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=f.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:g.label,fontSize:"12px",textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Oe(e,t){for(const i of I.values())if(i.cardIndex===e)return;const n=t.label??"Wafer map",o=Kt++,s=v[e]?.getOptions(),c=$n(n);if(c){const i=c.document;i.title=n,Object.assign(i.documentElement.style,{height:"100%"}),Object.assign(i.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),Hn(f,i.documentElement);const d=jn(f,i.documentElement,()=>A.setOptions({})),l=i.createElement("div");l.dataset.wmapWindowBanner="1",l.textContent=n,Object.assign(l.style,{display:"none",padding:"6px 12px",fontSize:"12px",fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),i.body.appendChild(l);const a=i.createElement("div");Object.assign(a.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),i.body.appendChild(a);const{wrap:u,metaPanel:h}=Dt(i,n,t.wafer.metadata??void 0),b=i.createElement("div");Object.assign(b.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"}),b.appendChild(u),a.appendChild(b);const S=i.createElement("div");Object.assign(S.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),h&&S.appendChild(h),a.appendChild(S);const A=Ge(S,t,void 0,s),H=setInterval(()=>{c.closed&&Te(o)},400);c.addEventListener("pagehide",()=>Te(o)),I.set(o,{id:o,ctrl:A,cardIndex:e,label:n,closePollId:H,stopThemeSync:d,close:()=>{c.closed||c.close()},setTitle:K=>{i.title=K,l.textContent=K,l.style.display="block"}})}else{const i=Pn({title:n,onClose:()=>Te(o),anchor:f});i.contentWrap.style.flexDirection="column",Bt(i,n,t.wafer.metadata??void 0);const d=Ge(i.contentWrap,t,void 0,s);I.set(o,{id:o,ctrl:d,cardIndex:e,label:n,closePollId:null,close:()=>i.close(),setTitle:l=>{const a=i.box.querySelector("[data-wmap-window-title]");a&&(a.textContent=l,a.title=l)}})}v[e]?.destroy(),v[e]=null,xn(e,c!==null),wn(e)}function Ge(e,t,n,o){const s=t.viewOptions?{...r,...t.viewOptions}:r,c=o?{...s,...o}:s,d={...n!==void 0?{...c,plotMode:"value",activeTest:n}:c,showLegend:!0},l=Qe(e,t,{viewOptions:d,toolbarControls:"full",showTooltip:!0,padding:Q,legendPosition:oe,fallbackFormat:we,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showMetadataBadge:!1});return l.setViewControlsVisible(!0),l.setSummaryVisible(!0),l.setExpandVisible(!1),l}function Te(e){const t=I.get(e);if(!t)return;I.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const o=t.cardIndex,s=k[o];if(!s)return;const c={...s,viewOptions:n};k[o]=c;const{card:i,ctrl:d,canvasWrapper:l,expandBtn:a}=_e(c,o,k.length);q[o]?.parentElement?.replaceWith(i),v[o]=d,q[o]=l,Z[o]=a}function vn(e){const t=I.get(e);t&&(t.close(),Te(e))}function Cn(){for(const e of I.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function Sn(){const e=[...B.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),s=e[0].width,c=e[0].height,i=8,d=window.devicePixelRatio||1,l=Math.round(26*d),a=Math.round(12*d),u=f.ownerDocument.createElement("canvas");u.width=n*s+(n-1)*i,u.height=o*(c+l)+(o-1)*i;const h=u.getContext("2d"),b=Tn(B);h.fillStyle=b.background,h.fillRect(0,0,u.width,u.height),e.forEach((S,A)=>{const H=A%n,K=Math.floor(A/n),me=H*(s+i),y=K*(c+l+i),L=S.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";h.fillStyle=b.surface,h.fillRect(me,y,s,l),h.fillStyle=b.text,h.font=`700 ${a}px system-ui, sans-serif`,h.textAlign="left",h.textBaseline="middle",h.fillText(L,me+Math.round(10*d),y+l/2,s-Math.round(20*d)),h.drawImage(S,me,y+l)}),u.toBlob(S=>{S&&qn(S,ne,p.onSaveImage)})}return{setItems(e){w=e.map(n=>typeof n=="function"?null:n);const t=r.plotMode;if(he.has(t))if(e.some(o=>typeof o=="function"))V(e);else{const o=Ne(t);r={...r,...o},V(pe(t))}else V(e)},setOptions(e){C(e,{fireCallback:!1})},getOptions(){return{...r}},setFallbackFormat(e){we=e;for(const t of v)t&&t.setFallbackFormat(e)},setLotStatsSummary(e){E=e,ht(),m&&R(),X()},setColumns(e){Mt(e)},openUserGuide:bt,destroy(){Re++;for(const e of[...I.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();I.clear();for(const e of v)e&&e.destroy();v=[],re()?.remove(),Et.disconnect(),te&&((f.ownerDocument.defaultView??window).cancelAnimationFrame(te),te=0),f.ownerDocument.removeEventListener("click",Se,!0),window.removeEventListener("blur",it),Gt(),Rt(),fe.remove(),F.remove(),m?.remove(),ue?.destroy()}}}
@@ -1,3 +1,3 @@
1
- import{isParametricTest as xt}from"../renderer/buildWaferMap.js";import{buildRingRegions as K,buildQuadrantRegions as Z,buildRegionYieldData as bt}from"../stats/regions.js";import{computeFunctionalYield as vt}from"../stats/analyzeWaferMap.js";import{openHtmlReport as J}from"../stats/renderFindingsReport.js";import{renderSummaryReportHtml as wt,renderLotSummaryReportHtml as yt}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as Ct}from"../stats/findingsNarrative.js";import{filterFindings as St}from"../stats/filterFindings.js";import{buildFacetTable as kt,prettyKey as tt}from"../stats/facets.js";import{commonMetadata as et}from"../stats/facets.js";import{resolveMetadataColumns as Bt}from"../stats/metadataColumns.js";import{getColorScheme as $t}from"../renderer/colorSchemes.js";import{buildWarningsBanner as _,collectWarnings as nt}from"./warnings.js";export{_ as buildWarningsBanner};import{fmt as it,fmtAggregationMethod as Lt,plainBinTerms as P}from"../renderer/fmt.js";import{getUniqueTestNumbers as Dt}from"../renderer/buildView.js";import{quantile as Q}from"../stats/math.js";import{makeLabeledSelect as ot}from"./charts/chartShell.js";import{CLR as v,sevColor as G,openModal as at,saveTextFile as rt}from"./toolbar.js";import{buildDieListSection as Rt}from"./dieList.js";import{medianOfSorted as Ft}from"../core/utils.js";import{metadataDisplayValue as Tt}from"../core/metadata.js";const Et=v.panelBg,Y=`1px solid ${v.menuBorder}`,Nt="12px",I=v.label,z=v.value,st="10px";function l(t,i,n,e=document){const o=e.createElement(t);return i&&Object.assign(o.style,i),n!==void 0&&(o.textContent=n),o}function H(t){return l("div",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,marginBottom:"6px"},t)}function lt(t,i=!0,n){const e=l("div"),o=document.createElement("button");o.type="button",Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const d=l("span",{fontSize:"9px",color:I,transition:"transform 0.15s",transform:i?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:"1",marginRight:"1px"},"\u25B6"),f=l("span",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,flex:"1"},t);if(o.setAttribute("aria-expanded",i?"true":"false"),o.appendChild(d),o.appendChild(f),n){const a=l("span",{fontSize:"9px",fontWeight:"700",background:v.warnBg,color:v.warnText,borderRadius:"10px",padding:"1px 5px"},n);o.appendChild(a)}const c=l("div");c.style.display=i?"block":"none";let s=i;return o.addEventListener("click",()=>{s=!s,c.style.display=s?"block":"none",d.style.transform=s?"rotate(90deg)":"rotate(0deg)",o.setAttribute("aria-expanded",s?"true":"false")}),e.appendChild(o),e.appendChild(c),{outer:e,content:c}}function dt(){return l("div",{height:"1px",background:v.separator,margin:`${Nt} 0`,flexShrink:"0"})}function U(t,i,n=v.barFill,e,o,d){const f=l("div",{marginBottom:"5px"}),c=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",color:z,marginBottom:"2px"}),s=l("span",{},t),a=l("span",{fontWeight:"600"},`${i.toFixed(1)}%`);c.appendChild(s),c.appendChild(a);const p=e!==void 0?e:Math.min(100,Math.max(0,i)),h=d?v.barFillMuted:n,g=l("div",{position:"relative",height:"9px",background:v.bgActive,borderRadius:"4px",overflow:"hidden"}),T=l("div",{height:"100%",width:`${p}%`,background:h,borderRadius:"4px",transition:"width 0.3s ease"});if(g.appendChild(T),o!==void 0){const N=l("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"1px",background:v.infoText,opacity:"0.5"});g.appendChild(N)}return f.appendChild(c),f.appendChild(g),f}function O(t,i,n){const e=l("div",{background:v.menuBg,border:Y,borderRadius:"6px",padding:"8px 10px",textAlign:"center",flex:"1"}),o=l("div",{fontSize:"20px",fontWeight:"700",color:z,lineHeight:"1.2"},t),d=l("div",{fontSize:"10px",color:I,marginTop:"2px"},i);return e.appendChild(o),e.appendChild(d),n&&e.appendChild(l("div",{fontSize:"9px",color:I,opacity:"0.85"},n)),e}function Mt(t,i){const n=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",gap:"8px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},t),o=l("span",{color:z,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}function Wt(t,i){const n=l("div",{display:"flex",fontSize:"11px",gap:"6px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},`${t}:`),o=l("span",{color:z,fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}export function metadataEntries(t){const i=[];for(const[n,e]of Object.entries(t)){const o=Tt(e);o!==void 0&&i.push([n,o])}return i}export function buildFacetSummaryChips(t,i=3){if(!t.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 10px",fontSize:"11px"});for(const e of t){const o=l("span",{whiteSpace:"nowrap"}),d=l("span",{color:I},`${tt(e.key)}: `);o.appendChild(d);const f=e.values.slice(0,i),c=e.values.length-f.length;let s=f.map(a=>a.value).join(", ");c>0&&(s+=` +${c} more`),o.appendChild(document.createTextNode(s)),n.appendChild(o)}return n}export function buildMetadataStripRow(t,i,n){const e=kt(t,n),o=buildFacetSummaryChips(e);if(!o&&!i)return null;const d=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(i){const f=l("span",{fontWeight:"500",whiteSpace:"nowrap"},i.aggrMethod?`${i.lotSize} wafers stacked \xB7 ${i.aggrMethod}`:`${i.lotSize} wafers stacked`);d.appendChild(f)}return o&&d.appendChild(o),d}const It={display:"flex",flexDirection:"column",gap:"6px",background:v.menuBg,border:`1px solid ${v.menuBorder}`,borderRadius:"6px",padding:"6px 10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,i,n){const e=buildMetadataStripRow(t,i,n);if(!e)return null;const o=l("div",It);return o.appendChild(e),o}export function buildCompactMetadataRows(t){const i=metadataEntries(t);if(!i.length)return null;const n=l("div");for(const[e,o]of i)n.appendChild(Wt(tt(e),o));return n}export function buildMetadataInfoSection(t,i){const n=buildMetadataStripRow(t,i,{facetableOnly:t.length>1});if(!n)return null;const e=l("div");return e.appendChild(H("Wafer Info")),e.appendChild(n),e}export function buildYieldSection(t,i,n=[1]){const e=l("div");e.appendChild(H("Summary"));const o=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});if(o.appendChild(O(String(t.totalDies),"Total dies")),t.partialDies>0&&o.appendChild(O(String(t.partialDies),"Partial")),t.yieldPercent!==null){const d=n.length===1?`bin ${n[0]}`:`bins ${n.join(", ")}`;o.appendChild(O(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${d}`))}return e.appendChild(o),t.edgeExcludedDies>0&&e.appendChild(Mt("Edge excluded (outer zone)",String(t.edgeExcludedDies))),e}export function buildBinSection(t,i,n,e,o){const d=new Map;if(o)for(const[p,h]of Object.entries(o))d.set(Number(p),h);else for(const p of t){if(p.partial||p.edgeExcluded)continue;const h=n==="hard"?p.hbin:p.sbin;h!=null&&d.set(h,(d.get(h)??0)+1)}if(!d.size)return null;const f=[...d.values()].reduce((p,h)=>p+h,0),c=i?new Map(i.map(p=>[p.bin,p])):null,s=[...d.entries()].sort((p,h)=>p[0]-h[0]),a=l("div");a.appendChild(H(n==="hard"?"Hard Bin Breakdown":"Soft Bin Breakdown"));for(const[p,h]of s){const g=c?.get(p),T=g?.name?`Bin ${p} \xB7 ${g.name}`:`Bin ${p}`,N=h/f*100,B=$t(e),E=(e==="custom"?g?.color:void 0)??B.forBin(p);a.appendChild(U(`${T} (${h})`,N,E))}return a}export function buildLotBinSection(t,i,n,e){return buildBinSection(t,i,n,e)}function j(t,i,n,e,o,d){const f=bt(t,i,n,e,o);if(!f.length)return null;const c=l("div");c.appendChild(H(d));for(const{label:s,n:a,yieldPercent:p}of f)c.appendChild(U(`${s} (N=${a})`,p));return c}export function buildRingSection(t,i,n,e){return j([t],[i],n,e,K,"Ring Yield")}export function buildQuadrantSection(t,i,n,e){return j([t],[i],n,e,Z,"Quadrant Yield")}export function buildLotRingSection(t,i,n,e){return j(t,i,n,e,K,"Ring Yield")}export function buildLotQuadrantSection(t,i,n,e){return j(t,i,n,e,Z,"Quadrant Yield")}export function buildLotOverviewSection(t){const i=l("div");i.appendChild(H("Lot Summary"));const n=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});n.appendChild(O(String(t.stats.waferCount),"Wafers"));const e=t.perWafer.map(o=>o.summary.stats.yieldPercent).filter(o=>o!==null);if(e.length){const o=e.reduce((d,f)=>d+f,0)/e.length;n.appendChild(O(`${o.toFixed(1)}%`,"Mean wafer yield"))}return i.appendChild(n),i}export function buildPerWaferYieldSection(t,i,n){const e=t.perWafer.map(a=>({waferIndex:a.waferIndex,label:(i[a.waferIndex]?.label??`W${a.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:a.summary.stats.yieldPercent})).filter(a=>a.yieldPct!==null);if(!e.length)return null;const o=Math.min(...e.map(a=>a.yieldPct)),d=Math.max(...e.map(a=>a.yieldPct)),f=o===d?"":` (${o.toFixed(1)}\u2013${d.toFixed(1)}%)`,c=Ft([...e.map(a=>a.yieldPct)].sort((a,p)=>a-p)),s=l("div");s.appendChild(H("Wafer Yield"+f));for(const{waferIndex:a,label:p,yieldPct:h}of e){const g=U(p,h,void 0,void 0,c,h<c);n&&(g.style.cursor="pointer",g.style.borderRadius="4px",g.style.padding="2px 3px",g.style.marginLeft="-3px",g.style.marginRight="-3px",g.setAttribute("role","button"),g.setAttribute("aria-label",`${p}, ${h.toFixed(1)}% yield \u2014 view wafer`),g.tabIndex=0,g.addEventListener("mouseenter",()=>{g.style.background=v.bgHover}),g.addEventListener("mouseleave",()=>{g.style.background=""}),g.addEventListener("focus",()=>{g.style.background=v.bgHover}),g.addEventListener("blur",()=>{g.style.background=""}),g.addEventListener("click",()=>n(a)),g.addEventListener("keydown",T=>{(T.key==="Enter"||T.key===" ")&&(T.preventDefault(),n(a))})),s.appendChild(g)}return s}function zt(t){const i=[...t].sort((o,d)=>o-d),n=t.reduce((o,d)=>o+d,0)/t.length,e=t.reduce((o,d)=>o+(d-n)**2,0)/t.length;return{min:i[0],max:i[i.length-1],mean:n,count:t.length,stddev:Math.sqrt(e),median:Q(i,.5),q1:Q(i,.25),q3:Q(i,.75)}}function pt(t,i){if(!t)return[];const n=t.waferMetadata??(t.perWaferMetadata?et(t.perWaferMetadata.map(e=>({metadata:e}))):void 0);return!n||!Object.keys(n).length?[]:Bt({waferMetadata:n,waferPlacement:"csv",reservedLabels:i}).columns}export function csvField(t){return/[",\n]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}export function buildTestSection(t,i,n,e,o,d){const f=t.filter(r=>!r.partial&&!r.edgeExcluded),c=new Map((e?.perTestStats??[]).map(r=>[r.testNumber,r])),s=new Map((e?.testSpecYield??[]).map(r=>[r.testNumber,r]));let a;if(i?.length?a=i.filter(xt).map(r=>({testNumber:r.testNumber,name:r.name,unit:r.unit,limitLow:r.limitLow,limitHigh:r.limitHigh})):a=Dt(f).map(m=>({testNumber:m,name:`Test ${m}`})),!a.length)return null;const p=a.filter(r=>f.some(m=>{const D=m.testValues?.[r.testNumber];return D!==void 0&&isFinite(D)}));if(!p.length)return null;const h=p.some(r=>r.limitLow!==void 0||r.limitHigh!==void 0),g=[];for(const r of p){const m=c.get(r.testNumber),D=m&&m.stddev!==void 0&&m.median!==void 0&&m.q1!==void 0&&m.q3!==void 0;let y;if(D){const b=m;y={testNumber:r.testNumber,min:b.min,max:b.max,mean:b.mean,count:b.count,stddev:b.stddev,median:b.median,q1:b.q1,q3:b.q3}}else{const b=f.map(F=>F.testValues?.[r.testNumber]).filter(F=>F!==void 0&&isFinite(F));if(!b.length)continue;y={testNumber:r.testNumber,...zt(b)}}let x=null,S=0;if(r.limitLow!==void 0||r.limitHigh!==void 0){const b=s.get(r.testNumber);if(b)({yieldPercent:x,totalDies:S}=b);else{const F=f.map(w=>w.testValues?.[r.testNumber]).filter(w=>w!==void 0&&isFinite(w)),W=F.filter(w=>r.limitLow!==void 0&&w<r.limitLow||r.limitHigh!==void 0&&w>r.limitHigh).length;S=F.length,x=F.length>0?(F.length-W)/F.length*100:null}}g.push({entry:r,stats:y,specYieldPct:x,specN:S})}if(!g.length)return null;const T=l("div"),N=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),B=H(d?.populationLabel?`Test Values (${g.length}) \u2014 ${d.populationLabel}`:`Test Values (${g.length})`);B.style.marginBottom="0",N.appendChild(B);const E=document.createElement("button");E.type="button",E.textContent="Export CSV",Object.assign(E.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"}),E.addEventListener("click",()=>{const r=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&r.push("LSL","USL","Spec Yield %","Spec Yield N");const m=pt(d,r),y=[[...m.map(S=>S.label),...r].map(csvField).join(",")],x=S=>it(S,void 0,"engineering");for(const{entry:S,stats:b,specYieldPct:F,specN:W}of g){const w=[...m.map(M=>M.constant??""),S.name,S.unit??"",String(b.count),x(b.min),x(b.q1),x(b.median),x(b.mean),x(b.q3),x(b.max),x(b.stddev)];h&&w.push(S.limitLow!==void 0?x(S.limitLow):"",S.limitHigh!==void 0?x(S.limitHigh):"",F!==null?F.toFixed(1):"",S.limitLow!==void 0||S.limitHigh!==void 0?String(W):""),y.push(w.map(csvField).join(","))}rt(y.join(`
2
- `),"test-values.csv","text/csv",o)}),N.appendChild(E),T.appendChild(N);const R=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),L=document.createElement("thead"),u=document.createElement("tr"),$=["Test","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&$.push("LSL","USL","Spec yield");for(const r of $){const m=l("th",{textAlign:r==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${v.menuBorder}`,whiteSpace:"nowrap"},r);u.appendChild(m)}L.appendChild(u),R.appendChild(L);const k=document.createElement("tbody");for(const{entry:r,stats:m,specYieldPct:D,specN:y}of g){const x=F=>it(F,r.unit,n),S=document.createElement("tr"),b=(F,W="right")=>{const w=l("td",{textAlign:W,padding:"4px 8px",borderBottom:`1px solid ${v.menuBorder}`,color:z,whiteSpace:"nowrap"},F);S.appendChild(w)};b(r.name,"left"),b(`${m.count}`),b(x(m.min)),b(x(m.q1)),b(x(m.median)),b(x(m.mean)),b(x(m.q3)),b(x(m.max)),b(x(m.stddev)),h&&(b(r.limitLow!==void 0?x(r.limitLow):"\u2014"),b(r.limitHigh!==void 0?x(r.limitHigh):"\u2014"),b(D!==null?`${D.toFixed(1)}% (N=${y})`:"\u2014")),k.appendChild(S)}R.appendChild(k);const C=l("div",{overflowX:"auto"});return C.appendChild(R),T.appendChild(C),T}export function buildFunctionalTestSection(t,i,n,e,o){const d=n??vt(t,i);if(!d?.length)return null;const f=l("div"),c=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),s=H(o?.populationLabel?`Functional Tests (${d.length}) \u2014 ${o.populationLabel}`:`Functional Tests (${d.length})`);s.style.marginBottom="0",c.appendChild(s);const a=document.createElement("button");a.type="button",a.textContent="Export CSV",Object.assign(a.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"}),a.addEventListener("click",()=>{const B=["Test","N","Pass","Fail","Pass Rate %"],E=pt(o,B),R=[[...E.map(L=>L.label),...B].map(csvField).join(",")];for(const L of d)R.push([...E.map(u=>u.constant??""),L.label,String(L.totalDies),String(L.passDies),String(L.failDies),L.passRatePercent!==null?L.passRatePercent.toFixed(1):""].map(csvField).join(","));rt(R.join(`
3
- `),"functional-tests.csv","text/csv",e)}),c.appendChild(a),f.appendChild(c);const p=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),h=document.createElement("thead"),g=document.createElement("tr");for(const B of["Test","N","Pass","Fail","Pass rate"])g.appendChild(l("th",{textAlign:B==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${v.menuBorder}`,whiteSpace:"nowrap"},B));h.appendChild(g),p.appendChild(h);const T=document.createElement("tbody");for(const B of d){const E=document.createElement("tr"),R=(L,u="right")=>{E.appendChild(l("td",{textAlign:u,padding:"4px 8px",borderBottom:`1px solid ${v.menuBorder}`,color:z,whiteSpace:"nowrap"},L))};R(B.label,"left"),R(String(B.totalDies)),R(String(B.passDies)),R(String(B.failDies)),R(B.passRatePercent!==null?`${B.passRatePercent.toFixed(1)}% (N=${B.totalDies})`:"\u2014"),T.appendChild(E)}p.appendChild(T);const N=l("div",{overflowX:"auto"});return N.appendChild(p),f.appendChild(N),f}export function buildLotFunctionalSection(t,i,n,e){const o=n?.length?{perWaferMetadata:n.map(d=>d.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;if(n?.length&&n.every(d=>d.stats.functionalYield!==void 0)){const d=new Map;for(const c of n)for(const s of c.stats.functionalYield??[]){const a=d.get(s.testNumber)??{label:s.label,passDies:0,failDies:0,totalDies:0};a.passDies+=s.passDies,a.failDies+=s.failDies,a.totalDies+=s.totalDies,d.set(s.testNumber,a)}const f=[...d.entries()].map(([c,s])=>({testNumber:c,...s,passRatePercent:s.totalDies>0?s.passDies/s.totalDies*100:null}));if(f.length)return buildFunctionalTestSection(t,i,f,e,o)}return buildFunctionalTestSection(t,i,void 0,e,o)}const A={unusual:0,notable:1,info:2};function X(t){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:G(t),flexShrink:"0"})}function ct(t,i){let n=t.summary;return i&&(n.startsWith(`${i} has `)?n=n.slice(i.length+5):n.startsWith(`${i} `)&&(n=n.slice(i.length+1))),n=P(n),n.length?n[0].toUpperCase()+n.slice(1):n}export function buildFindingsSection(t,i,n,e,o=!1){if(!t.length)return null;const d=t.some(u=>u.severity==="unusual"||u.severity==="notable"),f=d?t.filter(u=>u.severity!=="info").length.toString():void 0,{outer:c,content:s}=o?(()=>{const u=l("div");return{outer:u,content:u}})():lt(`Findings (${t.length})`,d,f);function a(u){return u.reduce(($,k)=>A[k.severity]<A[$]?k.severity:$,"info")}function p(u){const $=new Map;for(const C of u){const r=`${C.comparison.family}\0${C.comparison.left}`,m=$.get(r)??[];m.push(C),$.set(r,m)}const k=[...$.entries()].map(([C,r])=>{const m=[...r].sort((D,y)=>A[D.severity]-A[y.severity]);return{key:C,findings:m,worst:a(m)}});return k.sort((C,r)=>A[C.worst]-A[r.worst]),k}function h(u,$){const C={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[u]??u;return $.toLowerCase().startsWith(C.toLowerCase())?$:`${C}: ${$}`}const g=t.filter(u=>u.comparison.family==="spatial-pattern"),T=new Set([...g.flatMap(u=>u.relatedIds??[]),...t.flatMap(u=>u.absorbedIds??[])]),N=t.filter(u=>u.comparison.family!=="spatial-pattern"&&!T.has(u.id)),B=p(N);function E(u,$=!1,k){const C=e===u.id,r=document.createElement("button");return r.type="button",r.dataset.wmapFinding=u.id,r.textContent=ct(u,k),r.title=u.summary,r.setAttribute("aria-current",C?"true":"false"),Object.assign(r.style,{border:`1px solid ${v.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:C?v.bgActive:v.menuBg,borderRadius:"6px",padding:$?"6px 10px":"8px 10px",textAlign:"left",fontSize:$?"10px":"11px",fontWeight:C?"600":"400",color:v.iconHover,cursor:"pointer",width:"100%",marginBottom:"4px"}),r.addEventListener("click",()=>n(u,r)),r}const R=P(Ct(t)??"");if(R){const u=l("div",{background:v.bgActive,borderRadius:"6px",padding:"8px 10px",marginBottom:"8px",display:"flex",gap:"8px",alignItems:"flex-start"}),$=l("span",{flex:"1",fontSize:"12px",lineHeight:"1.5",color:v.iconHover},R);u.appendChild($);const k=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:"10px",color:v.icon,cursor:"pointer",padding:"0",lineHeight:"1.5",whiteSpace:"nowrap"},"Detail \u25B8");k.type="button",k.addEventListener("click",()=>{const C=at({title:"Findings Summary",onClose:()=>{},anchor:k}),r=l("p",{fontSize:"16px",lineHeight:"1.6",color:v.iconHover,padding:"20px 24px 16px",margin:"0",borderBottom:`1px solid ${v.menuBorder}`,flexShrink:"0"},R);C.contentWrap.appendChild(r);const m=l("div",{overflowY:"auto",padding:"16px 24px",flex:"1"}),D=(y,x)=>{const S=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:"13px",fontWeight:"600",color:z,marginTop:"10px",marginBottom:"4px"});return S.appendChild(X(y)),S.appendChild(l("span",{},x)),S};for(const y of g){m.appendChild(D(y.severity,y.comparison.left)),m.appendChild(l("div",{fontSize:"13px",color:v.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},P(y.summary)));const x=t.filter(S=>y.relatedIds?.includes(S.id));for(const S of x)m.appendChild(l("div",{fontSize:"12px",color:v.icon,padding:"2px 0 2px 23px",marginBottom:"2px"},P(S.summary)))}for(const y of B){const[x,S]=y.key.split("\0");m.appendChild(D(y.worst,h(x,S)));for(const b of y.findings)m.appendChild(l("div",{fontSize:"13px",color:v.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},ct(b,S)))}C.contentWrap.appendChild(m),Object.assign(C.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),u.appendChild(k),s.appendChild(u)}let L=!0;for(const u of g){L||s.appendChild(l("div",{height:"1px",background:v.separator,margin:"4px 0"})),L=!1;const $=t.filter(D=>u.relatedIds?.includes(D.id)),k=$.length>0,C=l("div",{position:"relative",marginBottom:k?"2px":"4px"}),r=e===u.id,m=document.createElement("button");if(m.type="button",m.dataset.wmapFinding=u.id,Object.assign(m.style,{border:`1px solid ${v.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:r?v.bgActive:v.menuBg,borderRadius:"6px",padding:"8px 32px 8px 10px",textAlign:"left",fontSize:"11px",fontWeight:r?"600":"500",color:v.iconHover,cursor:"pointer",width:"100%"}),m.textContent=P(u.summary),m.title=u.summary,m.setAttribute("aria-current",r?"true":"false"),m.addEventListener("click",()=>n(u,m)),C.appendChild(m),k){const D=l("div",{display:"none",paddingLeft:"12px",marginBottom:"4px"});for(const S of $)D.appendChild(E(S,!0));C.appendChild(D);let y=!1;const x=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:"10px",color:v.icon,cursor:"pointer",padding:"2px 4px",lineHeight:"1"},"\u25B8");x.type="button",x.title="Show supporting findings",x.setAttribute("aria-label","Show supporting findings"),x.setAttribute("aria-expanded","false"),x.addEventListener("click",S=>{S.stopPropagation(),y=!y,D.style.display=y?"block":"none",x.textContent=y?"\u25BE":"\u25B8";const b=y?"Hide supporting findings":"Show supporting findings";x.title=b,x.setAttribute("aria-label",b),x.setAttribute("aria-expanded",String(y))}),C.appendChild(x)}s.appendChild(C)}for(const u of B){L||s.appendChild(l("div",{height:"1px",background:v.separator,margin:"4px 0"})),L=!1;const[$,k]=u.key.split("\0"),C=l("div",{display:"flex",alignItems:"center",gap:"6px",fontSize:"11px",fontWeight:"600",color:z,margin:"2px 0 4px"});C.appendChild(X(u.worst)),C.appendChild(l("span",{},h($,k))),s.appendChild(C);for(const r of u.findings)s.appendChild(E(r,!1,k))}return c}const Ht=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],At=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],Pt=["unusual","notable","info"],Yt={unusual:"Unusual",notable:"Notable",info:"Info"};function Ot(t,i,n){const e=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"10px",marginBottom:"10px",paddingBottom:"10px",borderBottom:`1px solid ${v.separator}`}),o={unusual:0,notable:0,info:0};for(const s of t)o[s.severity]++;const d=Pt.filter(s=>o[s]>0),f=new Set(i.severity===void 0?d:Array.isArray(i.severity)?i.severity:[i.severity]),c=l("div",{display:"flex",gap:"4px",flexWrap:"wrap"});for(const s of d){const a=document.createElement("button");a.type="button";const p=()=>{const h=f.has(s);a.setAttribute("aria-pressed",h?"true":"false"),Object.assign(a.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${v.menuBorder}`,borderRadius:"10px",background:h?v.bgActive:"none",opacity:h?"1":"0.5",color:v.text,fontSize:"11px",padding:"2px 8px",cursor:"pointer"})};a.appendChild(X(s)),a.appendChild(l("span",{},`${Yt[s]} ${o[s]}`)),a.title=f.has(s)?"Click to hide these findings":"Click to show these findings",p(),a.addEventListener("click",()=>{f.has(s)?f.delete(s):f.add(s),i.severity=f.size===d.length?void 0:[...f],n()}),c.appendChild(a)}return e.appendChild(c),e.appendChild(ot("Kind:",Ht,i.kind??"",s=>{i.kind=s||void 0,n()},{maxWidth:"130px"})),e.appendChild(ot("Region:",At,i.family??"",s=>{i.family=s||void 0,n()},{maxWidth:"150px"})),e}export function buildFindingsSectionWithFilter(t,i,n,e,o){if(!t.findings.length)return null;const d=t.findings.some(h=>h.severity==="unusual"||h.severity==="notable"),f=d?t.findings.filter(h=>h.severity!=="info").length.toString():void 0,{outer:c,content:s}=lt(`Findings (${t.findings.length})`,d,f);s.appendChild(Ot(t.findings,e,o));const a=St(t,e);if(!a.length)return s.appendChild(l("div",{color:I,fontSize:"11px",textAlign:"center",padding:"16px 8px"},"No findings match the current filter.")),c;const p=buildFindingsSection(a,t,i,n,!0);return p&&s.appendChild(p),c}export function buildLotTestSection(t,i,n,e,o){const d=e?.length?{perWaferMetadata:e.map(c=>c.wafer??{}),populationLabel:`${e.length} wafer${e.length===1?"":"s"} pooled`}:void 0;let f;if(e?.length&&e.every(c=>c.stats.perTestStats!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.perTestStats??[]){const p=c.get(a.testNumber);p?(p.n+=a.count,p.sum+=a.mean*a.count,p.min=Math.min(p.min,a.min),p.max=Math.max(p.max,a.max)):c.set(a.testNumber,{n:a.count,sum:a.mean*a.count,min:a.min,max:a.max})}f={perTestStats:[...c.entries()].map(([s,a])=>({testNumber:s,count:a.n,min:a.min,max:a.max,mean:a.sum/a.n}))}}if(e?.length&&e.every(c=>c.stats.testSpecYield!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.testSpecYield??[]){const p=c.get(a.testNumber);p?(p.passDies+=a.passDies,p.totalDies+=a.totalDies):c.set(a.testNumber,{passDies:a.passDies,totalDies:a.totalDies})}f={...f,testSpecYield:[...c.entries()].map(([s,a])=>({testNumber:s,totalDies:a.totalDies,yieldPercent:a.totalDies>0?a.passDies/a.totalDies*100:null}))}}return buildTestSection(t,i,n,f,o,d)}export function createSummaryPanelEl(t,i=document){const n=t==="top"||t==="bottom",e=l("div",{background:Et,border:Y,borderRadius:"6px",padding:"12px",overflowY:n?"hidden":"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:"system-ui, sans-serif",fontSize:"12px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)"},void 0,i);return n?(e.style.height="180px",e.style.width="100%"):(e.style.width="260px",e.style.maxHeight="100%"),e}export function wrapWithSummaryPanel(t,i,n){const e=n==="top"||n==="bottom",o=l("div",{display:"flex",flexDirection:e?"column":"row",gap:"8px",width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:e?"flex-start":"stretch"});return t.style.flex="1 1 0",t.style.minWidth="0",t.style.minHeight="0",n==="right"||n==="bottom"?(o.appendChild(t),o.appendChild(i)):(o.appendChild(i),o.appendChild(t)),o}function ut(t){return l("div",{fontSize:"13px",fontWeight:"700",color:z,marginBottom:"10px"},t)}function q(t,i){const n=l("button",{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"},t);return n.type="button",n.addEventListener("click",i),n}function ft(...t){const i=t.filter(e=>!!e);if(!i.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",gap:"6px",marginBottom:"10px"});for(const e of i)n.appendChild(e);return n}function mt(t,i,n,e,o,d,f,c,s){const a=t.ownerDocument,p=at({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:a});p.contentWrap.style.padding="14px 16px";const h=Rt(i,n,{...f,title:e,onSaveText:c,waferMetadata:o,metadataFields:d,extraColumn:s,ownerDocument:a});h&&p.contentWrap.appendChild(h)}export function renderWaferSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h=[1],ringCount:g=4,colorScheme:T,fallbackFormat:N,onFindingClick:B,activeFindingId:E=null,findingsFilter:R,onFindingsFilterChange:L,onSaveText:u,metadataFields:$,dieListOptions:k}=i;t.appendChild(ut("Wafer Summary"));const C=i.warnings??nt({statsSummary:p});C.length&&t.appendChild(_(C,t.ownerDocument));const r=d&&f?q("Summary report",()=>{J(wt({wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h,ringCount:g}))}):null,m=(k?.enabled??!0)&&o.length?q("View die list",()=>{mt(t,o,a,`Die list \u2014 ${o.length} dies`,e.metadata,$,k,u)}):null,D=ft(r,m);D&&t.appendChild(D);const y=[],x=p?.stats.isLotStack?p.stats:void 0,S=x?.lotSize!==void 0?{lotSize:x.lotSize,aggrMethod:Lt(x.aggregationMethod)}:void 0;y.push(buildMetadataInfoSection([{metadata:e.metadata??void 0}],S)),d&&f&&y.push(buildYieldSection(d,f,h));const b=o.some(M=>M.hbin!=null),F=o.some(M=>M.sbin!=null);b?y.push(buildBinSection(o,c,"hard",T,p?.stats.hardBinCounts)):F&&y.push(buildBinSection(o,s,"soft",T,p?.stats.softBinCounts)),y.push(buildRingSection(o,e,g,h)),y.push(buildQuadrantSection(o,e,g,h));const W=e.metadata?{waferMetadata:e.metadata}:void 0;y.push(buildTestSection(o,a,N,p?.stats,u,W)),y.push(buildFunctionalTestSection(o,a,p?.stats.functionalYield,u,W)),p&&B&&R&&L&&y.push(buildFindingsSectionWithFilter(p,B,E,R,L));let w=!0;for(const M of y)M&&(w||t.appendChild(dt()),w=!1,t.appendChild(M));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}export function renderLotSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{lotSummary:e,items:o,hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s=[1],ringCount:a=4,colorScheme:p,fallbackFormat:h,onFindingClick:g,activeFindingId:T=null,onWaferClick:N,findingsFilter:B,onFindingsFilterChange:E,onSaveText:R,dieListOptions:L}=i;t.appendChild(ut(`Lot Summary \u2014 ${e.stats.waferCount} wafer${e.stats.waferCount===1?"":"s"}`));const u=i.warnings??nt({lotStatsSummary:e});u.length&&t.appendChild(_(u,t.ownerDocument));const $=q("Summary report",()=>{J(yt({items:o.map((w,M)=>({label:w?.label??`W${M+1}`,wafer:w?.wafer,dies:w?.dies,statsSummary:w?.statsSummary})),hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s,ringCount:a}))}),k=[],C=[],r=[],m=new WeakMap;for(let w=0;w<o.length;w++){const M=o[w];if(!M){C.push([]);continue}M.wafer&&k.push(M.wafer);const V=M.dies??[],ht=M.label??`W${w+1}`;for(const gt of V)m.set(gt,ht);C.push(V),r.push(...V)}const D=L?.enabled??!0?q("View die list",()=>{r.length&&mt(t,r,c,`Die list \u2014 ${r.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,et(o.filter(w=>!!w).map(w=>({metadata:w.wafer?.metadata}))),o.find(w=>w?.metadataFields?.length)?.metadataFields,L,R,{label:"Wafer",get:w=>m.get(w)})}):null,y=ft($,D);y&&t.appendChild(y);const x=r.some(w=>w.hbin!=null),S=r.some(w=>w.sbin!=null),b=o.map(w=>w?.statsSummary).filter(w=>!!w),F=[buildLotOverviewSection(e),buildPerWaferYieldSection(e,o,N),x?buildLotBinSection(r,d,"hard",p):S?buildLotBinSection(r,f,"soft",p):null,buildLotRingSection(C,k,a,s),buildLotQuadrantSection(C,k,a,s),c?.length?buildLotTestSection(r,c,h,b,R):null,c?.length?buildLotFunctionalSection(r,c,b,R):null];g&&B&&E&&F.push(buildFindingsSectionWithFilter(e,g,T,B,E));let W=!0;for(const w of F)w&&(W||t.appendChild(dt()),W=!1,t.appendChild(w));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}
1
+ import{isParametricTest as bt}from"../renderer/buildWaferMap.js";import{buildRingRegions as J,buildQuadrantRegions as tt,buildRegionYieldData as wt}from"../stats/regions.js";import{computeFunctionalYield as vt}from"../stats/analyzeWaferMap.js";import{renderSummaryReportHtml as yt,renderLotSummaryReportHtml as Ct}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as St}from"../stats/findingsNarrative.js";import{filterFindings as kt}from"../stats/filterFindings.js";import{buildFacetTable as Bt,prettyKey as et}from"../stats/facets.js";import{commonMetadata as nt}from"../stats/facets.js";import{resolveMetadataColumns as Lt}from"../stats/metadataColumns.js";import{getColorScheme as $t}from"../renderer/colorSchemes.js";import{buildWarningsBanner as Q,collectWarnings as it}from"./warnings.js";export{Q as buildWarningsBanner};import{fmt as ot,fmtAggregationMethod as Dt,plainBinTerms as Y}from"../renderer/fmt.js";import{getUniqueTestNumbers as Rt}from"../renderer/buildView.js";import{quantile as G}from"../stats/math.js";import{makeLabeledSelect as at}from"./charts/chartShell.js";import{CLR as b,sevColor as U,openModal as rt,openReportModal as st,saveTextFile as lt}from"./toolbar.js";import{buildDieListSection as Ft}from"./dieList.js";import{medianOfSorted as Nt}from"../core/utils.js";import{metadataDisplayValue as Tt}from"../core/metadata.js";const Et=b.panelBg,O=`1px solid ${b.menuBorder}`,Mt="12px",I=b.label,H=b.value,dt="10px";function l(t,i,n,e=document){const o=e.createElement(t);return i&&Object.assign(o.style,i),n!==void 0&&(o.textContent=n),o}function A(t){return l("div",{fontSize:dt,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,marginBottom:"6px"},t)}function pt(t,i=!0,n){const e=l("div"),o=document.createElement("button");o.type="button",Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const d=l("span",{fontSize:"9px",color:I,transition:"transform 0.15s",transform:i?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:"1",marginRight:"1px"},"\u25B6"),f=l("span",{fontSize:dt,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,flex:"1"},t);if(o.setAttribute("aria-expanded",i?"true":"false"),o.appendChild(d),o.appendChild(f),n){const a=l("span",{fontSize:"9px",fontWeight:"700",background:b.warnBg,color:b.warnText,borderRadius:"10px",padding:"1px 5px"},n);o.appendChild(a)}const c=l("div");c.style.display=i?"block":"none";let s=i;return o.addEventListener("click",()=>{s=!s,c.style.display=s?"block":"none",d.style.transform=s?"rotate(90deg)":"rotate(0deg)",o.setAttribute("aria-expanded",s?"true":"false")}),e.appendChild(o),e.appendChild(c),{outer:e,content:c}}function ct(){return l("div",{height:"1px",background:b.separator,margin:`${Mt} 0`,flexShrink:"0"})}function X(t,i,n=b.barFill,e,o,d){const f=l("div",{marginBottom:"5px"}),c=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",color:H,marginBottom:"2px"}),s=l("span",{},t),a=l("span",{fontWeight:"600"},`${i.toFixed(1)}%`);c.appendChild(s),c.appendChild(a);const p=e!==void 0?e:Math.min(100,Math.max(0,i)),g=d?b.barFillMuted:n,h=l("div",{position:"relative",height:"9px",background:b.bgActive,borderRadius:"4px",overflow:"hidden"}),D=l("div",{height:"100%",width:`${p}%`,background:g,borderRadius:"4px",transition:"width 0.3s ease"});if(h.appendChild(D),o!==void 0){const M=l("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"1px",background:b.infoText,opacity:"0.5"});h.appendChild(M)}return f.appendChild(c),f.appendChild(h),f}function j(t,i,n){const e=l("div",{background:b.menuBg,border:O,borderRadius:"6px",padding:"8px 10px",textAlign:"center",flex:"1"}),o=l("div",{fontSize:"20px",fontWeight:"700",color:H,lineHeight:"1.2"},t),d=l("div",{fontSize:"10px",color:I,marginTop:"2px"},i);return e.appendChild(o),e.appendChild(d),n&&e.appendChild(l("div",{fontSize:"9px",color:I,opacity:"0.85"},n)),e}function Wt(t,i){const n=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",gap:"8px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},t),o=l("span",{color:H,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}function It(t,i){const n=l("div",{display:"flex",fontSize:"11px",gap:"6px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},`${t}:`),o=l("span",{color:H,fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}export function metadataEntries(t){const i=[];for(const[n,e]of Object.entries(t)){const o=Tt(e);o!==void 0&&i.push([n,o])}return i}export function buildFacetSummaryChips(t,i=3){if(!t.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 10px",fontSize:"11px"});for(const e of t){const o=l("span",{whiteSpace:"nowrap"}),d=l("span",{color:I},`${et(e.key)}: `);o.appendChild(d);const f=e.values.slice(0,i),c=e.values.length-f.length;let s=f.map(a=>a.value).join(", ");c>0&&(s+=` +${c} more`),o.appendChild(document.createTextNode(s)),n.appendChild(o)}return n}export function buildMetadataStripRow(t,i,n){const e=Bt(t,n),o=buildFacetSummaryChips(e);if(!o&&!i)return null;const d=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(i){const f=l("span",{fontWeight:"500",whiteSpace:"nowrap"},i.aggrMethod?`${i.lotSize} wafers stacked \xB7 ${i.aggrMethod}`:`${i.lotSize} wafers stacked`);d.appendChild(f)}return o&&d.appendChild(o),d}const zt={display:"flex",flexDirection:"column",gap:"6px",background:b.menuBg,border:`1px solid ${b.menuBorder}`,borderRadius:"6px",padding:"6px 10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,i,n){const e=buildMetadataStripRow(t,i,n);if(!e)return null;const o=l("div",zt);return o.appendChild(e),o}export function buildCompactMetadataRows(t){const i=metadataEntries(t);if(!i.length)return null;const n=l("div");for(const[e,o]of i)n.appendChild(It(et(e),o));return n}export function buildMetadataInfoSection(t,i){const n=buildMetadataStripRow(t,i,{facetableOnly:t.length>1});if(!n)return null;const e=l("div");return e.appendChild(A("Wafer Info")),e.appendChild(n),e}export function buildYieldSection(t,i,n=[1]){const e=l("div");e.appendChild(A("Summary"));const o=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});if(o.appendChild(j(String(t.totalDies),"Total dies")),t.partialDies>0&&o.appendChild(j(String(t.partialDies),"Partial")),t.yieldPercent!==null){const d=n.length===1?`bin ${n[0]}`:`bins ${n.join(", ")}`;o.appendChild(j(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${d}`))}return e.appendChild(o),t.edgeExcludedDies>0&&e.appendChild(Wt("Edge excluded (outer zone)",String(t.edgeExcludedDies))),e}export function buildBinSection(t,i,n,e,o){const d=new Map;if(o)for(const[p,g]of Object.entries(o))d.set(Number(p),g);else for(const p of t){if(p.partial||p.edgeExcluded)continue;const g=n==="hard"?p.hbin:p.sbin;g!=null&&d.set(g,(d.get(g)??0)+1)}if(!d.size)return null;const f=[...d.values()].reduce((p,g)=>p+g,0),c=i?new Map(i.map(p=>[p.bin,p])):null,s=[...d.entries()].sort((p,g)=>p[0]-g[0]),a=l("div");a.appendChild(A(n==="hard"?"Hard Bin Breakdown":"Soft Bin Breakdown"));for(const[p,g]of s){const h=c?.get(p),D=h?.name?`Bin ${p} \xB7 ${h.name}`:`Bin ${p}`,M=g/f*100,B=$t(e),T=(e==="custom"?h?.color:void 0)??B.forBin(p);a.appendChild(X(`${D} (${g})`,M,T))}return a}export function buildLotBinSection(t,i,n,e){return buildBinSection(t,i,n,e)}function q(t,i,n,e,o,d){const f=wt(t,i,n,e,o);if(!f.length)return null;const c=l("div");c.appendChild(A(d));for(const{label:s,n:a,yieldPercent:p}of f)c.appendChild(X(`${s} (N=${a})`,p));return c}export function buildRingSection(t,i,n,e){return q([t],[i],n,e,J,"Ring Yield")}export function buildQuadrantSection(t,i,n,e){return q([t],[i],n,e,tt,"Quadrant Yield")}export function buildLotRingSection(t,i,n,e){return q(t,i,n,e,J,"Ring Yield")}export function buildLotQuadrantSection(t,i,n,e){return q(t,i,n,e,tt,"Quadrant Yield")}export function buildLotOverviewSection(t){const i=l("div");i.appendChild(A("Lot Summary"));const n=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});n.appendChild(j(String(t.stats.waferCount),"Wafers"));const e=t.perWafer.map(o=>o.summary.stats.yieldPercent).filter(o=>o!==null);if(e.length){const o=e.reduce((d,f)=>d+f,0)/e.length;n.appendChild(j(`${o.toFixed(1)}%`,"Mean wafer yield"))}return i.appendChild(n),i}export function buildPerWaferYieldSection(t,i,n){const e=t.perWafer.map(a=>({waferIndex:a.waferIndex,label:(i[a.waferIndex]?.label??`W${a.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:a.summary.stats.yieldPercent})).filter(a=>a.yieldPct!==null);if(!e.length)return null;const o=Math.min(...e.map(a=>a.yieldPct)),d=Math.max(...e.map(a=>a.yieldPct)),f=o===d?"":` (${o.toFixed(1)}\u2013${d.toFixed(1)}%)`,c=Nt([...e.map(a=>a.yieldPct)].sort((a,p)=>a-p)),s=l("div");s.appendChild(A("Wafer Yield"+f));for(const{waferIndex:a,label:p,yieldPct:g}of e){const h=X(p,g,void 0,void 0,c,g<c);n&&(h.style.cursor="pointer",h.style.borderRadius="4px",h.style.padding="2px 3px",h.style.marginLeft="-3px",h.style.marginRight="-3px",h.setAttribute("role","button"),h.setAttribute("aria-label",`${p}, ${g.toFixed(1)}% yield \u2014 view wafer`),h.tabIndex=0,h.addEventListener("mouseenter",()=>{h.style.background=b.bgHover}),h.addEventListener("mouseleave",()=>{h.style.background=""}),h.addEventListener("focus",()=>{h.style.background=b.bgHover}),h.addEventListener("blur",()=>{h.style.background=""}),h.addEventListener("click",()=>n(a)),h.addEventListener("keydown",D=>{(D.key==="Enter"||D.key===" ")&&(D.preventDefault(),n(a))})),s.appendChild(h)}return s}function Ht(t){const i=[...t].sort((o,d)=>o-d),n=t.reduce((o,d)=>o+d,0)/t.length,e=t.reduce((o,d)=>o+(d-n)**2,0)/t.length;return{min:i[0],max:i[i.length-1],mean:n,count:t.length,stddev:Math.sqrt(e),median:G(i,.5),q1:G(i,.25),q3:G(i,.75)}}function ut(t,i){if(!t)return[];const n=t.waferMetadata??(t.perWaferMetadata?nt(t.perWaferMetadata.map(e=>({metadata:e}))):void 0);return!n||!Object.keys(n).length?[]:Lt({waferMetadata:n,waferPlacement:"csv",reservedLabels:i}).columns}const At=/^[=+\-@]/;export function csvField(t){const i=At.test(t)&&Number.isNaN(Number(t))?`'${t}`:t;return/[",\n\r]/.test(i)?`"${i.replace(/"/g,'""')}"`:i}export function buildTestSection(t,i,n,e,o,d){const f=t.filter(r=>!r.partial&&!r.edgeExcluded),c=new Map((e?.perTestStats??[]).map(r=>[r.testNumber,r])),s=new Map((e?.testSpecYield??[]).map(r=>[r.testNumber,r]));let a;if(i?.length?a=i.filter(bt).map(r=>({testNumber:r.testNumber,name:r.name,unit:r.unit,limitLow:r.limitLow,limitHigh:r.limitHigh})):a=Rt(f).map(m=>({testNumber:m,name:`Test ${m}`})),!a.length)return null;const p=a.filter(r=>f.some(m=>{const $=m.testValues?.[r.testNumber];return $!==void 0&&isFinite($)}));if(!p.length)return null;const g=p.some(r=>r.limitLow!==void 0||r.limitHigh!==void 0),h=[];for(const r of p){const m=c.get(r.testNumber),$=m&&m.stddev!==void 0&&m.median!==void 0&&m.q1!==void 0&&m.q3!==void 0;let v;if($){const w=m;v={testNumber:r.testNumber,min:w.min,max:w.max,mean:w.mean,count:w.count,stddev:w.stddev,median:w.median,q1:w.q1,q3:w.q3}}else{const w=f.map(N=>N.testValues?.[r.testNumber]).filter(N=>N!==void 0&&isFinite(N));if(!w.length)continue;v={testNumber:r.testNumber,...Ht(w)}}let x=null,S=0;if(r.limitLow!==void 0||r.limitHigh!==void 0){const w=s.get(r.testNumber);if(w)({yieldPercent:x,totalDies:S}=w);else{const N=f.map(E=>E.testValues?.[r.testNumber]).filter(E=>E!==void 0&&isFinite(E)),W=N.filter(E=>r.limitLow!==void 0&&E<r.limitLow||r.limitHigh!==void 0&&E>r.limitHigh).length;S=N.length,x=N.length>0?(N.length-W)/N.length*100:null}}h.push({entry:r,stats:v,specYieldPct:x,specN:S})}if(!h.length)return null;const D=l("div"),M=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),B=A(d?.populationLabel?`Test Values (${h.length}) \u2014 ${d.populationLabel}`:`Test Values (${h.length})`);B.style.marginBottom="0",M.appendChild(B);const T=document.createElement("button");T.type="button",T.textContent="Export CSV",Object.assign(T.style,{background:"none",border:O,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:b.iconHover,padding:"2px 7px"}),T.addEventListener("click",()=>{const r=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];g&&r.push("LSL","USL","Spec Yield %","Spec Yield N");const m=ut(d,r),v=[[...m.map(S=>S.label),...r].map(csvField).join(",")],x=S=>ot(S,void 0,"engineering");for(const{entry:S,stats:w,specYieldPct:N,specN:W}of h){const E=[...m.map(y=>y.constant??""),S.name,S.unit??"",String(w.count),x(w.min),x(w.q1),x(w.median),x(w.mean),x(w.q3),x(w.max),x(w.stddev)];g&&E.push(S.limitLow!==void 0?x(S.limitLow):"",S.limitHigh!==void 0?x(S.limitHigh):"",N!==null?N.toFixed(1):"",S.limitLow!==void 0||S.limitHigh!==void 0?String(W):""),v.push(E.map(csvField).join(","))}lt(v.join(`
2
+ `),"test-values.csv","text/csv",o)}),M.appendChild(T),D.appendChild(M);const F=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),R=document.createElement("thead"),u=document.createElement("tr"),L=["Test","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];g&&L.push("LSL","USL","Spec yield");for(const r of L){const m=l("th",{textAlign:r==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${b.menuBorder}`,whiteSpace:"nowrap"},r);u.appendChild(m)}R.appendChild(u),F.appendChild(R);const k=document.createElement("tbody");for(const{entry:r,stats:m,specYieldPct:$,specN:v}of h){const x=N=>ot(N,r.unit,n),S=document.createElement("tr"),w=(N,W="right")=>{const E=l("td",{textAlign:W,padding:"4px 8px",borderBottom:`1px solid ${b.menuBorder}`,color:H,whiteSpace:"nowrap"},N);S.appendChild(E)};w(r.name,"left"),w(`${m.count}`),w(x(m.min)),w(x(m.q1)),w(x(m.median)),w(x(m.mean)),w(x(m.q3)),w(x(m.max)),w(x(m.stddev)),g&&(w(r.limitLow!==void 0?x(r.limitLow):"\u2014"),w(r.limitHigh!==void 0?x(r.limitHigh):"\u2014"),w($!==null?`${$.toFixed(1)}% (N=${v})`:"\u2014")),k.appendChild(S)}F.appendChild(k);const C=l("div",{overflowX:"auto"});return C.appendChild(F),D.appendChild(C),D}export function buildFunctionalTestSection(t,i,n,e,o){const d=n??vt(t,i);if(!d?.length)return null;const f=l("div"),c=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),s=A(o?.populationLabel?`Functional Tests (${d.length}) \u2014 ${o.populationLabel}`:`Functional Tests (${d.length})`);s.style.marginBottom="0",c.appendChild(s);const a=document.createElement("button");a.type="button",a.textContent="Export CSV",Object.assign(a.style,{background:"none",border:O,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:b.iconHover,padding:"2px 7px"}),a.addEventListener("click",()=>{const B=["Test","N","Pass","Fail","Pass Rate %"],T=ut(o,B),F=[[...T.map(R=>R.label),...B].map(csvField).join(",")];for(const R of d)F.push([...T.map(u=>u.constant??""),R.label,String(R.totalDies),String(R.passDies),String(R.failDies),R.passRatePercent!==null?R.passRatePercent.toFixed(1):""].map(csvField).join(","));lt(F.join(`
3
+ `),"functional-tests.csv","text/csv",e)}),c.appendChild(a),f.appendChild(c);const p=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),g=document.createElement("thead"),h=document.createElement("tr");for(const B of["Test","N","Pass","Fail","Pass rate"])h.appendChild(l("th",{textAlign:B==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${b.menuBorder}`,whiteSpace:"nowrap"},B));g.appendChild(h),p.appendChild(g);const D=document.createElement("tbody");for(const B of d){const T=document.createElement("tr"),F=(R,u="right")=>{T.appendChild(l("td",{textAlign:u,padding:"4px 8px",borderBottom:`1px solid ${b.menuBorder}`,color:H,whiteSpace:"nowrap"},R))};F(B.label,"left"),F(String(B.totalDies)),F(String(B.passDies)),F(String(B.failDies)),F(B.passRatePercent!==null?`${B.passRatePercent.toFixed(1)}% (N=${B.totalDies})`:"\u2014"),D.appendChild(T)}p.appendChild(D);const M=l("div",{overflowX:"auto"});return M.appendChild(p),f.appendChild(M),f}export function buildLotFunctionalSection(t,i,n,e){const o=n?.length?{perWaferMetadata:n.map(d=>d.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;if(n?.length&&n.every(d=>d.stats.functionalYield!==void 0)){const d=new Map;for(const c of n)for(const s of c.stats.functionalYield??[]){const a=d.get(s.testNumber)??{label:s.label,passDies:0,failDies:0,totalDies:0};a.passDies+=s.passDies,a.failDies+=s.failDies,a.totalDies+=s.totalDies,d.set(s.testNumber,a)}const f=[...d.entries()].map(([c,s])=>({testNumber:c,...s,passRatePercent:s.totalDies>0?s.passDies/s.totalDies*100:null}));if(f.length)return buildFunctionalTestSection(t,i,f,e,o)}return buildFunctionalTestSection(t,i,void 0,e,o)}const P={unusual:0,notable:1,info:2};function K(t){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:U(t),flexShrink:"0"})}function ft(t,i){let n=t.summary;return i&&(n.startsWith(`${i} has `)?n=n.slice(i.length+5):n.startsWith(`${i} `)&&(n=n.slice(i.length+1))),n=Y(n),n.length?n[0].toUpperCase()+n.slice(1):n}export function buildFindingsSection(t,i,n,e,o=!1){if(!t.length)return null;const d=t.some(u=>u.severity==="unusual"||u.severity==="notable"),f=d?t.filter(u=>u.severity!=="info").length.toString():void 0,{outer:c,content:s}=o?(()=>{const u=l("div");return{outer:u,content:u}})():pt(`Findings (${t.length})`,d,f);function a(u){return u.reduce((L,k)=>P[k.severity]<P[L]?k.severity:L,"info")}function p(u){const L=new Map;for(const C of u){const r=`${C.comparison.family}\0${C.comparison.left}`,m=L.get(r)??[];m.push(C),L.set(r,m)}const k=[...L.entries()].map(([C,r])=>{const m=[...r].sort(($,v)=>P[$.severity]-P[v.severity]);return{key:C,findings:m,worst:a(m)}});return k.sort((C,r)=>P[C.worst]-P[r.worst]),k}function g(u,L){const C={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[u]??u;return L.toLowerCase().startsWith(C.toLowerCase())?L:`${C}: ${L}`}const h=t.filter(u=>u.comparison.family==="spatial-pattern"),D=new Set([...h.flatMap(u=>u.relatedIds??[]),...t.flatMap(u=>u.absorbedIds??[])]),M=t.filter(u=>u.comparison.family!=="spatial-pattern"&&!D.has(u.id)),B=p(M);function T(u,L=!1,k){const C=e===u.id,r=document.createElement("button");return r.type="button",r.dataset.wmapFinding=u.id,r.textContent=ft(u,k),r.title=u.summary,r.setAttribute("aria-current",C?"true":"false"),Object.assign(r.style,{border:`1px solid ${b.menuBorder}`,borderLeft:`3px solid ${U(u.severity)}`,background:C?b.bgActive:b.menuBg,borderRadius:"6px",padding:L?"6px 10px":"8px 10px",textAlign:"left",fontSize:L?"10px":"11px",fontWeight:C?"600":"400",color:b.iconHover,cursor:"pointer",width:"100%",marginBottom:"4px"}),r.addEventListener("click",()=>n(u,r)),r}const F=Y(St(t)??"");if(F){const u=l("div",{background:b.bgActive,borderRadius:"6px",padding:"8px 10px",marginBottom:"8px",display:"flex",gap:"8px",alignItems:"flex-start"}),L=l("span",{flex:"1",fontSize:"12px",lineHeight:"1.5",color:b.iconHover},F);u.appendChild(L);const k=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:"10px",color:b.icon,cursor:"pointer",padding:"0",lineHeight:"1.5",whiteSpace:"nowrap"},"Detail \u25B8");k.type="button",k.addEventListener("click",()=>{const C=rt({title:"Findings Summary",onClose:()=>{},anchor:k}),r=l("p",{fontSize:"16px",lineHeight:"1.6",color:b.iconHover,padding:"20px 24px 16px",margin:"0",borderBottom:`1px solid ${b.menuBorder}`,flexShrink:"0"},F);C.contentWrap.appendChild(r);const m=l("div",{overflowY:"auto",padding:"16px 24px",flex:"1"}),$=(v,x)=>{const S=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:"13px",fontWeight:"600",color:H,marginTop:"10px",marginBottom:"4px"});return S.appendChild(K(v)),S.appendChild(l("span",{},x)),S};for(const v of h){m.appendChild($(v.severity,v.comparison.left)),m.appendChild(l("div",{fontSize:"13px",color:b.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},Y(v.summary)));const x=t.filter(S=>v.relatedIds?.includes(S.id));for(const S of x)m.appendChild(l("div",{fontSize:"12px",color:b.icon,padding:"2px 0 2px 23px",marginBottom:"2px"},Y(S.summary)))}for(const v of B){const[x,S]=v.key.split("\0");m.appendChild($(v.worst,g(x,S)));for(const w of v.findings)m.appendChild(l("div",{fontSize:"13px",color:b.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},ft(w,S)))}C.contentWrap.appendChild(m),Object.assign(C.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),u.appendChild(k),s.appendChild(u)}let R=!0;for(const u of h){R||s.appendChild(l("div",{height:"1px",background:b.separator,margin:"4px 0"})),R=!1;const L=t.filter($=>u.relatedIds?.includes($.id)),k=L.length>0,C=l("div",{position:"relative",marginBottom:k?"2px":"4px"}),r=e===u.id,m=document.createElement("button");if(m.type="button",m.dataset.wmapFinding=u.id,Object.assign(m.style,{border:`1px solid ${b.menuBorder}`,borderLeft:`3px solid ${U(u.severity)}`,background:r?b.bgActive:b.menuBg,borderRadius:"6px",padding:"8px 32px 8px 10px",textAlign:"left",fontSize:"11px",fontWeight:r?"600":"500",color:b.iconHover,cursor:"pointer",width:"100%"}),m.textContent=Y(u.summary),m.title=u.summary,m.setAttribute("aria-current",r?"true":"false"),m.addEventListener("click",()=>n(u,m)),C.appendChild(m),k){const $=l("div",{display:"none",paddingLeft:"12px",marginBottom:"4px"});for(const S of L)$.appendChild(T(S,!0));C.appendChild($);let v=!1;const x=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:"10px",color:b.icon,cursor:"pointer",padding:"2px 4px",lineHeight:"1"},"\u25B8");x.type="button",x.title="Show supporting findings",x.setAttribute("aria-label","Show supporting findings"),x.setAttribute("aria-expanded","false"),x.addEventListener("click",S=>{S.stopPropagation(),v=!v,$.style.display=v?"block":"none",x.textContent=v?"\u25BE":"\u25B8";const w=v?"Hide supporting findings":"Show supporting findings";x.title=w,x.setAttribute("aria-label",w),x.setAttribute("aria-expanded",String(v))}),C.appendChild(x)}s.appendChild(C)}for(const u of B){R||s.appendChild(l("div",{height:"1px",background:b.separator,margin:"4px 0"})),R=!1;const[L,k]=u.key.split("\0"),C=l("div",{display:"flex",alignItems:"center",gap:"6px",fontSize:"11px",fontWeight:"600",color:H,margin:"2px 0 4px"});C.appendChild(K(u.worst)),C.appendChild(l("span",{},g(L,k))),s.appendChild(C);for(const r of u.findings)s.appendChild(T(r,!1,k))}return c}const Pt=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],Yt=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],Ot=["unusual","notable","info"],jt={unusual:"Unusual",notable:"Notable",info:"Info"};function qt(t,i,n){const e=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"10px",marginBottom:"10px",paddingBottom:"10px",borderBottom:`1px solid ${b.separator}`}),o={unusual:0,notable:0,info:0};for(const s of t)o[s.severity]++;const d=Ot.filter(s=>o[s]>0),f=new Set(i.severity===void 0?d:Array.isArray(i.severity)?i.severity:[i.severity]),c=l("div",{display:"flex",gap:"4px",flexWrap:"wrap"});for(const s of d){const a=document.createElement("button");a.type="button";const p=()=>{const g=f.has(s);a.setAttribute("aria-pressed",g?"true":"false"),Object.assign(a.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${b.menuBorder}`,borderRadius:"10px",background:g?b.bgActive:"none",opacity:g?"1":"0.5",color:b.text,fontSize:"11px",padding:"2px 8px",cursor:"pointer"})};a.appendChild(K(s)),a.appendChild(l("span",{},`${jt[s]} ${o[s]}`)),a.title=f.has(s)?"Click to hide these findings":"Click to show these findings",p(),a.addEventListener("click",()=>{f.has(s)?f.delete(s):f.add(s),i.severity=f.size===d.length?void 0:[...f],n()}),c.appendChild(a)}return e.appendChild(c),e.appendChild(at("Kind:",Pt,i.kind??"",s=>{i.kind=s||void 0,n()},{maxWidth:"130px"})),e.appendChild(at("Region:",Yt,i.family??"",s=>{i.family=s||void 0,n()},{maxWidth:"150px"})),e}export function buildFindingsSectionWithFilter(t,i,n,e,o){if(!t.findings.length)return null;const d=t.findings.some(g=>g.severity==="unusual"||g.severity==="notable"),f=d?t.findings.filter(g=>g.severity!=="info").length.toString():void 0,{outer:c,content:s}=pt(`Findings (${t.findings.length})`,d,f);s.appendChild(qt(t.findings,e,o));const a=kt(t,e);if(!a.length)return s.appendChild(l("div",{color:I,fontSize:"11px",textAlign:"center",padding:"16px 8px"},"No findings match the current filter.")),c;const p=buildFindingsSection(a,t,i,n,!0);return p&&s.appendChild(p),c}export function buildLotTestSection(t,i,n,e,o){const d=e?.length?{perWaferMetadata:e.map(c=>c.wafer??{}),populationLabel:`${e.length} wafer${e.length===1?"":"s"} pooled`}:void 0;let f;if(e?.length&&e.every(c=>c.stats.perTestStats!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.perTestStats??[]){const p=c.get(a.testNumber);p?(p.n+=a.count,p.sum+=a.mean*a.count,p.min=Math.min(p.min,a.min),p.max=Math.max(p.max,a.max)):c.set(a.testNumber,{n:a.count,sum:a.mean*a.count,min:a.min,max:a.max})}f={perTestStats:[...c.entries()].map(([s,a])=>({testNumber:s,count:a.n,min:a.min,max:a.max,mean:a.sum/a.n}))}}if(e?.length&&e.every(c=>c.stats.testSpecYield!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.testSpecYield??[]){const p=c.get(a.testNumber);p?(p.passDies+=a.passDies,p.totalDies+=a.totalDies):c.set(a.testNumber,{passDies:a.passDies,totalDies:a.totalDies})}f={...f,testSpecYield:[...c.entries()].map(([s,a])=>({testNumber:s,totalDies:a.totalDies,yieldPercent:a.totalDies>0?a.passDies/a.totalDies*100:null}))}}return buildTestSection(t,i,n,f,o,d)}export function createSummaryPanelEl(t,i=document){const n=t==="top"||t==="bottom",e=l("div",{background:Et,border:O,borderRadius:"6px",padding:"12px",overflowY:n?"hidden":"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:"system-ui, sans-serif",fontSize:"12px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)"},void 0,i);return n?(e.style.height="180px",e.style.width="100%"):(e.style.width="260px",e.style.maxHeight="100%"),e}export function wrapWithSummaryPanel(t,i,n){const e=n==="top"||n==="bottom",o=l("div",{display:"flex",flexDirection:e?"column":"row",gap:"8px",width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:e?"flex-start":"stretch"});return t.style.flex="1 1 0",t.style.minWidth="0",t.style.minHeight="0",n==="right"||n==="bottom"?(o.appendChild(t),o.appendChild(i)):(o.appendChild(i),o.appendChild(t)),o}function mt(t){return l("div",{fontSize:"13px",fontWeight:"700",color:H,marginBottom:"10px"},t)}function V(t,i){const n=l("button",{background:"none",border:O,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:b.iconHover,padding:"2px 7px"},t);return n.type="button",n.addEventListener("click",i),n}function ht(...t){const i=t.filter(e=>!!e);if(!i.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",gap:"6px",marginBottom:"10px"});for(const e of i)n.appendChild(e);return n}function gt(t,i,n,e,o,d,f,c,s,a,p){const g=t.ownerDocument,h=rt({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:g});h.contentWrap.style.padding="14px 16px";const D=Ft(i,n,{...f,title:e,onSaveText:c,waferMetadata:o,metadataFields:d,extraColumn:s,getWafer:a,ringCount:p,ownerDocument:g});D&&h.contentWrap.appendChild(D)}export function renderWaferSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:g=[1],ringCount:h=4,colorScheme:D,fallbackFormat:M,onFindingClick:B,activeFindingId:T=null,findingsFilter:F,onFindingsFilterChange:R,onSaveText:u,metadataFields:L,dieListOptions:k}=i;t.appendChild(mt("Wafer Summary"));const C=i.warnings??it({statsSummary:p});C.length&&t.appendChild(Q(C,t.ownerDocument));const r=d&&f?V("Summary report",()=>{st(yt({wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:g,ringCount:h}),{anchor:t})}):null,m=(k?.enabled??!0)&&o.length?V("View die list",()=>{gt(t,o,a,`Die list \u2014 ${o.length} dies`,e.metadata,L,k,u,void 0,()=>e,h)}):null,$=ht(r,m);$&&t.appendChild($);const v=[],x=p?.stats.isLotStack?p.stats:void 0,S=x?.lotSize!==void 0?{lotSize:x.lotSize,aggrMethod:Dt(x.aggregationMethod)}:void 0;v.push(buildMetadataInfoSection([{metadata:e.metadata??void 0}],S)),d&&f&&v.push(buildYieldSection(d,f,g));const w=o.some(y=>y.hbin!=null),N=o.some(y=>y.sbin!=null);w?v.push(buildBinSection(o,c,"hard",D,p?.stats.hardBinCounts)):N&&v.push(buildBinSection(o,s,"soft",D,p?.stats.softBinCounts)),v.push(buildRingSection(o,e,h,g)),v.push(buildQuadrantSection(o,e,h,g));const W=e.metadata?{waferMetadata:e.metadata}:void 0;v.push(buildTestSection(o,a,M,p?.stats,u,W)),v.push(buildFunctionalTestSection(o,a,p?.stats.functionalYield,u,W)),p&&B&&F&&R&&v.push(buildFindingsSectionWithFilter(p,B,T,F,R));let E=!0;for(const y of v)y&&(E||t.appendChild(ct()),E=!1,t.appendChild(y));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}export function renderLotSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{lotSummary:e,items:o,hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s=[1],ringCount:a=4,colorScheme:p,fallbackFormat:g,onFindingClick:h,activeFindingId:D=null,onWaferClick:M,findingsFilter:B,onFindingsFilterChange:T,onSaveText:F,dieListOptions:R}=i;t.appendChild(mt(`Lot Summary \u2014 ${e.stats.waferCount} wafer${e.stats.waferCount===1?"":"s"}`));const u=i.warnings??it({lotStatsSummary:e});u.length&&t.appendChild(Q(u,t.ownerDocument));const L=V("Summary report",()=>{st(Ct({items:o.map((y,z)=>({label:y?.label??`W${z+1}`,wafer:y?.wafer,dies:y?.dies,statsSummary:y?.statsSummary})),hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s,ringCount:a}),{anchor:t})}),k=[],C=[],r=[],m=new WeakMap,$=new WeakMap;for(let y=0;y<o.length;y++){const z=o[y];if(!z){C.push([]);continue}z.wafer&&k.push(z.wafer);const _=z.dies??[],xt=z.label??`W${y+1}`;for(const Z of _)m.set(Z,xt),z.wafer&&$.set(Z,z.wafer);C.push(_),r.push(..._)}const v=R?.enabled??!0?V("View die list",()=>{r.length&&gt(t,r,c,`Die list \u2014 ${r.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,nt(o.filter(y=>!!y).map(y=>({metadata:y.wafer?.metadata}))),o.find(y=>y?.metadataFields?.length)?.metadataFields,R,F,{label:"Wafer",get:y=>m.get(y)},y=>$.get(y),a)}):null,x=ht(L,v);x&&t.appendChild(x);const S=r.some(y=>y.hbin!=null),w=r.some(y=>y.sbin!=null),N=o.map(y=>y?.statsSummary).filter(y=>!!y),W=[buildLotOverviewSection(e),buildPerWaferYieldSection(e,o,M),S?buildLotBinSection(r,d,"hard",p):w?buildLotBinSection(r,f,"soft",p):null,buildLotRingSection(C,k,a,s),buildLotQuadrantSection(C,k,a,s),c?.length?buildLotTestSection(r,c,g,N,F):null,c?.length?buildLotFunctionalSection(r,c,N,F):null];h&&B&&T&&W.push(buildFindingsSectionWithFilter(e,h,D,B,T));let E=!0;for(const y of W)y&&(E||t.appendChild(ct()),E=!1,t.appendChild(y));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}