@wafertools/wafermap 0.25.0 → 0.26.1
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 +33 -1
- package/dist/packages/canvas-adapter/dieList.d.ts +17 -0
- package/dist/packages/canvas-adapter/dieList.js +7 -7
- package/dist/packages/canvas-adapter/icons.js +1 -1
- package/dist/packages/canvas-adapter/index.d.ts +4 -0
- package/dist/packages/canvas-adapter/index.js +1 -1
- package/dist/packages/canvas-adapter/renderWaferGallery.js +2 -2
- package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
- package/dist/packages/canvas-adapter/toolbar.d.ts +55 -0
- package/dist/packages/canvas-adapter/toolbar.js +2 -2
- package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
- package/dist/packages/canvas-adapter/userGuideHtml.js +42 -4
- package/dist/packages/canvas-adapter/version.d.ts +2 -2
- package/dist/packages/canvas-adapter/version.js +1 -1
- package/dist/packages/renderer/buildView.js +1 -1
- package/dist/packages/renderer/buildWaferMap.d.ts +5 -1
- package/dist/packages/renderer/buildWaferMap.js +1 -1
- package/dist/packages/stats/analyzeWaferLot.js +1 -1
- package/dist/packages/stats/reportHtml.d.ts +6 -4
- package/dist/packages/stats/types.d.ts +14 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,38 @@ under `### Breaking`.
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## [0.26.1] — 2026-08-28
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **The built-in guide window read as broken in a dark host theme — pale, near-illegible text on a plain white page.** `.wmap-guide`'s CSS set `color: var(--wmap-text, #1a1a1a)` but never a matching `background`, so a popup window that copies `--wmap-*` tokens from a dark host (`copyWmapThemeTokens`) got dark-appropriate (pale) text with no dark background to put it on. Added `background: var(--wmap-surface, #fff)` to `.wmap-guide`, so background now follows the same synced tokens the text already did.
|
|
30
|
+
- **`edgeExcluded` dies rendered almost invisibly against the default light data colour scheme.** The fill (`#eceef0`) was lighter than the "no data" fill and barely darker than the canvas's own default background (`#f5f5f5`) — an excluded die read as blank/missing rather than "measured but excluded." Now a visibly darker, distinct grey (`#aab0ba`) — deliberately darker than the no-data fill too, since an excluded die had real data and should read as present-but-set-aside, not as more of the same "nothing here."
|
|
31
|
+
|
|
32
|
+
## [0.26.0] — 2026-08-28
|
|
33
|
+
|
|
34
|
+
### Breaking
|
|
35
|
+
|
|
36
|
+
- **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`.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **`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.
|
|
41
|
+
- **`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).
|
|
42
|
+
- **`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.
|
|
43
|
+
- **`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.
|
|
44
|
+
- **`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.
|
|
45
|
+
- **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.
|
|
46
|
+
- **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.
|
|
47
|
+
- **`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.
|
|
48
|
+
- **`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.
|
|
49
|
+
- 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.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- **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.
|
|
54
|
+
- **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.
|
|
55
|
+
- **`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.
|
|
56
|
+
|
|
25
57
|
## [0.25.0] — 2026-08-25
|
|
26
58
|
|
|
27
59
|
### Added
|
|
@@ -29,7 +61,7 @@ under `### Breaking`.
|
|
|
29
61
|
- `WaferViewOptions.showLegend` (`renderWaferMap`) — hide the legend/colorbar entirely, for a host that provides its own equivalent control. Default `true`, matching prior behaviour.
|
|
30
62
|
- `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
63
|
- `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` —
|
|
64
|
+
- `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
65
|
|
|
34
66
|
### Fixed
|
|
35
67
|
|
|
@@ -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
|
|
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: ${
|
|
6
|
-
border-bottom: 1px solid ${
|
|
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: ${
|
|
10
|
-
border-bottom: 1px solid ${
|
|
9
|
+
padding: 3px 8px; color: ${r.text};
|
|
10
|
+
border-bottom: 1px solid ${r.menuBorder}; white-space: nowrap;
|
|
11
11
|
}
|
|
12
|
-
`,n.head.appendChild(
|
|
13
|
-
`),t.csvFilename??"dies.csv","text/csv",t.onSaveText)}),
|
|
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,
|
|
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()}}}
|