@wafertools/wafermap 0.28.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/AGENTS.md +13 -14
  2. package/CHANGELOG.md +291 -0
  3. package/README.md +5 -5
  4. package/dist/packages/canvas-adapter/deprecated.d.ts +10 -0
  5. package/dist/packages/canvas-adapter/deprecated.js +1 -0
  6. package/dist/packages/canvas-adapter/dieList.d.ts +1 -3
  7. package/dist/packages/canvas-adapter/dieList.js +7 -7
  8. package/dist/packages/canvas-adapter/index.d.ts +1 -3
  9. package/dist/packages/canvas-adapter/index.js +1 -1
  10. package/dist/packages/canvas-adapter/insightsTab.d.ts +0 -1
  11. package/dist/packages/canvas-adapter/insightsTab.js +1 -1
  12. package/dist/packages/canvas-adapter/maplessSummary.d.ts +3 -0
  13. package/dist/packages/canvas-adapter/maplessSummary.js +1 -1
  14. package/dist/packages/canvas-adapter/renderWaferGallery.d.ts +1 -40
  15. package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
  16. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +81 -104
  17. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
  18. package/dist/packages/canvas-adapter/summaryPanel.d.ts +11 -8
  19. package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
  20. package/dist/packages/canvas-adapter/toCanvas.d.ts +20 -12
  21. package/dist/packages/canvas-adapter/toCanvas.js +1 -1
  22. package/dist/packages/canvas-adapter/toolbar.d.ts +2 -0
  23. package/dist/packages/canvas-adapter/toolbar.js +2 -2
  24. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
  25. package/dist/packages/canvas-adapter/userGuideHtml.js +14 -10
  26. package/dist/packages/canvas-adapter/version.d.ts +2 -2
  27. package/dist/packages/canvas-adapter/version.js +1 -1
  28. package/dist/packages/canvas-adapter/warnings.js +1 -1
  29. package/dist/packages/core/deprecated.d.ts +64 -0
  30. package/dist/packages/core/deprecated.js +1 -0
  31. package/dist/packages/core/index.d.ts +1 -3
  32. package/dist/packages/core/index.js +1 -1
  33. package/dist/packages/core/passBins.d.ts +33 -0
  34. package/dist/packages/core/passBins.js +1 -0
  35. package/dist/packages/core/waferLabel.d.ts +25 -0
  36. package/dist/packages/core/waferLabel.js +1 -0
  37. package/dist/packages/renderer/binColors.d.ts +67 -13
  38. package/dist/packages/renderer/binColors.js +1 -1
  39. package/dist/packages/renderer/buildView.d.ts +23 -9
  40. package/dist/packages/renderer/buildView.js +1 -1
  41. package/dist/packages/renderer/buildWaferMap.d.ts +47 -13
  42. package/dist/packages/renderer/buildWaferMap.js +1 -1
  43. package/dist/packages/renderer/colorMap.d.ts +4 -3
  44. package/dist/packages/renderer/colorSchemes.d.ts +21 -6
  45. package/dist/packages/renderer/colorSchemes.js +1 -1
  46. package/dist/packages/renderer/deprecate.d.ts +24 -0
  47. package/dist/packages/renderer/deprecate.js +1 -0
  48. package/dist/packages/renderer/deprecated.d.ts +45 -0
  49. package/dist/packages/renderer/deprecated.js +1 -0
  50. package/dist/packages/renderer/index.d.ts +2 -3
  51. package/dist/packages/renderer/index.js +1 -1
  52. package/dist/packages/stats/analyzeWaferMap.js +1 -1
  53. package/dist/packages/stats/binPareto.d.ts +6 -1
  54. package/dist/packages/stats/clusterDetection.d.ts +0 -2
  55. package/dist/packages/stats/deprecated.d.ts +87 -0
  56. package/dist/packages/stats/deprecated.js +1 -0
  57. package/dist/packages/stats/index.d.ts +3 -14
  58. package/dist/packages/stats/index.js +1 -1
  59. package/dist/packages/stats/regions.d.ts +7 -2
  60. package/dist/packages/stats/regions.js +1 -1
  61. package/dist/packages/stats/renderSummaryReport.d.ts +3 -0
  62. package/dist/packages/stats/renderSummaryReport.js +34 -34
  63. package/dist/packages/stats/types.d.ts +0 -43
  64. package/dist/packages/stats/yield.d.ts +12 -6
  65. package/dist/packages/stats/yield.js +1 -1
  66. package/package.json +1 -1
@@ -25,6 +25,13 @@ export interface WaferPreferences {
25
25
  * `listValueColorSchemes()`. Default `'default'`.
26
26
  */
27
27
  valueColorScheme?: string;
28
+ /**
29
+ * Flip the value gradient so high values take its low-end colour. Default
30
+ * false — every built-in gradient reads low = dark, high = light. Offered in
31
+ * the Colour scheme menu as "Reverse gradient"; applies to the dies, the
32
+ * colorbar and the mapless summary together.
33
+ */
34
+ reverseValueScheme?: boolean;
28
35
  /**
29
36
  * Honour `BinDef.color` where a bin definition supplies one. Default true.
30
37
  * The toolbar offers the toggle only when some definition carries a colour.
@@ -39,9 +46,17 @@ export interface WaferPreferences {
39
46
  showQuadrantBoundaries?: boolean;
40
47
  showReticle?: boolean;
41
48
  showXYIndicator?: boolean;
42
- ringCount?: number;
43
49
  /** Legend position for bin modes. Default 'default'. */
44
50
  legendPosition?: 'default' | 'compact' | 'bottom' | 'top' | 'left' | 'floating';
51
+ /**
52
+ * Format for unitless values outside the normal display range [0.1, 9999].
53
+ * `'engineering'` (default): multiples-of-3 exponent notation (e.g. `12E-6`).
54
+ * `'si'`: SI prefix with no unit suffix (e.g. `12 µ`).
55
+ * Values with a unit always use SI prefix regardless of this setting.
56
+ * Set it like any other preference — `viewOptions` or `setOptions` — the one
57
+ * place it is set (it used to have four).
58
+ */
59
+ fallbackFormat?: 'si' | 'engineering';
45
60
  /**
46
61
  * Draw this map's own legend block — the categorical bin legend, the spec/
47
62
  * pass-fail legend, or the value colorbar, whichever the plot mode calls for.
@@ -126,24 +141,6 @@ export interface WaferDisplayState {
126
141
  test: number;
127
142
  range: [number, number];
128
143
  };
129
- /**
130
- * The full, ordered list of metadata values to assign colours from in
131
- * `metadata` plot mode — applied only when `key` matches `activeMetadataKey`.
132
- * Set by a host rendering several wafers together (`renderWaferGallery` does
133
- * it for you) so every map indexes into ONE list; without it each map derives
134
- * the order from its own dies, and a wafer missing a value the others have
135
- * paints every later value in the next map's colour. See `ViewOptions`.
136
- */
137
- metadataValueOrder?: {
138
- key: string;
139
- values: string[];
140
- };
141
- /**
142
- * Bin colours resolved over the whole population being shown together —
143
- * set by `renderWaferGallery` so a bin is one colour on every card. A lone
144
- * map leaves it unset and resolves over its own dies. See `ViewOptions.binColors`.
145
- */
146
- binColors?: BinColors;
147
144
  /**
148
145
  * Aggregation method for `stackedValues` mode.
149
146
  * Drives both the per-die aggregation and the hover tooltip label.
@@ -151,11 +148,6 @@ export interface WaferDisplayState {
151
148
  * Defaults to `'mean'` when not set.
152
149
  */
153
150
  aggregationMethod?: string;
154
- /**
155
- * Total number of wafers in the lot — used to compute bin occurrence percentage
156
- * in `stackedBins` hover tooltips.
157
- */
158
- lotSize?: number;
159
151
  }
160
152
  /**
161
153
  * All scene-level options that the toolbar can control.
@@ -172,7 +164,7 @@ export type WaferViewOptions = WaferPreferences & WaferDisplayState;
172
164
  *
173
165
  * That inheritance leaked 16 low-level fields onto the top-level render API, and
174
166
  * five of them were **accepted and silently ignored** — `renderWaferMap` computes
175
- * or overrides them on every draw (`topClearance` is hardcoded to 0,
167
+ * or overrides them on every draw (`topClearance` was always 0, and has since been removed from `toCanvas` too;
176
168
  * `minRightReserve` is derived from the legend, and `markFailingDies`/`activeBin`/
177
169
  * `hoverBin` are read from `viewOptions` and internal hover state instead). An
178
170
  * option that is typed, documented and ignored costs a caller a debugging session
@@ -187,7 +179,7 @@ export type WaferViewOptions = WaferPreferences & WaferDisplayState;
187
179
  * of the ten options that DO work in exchange for tidiness alone, and the defect
188
180
  * here was the five that don't.
189
181
  */
190
- type ForwardedDrawOptions = Pick<ToCanvasOptions, 'padding' | 'background' | 'showColorbar' | 'colorbarWidth' | 'showAxes' | 'showTitle' | 'legendPosition' | 'legendOffset' | 'diePitchMm' | 'fallbackFormat' | 'metadataFields'>;
182
+ type ForwardedDrawOptions = Pick<ToCanvasOptions, 'padding' | 'background' | 'showColorbar' | 'colorbarWidth' | 'showAxes' | 'showTitle' | 'legendOffset' | 'diePitchMm' | 'metadataFields'>;
191
183
  export interface RenderOptions extends ForwardedDrawOptions {
192
184
  /** Initial scene display options. All are overridable via the toolbar. */
193
185
  viewOptions?: WaferViewOptions;
@@ -223,40 +215,8 @@ export interface RenderOptions extends ForwardedDrawOptions {
223
215
  * result has no metadata/lot-stack context.
224
216
  */
225
217
  showIdentity?: boolean;
226
- /**
227
- * Inset for this map's own chrome row (identity + toolbar) and for a Summary
228
- * panel docked inside the map area, from the edge of the map area.
229
- *
230
- * Defaults to `EDGE_GUTTER` — correct for a standalone map, where the map
231
- * area IS the region and its chrome is a bounded surface against that edge.
232
- * Pass the smaller `MAP_CHROME_INSET` when the map is embedded in a surface
233
- * that already provides its own inset (this is what `renderWaferGallery`
234
- * passes for its cards); a second full gutter inside one stacks two, which
235
- * reads as a toolbar standing well off the side of the card.
236
- */
237
- chromeInset?: string;
238
218
  /** Optional precomputed wafer-level stats summary. Enables the summary panel toggle button in the toolbar. */
239
219
  statsSummary?: StatsSummary;
240
- /**
241
- * Bin numbers treated as pass for yield calculation in the summary panel.
242
- * Defaults to `[1]`. Must match the `passBins` passed to `analyzeWaferMap` / `buildWaferMap`
243
- * to ensure the summary panel yield label is consistent with the rest of the display.
244
- */
245
- passBins?: number[];
246
- /**
247
- * 'full' (default) shows all toolbar controls.
248
- * 'view-only' shows only zoom, reset, box-select, and download — used by gallery cards.
249
- */
250
- toolbarControls?: 'full' | 'view-only';
251
- /**
252
- * Show the plot mode selector in the toolbar. Default true.
253
- * Set to false when the host application manages mode switching itself.
254
- */
255
- showPlotModeSelector?: boolean;
256
- /** Minimum zoom relative to fit. Default 0.4. */
257
- minZoom?: number;
258
- /** Maximum zoom relative to fit. Default 20. */
259
- maxZoom?: number;
260
220
  /** Filename for the PNG download (without extension). Default `'wafermap'`. */
261
221
  downloadFilename?: string;
262
222
  /**
@@ -306,12 +266,6 @@ export interface RenderOptions extends ForwardedDrawOptions {
306
266
  * identity data into an export.
307
267
  */
308
268
  dieList?: DieListDisplayOptions;
309
- /**
310
- * Custom tooltip renderer. When provided, replaces the built-in tooltip content.
311
- * Return a string (set as innerHTML), an HTMLElement (appended directly), or null to suppress the tooltip.
312
- * The built-in tooltip wrapper (positioning, show/hide behaviour) is preserved.
313
- */
314
- renderTooltip?: (die: Die) => string | HTMLElement | null;
315
269
  /**
316
270
  * Show a help button in the toolbar that opens the built-in end-user guide in a modal.
317
271
  * Default false. Enable in applications that want to surface the guide without linking externally.
@@ -323,8 +277,6 @@ export interface RenderOptions extends ForwardedDrawOptions {
323
277
  * has one help button instead of two. See `UserGuideExtension`.
324
278
  */
325
279
  userGuideExtension?: UserGuideExtension;
326
- /** Override the expand action for both the expand button and the E key. Used by the gallery to route through its own modal logic. */
327
- onExpand?: () => void;
328
280
  /**
329
281
  * Show the expand button in the toolbar and enable the E-key shortcut.
330
282
  * Default true. Independent of `showIdentity` — expand is a view control,
@@ -343,15 +295,6 @@ export interface RenderOptions extends ForwardedDrawOptions {
343
295
  * inset, or an explicit CSS height). Width always comes from the container.
344
296
  */
345
297
  height?: number | string;
346
- /**
347
- * Cap the map's rendered width and height at this many CSS pixels. When
348
- * the container is larger, the map sits top-left aligned within it rather
349
- * than stretching to fill it. Number only (a fixed pixel ceiling, not a
350
- * responsive length like `height`). Omit for no cap (fills the container,
351
- * current behaviour). The expand button/E-key still opens the map at full
352
- * size, unaffected by this cap.
353
- */
354
- maxSize?: number;
355
298
  /**
356
299
  * Base `z-index` for wmap's transient overlays — toolbar menus, the die
357
300
  * tooltip, the expand modal, and the user-guide modal. wmap layers its own
@@ -387,8 +330,6 @@ export interface RenderOptions extends ForwardedDrawOptions {
387
330
  warnings?: WarningsOptions;
388
331
  }
389
332
  export interface WaferMapController {
390
- /** Update the die data (e.g. after a data reload) — rebuilds scene, preserves zoom/pan. */
391
- setDies(dies: Die[]): void;
392
333
  /** Replace the wafer map result entirely — updates both wafer geometry and die data, preserves zoom/pan. */
393
334
  setResult(result: WaferMapResult): void;
394
335
  /** Merge scene option overrides — rebuilds scene, preserves zoom/pan. */
@@ -407,50 +348,25 @@ export interface WaferMapController {
407
348
  clearSelection(): void;
408
349
  /** Reset zoom and pan to fitted view. */
409
350
  resetZoom(): void;
410
- /** Update the fallback format for unitless values and re-render. */
411
- setFallbackFormat(format: 'si' | 'engineering'): void;
412
351
  /** Replace the current stats summary used by the built-in Summary panel. */
413
352
  setStatsSummary(summary: StatsSummary | undefined): void;
414
- /** Show or hide the Summary toolbar button without affecting the panel's content. */
415
- setSummaryVisible(visible: boolean): void;
416
- /** Show or hide the scene-control toolbar buttons (mode, orientation, etc). */
417
- setViewControlsVisible(visible: boolean): void;
418
- /** Show or hide the expand toolbar button. */
419
- setExpandVisible(visible: boolean): void;
420
- /** Show or hide the help toolbar button. */
421
- setHelpButtonVisible(visible: boolean): void;
422
- /** Show or hide the identity header without affecting its content. */
423
- setIdentityVisible(visible: boolean): void;
424
353
  /**
425
354
  * Opens the built-in end-user guide window — the same action the help
426
355
  * toolbar button performs, but callable directly. Works regardless of
427
- * `showHelpButton`/`setHelpButtonVisible`'s current value, so a host that
356
+ * `showHelpButton`, so a host that
428
357
  * hides wmap's own help button (e.g. to fold it into its own combined help
429
358
  * menu) can still trigger the guide without a DOM query against wmap's
430
359
  * internal button markup.
431
360
  */
432
361
  openUserGuide(): void;
433
- /** Close the auto-mounted Summary panel if it is open. No-op if no panel exists. */
434
- closeSummaryPanel(): void;
435
362
  /** Programmatically open/close the Insights tab. No-op if `insights.enabled` was not set. */
436
363
  setInsightsOpen(open: boolean): void;
437
- /** Move the floating tooltip into a different parent (e.g. a maximized modal box). */
438
- setTooltipParent(parent: HTMLElement): void;
439
- /**
440
- * Returns the current legend entries in `hardBin`/`softBin`/`metadata` modes, `null` in other
441
- * modes. Each entry includes the bin number (or metadata value string), display name, and color.
442
- */
443
- getActiveLegend(): Array<{
444
- bin: number | string;
445
- name: string;
446
- color: string;
447
- }> | null;
448
364
  /** Remove all event listeners and DOM elements. */
449
365
  destroy(): void;
450
366
  }
451
367
  /** Options that change die colours without changing what the view contains —
452
368
  * any of them means every colour-bearing surface (panels, footer) redraws. */
453
- export declare const COLOR_KEYS: readonly (keyof WaferViewOptions)[];
369
+ export declare const COLOR_KEYS: readonly (keyof CardViewOptions)[];
454
370
  export declare function classifyChanged(keys: (keyof WaferViewOptions)[]): 'preference' | 'state' | 'mixed';
455
371
  /**
456
372
  * What `renderWaferMap` actually needs: a wafer and its dies, plus anything
@@ -467,7 +383,68 @@ export declare function classifyChanged(keys: (keyof WaferViewOptions)[]): 'pref
467
383
  * and each such read had to be found the hard way. Declaring them optional
468
384
  * hands that job back to the compiler.
469
385
  */
386
+ /** @internal State a gallery shares with every card so one lot reads as one lot. */
387
+ export interface CardSharedState {
388
+ /**
389
+ * The full, ordered list of metadata values to assign colours from in
390
+ * `metadata` plot mode — applied only when `key` matches `activeMetadataKey`.
391
+ * Set by a host rendering several wafers together (`renderWaferGallery` does
392
+ * it for you) so every map indexes into ONE list; without it each map derives
393
+ * the order from its own dies, and a wafer missing a value the others have
394
+ * paints every later value in the next map's colour. See `ViewOptions`.
395
+ */
396
+ metadataValueOrder?: {
397
+ key: string;
398
+ values: string[];
399
+ };
400
+ /**
401
+ * Bin colours resolved over the whole population being shown together —
402
+ * set by `renderWaferGallery` so a bin is one colour on every card. A lone
403
+ * map leaves it unset and resolves over its own dies. See `ViewOptions.binColors`.
404
+ */
405
+ binColors?: BinColors;
406
+ /**
407
+ * Total number of wafers in the lot — the percentage denominator in
408
+ * `stackedBins`/`stackedSoftBins` hover tooltips.
409
+ */
410
+ lotSize?: number;
411
+ }
412
+ /** @internal */
413
+ export type CardViewOptions = WaferViewOptions & CardSharedState;
414
+ /** @internal Options only renderWaferGallery passes. */
415
+ export interface CardRenderOptions extends Omit<RenderOptions, 'viewOptions'> {
416
+ viewOptions?: CardViewOptions;
417
+ /**
418
+ * Inset for this map's own chrome row (identity + toolbar) and for a Summary
419
+ * panel docked inside the map area, from the edge of the map area.
420
+ *
421
+ * Defaults to `EDGE_GUTTER` — correct for a standalone map, where the map
422
+ * area IS the region and its chrome is a bounded surface against that edge.
423
+ * Pass the smaller `MAP_CHROME_INSET` when the map is embedded in a surface
424
+ * that already provides its own inset (this is what `renderWaferGallery`
425
+ * passes for its cards); a second full gutter inside one stacks two, which
426
+ * reads as a toolbar standing well off the side of the card.
427
+ */
428
+ chromeInset?: string;
429
+ /** Replaces the expand action for both the expand button and the E key. */
430
+ onExpand?: () => void;
431
+ }
432
+ /** @internal */
433
+ export interface CardController extends WaferMapController {
434
+ setOptions(opts: Partial<CardViewOptions>): void;
435
+ getOptions(): CardViewOptions;
436
+ /** Show or hide the Summary toolbar button without affecting the panel's content. */
437
+ setSummaryVisible(visible: boolean): void;
438
+ /** Show or hide the view-control toolbar buttons (mode, orientation, etc). */
439
+ setViewControlsVisible(visible: boolean): void;
440
+ /** Show or hide the expand toolbar button. */
441
+ setExpandVisible(visible: boolean): void;
442
+ }
443
+ /** @internal The public view of a card's options: everything but the gallery's shared state. */
444
+ export declare function toPublicViewOptions(opts: CardViewOptions): WaferViewOptions;
470
445
  export type RenderableWaferMap = Pick<WaferMapResult, 'wafer' | 'dies'> & Partial<Omit<WaferMapResult, 'wafer' | 'dies'>>;
471
446
  export declare function renderWaferMap(container: HTMLElement, result: RenderableWaferMap, options?: RenderOptions): WaferMapController;
447
+ /** @internal renderWaferMap plus the gallery-only options and controller methods. */
448
+ export declare function renderWaferMapCard(container: HTMLElement, result: RenderableWaferMap, options?: CardRenderOptions): CardController;
472
449
  export {};
473
450
  //# sourceMappingURL=renderWaferMap.d.ts.map
@@ -1 +1 @@
1
- import{buildView as vi,buildHoverText as xi,findTestDef as ct,resolveTestNumber as Nt}from"../renderer/buildView.js";import{toCanvas as Ci,BIN_LEGEND_W as Fn,BIN_LEGEND_W_COMPACT as wi,BIN_LEGEND_ADAPT_COMPACT as Si,BIN_LEGEND_ADAPT_FLOATING as Mi}from"./toCanvas.js";import{buildWaferMap as Ei,getTestPassStatus as Di,isParametricTest as jt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Bi}from"../stats/analyzeWaferMap.js";import{SHADOW as ki,LEADING as An,wireControlHover as zn,SPACE as W,EDGE_GUTTER as Li,RADIUS as Yn,FONT as ft,CLR as x,applyOverlayZ as Ti,getTooltip as Vn,hideTooltip as pt,reparentTooltip as Oi,positionTooltip as Kt,createToolbarHelpers as Pi,buildModeMenuEl as Ri,openReparentedModal as Ii,openUserGuideWindow as Wi,makePaletteBtn as Hi,makeLogScaleBtn as Fi,makeLegendStyleBtn as Ai,makeOverlaysBtn as zi,makeOrientationBtn as Yi,menuLayerFor as Xn,saveImageBlob as Vi,markMenuTrigger as _e,wireMenuA11y as Nn,wireExpandToggle as Xi,nextFrame as _t,requestedPassFailDisplay as Ni,overlayMenuRows as ji,anyOverlayActive as Ki,logWmapVersionOnce as _i,buildDataModeEntries as $i,metadataKeyHasData as Gi,metadataModeEntry as Ui}from"./toolbar.js";import{createSummaryPanelEl as $t,wrapWithSummaryPanel as Gt,renderWaferSummaryContent as Zi}from"./summaryPanel.js";import{collectWarnings as Qi,buildWarningsMenuEl as qi,severityOf as Ji}from"./warnings.js";import{ICONS as jn}from"./icons.js";import{metadataValueColor as eo,NO_DATA_FILL as to}from"../renderer/colorMap.js";import{createIdentityHeader as no,collapsedLabel as Ut}from"./identityHeader.js";import{getDieKey as Be,hasPosition as Kn,isPositionedDie as io}from"../core/dies.js";import{buildDieListSection as oo}from"./dieList.js";import{buildMaplessSummary as so}from"./maplessSummary.js";import{resolveBinColors as lo,binColorWarning as ao}from"../renderer/binColors.js";const _n=new Set(["binColorScheme","valueColorScheme","useDefinedBinColors","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","ringCount","legendPosition","logScale","colorbarRangeMode","markFailingDies"]);export const COLOR_KEYS=["binColorScheme","valueColorScheme","useDefinedBinColors","binColors"];export function classifyChanged(K){const y=K.some(g=>_n.has(g)),C=K.some(g=>!_n.has(g));return y&&C?"mixed":y?"preference":"state"}export function renderWaferMap(K,y,C={}){_i();const g=K.ownerDocument,H=g.defaultView??window;H.getComputedStyle(K).position==="static"&&(K.style.position="relative");const $n=K.clientHeight;C.height!=null&&(K.style.height=typeof C.height=="number"?`${C.height}px`:C.height);const ut=y.dataCoverage?y.dataCoverage.unpositionedDies:y.dies.filter(e=>!Kn(e)).length,$e=(y.dataCoverage?y.dataCoverage.totalDies:y.dies.length-ut)===0&&ut>0,ke=g.createElement("div");Object.assign(ke.style,{display:"flex",flexDirection:"column",width:"100%",height:"100%"}),K.appendChild(ke);const le=g.createElement("div");Object.assign(le.style,{position:"relative",width:"100%",flex:"1 1 auto",minHeight:"0"}),C.maxSize!=null&&(le.style.maxWidth=`${C.maxSize}px`,le.style.maxHeight=`${C.maxSize}px`);const ge=C.chromeInset??Li,_=g.createElement("div");Object.assign(_.style,{display:"flex",alignItems:"stretch",gap:W.sm,background:x.canvasBg,paddingBottom:W.lg,paddingTop:ge,paddingLeft:ge,paddingRight:ge,flexShrink:"0",minWidth:"0"}),ke.appendChild(_),ke.appendChild(le);function ve(){const e=[..._.children].some(t=>t.style.display!=="none");_.style.display=e?"flex":"none"}const S=g.createElement("div");Object.assign(S.style,{position:"relative",width:"100%",height:"100%"});const a=g.createElement("canvas");Object.assign(a.style,{width:"100%",height:"100%",display:"block"}),S.appendChild(a),le.appendChild(S);let Ge=null;if(ut>0){let n=function(){if(t){const d=oo(e,y.testDefs,{...C.dieList,onSaveText:C.onSaveText,waferMetadata:$.metadata,metadataFields:ce,ownerDocument:g});if(d)return d}const o=ct(y.testDefs,p.activeTest??0),s=jt(o)?p.logScale??o?.logScale??!1:!1;return so(e,y.testDefs,{plotMode:p.plotMode??"hardBin",activeTest:p.activeTest,hbinDefs:G,sbinDefs:U,binColors:m.binColors,valueColorScheme:p.valueColorScheme,logScale:s,colorbarRangeMode:p.colorbarRangeMode,valueRangeDies:y.dies})},i=function(o){const s=g.createElement("button");return s.type="button",zn(s),Object.assign(s.style,{fontSize:ft.body,padding:`${W.xxs} ${W.sm}`,borderRadius:Yn.control,flexShrink:"0",border:`1px solid ${x.menuBorder}`,background:x.menuBg,color:x.text,cursor:"pointer"}),s.textContent=t?"View chart":"View die list",s.addEventListener("click",d=>{d.stopPropagation(),t=!t,s.textContent=t?"View chart":"View die list",o()}),s};const e=y.dies.filter(o=>!Kn(o));let t=!1;if($e){const o=g.createElement("div");Object.assign(o.style,{position:"absolute",inset:"0",background:x.panelBg,padding:W.xl,boxSizing:"border-box",overflow:"hidden",display:"flex",flexDirection:"column",gap:W.md,zIndex:"1"});const s=g.createElement("div");Object.assign(s.style,{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:W.md});const d=g.createElement("span");Object.assign(d.style,{fontSize:ft.body,color:x.label,lineHeight:An.base}),d.textContent="No die position data for this wafer.",s.appendChild(d);const r=g.createElement("div");Object.assign(r.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),s.appendChild(i(()=>r.replaceChildren(n()))),o.appendChild(s),o.appendChild(r),S.appendChild(o),Ge=()=>{t||r.replaceChildren(n())}}else{const o=g.createElement("div");Object.assign(o.style,{position:"absolute",left:"0",right:"0",bottom:"0",zIndex:"3",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,fontSize:ft.body,color:x.text,cursor:"pointer",padding:`${W.xs} ${W.md}`,display:"flex",alignItems:"center",justifyContent:"space-between",gap:W.md}),zn(o,"bare");const s=g.createElement("span");s.textContent=`+${e.length} ${e.length===1?"die":"dies"} without position data`,o.appendChild(s);const d=g.createElement("span");d.textContent="\u25BE",Object.assign(d.style,{fontSize:ft.body,lineHeight:An.none,color:x.label,flexShrink:"0"}),o.appendChild(d),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`${e.length} dies without position data. Click to view.`);let r=null,l=null;Xi(o,c=>{if(d.textContent=c?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(c)),c){r=g.createElement("div");const f=o.getBoundingClientRect().height||28;Object.assign(r.style,{position:"absolute",left:"0",right:"0",bottom:`${f}px`,top:"20%",zIndex:"2",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,padding:W.md,boxSizing:"border-box",display:"flex",flexDirection:"column",gap:W.md}),r.addEventListener("click",Q=>Q.stopPropagation());const h=g.createElement("div");Object.assign(h.style,{display:"flex",justifyContent:"flex-end"}),h.appendChild(i(()=>{l&&l.replaceChildren(n())})),r.appendChild(h),l=g.createElement("div"),Object.assign(l.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),l.appendChild(n()),r.appendChild(l),S.appendChild(r)}else r&&(r.remove(),r=null,l=null)}),S.appendChild(o),Ge=()=>{l&&!t&&l.replaceChildren(n())}}}const{onHover:Ue,onClick:Gn,onSelect:he,onViewOptionsChange:Un,showTooltip:Zn=!0,showToolbar:Le=!0,showIdentity:Zt=!0,toolbarControls:gt="full",showPlotModeSelector:Qn=!0,minZoom:qn=.4,maxZoom:Jn=20,summaryPanel:Te,renderTooltip:Qt,passBins:Ze=[1],showHelpButton:qt=!1,userGuideExtension:ei,onExpand:Jt,showExpandButton:en=!0,zIndex:ti,insights:ht,warnings:tn,viewOptions:ni={},...ae}=C,Oe=ht?.enabled??!1,nn=tn?.display??!0,ii=Ti(ti);let Pe=ae.fallbackFormat,re=C.statsSummary,de=[],on=!1,Qe=null,sn=!1;function mt(){const e=Qi({result:y,statsSummary:re,extra:Qe?[Qe]:[]}),t=e.length!==de.length||e.some((n,i)=>n.code!==de[i]?.code||n.message!==de[i]?.message);de=e,(t||!on)&&(on=!0,tn?.onWarning?.(e))}mt();let yt=y,$=y.wafer,te=y.dies,E=new Set,G=y.hbinDefs,U=y.sbinDefs,ne=y.testDefs,ce=y.metadataFields,ln=y.reticles?.length?y.reticles:void 0,an=y.reticleConfig,rn=y.view?.dataAxisFlip,bt=y.isLotStack??!1,vt=y.aggrMethod,xt=y.lotSize;const oi=Le&&gt!=="view-only"&&Oe;let Ct=!1,Z=null,z=null,J=null;Zt&&(Z=no(Ut($.metadata??{},Re())??"",$.metadata,{lotStack:Re(),ownerDocument:g}),S.appendChild(Z.metaPanel),Z.isEmpty()||(z=dn(Z.wrap),_.insertBefore(z,_.firstChild),ve()));function dn(e){const t=g.createElement("div");return Object.assign(t.style,{display:"flex",alignItems:"center",padding:`${W.sm} ${W.lg}`,flex:"1 1 auto",minWidth:"0",overflow:"hidden",gap:W.sm}),Object.assign(e.style,{flex:"1",minWidth:"0"}),t.appendChild(e),t}function Re(){return bt?{lotSize:xt??1,aggrMethod:vt}:void 0}function si(){if(!Z)return;Z.update(Ut($.metadata??{},Re())??"",$.metadata,Re());const e=z?.isConnected??!1,t=!Z.isEmpty();!t&&e?(z.remove(),z=null):t&&!e&&(z=dn(Z.wrap),z.style.display=Ct?"none":"",_.insertBefore(z,_.firstChild),ve())}const li=[...G??[],...U??[]].some(e=>e.color);let p={plotMode:"hardBin",showDieLabels:!1,showPartialDies:!0,showRingBoundaries:!1,showQuadrantBoundaries:!1,showReticle:!1,showXYIndicator:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,legendPosition:ae.legendPosition??"default",...ni},Y=null,ie=!1,cn=null;function ai(){return Oe?Y?Promise.resolve(Y):(cn??=import("./insightsTab.js").then(({createInsightsTab:e})=>(Y=e({getItems:()=>[{wafer:$,dies:te,hbinDefs:G,sbinDefs:U,testDefs:ne,label:String($.metadata?.waferId??""),statsSummary:re}],getBinColors:()=>m.binColors,passBins:Ze,getRingCount:()=>p.ringCount??4,onSaveImage:C.onSaveImage,onSaveText:C.onSaveText,defaultView:ht?.defaultView,showMetadataStrip:!1,contentInset:ge,backTab:oi?void 0:{label:"Map",onBack:()=>Ie(!1)},onOpenGuide:qt&&!Le?()=>At():void 0,focusTest:t=>{D({plotMode:"value",activeTest:t,highlightBin:void 0}),Ie(!1)},ownerDocument:g}),Object.assign(Y.el.style,{position:"absolute",inset:"0",background:x.canvasBg,overflowY:"auto",paddingTop:"0"}),Y.el.style.display="none",le.appendChild(Y.el),Y)),cn):Promise.resolve(null)}let fn=0;const wt=["wheel","touchstart","pointerdown","keydown"];function ri(e,t){if(t<=0)return;let n=!1;const i=[],o=()=>{n=!0;for(const d of i)H.clearTimeout(d);i.length=0;for(const d of wt)e.removeEventListener(d,o)},s=()=>n||!ie?!0:(e.scrollTop=t,e.scrollTop>=t);if(!s()){for(const d of wt)e.addEventListener(d,o,{passive:!0,once:!0});for(const d of[0,50,150,300,600])i.push(H.setTimeout(()=>{s()},d));i.push(H.setTimeout(()=>{for(const d of wt)e.removeEventListener(d,o)},700))}}function Ie(e){if(!Oe)return;const t=ie;ie=e,Y&&!e&&t&&(fn=Y.el.scrollTop),Y&&(Y.el.style.display=e?"flex":"none"),F&&(F.style.display=e||$e?"none":"flex"),T&&(T.style.display=e?"none":"flex"),J&&(J.style.display=ye?"none":"flex"),oe&&(oe.style.display="flex"),z&&(z.style.display=Ct?"none":""),ve(),Z&&e&&Z.collapse(),it(),A&&(A.innerHTML=e?jn.wafer:jn.analysis,A.ariaLabel=e?"Back to wafer view":"Insights"),e&&ai().then(n=>{!n||!ie||(n.el.style.display="flex",n.render(),ri(n.el,fn))})}Oe&&ht?.defaultOpen&&queueMicrotask(()=>Ie(!0));let m,pn,V=null,k=null,St=[],Mt;function un(e){Mt!==e&&(Mt=e,v())}let We=null,Et=ae.legendOffset??{x:0,y:0},He=!1,xe=!1,Fe={x:0,y:0},Dt={x:0,y:0},me=!1,Ce=!1,X="pan",we={x:0,y:0},qe={x:0,y:0},O={x:0,y:0},P={x:0,y:0},Ae=!1,Se=!1;function ze(){const e=p;m=vi($,te.filter(io),{plotMode:e.plotMode,binColorScheme:e.binColorScheme,valueColorScheme:e.valueColorScheme,useDefinedBinColors:e.useDefinedBinColors,binColors:e.binColors??lo(te,{passBins:Ze,binColorScheme:e.binColorScheme,hbinDefs:G,sbinDefs:U,useDefinedBinColors:e.useDefinedBinColors}),passBins:Ze,showDieLabels:e.showDieLabels,showPartialDies:e.showPartialDies,showRingBoundaries:e.showRingBoundaries,showQuadrantBoundaries:e.showQuadrantBoundaries,showReticle:e.showReticle,showXYIndicator:e.showXYIndicator,reticles:ln,ringCount:e.ringCount,highlightBin:e.highlightBin,highlightMetadataValue:e.highlightMetadataValue,activeTest:e.activeTest,activeMetadataKey:e.activeMetadataKey,testDefs:ne,valueRange:e.valueRange,metadataValueOrder:e.metadataValueOrder,logScale:e.logScale,isLotStack:bt,aggregationMethod:vt??e.aggregationMethod,lotSize:xt??e.lotSize,dataAxisFlip:rn,colorbarRangeMode:e.colorbarRangeMode,passFailDisplay:e.passFailDisplay,fallbackFormat:Pe,interactiveTransform:{rotation:e.rotation??0,flipX:e.flipX??!1,flipY:e.flipY??!1}},{hbinDefs:G,sbinDefs:U,metadataFields:ce}),pn=new Map(m.dies.map((n,i)=>[Be(n),i]));const t=e.binColors?null:ao(m.binColors,m.plotMode);t?.message!==Qe?.message&&(Qe=t,mt(),sn&&Bt())}ze();let N=null,Me=null,Je=null,gn=C.findingsNotice,di={},R=null,fe=null;function ci(e){const{kind:t,index:n}=e.variable;D(t==="test"?{plotMode:"value",activeTest:n??0,highlightBin:void 0}:t==="softBin"?{plotMode:"softBin",highlightBin:void 0}:{plotMode:"hardBin",highlightBin:void 0});const i=e.highlight;i.kind==="bin"?(Rt(i.dieKeys),D({highlightBin:i.bin})):(i.kind==="region"||i.kind==="dies")&&Rt(i.dieKeys)}function hn(e){Zi(e,{wafer:$,dies:te,yieldSummary:yt.yield,dataCoverage:yt.dataCoverage,hbinDefs:G,sbinDefs:U,testDefs:ne,statsSummary:re,warnings:nn?de:[],passBins:Ze,ringCount:p.ringCount??4,binColors:m.binColors,plotMode:p.plotMode??"hardBin",metadataShownElsewhere:Zt,fallbackFormat:Pe,activeFindingId:Je,findingsFilter:di,findingsNotice:gn,onFindingsFilterChange:pe,onSaveText:C.onSaveText,metadataFields:ce,dieListOptions:C.dieList,onFindingClick:(t,n)=>{Je===t.id?(Je=null,Rt([]),D({highlightBin:void 0})):(Je=t.id,ci(t)),pe()}})}function pe(){N&&hn(N)}function Ye(){R&&hn(R)}if(Te?.placement){const e=Te.placement;N=$t(e,ge,g);const t=S.parentElement,n=S.nextSibling;Me=Gt(S,N,e),t?.insertBefore(Me,n),pe()}else if(re){const e=Te?.defaultOpen??!Le;R=$t("right",ge,g),R.style.display=e?"block":"none";const t=S.parentElement,n=S.nextSibling;fe=Gt(S,R,"right"),t?.insertBefore(fe,n),Ye()}const w=Zn?Vn(g):null;let oe=null,L=null,F=null,T=null,et=null,I=null,tt=null,A=null,se=null,nt=null;sn=!0;function Bt(){if(!se||!nt)return;const e=de.length,t=e>0;if(se.style.display=t?"flex":"none",nt.style.display=t?"":"none",!t)return;const n=Ji(de[0]),i=`${e} data ${e===1?"warning":"warnings"}`;se.style.color=n==="error"?x.errText:x.warnText,se.ariaLabel=n==="error"?`${i} \u2014 the map may be positionally wrong`:i}let kt=null,mn=null,Lt=null,Tt=null,Ot=null,Pt=null;function Rt(e){E=new Set(e??[]),he&&he(Ft()),v()}function it(){if(!I)return;const e=!!(N??R);I.style.display=re&&e&&!ie?"flex":"none";const t=N??R,n=t?t.style.display!=="none":!1;re?.hasNotableFindings&&!n?I.style.color=x.findingIndicator:I.dataset.active||(I.style.color=x.icon)}if(Le){let f=function(B){X=B,i(Q,B==="zoom"),i(M,B==="pan"),et&&i(et,B==="select"),a.style.cursor=B==="pan"?"grab":"crosshair"};oe=g.createElement("div"),oe.dataset.wmapToolbar="single",Object.assign(oe.style,{marginLeft:"auto",flexShrink:"0",display:"flex",flexDirection:"row",alignItems:"center",flexWrap:"wrap-reverse",justifyContent:"flex-end",maxWidth:"100%",background:x.menuBg,border:`1px solid ${x.menuBorder}`,borderRadius:Yn.control,boxShadow:ki.panel,pointerEvents:"auto"});const e=Vn(g),t=Pi(e),{makeBtn:n,setActive:i,makeSep:o,makeMenuRow:s,makeMenuSection:d,closeOpenMenu:r,getOpenMenu:l,setOpenMenu:c}=t;kt=r,mn=l,g.addEventListener("click",r,!0),F=g.createElement("div"),Object.assign(F.style,{display:$e?"none":"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),oe.appendChild(F);const h=n("download","Download PNG",ui);F.appendChild(h),F.appendChild(o());const Q=n("zoomMode","Zoom (drag to zoom region)",()=>f("zoom")),De=n("zoomIn","Zoom in",()=>Ee(a.clientWidth/2,a.clientHeight/2,1.2)),ee=n("zoomOut","Zoom out",()=>Ee(a.clientWidth/2,a.clientHeight/2,1/1.2)),ue=n("reset","Reset zoom (double-click)",()=>st());F.appendChild(Q),F.appendChild(De),F.appendChild(ee),F.appendChild(ue),F.appendChild(o());const M=n("pan","Pan (drag to move)",()=>f("pan"));if(F.appendChild(M),et=n("boxSelect","Select (drag to select dies)",()=>f("select")),F.appendChild(et),i(M,!0),gt!=="view-only"){let B=function(u){return u.plotMode!==(p.plotMode??"hardBin")?!1:u.plotMode==="value"?(p.activeTest??0)===(u.activeTest??0):u.plotMode==="metadata"?p.activeMetadataKey===u.activeMetadataKey:!0},zt=function(u,b){u.activeTest!==void 0?D({plotMode:u.plotMode,activeTest:u.activeTest,activeMetadataKey:void 0,logScale:u.logScale}):u.activeMetadataKey!==void 0?D({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:u.activeMetadataKey,passFailDisplay:"off"}):D({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),b.remove(),c(null),_e(q,!1)};L=g.createElement("div"),Object.assign(L.style,{display:"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),oe.appendChild(L),T=g.createElement("div"),Object.assign(T.style,{display:"flex",alignItems:"center",gap:"0"}),L.appendChild(T),T.appendChild(o());const lt=()=>{const u=l();u&&(u.remove(),c(null)),_e(q,!1)},q=n("mode","Plot mode",()=>{if(l()){lt();return}const u=te,b=m.testDefs,{testEntries:dt,binEntries:be,stackedEntries:Ne}=$i(u,b,{includeStacked:m.isLotStack}),Xt=(ce??[]).filter(Ke=>Gi(u,Ke.key)).map(Ui),je=Ri(q.getBoundingClientRect(),dt,be,Ne,B,zt,{makeMenuRow:s,makeMenuSection:d},p.plotMode??"hardBin",q.ownerDocument.defaultView??window,Xt);Xn(q).appendChild(je),c(je),_e(q,!0),Nn(je,q,lt)});_e(q,!1);const{btn:at,sync:Xe}=Hi(t,()=>({...p,plotMode:p.plotMode??"hardBin"}),()=>li,D);Tt=Xe,Tt();const Yt=zi(t,()=>{const u=!!m.hasReticle,b=(p.plotMode??"hardBin")==="value",{testNumber:dt}=Nt(p.activeTest??0,m.testDefs),be=ct(m.testDefs,dt),Ne=b&&be!==void 0&&!jt(be),Xt=b&&!Ne&&(be?.limitLow!==void 0||be?.limitHigh!==void 0),je=b&&!Ne&&m.dies.some(Ke=>Di(Ke,dt,be)!==void 0);return ji(p,u,{functionalActive:Ne,hasLimits:Xt,hasRecorded:je,binMode:(p.plotMode??"hardBin")==="hardBin"||(p.plotMode??"hardBin")==="softBin"},Ke=>D(Ke))},()=>Ki(p)),{btn:Vt,sync:gi}=Ai(t,()=>p,u=>D({legendPosition:u}));Lt=gi,Lt();const Hn=()=>{const{testNumber:u}=Nt(p.activeTest??0,ne),b=ct(ne,u);return b!==void 0&&!jt(b)},{btn:hi,sync:mi}=Fi(t,()=>({...p,functionalActive:Hn()}),u=>D(u));Ot=mi,Ot();const yi=()=>{const{testNumber:u}=Nt(p.activeTest??0,ne),b=ct(ne,u);return b!==void 0&&(b.limitLow!==void 0||b.limitHigh!==void 0)},rt=n("specRange","Colorbar range: spec limits",()=>{const u=p.colorbarRangeMode==="data"?"spec":"data";D({colorbarRangeMode:u})});Pt=()=>{const u=p.plotMode==="value"&&yi()&&Ni(p)==="off"&&!Hn();rt.style.display=u?"":"none";const b=(p.colorbarRangeMode??"spec")==="spec";i(rt,b),rt.ariaLabel=b?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"},Pt();const bi=Yi(t,()=>p,u=>D(u));Qn&&T.appendChild(q),T.appendChild(at),T.appendChild(hi),T.appendChild(rt),$e||(T.appendChild(o()),T.appendChild(Yt),T.appendChild(o()),T.appendChild(Vt),T.appendChild(o()),T.appendChild(bi)),re&&(I=n("findings","Summary panel",()=>{const u=N??R;if(!u)return;const b=u.style.display!=="none";u.style.display=b?"none":"block",i(I,!b),it()}),L.appendChild(o()),L.appendChild(I),R?.style.display!=="none"&&i(I,!0),it()),nn&&(nt=o(),se=n("warning","Data warnings",()=>{const u=l();if(r(new MouseEvent("click")),u)return;const b=qi(se.getBoundingClientRect(),de,H);Xn(le).appendChild(b),c(b),Nn(b,se,()=>r(new MouseEvent("click")))}),_e(se,!1),L.appendChild(nt),L.appendChild(se),Bt()),Oe&&(L.appendChild(o()),A=n("analysis","Insights",()=>{Ie(!ie),i(A,ie)}),A.dataset.wmapInsightsBtn="1",L.appendChild(A)),en&&(L.appendChild(o()),J=n("expand","Expand (E)",Jt??yn),L.appendChild(J)),qt&&(L.appendChild(o()),tt=n("help","User guide",()=>At()),L.appendChild(tt))}_.appendChild(oe),ve()}let ye=null;function yn(){ye&&(ye.close(),ye=null);const e=le;e.style.flex="1",e.style.minWidth="0",e.style.minHeight="0";const t=e.style.maxWidth,n=e.style.maxHeight;e.style.maxWidth="none",e.style.maxHeight="none";const i=Ut($.metadata??{},Re()),o=_.childElementCount>0?[_,e]:[e],s=Ii(o,{ownerDocument:g,boxSize:ie?{width:"min(96vw, 1600px)",height:"min(92vh, 1000px)"}:void 0,onClosed:()=>{ye=null,e.style.maxWidth=t,e.style.maxHeight=n,J&&(J.style.display="flex"),ie||a.focus({preventScroll:!0})}});s&&(s.box.setAttribute("aria-label",i??"Expanded wafer map"),o.length>1&&(s.contentWrap.style.flexDirection="column"),ye=s,J&&(J.style.display="none"))}function bn(e){const t=p.plotMode;p={...p,...e},e.plotMode!==void 0&&e.plotMode,Object.keys(e).every(s=>s==="legendPosition"||s==="showLegend"||s==="markFailingDies")||ze(),Lt?.(),Tt?.(),Ot?.(),Pt?.(),v();const i=e.plotMode!==void 0&&e.plotMode!==t,o=COLOR_KEYS.some(s=>s in e);(o||i)&&(pe(),Ye()),(o||i||e.activeTest!==void 0||e.logScale!==void 0||e.colorbarRangeMode!==void 0)&&Ge?.()}function D(e){bn(e);const t=Object.keys(e);Un?.(p,t,classifyChanged(t))}let It=!1;function Wt(){It||(It=!0,_t(()=>{It=!1,v()},H))}function v(){const e=k??void 0,t=m.dies[0],n=t?{x:t.width,y:t.height}:ae.diePitchMm,i=Math.floor(a.clientWidth||a.width),o=!!(G?.length||U?.length||m.dies.some(h=>h.hbin!=null||h.sbin!=null)),s=p.legendPosition??"default",d=p.showLegend??!0,r=s==="default"||s==="compact",l=(ae.colorbarWidth??16)+28,c=o&&r?s!=="default"?Math.max(Fn,l):i<Mi?0:i<Si?Math.max(wi,l):Math.max(Fn,l):void 0,f=Ci(a,m,{...ae,topClearance:0,minRightReserve:d?c:0,showColorbar:d&&(ae.showColorbar??!0),markFailingDies:p.markFailingDies??!1,legendPosition:s,legendOffset:Et,diePitchMm:n,fallbackFormat:Pe,showAxes:ae.showAxes??k!==null,viewport:e,activeBin:p.plotMode==="metadata"?p.highlightMetadataValue:p.highlightBin,hoverBin:Mt,hbinDefs:G,sbinDefs:U,metadataFields:ce});St=f.binLegendRows,We=f.legendBox??null,k===null&&(V=f.viewport),E.size>0&&fi(),Ce&&pi()}function fi(){const e=j();if(!e)return;const t=a.getContext("2d"),n=m.hoverPoints,i=m.rectangles[0],o=i?i.width/2*e.ppm:e.ppm*.5,s=i?i.height/2*e.ppm:e.ppm*.5,d=Math.max(1,Math.min(3,o*.08)),r=o-d,l=s-d,c=[];for(const f of E){const h=pn.get(f);h!==void 0&&c.push({sx:e.originX+n[h].x*e.ppm,sy:e.originY-n[h].y*e.ppm})}if(c.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.fill(),t.strokeStyle="rgba(255,255,255,0.9)",t.lineWidth=3,t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.stroke(),t.strokeStyle="rgba(0,0,0,0.9)",t.lineWidth=1.5,t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.stroke(),t.restore()}}function pi(){const e=a.getContext("2d"),t=Math.min(O.x,P.x),n=Math.min(O.y,P.y),i=Math.abs(P.x-O.x),o=Math.abs(P.y-O.y);e.save(),e.fillStyle="rgba(0,0,0,0.08)",e.fillRect(t,n,i,o),e.setLineDash([5,3]),e.strokeStyle="rgba(255,255,255,0.9)",e.lineWidth=3,e.strokeRect(t,n,i,o),e.strokeStyle="rgba(0,0,0,0.9)",e.lineWidth=1.5,e.strokeRect(t,n,i,o),e.restore()}function ui(){a.toBlob(e=>{e&&Vi(e,C.downloadFilename??"wafermap",C.onSaveImage)})}function vn(e){return V?Math.max(V.ppm*qn,Math.min(V.ppm*Jn,e)):e}function Ee(e,t,n){const i=k??V;if(!i)return;const o=vn(i.ppm*n),s=o/i.ppm,d=e-(e-i.originX)*s,r=t-(t-i.originY)*s,l=(V?.snapDist??1)/(o/(V?.ppm??o));k={originX:d,originY:r,ppm:o,snapDist:l},v()}function j(){return k??V}function xn(e){if(e.ctrlKey||e.metaKey){e.preventDefault();const t=a.getBoundingClientRect(),n=e.deltaY<0?1.12:1/1.12;Ee(e.clientX-t.left,e.clientY-t.top,n)}else if(k!==null){e.preventDefault();const t=j(),n=k.snapDist;k={originX:t.originX-e.deltaX,originY:t.originY-e.deltaY,ppm:t.ppm,snapDist:n},v()}}function Cn(e,t,n){return e>=n.x&&e<n.x+n.w&&t>=n.y&&t<n.y+n.h}function wn(e){if(e.button!==0||!j())return;a.focus({preventScroll:!0}),a.setPointerCapture(e.pointerId);const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(We&&p.legendPosition==="floating"&&Cn(n,i,We)){xe=!0,Fe={x:n,y:i},Dt={...Et};return}if(Ae&&X!=="pan"){Se=!0,me=!0,we={x:n,y:i},qe={x:j().originX,y:j().originY},a.style.cursor="grabbing";return}if(X==="zoom"||X==="select"){Ce=!0,O=P={x:n,y:i};return}me=!0,we={x:n,y:i},qe={x:j().originX,y:j().originY},a.style.cursor="grabbing"}function Sn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(Ce){P={x:n,y:i},Wt();return}if(xe){const f=n-Fe.x,h=i-Fe.y;f*f+h*h>16&&(xe=!1,He=!0,a.style.cursor="grabbing")}if(He){Et={x:Dt.x+(n-Fe.x),y:Dt.y+(i-Fe.y)},Wt();return}if(me){const f=j(),h=k?.snapDist??V?.snapDist??1;k={originX:qe.x+(n-we.x),originY:qe.y+(i-we.y),ppm:f.ppm,snapDist:h},Wt();return}const o=j();if(!o)return;const s=(n-o.originX)/o.ppm,d=(o.originY-i)/o.ppm,l=Bn(s,d,o.snapDist)?.die??null,c=St.find(f=>n>=f.x&&n<f.x+f.w&&i>=f.y&&i<f.y+f.h);if(un(c?c.bin:void 0),c){a.style.cursor="pointer",w&&(w.innerHTML=c.label??`Bin ${c.bin}`,w.style.display="block",Kt(w,a,e.clientX,e.clientY)),Ue?.(null,e);return}if(X==="pan"&&(a.style.cursor=l?"crosshair":"grab"),w)if(l)if(Qt){const f=Qt(l);f===null?w.style.display="none":(typeof f=="string"?w.innerHTML=f:(w.innerHTML="",w.appendChild(f)),w.style.display="block",Kt(w,a,e.clientX,e.clientY))}else w.innerHTML=xi(l,m.plotMode,{testDefs:ne,hbinDefs:G,sbinDefs:U,fallbackFormat:Pe,aggrMethod:m.aggrMethod,lotSize:m.lotSize,metadataFields:ce,activeTest:m.activeTest,reticleConfig:an}),w.style.display="block",Kt(w,a,e.clientX,e.clientY);else w.style.display="none";Ue?.(l,e)}function Mn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top,o=e.ctrlKey||e.metaKey;if(w&&(n<0||i<0||n>t.width||i>t.height)&&(w.style.display="none"),Ce){Ce=!1,P={x:n,y:i};const r=n-O.x,l=i-O.y,c=j();if(X==="zoom"){if(r*r+l*l<25)Ee(n,i,2);else if(c){const f=Math.min(O.x,P.x),h=Math.max(O.x,P.x),Q=Math.min(O.y,P.y),De=Math.max(O.y,P.y),ee=h-f,ue=De-Q;if(ee>4&&ue>4){const M=a.clientWidth,B=a.clientHeight,zt=M/ee,lt=B/ue,q=Math.min(zt,lt),at=vn(c.ppm*q),Xe=at/c.ppm,Yt=(f+h)/2,Vt=(Q+De)/2;k={originX:M/2-(Yt-c.originX)*Xe,originY:B/2-(Vt-c.originY)*Xe,ppm:at,snapDist:c.snapDist/Xe}}}v(),a.style.cursor="crosshair";return}if(r*r+l*l<25)Ht(n,i,o,e);else if(c){const f=(Math.min(O.x,P.x)-c.originX)/c.ppm,h=(Math.max(O.x,P.x)-c.originX)/c.ppm,Q=(c.originY-Math.max(O.y,P.y))/c.ppm,De=(c.originY-Math.min(O.y,P.y))/c.ppm,ee=m.hoverPoints,ue=[];for(let M=0;M<ee.length;M++)if(ee[M].x>=f&&ee[M].x<=h&&ee[M].y>=Q&&ee[M].y<=De){const B=m.dies[M];B&&ue.push(B)}if(o)for(const M of ue){const B=Be(M);E.has(B)?E.delete(B):E.add(B)}else E=new Set(ue.map(M=>Be(M)));he?.(Ft())}v(),a.style.cursor="crosshair";return}if(xe){xe=!1,Ht(n,i,o,e);return}if(He){He=!1,a.style.cursor="grab";return}if(!me)return;if(me=!1,Se){Se=!1,a.style.cursor=Ae||X==="pan"?"grab":"crosshair";return}a.style.cursor=X==="pan"?"grab":"crosshair";const s=n-we.x,d=i-we.y;s*s+d*d<25&&Ht(n,i,o,e)}function Ht(e,t,n,i){for(const r of St)if(e>=r.x&&e<r.x+r.w&&t>=r.y&&t<r.y+r.h){if(typeof r.bin=="number"){const l=p.highlightBin===r.bin?void 0:r.bin;D({highlightBin:l})}else{const l=p.highlightMetadataValue===r.bin?void 0:r.bin;D({highlightMetadataValue:l})}return}if(We&&Cn(e,t,We))return;const o=j();if(!o)return;const d=Bn((e-o.originX)/o.ppm,(o.originY-t)/o.ppm,o.snapDist)?.die??null;if(d){Gn?.(d,i);const r=Be(d);n?E.has(r)?E.delete(r):E.add(r):E=new Set([r]),he?.(Ft()),v()}else n||(E=new Set,he?.([]),v())}function Ft(){const e=[],t=m.hoverPoints;for(let n=0;n<t.length;n++){const i=m.dies[n];i&&E.has(Be(i))&&e.push(i)}return e}function En(){un(void 0),w&&pt(g),Ue?.(null,new MouseEvent("mouseleave")),a.style.cursor=X==="pan"?"grab":"crosshair"}function Dn(){me=!1,Se=!1,Ce=!1,xe=!1,He=!1,w&&pt(g),Ue?.(null,new MouseEvent("mouseleave")),a.style.cursor=X==="pan"?"grab":"crosshair",v()}function Bn(e,t,n){const i=m.hoverPoints,o=m.rectangles;for(let l=0;l<o.length;l++){const c=o[l];if(Math.abs(e-c.x)<=c.width/2&&Math.abs(t-c.y)<=c.height/2){const f=m.dies[l];return f?{die:f,index:l}:null}}let s=null,d=-1,r=n*n;for(let l=0;l<i.length;l++){const c=i[l].x-e,f=i[l].y-t,h=c*c+f*f;h<r&&(r=h,s=m.dies[l]??null,d=l)}return s?{die:s,index:d}:null}const kn=new H.ResizeObserver(()=>{V=null,k=null,v()});kn.observe(a),C.height==null&&$n<=0&&_t(()=>_t(()=>{K.clientHeight>0||console.warn("[wafermap] The map container has zero height, so the map cannot render. renderWaferMap fills its container \u2014 give the container a resolved height: an explicit CSS `height` (e.g. 600px), a height-resolved flex/grid parent, or `position:absolute; inset:0`. Alternatively pass `{ height: 600 }` in the render options and the library will size it for you.")}));let Ve=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`);const ot=()=>{Ve.removeEventListener("change",ot),Ve=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`),Ve.addEventListener("change",ot),v()};Ve.addEventListener("change",ot);const Ln=H.matchMedia("(prefers-color-scheme: dark)"),Tn=()=>v();Ln.addEventListener("change",Tn);const On=()=>{w&&pt(g)};H.addEventListener("blur",On);function Pn(e){if(e.key==="Escape"&&E.size>0&&(E=new Set,he?.([]),v()),(e.key==="e"||e.key==="E")&&gt!=="view-only"&&en&&(e.stopPropagation(),(Jt??yn)()),(e.ctrlKey||e.metaKey)&&(e.key==="="||e.key==="+"?(e.preventDefault(),Ee(a.clientWidth/2,a.clientHeight/2,1.2)):e.key==="-"?(e.preventDefault(),Ee(a.clientWidth/2,a.clientHeight/2,1/1.2)):e.key==="0"&&(e.preventDefault(),st())),!e.ctrlKey&&!e.metaKey&&!e.shiftKey){const n=j();if(n){const i=k?.snapDist??V?.snapDist??1;let o=0,s=0;e.key==="ArrowLeft"&&(o=20,e.preventDefault()),e.key==="ArrowRight"&&(o=-20,e.preventDefault()),e.key==="ArrowUp"&&(s=20,e.preventDefault()),e.key==="ArrowDown"&&(s=-20,e.preventDefault()),(o||s)&&(k={originX:n.originX+o,originY:n.originY+s,ppm:n.ppm,snapDist:i},v())}e.key===" "&&!Ae&&(e.preventDefault(),Ae=!0,X!=="pan"&&(a.style.cursor="grab"))}}function Rn(e){e.key===" "&&(Ae=!1,Se&&(me=!1,Se=!1),a.style.cursor=X==="pan"?"grab":"crosshair")}a.style.cursor="grab",a.setAttribute("tabindex","0"),a.addEventListener("wheel",xn,{passive:!1}),a.addEventListener("pointerdown",wn),a.addEventListener("pointermove",Sn),a.addEventListener("pointerup",Mn),a.addEventListener("pointerleave",En),a.addEventListener("pointercancel",Dn);const In=()=>st();a.addEventListener("dblclick",In),a.addEventListener("keydown",Pn),a.addEventListener("keyup",Rn);const Wn=e=>{e.stopPropagation()};a.addEventListener("click",Wn),a.clientWidth,v(),Ge?.();function st(){V=null,k=null,v()}function At(){import("./userGuideHtml.js").then(e=>Wi({buildWaferMap:Ei,renderWaferMap,renderWaferGallery:void 0,analyzeWaferMap:Bi},e.USER_GUIDE_HTML,ei,K))}return ve(),{setDies(e){te=e,ze(),v(),N&&pe()},setResult(e){yt=e,$=e.wafer,te=e.dies,G=e.hbinDefs,U=e.sbinDefs,ne=e.testDefs,ce=e.metadataFields,ln=e.reticles?.length?e.reticles:void 0,an=e.reticleConfig,rn=e.view?.dataAxisFlip,bt=e.isLotStack,vt=e.aggrMethod,xt=e.lotSize,si(),ze(),v(),N&&pe()},setOptions(e){bn(e)},getOptions(){return{...p}},resetZoom:st,setSelection(e){E=new Set(e.map(t=>Be(t))),v()},clearSelection(){E=new Set,he?.([]),v()},setFallbackFormat(e){Pe=e,ze(),v()},setFindingsNotice(e){gn=e,N?pe():R&&Ye()},setStatsSummary(e){if(re=e,mt(),Bt(),N)pe();else if(R)Ye();else if(e&&!Te?.placement){const t=Te?.defaultOpen??!Le;R=$t("right",ge,g),R.style.display=t?"block":"none";const n=S.parentElement,i=S.nextSibling;fe=Gt(S,R,"right"),n?.insertBefore(fe,i),Ye()}it()},setSummaryVisible(e){I&&(I.style.display=e?"flex":"none")},setViewControlsVisible(e){L&&(L.style.display=e?"flex":"none")},setExpandVisible(e){J&&(J.style.display=e?"flex":"none")},setHelpButtonVisible(e){tt&&(tt.style.display=e?"flex":"none")},setIdentityVisible(e){Ct=!e,z&&(z.style.display=e?"":"none"),ve()},openUserGuide:At,setInsightsOpen(e){Ie(e),A&&(e?(A.dataset.active="1",A.style.background=x.bgActive,A.style.color=x.iconActive):(delete A.dataset.active,A.style.background="transparent",A.style.color=x.icon))},closeSummaryPanel(){const e=N??R;!e||e.style.display==="none"||(e.style.display="none",I&&(delete I.dataset.active,I.style.background="transparent",I.style.color=x.icon))},setTooltipParent(e){w&&Oi(e)},getActiveLegend(){const e=p.plotMode;if(e==="metadata"){const s=p.activeMetadataKey;if(!s)return null;const d=ce?.find(l=>l.key===s),r=[...new Set(te.map(l=>l.metadata?.[s]).filter(l=>l!=null&&(typeof l=="string"||typeof l=="number"||typeof l=="boolean")).map(String))].sort();return r.length?r.map((l,c)=>{const f=d?.values?.find(Q=>Q.value===l),h=f?.color??eo(c);return{bin:l,name:f?.label??l,color:h}}):null}if(e!=="hardBin"&&e!=="softBin")return null;const t=e==="hardBin",n=t?G:U,i=[...new Set(te.map(s=>t?s.hbin:s.sbin).filter(s=>s!==void 0))].sort((s,d)=>s-d);if(!i.length)return null;const o=t?m.binColors.hard:m.binColors.soft;return i.map(s=>{const d=n?.find(r=>r.bin===s);return{bin:s,name:d?.name??`Bin ${s}`,color:o.get(s)??to}})},destroy(){ye?.close(),mn?.()?.remove(),kt&&g.removeEventListener("click",kt,!0),a.removeEventListener("wheel",xn),a.removeEventListener("pointerdown",wn),a.removeEventListener("pointermove",Sn),a.removeEventListener("pointerup",Mn),a.removeEventListener("pointerleave",En),a.removeEventListener("pointercancel",Dn),a.removeEventListener("dblclick",In),a.removeEventListener("keydown",Pn),a.removeEventListener("keyup",Rn),a.removeEventListener("click",Wn),kn.disconnect(),Ve.removeEventListener("change",ot),Ln.removeEventListener("change",Tn),H.removeEventListener("blur",On),ii(),w&&pt(g),oe?.remove(),Me&&(Me.parentElement?.insertBefore(S,Me),Me.remove()),fe&&(fe.parentElement?.insertBefore(S,fe),fe.remove()),S.remove(),a.style.cursor="",Y?.destroy(),Z?.destroy(),ke.remove()}}}
1
+ import{buildView as hi,buildHoverText as gi,findTestDef as rt,resolveTestNumber as Vt}from"../renderer/buildView.js";import{drawMapCanvas as mi,BIN_LEGEND_W as Pn,BIN_LEGEND_W_COMPACT as yi,BIN_LEGEND_ADAPT_COMPACT as bi,BIN_LEGEND_ADAPT_FLOATING as vi}from"./toCanvas.js";import{buildWaferMap as xi,getTestPassStatus as Ci,isParametricTest as zt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as wi}from"../stats/analyzeWaferMap.js";import{SHADOW as Si,LEADING as Rn,wireControlHover as In,SPACE as W,EDGE_GUTTER as Mi,RADIUS as Wn,FONT as dt,CLR as x,applyOverlayZ as Ei,getTooltip as Fn,hideTooltip as ct,positionTooltip as An,createToolbarHelpers as Di,buildModeMenuEl as Bi,openReparentedModal as ki,openUserGuideWindow as Li,makePaletteBtn as Ti,makeLogScaleBtn as Oi,makeLegendStyleBtn as Pi,makeOverlaysBtn as Ri,makeOrientationBtn as Ii,menuLayerFor as Hn,saveImageBlob as Wi,markMenuTrigger as _e,wireMenuA11y as Vn,wireExpandToggle as Fi,nextFrame as Yt,requestedPassFailDisplay as Ai,overlayMenuRows as Hi,anyOverlayActive as Vi,logWmapVersionOnce as zi,buildDataModeEntries as Yi,metadataKeyHasData as Ni,metadataModeEntry as Xi}from"./toolbar.js";import{waferDisplayLabel as ji}from"../core/waferLabel.js";import{createSummaryPanelEl as Nt,wrapWithSummaryPanel as Xt,renderWaferSummaryContent as _i}from"./summaryPanel.js";import{collectWarnings as Ki,buildWarningsMenuEl as $i,severityOf as Gi}from"./warnings.js";import{ICONS as zn}from"./icons.js";import{createIdentityHeader as Ui,collapsedLabel as jt}from"./identityHeader.js";import{getDieKey as Be,hasPosition as Yn,isPositionedDie as Zi}from"../core/dies.js";import{buildDieListSection as Qi}from"./dieList.js";import{buildMaplessSummary as qi}from"./maplessSummary.js";import{resolveBinColors as Ji,binColorWarning as eo}from"../renderer/binColors.js";import{INPUT_DEFAULT_PASS_BINS as to}from"../core/passBins.js";const Nn=new Set(["binColorScheme","valueColorScheme","reverseValueScheme","useDefinedBinColors","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","legendPosition","logScale","colorbarRangeMode","markFailingDies","fallbackFormat"]);export const COLOR_KEYS=["binColorScheme","valueColorScheme","reverseValueScheme","useDefinedBinColors","binColors"];export function classifyChanged(O){const g=O.some(f=>Nn.has(f)),v=O.some(f=>!Nn.has(f));return g&&v?"mixed":g?"preference":"state"}export function toPublicViewOptions(O){const{metadataValueOrder:g,binColors:v,lotSize:f,...B}=O;return B}export function renderWaferMap(O,g,v={}){return renderWaferMapCard(O,g,v)}export function renderWaferMapCard(O,g,v={}){zi();const f=O.ownerDocument,B=f.defaultView??window;B.getComputedStyle(O).position==="static"&&(O.style.position="relative");const Xn=O.clientHeight;v.height!=null&&(O.style.height=typeof v.height=="number"?`${v.height}px`:v.height);const pt=g.dataCoverage?g.dataCoverage.unpositionedDies:g.dies.filter(e=>!Yn(e)).length,Ke=(g.dataCoverage?g.dataCoverage.totalDies:g.dies.length-pt)===0&&pt>0,ke=f.createElement("div");Object.assign(ke.style,{display:"flex",flexDirection:"column",width:"100%",height:"100%"}),O.appendChild(ke);const me=f.createElement("div");Object.assign(me.style,{position:"relative",width:"100%",flex:"1 1 auto",minHeight:"0"});const de=v.chromeInset??Mi,j=f.createElement("div");Object.assign(j.style,{display:"flex",alignItems:"stretch",gap:W.sm,background:x.canvasBg,paddingBottom:W.lg,paddingTop:de,paddingLeft:de,paddingRight:de,flexShrink:"0",minWidth:"0"}),ke.appendChild(j),ke.appendChild(me);function Le(){const e=[...j.children].some(t=>t.style.display!=="none");j.style.display=e?"flex":"none"}const w=f.createElement("div");Object.assign(w.style,{position:"relative",width:"100%",height:"100%"});const s=f.createElement("canvas");Object.assign(s.style,{width:"100%",height:"100%",display:"block"}),w.appendChild(s),me.appendChild(w);let $e=null;if(pt>0){let n=function(){if(t){const p=Qi(e,g.testDefs,{...v.dieList,onSaveText:v.onSaveText,waferMetadata:_.metadata,metadataFields:pe,ownerDocument:f});if(p)return p}const o=rt(g.testDefs,d.activeTest??0),r=zt(o)?d.logScale??o?.logScale??!1:!1;return qi(e,g.testDefs,{plotMode:d.plotMode??"hardBin",activeTest:d.activeTest,hbinDefs:G,sbinDefs:U,binColors:y.binColors,valueColorScheme:d.valueColorScheme,reverseValueScheme:d.reverseValueScheme,logScale:r,colorbarRangeMode:d.colorbarRangeMode,valueRangeDies:g.dies})},i=function(o){const r=f.createElement("button");return r.type="button",In(r),Object.assign(r.style,{fontSize:dt.body,padding:`${W.xxs} ${W.sm}`,borderRadius:Wn.control,flexShrink:"0",border:`1px solid ${x.menuBorder}`,background:x.menuBg,color:x.text,cursor:"pointer"}),r.textContent=t?"View chart":"View die list",r.addEventListener("click",p=>{p.stopPropagation(),t=!t,r.textContent=t?"View chart":"View die list",o()}),r};const e=g.dies.filter(o=>!Yn(o));let t=!1;if(Ke){const o=f.createElement("div");Object.assign(o.style,{position:"absolute",inset:"0",background:x.panelBg,padding:W.xl,boxSizing:"border-box",overflow:"hidden",display:"flex",flexDirection:"column",gap:W.md,zIndex:"1"});const r=f.createElement("div");Object.assign(r.style,{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:W.md});const p=f.createElement("span");Object.assign(p.style,{fontSize:dt.body,color:x.label,lineHeight:Rn.base}),p.textContent="No die position data for this wafer.",r.appendChild(p);const l=f.createElement("div");Object.assign(l.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),r.appendChild(i(()=>l.replaceChildren(n()))),o.appendChild(r),o.appendChild(l),w.appendChild(o),$e=()=>{t||l.replaceChildren(n())}}else{const o=f.createElement("div");Object.assign(o.style,{position:"absolute",left:"0",right:"0",bottom:"0",zIndex:"3",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,fontSize:dt.body,color:x.text,cursor:"pointer",padding:`${W.xs} ${W.md}`,display:"flex",alignItems:"center",justifyContent:"space-between",gap:W.md}),In(o,"bare");const r=f.createElement("span");r.textContent=`+${e.length} ${e.length===1?"die":"dies"} without position data`,o.appendChild(r);const p=f.createElement("span");p.textContent="\u25BE",Object.assign(p.style,{fontSize:dt.body,lineHeight:Rn.none,color:x.label,flexShrink:"0"}),o.appendChild(p),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`${e.length} dies without position data. Click to view.`);let l=null,a=null;Fi(o,c=>{if(p.textContent=c?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(c)),c){l=f.createElement("div");const h=o.getBoundingClientRect().height||28;Object.assign(l.style,{position:"absolute",left:"0",right:"0",bottom:`${h}px`,top:"20%",zIndex:"2",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,padding:W.md,boxSizing:"border-box",display:"flex",flexDirection:"column",gap:W.md}),l.addEventListener("click",oe=>oe.stopPropagation());const m=f.createElement("div");Object.assign(m.style,{display:"flex",justifyContent:"flex-end"}),m.appendChild(i(()=>{a&&a.replaceChildren(n())})),l.appendChild(m),a=f.createElement("div"),Object.assign(a.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),a.appendChild(n()),l.appendChild(a),w.appendChild(l)}else l&&(l.remove(),l=null,a=null)}),w.appendChild(o),$e=()=>{a&&!t&&a.replaceChildren(n())}}}const{onHover:Ge,onClick:jn,onSelect:ce,onViewOptionsChange:_n,showTooltip:Kn=!0,showToolbar:Te=!0,showIdentity:_t=!0,summaryPanel:Oe,showHelpButton:Kt=!1,userGuideExtension:$n,onExpand:$t,showExpandButton:Gt=!0,zIndex:Gn,insights:ft,warnings:Ut,viewOptions:Un={},...ye}=v,Pe=ft?.enabled??!1,Zn=.4,Qn=20,Ue=[...g.passBins??to],Zt=Ut?.display??!0,qn=Ei(Gn);let se=v.statsSummary,le=[],Qt=!1,Ze=null,qt=!1;function ut(){const e=Ki({result:g,statsSummary:se,extra:Ze?[Ze]:[]}),t=e.length!==le.length||e.some((n,i)=>n.code!==le[i]?.code||n.message!==le[i]?.message);le=e,(t||!Qt)&&(Qt=!0,Ut?.onWarning?.(e))}ut();let be=g,_=g.wafer,ve=g.dies,M=new Set,G=g.hbinDefs,U=g.sbinDefs,ee=g.testDefs,pe=g.metadataFields,Jt=g.reticles?.length?g.reticles:void 0,en=g.reticleConfig,tn=g.view?.dataAxisFlip,ht=g.isLotStack??!1,gt=g.aggrMethod,mt=g.lotSize;const Jn=Te&&Pe;let V=null,Z=null,Q=null;_t&&(V=Ui(jt(_.metadata??{},Re())??"",_.metadata,{lotStack:Re(),ownerDocument:f}),w.appendChild(V.metaPanel),V.metaPanel.style.visibility="visible",V.isEmpty()||(Z=nn(V.wrap),j.insertBefore(Z,j.firstChild),Le()));function nn(e){const t=f.createElement("div");return Object.assign(t.style,{display:"flex",alignItems:"center",padding:`${W.sm} ${W.lg}`,flex:"1 1 auto",minWidth:"0",overflow:"hidden",gap:W.sm}),Object.assign(e.style,{flex:"1",minWidth:"0"}),t.appendChild(e),t}function Re(){return ht?{lotSize:mt??1,aggrMethod:gt}:void 0}function ei(){if(!V)return;V.update(jt(_.metadata??{},Re())??"",_.metadata,Re());const e=Z?.isConnected??!1,t=!V.isEmpty();!t&&e?(Z.remove(),Z=null):t&&!e&&(Z=nn(V.wrap),Z.style.display="",j.insertBefore(Z,j.firstChild),Le())}const ti=[...G??[],...U??[]].some(e=>e.color);let d={plotMode:"hardBin",showDieLabels:!1,showPartialDies:!0,showRingBoundaries:!1,showQuadrantBoundaries:!1,showReticle:!1,showXYIndicator:!1,rotation:0,flipX:!1,flipY:!1,legendPosition:"default",...Un},z=null,te=!1,on=null;function ni(){return Pe?z?Promise.resolve(z):(on??=import("./insightsTab.js").then(({createInsightsTab:e})=>(z=e({getItems:()=>[{wafer:_,dies:ve,hbinDefs:G,sbinDefs:U,testDefs:ee,label:ji({wafer:_},0),passBins:Ue,statsSummary:se}],getBinColors:()=>y.binColors,getRingCount:()=>be.ringCount??4,onSaveImage:v.onSaveImage,onSaveText:v.onSaveText,defaultView:ft?.defaultView,showMetadataStrip:!1,contentInset:de,backTab:Jn?void 0:{label:"Map",onBack:()=>Ie(!1)},onOpenGuide:Kt&&!Te?()=>It():void 0,focusTest:t=>{E({plotMode:"value",activeTest:t,highlightBin:void 0}),Ie(!1)},ownerDocument:f}),Object.assign(z.el.style,{position:"absolute",inset:"0",background:x.canvasBg,overflowY:"auto",paddingTop:"0"}),z.el.style.display="none",me.appendChild(z.el),z)),on):Promise.resolve(null)}let sn=0;const yt=["wheel","touchstart","pointerdown","keydown"];function ii(e,t){if(t<=0)return;let n=!1;const i=[],o=()=>{n=!0;for(const p of i)B.clearTimeout(p);i.length=0;for(const p of yt)e.removeEventListener(p,o)},r=()=>n||!te?!0:(e.scrollTop=t,e.scrollTop>=t);if(!r()){for(const p of yt)e.addEventListener(p,o,{passive:!0,once:!0});for(const p of[0,50,150,300,600])i.push(B.setTimeout(()=>{r()},p));i.push(B.setTimeout(()=>{for(const p of yt)e.removeEventListener(p,o)},700))}}function Ie(e){if(!Pe)return;const t=te;te=e,z&&!e&&t&&(sn=z.el.scrollTop),z&&(z.el.style.display=e?"flex":"none"),w.style.visibility=e?"hidden":"",A&&(A.style.display=e||Ke?"none":"flex"),T&&(T.style.display=e?"none":"flex"),Q&&(Q.style.display=he?"none":"flex"),ne&&(ne.style.display="flex"),Z&&(Z.style.display=""),Le(),V&&e&&V.collapse(),tt(),H&&(H.innerHTML=e?zn.wafer:zn.analysis,H.ariaLabel=e?"Back to wafer view":"Insights"),e&&ni().then(n=>{!n||!te||(n.el.style.display="flex",n.render(),ii(n.el,sn))})}Pe&&ft?.defaultOpen&&queueMicrotask(()=>Ie(!0));let y,ln,Y=null,k=null,bt=[],vt;function an(e){vt!==e&&(vt=e,C())}let We=null,xt=ye.legendOffset??{x:0,y:0},Fe=!1,xe=!1,Ae={x:0,y:0},Ct={x:0,y:0},fe=!1,Ce=!1,N="pan",we={x:0,y:0},Qe={x:0,y:0},P={x:0,y:0},R={x:0,y:0},He=!1,Se=!1;function wt(){const e=d;y=hi(_,ve.filter(Zi),{plotMode:e.plotMode,binColorScheme:e.binColorScheme,valueColorScheme:e.valueColorScheme,reverseValueScheme:e.reverseValueScheme,useDefinedBinColors:e.useDefinedBinColors,binColors:e.binColors??Ji(ve,{passBins:Ue,binColorScheme:e.binColorScheme,hbinDefs:G,sbinDefs:U,useDefinedBinColors:e.useDefinedBinColors}),passBins:Ue,showDieLabels:e.showDieLabels,showPartialDies:e.showPartialDies,showRingBoundaries:e.showRingBoundaries,showQuadrantBoundaries:e.showQuadrantBoundaries,showReticle:e.showReticle,showXYIndicator:e.showXYIndicator,reticles:Jt,ringCount:be.ringCount??4,highlightBin:e.highlightBin,highlightMetadataValue:e.highlightMetadataValue,activeTest:e.activeTest,activeMetadataKey:e.activeMetadataKey,testDefs:ee,valueRange:e.valueRange,metadataValueOrder:e.metadataValueOrder,logScale:e.logScale,isLotStack:ht,aggregationMethod:gt??e.aggregationMethod,lotSize:mt??e.lotSize,dataAxisFlip:tn,colorbarRangeMode:e.colorbarRangeMode,passFailDisplay:e.passFailDisplay,fallbackFormat:e.fallbackFormat,interactiveTransform:{rotation:e.rotation??0,flipX:e.flipX??!1,flipY:e.flipY??!1}},{hbinDefs:G,sbinDefs:U,metadataFields:pe}),ln=new Map(y.dies.map((n,i)=>[Be(n),i]));const t=e.binColors?null:eo(y.binColors,y.plotMode);t?.message!==Ze?.message&&(Ze=t,ut(),qt&&St())}wt();let q=null,Me=null,qe=null,rn=v.findingsNotice,oi={},F=null,ae=null;function si(e){const{kind:t,index:n}=e.variable;E(t==="test"?{plotMode:"value",activeTest:n??0,highlightBin:void 0}:t==="softBin"?{plotMode:"softBin",highlightBin:void 0}:{plotMode:"hardBin",highlightBin:void 0});const i=e.highlight;i.kind==="bin"?(Lt(i.dieKeys),E({highlightBin:i.bin})):(i.kind==="region"||i.kind==="dies")&&Lt(i.dieKeys)}function dn(e){_i(e,{wafer:_,dies:ve,yieldSummary:be.yield,dataCoverage:be.dataCoverage,hbinDefs:G,sbinDefs:U,testDefs:ee,statsSummary:se,warnings:Zt?le:[],passBins:Ue,ringCount:be.ringCount??4,binColors:y.binColors,plotMode:d.plotMode??"hardBin",metadataShownElsewhere:_t,fallbackFormat:d.fallbackFormat,activeFindingId:qe,findingsFilter:oi,findingsNotice:rn,onFindingsFilterChange:ue,onSaveText:v.onSaveText,metadataFields:pe,dieListOptions:v.dieList,onFindingClick:(t,n)=>{qe===t.id?(qe=null,Lt([]),E({highlightBin:void 0})):(qe=t.id,si(t)),ue()}})}function ue(){q&&dn(q)}function Ve(){F&&dn(F)}if(Oe?.placement){const e=Oe.placement;q=Nt(e,de,f);const t=w.parentElement,n=w.nextSibling;Me=Xt(w,q,e),t?.insertBefore(Me,n),ue()}else if(se){const e=Oe?.defaultOpen??!Te;F=Nt("right",de,f),F.style.display=e?"block":"none";const t=w.parentElement,n=w.nextSibling;ae=Xt(w,F,"right"),t?.insertBefore(ae,n),Ve()}const I=Kn?Fn(f):null;let ne=null,L=null,A=null,T=null,Je=null,K=null,cn=null,H=null,ie=null,et=null;qt=!0;function St(){if(!ie||!et)return;const e=le.length,t=e>0;if(ie.style.display=t?"flex":"none",et.style.display=t?"":"none",!t)return;const n=Gi(le[0]),i=`${e} data ${e===1?"warning":"warnings"}`;ie.style.color=n==="error"?x.errText:x.warnText,ie.ariaLabel=n==="error"?`${i} \u2014 the map may be positionally wrong`:i}let Mt=null,pn=null,Et=null,Dt=null,Bt=null,kt=null;function Lt(e){M=new Set(e??[]),ce&&ce(Rt()),C()}function tt(){if(!K)return;const e=!!(q??F);K.style.display=se&&e&&!te?"flex":"none";const t=q??F,n=t?t.style.display!=="none":!1;se?.hasNotableFindings&&!n?K.style.color=x.findingIndicator:K.dataset.active||(K.style.color=x.icon)}if(Te){let h=function(D){N=D,i(oe,D==="zoom"),i(S,D==="pan"),Je&&i(Je,D==="select"),s.style.cursor=D==="pan"?"grab":"crosshair"};ne=f.createElement("div"),ne.dataset.wmapToolbar="single",Object.assign(ne.style,{marginLeft:"auto",flexShrink:"0",display:"flex",flexDirection:"row",alignItems:"center",flexWrap:"wrap-reverse",justifyContent:"flex-end",maxWidth:"100%",background:x.menuBg,border:`1px solid ${x.menuBorder}`,borderRadius:Wn.control,boxShadow:Si.panel,pointerEvents:"auto"});const e=Fn(f),t=Di(e),{makeBtn:n,setActive:i,makeSep:o,makeMenuRow:r,makeMenuSection:p,closeOpenMenu:l,getOpenMenu:a,setOpenMenu:c}=t;Mt=l,pn=a,f.addEventListener("click",l,!0),A=f.createElement("div"),Object.assign(A.style,{display:Ke?"none":"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),ne.appendChild(A);const m=n("download","Download PNG",ri);A.appendChild(m),A.appendChild(o());const oe=n("zoomMode","Zoom (drag to zoom region)",()=>h("zoom")),De=n("zoomIn","Zoom in",()=>Ee(s.clientWidth/2,s.clientHeight/2,1.2)),J=n("zoomOut","Zoom out",()=>Ee(s.clientWidth/2,s.clientHeight/2,1/1.2)),re=n("reset","Reset zoom (double-click)",()=>it());A.appendChild(oe),A.appendChild(De),A.appendChild(J),A.appendChild(re),A.appendChild(o());const S=n("pan","Pan (drag to move)",()=>h("pan"));A.appendChild(S),Je=n("boxSelect","Select (drag to select dies)",()=>h("select")),A.appendChild(Je),i(S,!0);{let D=function(u){return u.plotMode!==(d.plotMode??"hardBin")?!1:u.plotMode==="value"?(d.activeTest??0)===(u.activeTest??0):u.plotMode==="metadata"?d.activeMetadataKey===u.activeMetadataKey:!0},Wt=function(u,b){u.activeTest!==void 0?E({plotMode:u.plotMode,activeTest:u.activeTest,activeMetadataKey:void 0,logScale:u.logScale}):u.activeMetadataKey!==void 0?E({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:u.activeMetadataKey,passFailDisplay:"off"}):E({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),b.remove(),c(null),_e($,!1)};L=f.createElement("div"),Object.assign(L.style,{display:"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),ne.appendChild(L),T=f.createElement("div"),Object.assign(T.style,{display:"flex",alignItems:"center",gap:"0"}),L.appendChild(T),T.appendChild(o());const ot=()=>{const u=a();u&&(u.remove(),c(null)),_e($,!1)},$=n("mode","Plot mode",()=>{if(a()){ot();return}const u=ve,b=y.testDefs,{testEntries:at,binEntries:ge,stackedEntries:Ne}=Yi(u,b,{includeStacked:y.isLotStack}),Ht=(pe??[]).filter(je=>Ni(u,je.key)).map(Xi),Xe=Bi($.getBoundingClientRect(),at,ge,Ne,D,Wt,{makeMenuRow:r,makeMenuSection:p},d.plotMode??"hardBin",$.ownerDocument.defaultView??window,Ht);Hn($).appendChild(Xe),c(Xe),_e($,!0),Vn(Xe,$,ot)});_e($,!1);const{btn:st,sync:Ye}=Ti(t,()=>({...d,plotMode:d.plotMode??"hardBin"}),()=>ti,E);Dt=Ye,Dt();const Ft=Ri(t,()=>{const u=!!y.hasReticle,b=(d.plotMode??"hardBin")==="value",{testNumber:at}=Vt(d.activeTest??0,y.testDefs),ge=rt(y.testDefs,at),Ne=b&&ge!==void 0&&!zt(ge),Ht=b&&!Ne&&(ge?.limitLow!==void 0||ge?.limitHigh!==void 0),Xe=b&&!Ne&&y.dies.some(je=>Ci(je,at,ge)!==void 0);return Hi(d,u,{functionalActive:Ne,hasLimits:Ht,hasRecorded:Xe,binMode:(d.plotMode??"hardBin")==="hardBin"||(d.plotMode??"hardBin")==="softBin"},je=>E(je))},()=>Vi(d)),{btn:At,sync:di}=Pi(t,()=>d,u=>E({legendPosition:u}));Et=di,Et();const On=()=>{const{testNumber:u}=Vt(d.activeTest??0,ee),b=rt(ee,u);return b!==void 0&&!zt(b)},{btn:ci,sync:pi}=Oi(t,()=>({...d,functionalActive:On()}),u=>E(u));Bt=pi,Bt();const fi=()=>{const{testNumber:u}=Vt(d.activeTest??0,ee),b=rt(ee,u);return b!==void 0&&(b.limitLow!==void 0||b.limitHigh!==void 0)},lt=n("specRange","Colorbar range: spec limits",()=>{const u=d.colorbarRangeMode==="data"?"spec":"data";E({colorbarRangeMode:u})});kt=()=>{const u=d.plotMode==="value"&&fi()&&Ai(d)==="off"&&!On();lt.style.display=u?"":"none";const b=(d.colorbarRangeMode??"spec")==="spec";i(lt,b),lt.ariaLabel=b?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"},kt();const ui=Ii(t,()=>d,u=>E(u));T.appendChild($),T.appendChild(st),T.appendChild(ci),T.appendChild(lt),Ke||(T.appendChild(o()),T.appendChild(Ft),T.appendChild(o()),T.appendChild(At),T.appendChild(o()),T.appendChild(ui)),se&&(K=n("findings","Summary panel",()=>{const u=q??F;if(!u)return;const b=u.style.display!=="none";u.style.display=b?"none":"block",i(K,!b),tt()}),L.appendChild(o()),L.appendChild(K),F?.style.display!=="none"&&i(K,!0),tt()),Zt&&(et=o(),ie=n("warning","Data warnings",()=>{const u=a();if(l(new MouseEvent("click")),u)return;const b=$i(ie.getBoundingClientRect(),le,B);Hn(me).appendChild(b),c(b),Vn(b,ie,()=>l(new MouseEvent("click")))}),_e(ie,!1),L.appendChild(et),L.appendChild(ie),St()),Pe&&(L.appendChild(o()),H=n("analysis","Insights",()=>{Ie(!te),i(H,te)}),H.dataset.wmapInsightsBtn="1",L.appendChild(H)),Gt&&(L.appendChild(o()),Q=n("expand","Expand (E)",$t??fn),L.appendChild(Q)),Kt&&(L.appendChild(o()),cn=n("help","User guide",()=>It()),L.appendChild(cn))}j.appendChild(ne),Le()}let he=null;function fn(){he&&(he.close(),he=null);const e=me;e.style.flex="1",e.style.minWidth="0",e.style.minHeight="0";const t=jt(_.metadata??{},Re()),n=j.childElementCount>0?[j,e]:[e],i=ki(n,{ownerDocument:f,boxSize:te?{width:"min(96vw, 1600px)",height:"min(92vh, 1000px)"}:void 0,onClosed:()=>{he=null,Q&&(Q.style.display="flex"),te||s.focus({preventScroll:!0})}});i&&(i.box.setAttribute("aria-label",t??"Expanded wafer map"),n.length>1&&(i.contentWrap.style.flexDirection="column"),he=i,Q&&(Q.style.display="none"))}function un(e){const t=d.plotMode;d={...d,...e},e.plotMode!==void 0&&e.plotMode,Object.keys(e).every(r=>r==="legendPosition"||r==="showLegend"||r==="markFailingDies")||wt(),Et?.(),Dt?.(),Bt?.(),kt?.(),C();const i=e.plotMode!==void 0&&e.plotMode!==t,o=COLOR_KEYS.some(r=>r in e);(o||i)&&(ue(),Ve()),(o||i||e.activeTest!==void 0||e.logScale!==void 0||e.colorbarRangeMode!==void 0)&&$e?.()}function E(e){un(e);const t=Object.keys(e);_n?.(d,t,classifyChanged(t))}let Tt=!1;function Ot(){Tt||(Tt=!0,Yt(()=>{Tt=!1,C()},B))}function C(){const e=k??void 0,t=y.dies[0],n=t?{x:t.width,y:t.height}:ye.diePitchMm,i=Math.floor(s.clientWidth||s.width),o=!!(G?.length||U?.length||y.dies.some(m=>m.hbin!=null||m.sbin!=null)),r=d.legendPosition??"default",p=d.showLegend??!0,l=r==="default"||r==="compact",a=(ye.colorbarWidth??16)+28,c=o&&l?r!=="default"?Math.max(Pn,a):i<vi?0:i<bi?Math.max(yi,a):Math.max(Pn,a):void 0,h=mi(s,y,{...ye,minRightReserve:p?c:0,showColorbar:p&&(ye.showColorbar??!0),markFailingDies:d.markFailingDies??!1,legendPosition:r,legendOffset:xt,diePitchMm:n,fallbackFormat:d.fallbackFormat,showAxes:ye.showAxes??k!==null,viewport:e,activeBin:d.plotMode==="metadata"?d.highlightMetadataValue:d.highlightBin,hoverBin:vt,hbinDefs:G,sbinDefs:U,metadataFields:pe});bt=h.binLegendRows,We=h.legendBox??null,k===null&&(Y=h.viewport),M.size>0&&li(),Ce&&ai()}function li(){const e=X();if(!e)return;const t=s.getContext("2d"),n=y.hoverPoints,i=y.rectangles[0],o=i?i.width/2*e.ppm:e.ppm*.5,r=i?i.height/2*e.ppm:e.ppm*.5,p=Math.max(1,Math.min(3,o*.08)),l=o-p,a=r-p,c=[];for(const h of M){const m=ln.get(h);m!==void 0&&c.push({sx:e.originX+n[m].x*e.ppm,sy:e.originY-n[m].y*e.ppm})}if(c.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:h,sy:m}of c)t.rect(h-l,m-a,l*2,a*2);t.fill(),t.strokeStyle="rgba(255,255,255,0.9)",t.lineWidth=3,t.beginPath();for(const{sx:h,sy:m}of c)t.rect(h-l,m-a,l*2,a*2);t.stroke(),t.strokeStyle="rgba(0,0,0,0.9)",t.lineWidth=1.5,t.beginPath();for(const{sx:h,sy:m}of c)t.rect(h-l,m-a,l*2,a*2);t.stroke(),t.restore()}}function ai(){const e=s.getContext("2d"),t=Math.min(P.x,R.x),n=Math.min(P.y,R.y),i=Math.abs(R.x-P.x),o=Math.abs(R.y-P.y);e.save(),e.fillStyle="rgba(0,0,0,0.08)",e.fillRect(t,n,i,o),e.setLineDash([5,3]),e.strokeStyle="rgba(255,255,255,0.9)",e.lineWidth=3,e.strokeRect(t,n,i,o),e.strokeStyle="rgba(0,0,0,0.9)",e.lineWidth=1.5,e.strokeRect(t,n,i,o),e.restore()}function ri(){s.toBlob(e=>{e&&Wi(e,v.downloadFilename??"wafermap",v.onSaveImage)})}function hn(e){return Y?Math.max(Y.ppm*Zn,Math.min(Y.ppm*Qn,e)):e}function Ee(e,t,n){const i=k??Y;if(!i)return;const o=hn(i.ppm*n),r=o/i.ppm,p=e-(e-i.originX)*r,l=t-(t-i.originY)*r,a=(Y?.snapDist??1)/(o/(Y?.ppm??o));k={originX:p,originY:l,ppm:o,snapDist:a},C()}function X(){return k??Y}function gn(e){if(e.ctrlKey||e.metaKey){e.preventDefault();const t=s.getBoundingClientRect(),n=e.deltaY<0?1.12:1/1.12;Ee(e.clientX-t.left,e.clientY-t.top,n)}else if(k!==null){e.preventDefault();const t=X(),n=k.snapDist;k={originX:t.originX-e.deltaX,originY:t.originY-e.deltaY,ppm:t.ppm,snapDist:n},C()}}function mn(e,t,n){return e>=n.x&&e<n.x+n.w&&t>=n.y&&t<n.y+n.h}function yn(e){if(e.button!==0||!X())return;s.focus({preventScroll:!0}),s.setPointerCapture(e.pointerId);const t=s.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(We&&d.legendPosition==="floating"&&mn(n,i,We)){xe=!0,Ae={x:n,y:i},Ct={...xt};return}if(He&&N!=="pan"){Se=!0,fe=!0,we={x:n,y:i},Qe={x:X().originX,y:X().originY},s.style.cursor="grabbing";return}if(N==="zoom"||N==="select"){Ce=!0,P=R={x:n,y:i};return}fe=!0,we={x:n,y:i},Qe={x:X().originX,y:X().originY},s.style.cursor="grabbing"}function bn(e){const t=s.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(Ce){R={x:n,y:i},Ot();return}if(xe){const h=n-Ae.x,m=i-Ae.y;h*h+m*m>16&&(xe=!1,Fe=!0,s.style.cursor="grabbing")}if(Fe){xt={x:Ct.x+(n-Ae.x),y:Ct.y+(i-Ae.y)},Ot();return}if(fe){const h=X(),m=k?.snapDist??Y?.snapDist??1;k={originX:Qe.x+(n-we.x),originY:Qe.y+(i-we.y),ppm:h.ppm,snapDist:m},Ot();return}const o=X();if(!o)return;const r=(n-o.originX)/o.ppm,p=(o.originY-i)/o.ppm,a=wn(r,p,o.snapDist)?.die??null,c=bt.find(h=>n>=h.x&&n<h.x+h.w&&i>=h.y&&i<h.y+h.h);if(an(c?c.bin:void 0),c){s.style.cursor="pointer",I&&(I.innerHTML=c.label??`Bin ${c.bin}`,I.style.display="block",An(I,s,e.clientX,e.clientY)),Ge?.(null,e);return}N==="pan"&&(s.style.cursor=a?"crosshair":"grab"),I&&(a?(I.innerHTML=gi(a,y.plotMode,{testDefs:ee,hbinDefs:G,sbinDefs:U,fallbackFormat:d.fallbackFormat,aggrMethod:y.aggrMethod,lotSize:y.lotSize,metadataFields:pe,activeTest:y.activeTest,reticleConfig:en}),I.style.display="block",An(I,s,e.clientX,e.clientY)):I.style.display="none"),Ge?.(a,e)}function vn(e){const t=s.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top,o=e.ctrlKey||e.metaKey;if(I&&(n<0||i<0||n>t.width||i>t.height)&&(I.style.display="none"),Ce){Ce=!1,R={x:n,y:i};const l=n-P.x,a=i-P.y,c=X();if(N==="zoom"){if(l*l+a*a<25)Ee(n,i,2);else if(c){const h=Math.min(P.x,R.x),m=Math.max(P.x,R.x),oe=Math.min(P.y,R.y),De=Math.max(P.y,R.y),J=m-h,re=De-oe;if(J>4&&re>4){const S=s.clientWidth,D=s.clientHeight,Wt=S/J,ot=D/re,$=Math.min(Wt,ot),st=hn(c.ppm*$),Ye=st/c.ppm,Ft=(h+m)/2,At=(oe+De)/2;k={originX:S/2-(Ft-c.originX)*Ye,originY:D/2-(At-c.originY)*Ye,ppm:st,snapDist:c.snapDist/Ye}}}C(),s.style.cursor="crosshair";return}if(l*l+a*a<25)Pt(n,i,o,e);else if(c){const h=(Math.min(P.x,R.x)-c.originX)/c.ppm,m=(Math.max(P.x,R.x)-c.originX)/c.ppm,oe=(c.originY-Math.max(P.y,R.y))/c.ppm,De=(c.originY-Math.min(P.y,R.y))/c.ppm,J=y.hoverPoints,re=[];for(let S=0;S<J.length;S++)if(J[S].x>=h&&J[S].x<=m&&J[S].y>=oe&&J[S].y<=De){const D=y.dies[S];D&&re.push(D)}if(o)for(const S of re){const D=Be(S);M.has(D)?M.delete(D):M.add(D)}else M=new Set(re.map(S=>Be(S)));ce?.(Rt())}C(),s.style.cursor="crosshair";return}if(xe){xe=!1,Pt(n,i,o,e);return}if(Fe){Fe=!1,s.style.cursor="grab";return}if(!fe)return;if(fe=!1,Se){Se=!1,s.style.cursor=He||N==="pan"?"grab":"crosshair";return}s.style.cursor=N==="pan"?"grab":"crosshair";const r=n-we.x,p=i-we.y;r*r+p*p<25&&Pt(n,i,o,e)}function Pt(e,t,n,i){for(const l of bt)if(e>=l.x&&e<l.x+l.w&&t>=l.y&&t<l.y+l.h){if(typeof l.bin=="number"){const a=d.highlightBin===l.bin?void 0:l.bin;E({highlightBin:a})}else{const a=d.highlightMetadataValue===l.bin?void 0:l.bin;E({highlightMetadataValue:a})}return}if(We&&mn(e,t,We))return;const o=X();if(!o)return;const p=wn((e-o.originX)/o.ppm,(o.originY-t)/o.ppm,o.snapDist)?.die??null;if(p){jn?.(p,i);const l=Be(p);n?M.has(l)?M.delete(l):M.add(l):M=new Set([l]),ce?.(Rt()),C()}else n||(M=new Set,ce?.([]),C())}function Rt(){const e=[],t=y.hoverPoints;for(let n=0;n<t.length;n++){const i=y.dies[n];i&&M.has(Be(i))&&e.push(i)}return e}function xn(){an(void 0),I&&ct(f),Ge?.(null,new MouseEvent("mouseleave")),s.style.cursor=N==="pan"?"grab":"crosshair"}function Cn(){fe=!1,Se=!1,Ce=!1,xe=!1,Fe=!1,I&&ct(f),Ge?.(null,new MouseEvent("mouseleave")),s.style.cursor=N==="pan"?"grab":"crosshair",C()}function wn(e,t,n){const i=y.hoverPoints,o=y.rectangles;for(let a=0;a<o.length;a++){const c=o[a];if(Math.abs(e-c.x)<=c.width/2&&Math.abs(t-c.y)<=c.height/2){const h=y.dies[a];return h?{die:h,index:a}:null}}let r=null,p=-1,l=n*n;for(let a=0;a<i.length;a++){const c=i[a].x-e,h=i[a].y-t,m=c*c+h*h;m<l&&(l=m,r=y.dies[a]??null,p=a)}return r?{die:r,index:p}:null}const Sn=new B.ResizeObserver(()=>{Y=null,k=null,C()});Sn.observe(s),v.height==null&&Xn<=0&&Yt(()=>Yt(()=>{O.clientHeight>0||console.warn("[wafermap] The map container has zero height, so the map cannot render. renderWaferMap fills its container \u2014 give the container a resolved height: an explicit CSS `height` (e.g. 600px), a height-resolved flex/grid parent, or `position:absolute; inset:0`. Alternatively pass `{ height: 600 }` in the render options and the library will size it for you.")}));let ze=B.matchMedia(`(resolution: ${B.devicePixelRatio}dppx)`);const nt=()=>{ze.removeEventListener("change",nt),ze=B.matchMedia(`(resolution: ${B.devicePixelRatio}dppx)`),ze.addEventListener("change",nt),C()};ze.addEventListener("change",nt);const Mn=B.matchMedia("(prefers-color-scheme: dark)"),En=()=>C();Mn.addEventListener("change",En);const Dn=()=>{I&&ct(f)};B.addEventListener("blur",Dn);function Bn(e){if(e.key==="Escape"&&M.size>0&&(M=new Set,ce?.([]),C()),(e.key==="e"||e.key==="E")&&Gt&&(e.stopPropagation(),($t??fn)()),(e.ctrlKey||e.metaKey)&&(e.key==="="||e.key==="+"?(e.preventDefault(),Ee(s.clientWidth/2,s.clientHeight/2,1.2)):e.key==="-"?(e.preventDefault(),Ee(s.clientWidth/2,s.clientHeight/2,1/1.2)):e.key==="0"&&(e.preventDefault(),it())),!e.ctrlKey&&!e.metaKey&&!e.shiftKey){const n=X();if(n){const i=k?.snapDist??Y?.snapDist??1;let o=0,r=0;e.key==="ArrowLeft"&&(o=20,e.preventDefault()),e.key==="ArrowRight"&&(o=-20,e.preventDefault()),e.key==="ArrowUp"&&(r=20,e.preventDefault()),e.key==="ArrowDown"&&(r=-20,e.preventDefault()),(o||r)&&(k={originX:n.originX+o,originY:n.originY+r,ppm:n.ppm,snapDist:i},C())}e.key===" "&&!He&&(e.preventDefault(),He=!0,N!=="pan"&&(s.style.cursor="grab"))}}function kn(e){e.key===" "&&(He=!1,Se&&(fe=!1,Se=!1),s.style.cursor=N==="pan"?"grab":"crosshair")}s.style.cursor="grab",s.setAttribute("tabindex","0"),s.addEventListener("wheel",gn,{passive:!1}),s.addEventListener("pointerdown",yn),s.addEventListener("pointermove",bn),s.addEventListener("pointerup",vn),s.addEventListener("pointerleave",xn),s.addEventListener("pointercancel",Cn);const Ln=()=>it();s.addEventListener("dblclick",Ln),s.addEventListener("keydown",Bn),s.addEventListener("keyup",kn);const Tn=e=>{e.stopPropagation()};s.addEventListener("click",Tn),s.clientWidth,C(),$e?.();function it(){Y=null,k=null,C()}function It(){import("./userGuideHtml.js").then(e=>Li({buildWaferMap:xi,renderWaferMap,renderWaferGallery:void 0,analyzeWaferMap:wi},e.USER_GUIDE_HTML,$n,O))}return Le(),{setResult(e){be=e,_=e.wafer,ve=e.dies,G=e.hbinDefs,U=e.sbinDefs,ee=e.testDefs,pe=e.metadataFields,Jt=e.reticles?.length?e.reticles:void 0,en=e.reticleConfig,tn=e.view?.dataAxisFlip,ht=e.isLotStack,gt=e.aggrMethod,mt=e.lotSize,ei(),wt(),C(),q&&ue()},setOptions(e){un(e)},getOptions(){return{...d}},resetZoom:it,setSelection(e){M=new Set(e.map(t=>Be(t))),C()},clearSelection(){M=new Set,ce?.([]),C()},setFindingsNotice(e){rn=e,q?ue():F&&Ve()},setStatsSummary(e){if(se=e,ut(),St(),q)ue();else if(F)Ve();else if(e&&!Oe?.placement){const t=Oe?.defaultOpen??!Te;F=Nt("right",de,f),F.style.display=t?"block":"none";const n=w.parentElement,i=w.nextSibling;ae=Xt(w,F,"right"),n?.insertBefore(ae,i),Ve()}tt()},setSummaryVisible(e){K&&(K.style.display=e?"flex":"none")},setViewControlsVisible(e){L&&(L.style.display=e?"flex":"none")},setExpandVisible(e){Q&&(Q.style.display=e?"flex":"none")},openUserGuide:It,setInsightsOpen(e){Ie(e),H&&(e?(H.dataset.active="1",H.style.background=x.bgActive,H.style.color=x.iconActive):(delete H.dataset.active,H.style.background="transparent",H.style.color=x.icon))},destroy(){he?.close(),pn?.()?.remove(),Mt&&f.removeEventListener("click",Mt,!0),s.removeEventListener("wheel",gn),s.removeEventListener("pointerdown",yn),s.removeEventListener("pointermove",bn),s.removeEventListener("pointerup",vn),s.removeEventListener("pointerleave",xn),s.removeEventListener("pointercancel",Cn),s.removeEventListener("dblclick",Ln),s.removeEventListener("keydown",Bn),s.removeEventListener("keyup",kn),s.removeEventListener("click",Tn),Sn.disconnect(),ze.removeEventListener("change",nt),Mn.removeEventListener("change",En),B.removeEventListener("blur",Dn),qn(),I&&ct(f),ne?.remove(),Me&&(Me.parentElement?.insertBefore(w,Me),Me.remove()),ae&&(ae.parentElement?.insertBefore(w,ae),ae.remove()),w.remove(),s.style.cursor="",z?.destroy(),V?.destroy(),ke.remove()}}}
@@ -90,19 +90,19 @@ export declare function buildYieldSection(yieldSummary: YieldSummary, dataCovera
90
90
  }, passBins?: number[]): HTMLDivElement;
91
91
  export declare function buildBinSection(dies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft',
92
92
  /**
93
- * The map's resolved colours for this bin type (`View.binColors.hard`/`.soft`),
94
- * so bars match die fills. Omitted ⇒ resolved here from `dies` with the
95
- * default palette — never a second colour rule.
93
+ * The map's resolved bin colours (`View.binColors`) — colours AND pass
94
+ * verdicts, so bars match die fills and pass rows sit where the map's legend
95
+ * puts them. Omitted ⇒ resolved here from `dies` — never a second rule.
96
96
  */
97
- binColors?: ReadonlyMap<number, string>,
97
+ binColors?: BinColors,
98
98
  /**
99
99
  * Precomputed counts (e.g. `StatsSummary.stats.hardBinCounts`/`.softBinCounts`,
100
100
  * already scoped to the yield-eligible population) — used directly instead
101
101
  * of re-walking `dies` when supplied.
102
102
  */
103
103
  precomputedCounts?: Record<number, number>,
104
- /** Pass bins, pinned to the top of the pareto ordering. See `binRows`. */
105
- passBins?: number[]): HTMLDivElement | null;
104
+ /** Used only to resolve colours and verdicts when `binColors` is omitted. */
105
+ passBins?: readonly number[]): HTMLDivElement | null;
106
106
  /**
107
107
  * The panels' bin section: identical bars to `buildBinSection`, wrapped in a
108
108
  * collapsible shell with a Hard/Soft selector.
@@ -134,7 +134,7 @@ export declare function buildBinBreakdownSection(params: {
134
134
  * precomputed bin counts exist (`hardBinCounts`/`softBinCounts` are
135
135
  * per-wafer only), so this scans the pooled `Die[]` directly, same as
136
136
  * `buildBinSection` does when it has no `precomputedCounts`. */
137
- export declare function buildLotBinSection(allDies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft', binColors?: ReadonlyMap<number, string>): HTMLDivElement | null;
137
+ export declare function buildLotBinSection(allDies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft', binColors?: BinColors): HTMLDivElement | null;
138
138
  /**
139
139
  * Region yield as ONE section with a Ring/Quadrant selector, replacing the two
140
140
  * always-on stacked sections (`Ring Yield` + `Quadrant Yield`) this used to render.
@@ -155,7 +155,8 @@ export declare function buildRegionYieldPanelSection(params: {
155
155
  diesByWafer: Die[][];
156
156
  allWafers: Wafer[];
157
157
  ringCount: number;
158
- passBins: number[];
158
+ /** One set for every wafer, or a lookup by index into `allWafers` — see `buildRegionYieldData`. */
159
+ passBins: readonly number[] | ((waferIndex: number) => readonly number[]);
159
160
  panel?: HTMLElement;
160
161
  }): HTMLDivElement | null;
161
162
  /** Lot overview — wafer count and mean (unweighted arithmetic mean of each
@@ -463,10 +464,12 @@ export declare function renderWaferSummaryContent(panel: HTMLDivElement, params:
463
464
  /** Render lot-level content into the panel. Clears existing content. */
464
465
  export declare function renderLotSummaryContent(panel: HTMLDivElement, params: {
465
466
  lotSummary: LotStatsSummary;
467
+ /** `passBins` on an item is that wafer's own (`WaferMapResult.passBins`) and wins over the top-level fallback. */
466
468
  items: Array<{
467
469
  label?: string;
468
470
  wafer?: Wafer;
469
471
  dies?: Die[];
472
+ passBins?: readonly number[];
470
473
  statsSummary?: StatsSummary;
471
474
  metadataFields?: MetadataFieldDef[];
472
475
  } | null>;