@wafertools/wafermap 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -22,6 +22,62 @@ under `### Breaking`.
22
22
 
23
23
  ---
24
24
 
25
+ ## [0.29.0] — 2026-09-12
26
+
27
+ ### Breaking
28
+
29
+ - **The default value gradient is now Viridis, and every perceptual gradient reads low = dark,
30
+ high = light.** The blue–cyan–yellow–red "thermal" ramp is removed. Like every rainbow ramp its
31
+ lightness is not monotonic — cyan and yellow both sit near peak while blue and red are much
32
+ darker — so two different readings land at the same apparent intensity, and the fast hue turns
33
+ at cyan and yellow draw contour lines that are not in the data. On a smooth parametric map that
34
+ shows up as a bright ring around the wafer centre that no process step put there. Users reported
35
+ exactly this: being unable to judge the difference between two colours that look equally
36
+ "intense". `'jet'` keeps the rainbow family available for anyone who wants it, already labelled
37
+ as such.
38
+ - **`viridis`, `cividis`, `plasma`, `inferno` and `greyscale` were registered reversed, and are
39
+ no longer.** Each was `forValue: t => ramp(1 - t)`, putting the *bright* end of the ramp at the
40
+ *low* end of the data, while `default`, `traffic` and `jet` ran the other way. Switching gradient
41
+ therefore inverted the map. On a stacked map the effect was backwards from what the mode is for:
42
+ the healthy bulk of the wafer (fail count 0) rendered as a glowing yellow field and the edge
43
+ ring, scratch or cluster you were looking for became dark specks on it. All five now match their
44
+ matplotlib/seaborn definitions. `tests/colorSchemes.test.mjs` measures L\* across every
45
+ perceptual built-in and fails if a reversal reappears.
46
+
47
+ This also corrects the record on the change that made thermal the default in the first place
48
+ (0.14.x, "the reversed-Viridis ramp rendered high values dark purple and low values yellow — not
49
+ intuitive"). The diagnosis was right and the remedy was aimed at the wrong thing: the defect was
50
+ the `1 - t`, not Viridis, and the `1 - t` survived the change that was meant to fix it.
51
+ - **The standalone `'viridis'` gradient name is gone** — Viridis *is* `'default'`, labelled
52
+ **Default (Viridis)**. Two menu rows drawing identical maps is the same defect that removed the
53
+ old standalone "Thermal" row. `getValueColorScheme('viridis')` falls back to `'default'`, so a
54
+ persisted `'viridis'` preference still renders Viridis; it no longer appears in
55
+ `listValueColorSchemes()`.
56
+ - **`View.reverseValueScheme` is a new required field on `View`.** Code that builds a `View`
57
+ literal must supply it; code that reads one is unaffected.
58
+
59
+ ### Added
60
+
61
+ - **`reverseValueScheme` (`ViewOptions`, `WaferPreferences`) — flips whichever gradient is
62
+ selected**, offered in the Colour scheme menu as **Reverse gradient**. One flag rather than a
63
+ reversed twin of every ramp: it doubles no menu, and a gradient a host registered itself gets
64
+ the behaviour for free. It is also what makes the direction rule above exception-free —
65
+ greyscale ships low = dark like everything else, and the print habit of "more ink means more" is
66
+ one tick box rather than a documented special case.
67
+ - **`resolveValueColorFn(name, reversed)` (`renderer`) — the single read-path for a value
68
+ gradient.** Die fills, the colorbar and the mapless summary's histogram bars each looked the
69
+ gradient up independently; a flag applied at some of them and not others would show one reading
70
+ in two different colours on one screen, with the colorbar — the thing the map is read against —
71
+ the likeliest to be missed. All three now resolve through this. Any host colouring by value
72
+ should too, passing `View.valueColorScheme` and `View.reverseValueScheme` together.
73
+ - **`'mako'` value gradient** (seaborn), sampled at nine even stops from
74
+ `sns.color_palette('mako', as_cmap=True)`. The closest thing to Viridis in lightness span, with
75
+ more separation at the top end. Its sibling `crest` was measured alongside it and deliberately
76
+ not added: at L\* ~31 → ~78 against Viridis's ~10 → ~93 it has too little span for a dense die
77
+ grid — on a stacked map a scratch all but disappeared into the surrounding green. Seaborn pitches
78
+ crest at line plots, where mako's dark end gets lost; that is a different job from colouring
79
+ thousands of adjacent dies.
80
+
25
81
  ## [0.28.0] — 2026-09-11
26
82
 
27
83
  ### Breaking
@@ -11,6 +11,9 @@ export interface MaplessSummaryOptions {
11
11
  binColors?: BinColors;
12
12
  /** The map's value gradient name, so histogram bars match its colorbar. */
13
13
  valueColorScheme?: string;
14
+ /** The map's `View.reverseValueScheme` — must travel with the name, or the
15
+ * bars read opposite to the colorbar they are meant to match. */
16
+ reverseValueScheme?: boolean;
14
17
  /** Effective log-scale setting for the active test — same resolution the
15
18
  * map itself uses (explicit viewOpts.logScale, falling back to the
16
19
  * TestDef's own default). */
@@ -1 +1 @@
1
- import{getDieTestValue as y}from"../renderer/buildWaferMap.js";import{resolveTestNumber as $,findTestDef as T}from"../renderer/buildView.js";import{buildBinSection as B}from"./summaryPanel.js";import{buildTestHistogramData as z}from"../stats/histogram.js";import{getValueColorScheme as N}from"../renderer/colorSchemes.js";import{TRACKING as V,SPACE as R,RADIUS as F,FONT as M,CLR as h,wireTooltip as I}from"./toolbar.js";import{fmt as v}from"../renderer/fmt.js";function d(o,n,t){const e=document.createElement(o);return n&&Object.assign(e.style,n),t!==void 0&&(e.textContent=t),e}function A(o,n,t,e,x){let p=1/0,m=-1/0;for(const s of o){const l=y(s,n);l!==void 0&&(l<p&&(p=l),l>m&&(m=l))}const c=e==="spec"&&t&&(t.limitLow!==void 0||t.limitHigh!==void 0);let a,r;c?(a=t.limitLow!==void 0?t.limitLow:isFinite(p)?p:0,r=t.limitHigh!==void 0?t.limitHigh:isFinite(m)?m:1):(a=isFinite(p)?p:0,r=isFinite(m)?m:1),a===r&&(r=a+1);const b=s=>Math.min(1,Math.max(0,s));if(x&&a>0&&r>0){const s=Math.log10(a),l=Math.log10(r)-s;return f=>f<=0?0:b((Math.log10(f)-s)/l)}return s=>b((s-a)/(r-a))}function W(o,n,t,e,x,p,m){const c=d("div",{display:"flex",flexDirection:"column",gap:R.xxs,minWidth:"0",flex:"1",minHeight:"0"});c.appendChild(d("div",{fontSize:M.meta,fontWeight:"700",letterSpacing:V,textTransform:"uppercase",color:h.label},n?.name?`${n.name} distribution`:"Value distribution"));const a=o[0].rangeLow,r=o[o.length-1].rangeHigh,b=r-a||1,s=i=>Math.min(1,Math.max(0,(i-a)/b)),l=N(e),f=A(x,t,n,p,m),g=Math.max(1,...o.map(i=>i.count)),S=d("div",{position:"relative",display:"flex",alignItems:"flex-end",gap:R.xxs,flex:"1",minHeight:"48px"});for(const i of o){const u=d("div",{flex:"1",minWidth:"2px",background:l.forValue(f((i.rangeLow+i.rangeHigh)/2)),height:`${i.count/g*100}%`,borderRadius:"1px 1px 0 0"});u.dataset.wmapBar="1",I(u,`${v(i.rangeLow,n?.unit)} \u2013 ${v(i.rangeHigh,n?.unit)}: ${i.count}`,{asDataPoint:!0}),S.appendChild(u)}const L=[];for(const[i,u]of[[n?.limitLow,"LSL"],[n?.limitHigh,"USL"]]){if(i===void 0||i<a||i>r)continue;const w=s(i)*100,C=d("div",{position:"absolute",top:"0",bottom:"0",left:`${w}%`,width:"2px",marginLeft:"-1px",background:h.value,boxShadow:`0 0 0 1px ${h.panelBg}`,pointerEvents:"none"});C.dataset.wmapLimitMarker="1",S.appendChild(C),L.push({pct:w,text:`${u} ${v(i,n?.unit)}`})}if(c.appendChild(S),L.length){const i=d("div",{position:"relative",height:"14px"});for(const{pct:u,text:w}of L){const C=Math.min(96,Math.max(4,u));i.appendChild(d("span",{position:"absolute",left:`${C}%`,top:"0",transform:"translateX(-50%)",whiteSpace:"nowrap",fontSize:M.body,fontWeight:"600",color:h.text,background:h.panelBg,border:`1px solid ${h.value}`,borderRadius:F.control,padding:"0 3px",lineHeight:"12px"},w))}c.appendChild(i)}const H=d("div",{display:"flex",justifyContent:"space-between",fontSize:M.body,color:h.label});return H.appendChild(d("span",{},v(o[0].rangeLow,n?.unit))),H.appendChild(d("span",{},v(o[o.length-1].rangeHigh,n?.unit))),c.appendChild(H),c}export function buildMaplessSummary(o,n,t){const{plotMode:e,activeTest:x,hbinDefs:p,sbinDefs:m,binColors:c,valueColorScheme:a,logScale:r=!1,colorbarRangeMode:b="spec",valueRangeDies:s}=t;if(e==="hardBin"||e==="softBin"){const l=e==="hardBin"?p:m,f=e==="hardBin"?c?.hard:c?.soft,g=B(o,l,e==="hardBin"?"hard":"soft",f);if(g)return g}else if(e==="value"){const{testNumber:l}=$(x??0,n),f=T(n,x??0),g=z([{dies:o}],l,12,f?.limitLow,f?.limitHigh);if(g.length)return W(g,f,l,a,s??o,b,r)}return d("div",{padding:R.xl,fontSize:M.body,color:h.label,textAlign:"center"},"No summary available for this view.")}
1
+ import{getDieTestValue as $}from"../renderer/buildWaferMap.js";import{resolveTestNumber as T,findTestDef as B}from"../renderer/buildView.js";import{buildBinSection as V}from"./summaryPanel.js";import{buildTestHistogramData as z}from"../stats/histogram.js";import{resolveValueColorFn as F}from"../renderer/colorSchemes.js";import{TRACKING as N,SPACE as y,RADIUS as I,FONT as S,CLR as f,wireTooltip as A}from"./toolbar.js";import{fmt as w}from"../renderer/fmt.js";function d(o,n,e){const a=document.createElement(o);return n&&Object.assign(a.style,n),e!==void 0&&(a.textContent=e),a}function W(o,n,e,a,b){let p=1/0,m=-1/0;for(const r of o){const s=$(r,n);s!==void 0&&(s<p&&(p=s),s>m&&(m=s))}const v=a==="spec"&&e&&(e.limitLow!==void 0||e.limitHigh!==void 0);let t,l;v?(t=e.limitLow!==void 0?e.limitLow:isFinite(p)?p:0,l=e.limitHigh!==void 0?e.limitHigh:isFinite(m)?m:1):(t=isFinite(p)?p:0,l=isFinite(m)?m:1),t===l&&(l=t+1);const h=r=>Math.min(1,Math.max(0,r));if(b&&t>0&&l>0){const r=Math.log10(t),s=Math.log10(l)-r;return c=>c<=0?0:h((Math.log10(c)-r)/s)}return r=>h((r-t)/(l-t))}function E(o,n,e,a,b,p,m,v){const t=d("div",{display:"flex",flexDirection:"column",gap:y.xxs,minWidth:"0",flex:"1",minHeight:"0"});t.appendChild(d("div",{fontSize:S.meta,fontWeight:"700",letterSpacing:N,textTransform:"uppercase",color:f.label},n?.name?`${n.name} distribution`:"Value distribution"));const l=o[0].rangeLow,h=o[o.length-1].rangeHigh,r=h-l||1,s=i=>Math.min(1,Math.max(0,(i-l)/r)),c=F(a,b),u=W(p,e,n,m,v),g=Math.max(1,...o.map(i=>i.count)),L=d("div",{position:"relative",display:"flex",alignItems:"flex-end",gap:y.xxs,flex:"1",minHeight:"48px"});for(const i of o){const x=d("div",{flex:"1",minWidth:"2px",background:c(u((i.rangeLow+i.rangeHigh)/2)),height:`${i.count/g*100}%`,borderRadius:"1px 1px 0 0"});x.dataset.wmapBar="1",A(x,`${w(i.rangeLow,n?.unit)} \u2013 ${w(i.rangeHigh,n?.unit)}: ${i.count}`,{asDataPoint:!0}),L.appendChild(x)}const H=[];for(const[i,x]of[[n?.limitLow,"LSL"],[n?.limitHigh,"USL"]]){if(i===void 0||i<l||i>h)continue;const C=s(i)*100,M=d("div",{position:"absolute",top:"0",bottom:"0",left:`${C}%`,width:"2px",marginLeft:"-1px",background:f.value,boxShadow:`0 0 0 1px ${f.panelBg}`,pointerEvents:"none"});M.dataset.wmapLimitMarker="1",L.appendChild(M),H.push({pct:C,text:`${x} ${w(i,n?.unit)}`})}if(t.appendChild(L),H.length){const i=d("div",{position:"relative",height:"14px"});for(const{pct:x,text:C}of H){const M=Math.min(96,Math.max(4,x));i.appendChild(d("span",{position:"absolute",left:`${M}%`,top:"0",transform:"translateX(-50%)",whiteSpace:"nowrap",fontSize:S.body,fontWeight:"600",color:f.text,background:f.panelBg,border:`1px solid ${f.value}`,borderRadius:I.control,padding:"0 3px",lineHeight:"12px"},C))}t.appendChild(i)}const R=d("div",{display:"flex",justifyContent:"space-between",fontSize:S.body,color:f.label});return R.appendChild(d("span",{},w(o[0].rangeLow,n?.unit))),R.appendChild(d("span",{},w(o[o.length-1].rangeHigh,n?.unit))),t.appendChild(R),t}export function buildMaplessSummary(o,n,e){const{plotMode:a,activeTest:b,hbinDefs:p,sbinDefs:m,binColors:v,valueColorScheme:t,reverseValueScheme:l,logScale:h=!1,colorbarRangeMode:r="spec",valueRangeDies:s}=e;if(a==="hardBin"||a==="softBin"){const c=a==="hardBin"?p:m,u=a==="hardBin"?v?.hard:v?.soft,g=V(o,c,a==="hardBin"?"hard":"soft",u);if(g)return g}else if(a==="value"){const{testNumber:c}=T(b??0,n),u=B(n,b??0),g=z([{dies:o}],c,12,u?.limitLow,u?.limitHigh);if(g.length)return E(g,u,c,t,l,s??o,r,h)}return d("div",{padding:y.xl,fontSize:S.body,color:f.label,textAlign:"center"},"No summary available for this view.")}
@@ -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.
@@ -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 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 Vn,SPACE as W,EDGE_GUTTER as Li,RADIUS as zn,FONT as ft,CLR as x,applyOverlayZ as Ti,getTooltip as Yn,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 Vi,makeOrientationBtn as zi,menuLayerFor as Xn,saveImageBlob as Yi,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","reverseValueScheme","useDefinedBinColors","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","ringCount","legendPosition","logScale","colorbarRangeMode","markFailingDies"]);export const COLOR_KEYS=["binColorScheme","valueColorScheme","reverseValueScheme","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,c.activeTest??0),s=jt(o)?c.logScale??o?.logScale??!1:!1;return so(e,y.testDefs,{plotMode:c.plotMode??"hardBin",activeTest:c.activeTest,hbinDefs:G,sbinDefs:U,binColors:m.binColors,valueColorScheme:c.valueColorScheme,reverseValueScheme:c.reverseValueScheme,logScale:s,colorbarRangeMode:c.colorbarRangeMode,valueRangeDies:y.dies})},i=function(o){const s=g.createElement("button");return s.type="button",Vn(s),Object.assign(s.style,{fontSize:ft.body,padding:`${W.xxs} ${W.sm}`,borderRadius:zn.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}),Vn(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,f=>{if(d.textContent=f?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(f)),f){r=g.createElement("div");const p=o.getBoundingClientRect().height||28;Object.assign(r.style,{position:"absolute",left:"0",right:"0",bottom:`${p}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,V=null,J=null;Zt&&(Z=no(Ut($.metadata??{},Re())??"",$.metadata,{lotStack:Re(),ownerDocument:g}),S.appendChild(Z.metaPanel),Z.isEmpty()||(V=dn(Z.wrap),_.insertBefore(V,_.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=V?.isConnected??!1,t=!Z.isEmpty();!t&&e?(V.remove(),V=null):t&&!e&&(V=dn(Z.wrap),V.style.display=Ct?"none":"",_.insertBefore(V,_.firstChild),ve())}const li=[...G??[],...U??[]].some(e=>e.color);let c={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},z=null,ie=!1,cn=null;function ai(){return Oe?z?Promise.resolve(z):(cn??=import("./insightsTab.js").then(({createInsightsTab:e})=>(z=e({getItems:()=>[{wafer:$,dies:te,hbinDefs:G,sbinDefs:U,testDefs:ne,label:String($.metadata?.waferId??""),statsSummary:re}],getBinColors:()=>m.binColors,passBins:Ze,getRingCount:()=>c.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(z.el.style,{position:"absolute",inset:"0",background:x.canvasBg,overflowY:"auto",paddingTop:"0"}),z.el.style.display="none",le.appendChild(z.el),z)),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,z&&!e&&t&&(fn=z.el.scrollTop),z&&(z.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"),V&&(V.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,Y=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 Ve(){const e=c;m=vi($,te.filter(io),{plotMode:e.plotMode,binColorScheme:e.binColorScheme,valueColorScheme:e.valueColorScheme,reverseValueScheme:e.reverseValueScheme,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())}Ve();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:c.ringCount??4,binColors:m.binColors,plotMode:c.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 ze(){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),ze()}const w=Zn?Yn(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 p=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:zn.control,boxShadow:ki.panel,pointerEvents:"auto"});const e=Yn(g),t=Pi(e),{makeBtn:n,setActive:i,makeSep:o,makeMenuRow:s,makeMenuSection:d,closeOpenMenu:r,getOpenMenu:l,setOpenMenu:f}=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)",()=>p("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)",()=>p("pan"));if(F.appendChild(M),et=n("boxSelect","Select (drag to select dies)",()=>p("select")),F.appendChild(et),i(M,!0),gt!=="view-only"){let B=function(u){return u.plotMode!==(c.plotMode??"hardBin")?!1:u.plotMode==="value"?(c.activeTest??0)===(u.activeTest??0):u.plotMode==="metadata"?c.activeMetadataKey===u.activeMetadataKey:!0},Vt=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(),f(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(),f(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,Vt,{makeMenuRow:s,makeMenuSection:d},c.plotMode??"hardBin",q.ownerDocument.defaultView??window,Xt);Xn(q).appendChild(je),f(je),_e(q,!0),Nn(je,q,lt)});_e(q,!1);const{btn:at,sync:Xe}=Hi(t,()=>({...c,plotMode:c.plotMode??"hardBin"}),()=>li,D);Tt=Xe,Tt();const zt=Vi(t,()=>{const u=!!m.hasReticle,b=(c.plotMode??"hardBin")==="value",{testNumber:dt}=Nt(c.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(c,u,{functionalActive:Ne,hasLimits:Xt,hasRecorded:je,binMode:(c.plotMode??"hardBin")==="hardBin"||(c.plotMode??"hardBin")==="softBin"},Ke=>D(Ke))},()=>Ki(c)),{btn:Yt,sync:gi}=Ai(t,()=>c,u=>D({legendPosition:u}));Lt=gi,Lt();const Hn=()=>{const{testNumber:u}=Nt(c.activeTest??0,ne),b=ct(ne,u);return b!==void 0&&!jt(b)},{btn:hi,sync:mi}=Fi(t,()=>({...c,functionalActive:Hn()}),u=>D(u));Ot=mi,Ot();const yi=()=>{const{testNumber:u}=Nt(c.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=c.colorbarRangeMode==="data"?"spec":"data";D({colorbarRangeMode:u})});Pt=()=>{const u=c.plotMode==="value"&&yi()&&Ni(c)==="off"&&!Hn();rt.style.display=u?"":"none";const b=(c.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=zi(t,()=>c,u=>D(u));Qn&&T.appendChild(q),T.appendChild(at),T.appendChild(hi),T.appendChild(rt),$e||(T.appendChild(o()),T.appendChild(zt),T.appendChild(o()),T.appendChild(Yt),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),f(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=c.plotMode;c={...c,...e},e.plotMode!==void 0&&e.plotMode,Object.keys(e).every(s=>s==="legendPosition"||s==="showLegend"||s==="markFailingDies")||Ve(),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(),ze()),(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?.(c,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=c.legendPosition??"default",d=c.showLegend??!0,r=s==="default"||s==="compact",l=(ae.colorbarWidth??16)+28,f=o&&r?s!=="default"?Math.max(Fn,l):i<Mi?0:i<Si?Math.max(wi,l):Math.max(Fn,l):void 0,p=Ci(a,m,{...ae,topClearance:0,minRightReserve:d?f:0,showColorbar:d&&(ae.showColorbar??!0),markFailingDies:c.markFailingDies??!1,legendPosition:s,legendOffset:Et,diePitchMm:n,fallbackFormat:Pe,showAxes:ae.showAxes??k!==null,viewport:e,activeBin:c.plotMode==="metadata"?c.highlightMetadataValue:c.highlightBin,hoverBin:Mt,hbinDefs:G,sbinDefs:U,metadataFields:ce});St=p.binLegendRows,We=p.legendBox??null,k===null&&(Y=p.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,f=[];for(const p of E){const h=pn.get(p);h!==void 0&&f.push({sx:e.originX+n[h].x*e.ppm,sy:e.originY-n[h].y*e.ppm})}if(f.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:p,sy:h}of f)t.rect(p-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:p,sy:h}of f)t.rect(p-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:p,sy:h}of f)t.rect(p-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&&Yi(e,C.downloadFilename??"wafermap",C.onSaveImage)})}function vn(e){return Y?Math.max(Y.ppm*qn,Math.min(Y.ppm*Jn,e)):e}function Ee(e,t,n){const i=k??Y;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=(Y?.snapDist??1)/(o/(Y?.ppm??o));k={originX:d,originY:r,ppm:o,snapDist:l},v()}function j(){return k??Y}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&&c.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 p=n-Fe.x,h=i-Fe.y;p*p+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 p=j(),h=k?.snapDist??Y?.snapDist??1;k={originX:qe.x+(n-we.x),originY:qe.y+(i-we.y),ppm:p.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,f=St.find(p=>n>=p.x&&n<p.x+p.w&&i>=p.y&&i<p.y+p.h);if(un(f?f.bin:void 0),f){a.style.cursor="pointer",w&&(w.innerHTML=f.label??`Bin ${f.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 p=Qt(l);p===null?w.style.display="none":(typeof p=="string"?w.innerHTML=p:(w.innerHTML="",w.appendChild(p)),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,f=j();if(X==="zoom"){if(r*r+l*l<25)Ee(n,i,2);else if(f){const p=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-p,ue=De-Q;if(ee>4&&ue>4){const M=a.clientWidth,B=a.clientHeight,Vt=M/ee,lt=B/ue,q=Math.min(Vt,lt),at=vn(f.ppm*q),Xe=at/f.ppm,zt=(p+h)/2,Yt=(Q+De)/2;k={originX:M/2-(zt-f.originX)*Xe,originY:B/2-(Yt-f.originY)*Xe,ppm:at,snapDist:f.snapDist/Xe}}}v(),a.style.cursor="crosshair";return}if(r*r+l*l<25)Ht(n,i,o,e);else if(f){const p=(Math.min(O.x,P.x)-f.originX)/f.ppm,h=(Math.max(O.x,P.x)-f.originX)/f.ppm,Q=(f.originY-Math.max(O.y,P.y))/f.ppm,De=(f.originY-Math.min(O.y,P.y))/f.ppm,ee=m.hoverPoints,ue=[];for(let M=0;M<ee.length;M++)if(ee[M].x>=p&&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=c.highlightBin===r.bin?void 0:r.bin;D({highlightBin:l})}else{const l=c.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 f=o[l];if(Math.abs(e-f.x)<=f.width/2&&Math.abs(t-f.y)<=f.height/2){const p=m.dies[l];return p?{die:p,index:l}:null}}let s=null,d=-1,r=n*n;for(let l=0;l<i.length;l++){const f=i[l].x-e,p=i[l].y-t,h=f*f+p*p;h<r&&(r=h,s=m.dies[l]??null,d=l)}return s?{die:s,index:d}:null}const kn=new H.ResizeObserver(()=>{Y=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 Ye=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`);const ot=()=>{Ye.removeEventListener("change",ot),Ye=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`),Ye.addEventListener("change",ot),v()};Ye.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??Y?.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(){Y=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,Ve(),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(),Ve(),v(),N&&pe()},setOptions(e){bn(e)},getOptions(){return{...c}},resetZoom:st,setSelection(e){E=new Set(e.map(t=>Be(t))),v()},clearSelection(){E=new Set,he?.([]),v()},setFallbackFormat(e){Pe=e,Ve(),v()},setFindingsNotice(e){gn=e,N?pe():R&&ze()},setStatsSummary(e){if(re=e,mt(),Bt(),N)pe();else if(R)ze();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),ze()}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,V&&(V.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=c.plotMode;if(e==="metadata"){const s=c.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,f)=>{const p=d?.values?.find(Q=>Q.value===l),h=p?.color??eo(f);return{bin:l,name:p?.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(),Ye.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="",z?.destroy(),Z?.destroy(),ke.remove()}}}
@@ -1 +1 @@
1
- import{fontPx as Ct}from"./toolbar.js";import{findTestDef as Re,buildMapTitle as Ce}from"../renderer/buildView.js";import{affineInvert as ze,affineVector as _e}from"../core/transforms.js";import{compareNatural as Je}from"../core/utils.js";import{getValueColorScheme as Ze}from"../renderer/colorSchemes.js";import{NO_DATA_FILL as je}from"../renderer/colorMap.js";import{SPEC_PASS_FILL as Be,SPEC_FAIL_LOW as Qe,SPEC_FAIL_HIGH as Pe,contrastTextColor as We}from"../renderer/colorMap.js";import{fmt as De,fmtColorbarAxis as ve}from"../renderer/fmt.js";import{resolveCanvasTheme as to}from"./canvasTheme.js";import{hitGridDims as eo}from"./hitGrid.js";function Oe(m,e,F,M,h){m.moveTo(e,F+h*M),m.lineTo(e-M*.9,F-h*M*.6),m.lineTo(e+M*.9,F-h*M*.6),m.closePath()}const oo=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),no=new Set(["hardBin","softBin","metadata"]),Z=()=>`${Ct(-2)}px system-ui, sans-serif`,Ie=3,Gt=2,so=6,lo=20,io=()=>`600 ${Ct()}px system-ui, sans-serif`,Vt=()=>`${Ct(-1)}px system-ui, sans-serif`,ao=()=>`600 ${Ct(-1)}px system-ui, sans-serif`,Ut=128,co=()=>`${Ct(-2)}px system-ui, sans-serif`,Fe=4,D=17,Y=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const Kt=28,mt=5,ut=8,ro=15;export function toCanvas(m,e,F={}){const M=to(m.parentElement??m),{padding:h=16,showColorbar:H=!0,markFailingDies:X=!1,colorbarWidth:P=16,background:pt=M.background,legendPosition:j="default",legendOffset:xt,showAxes:Mt=!1,diePitchMm:V,viewport:q,activeBin:N,hoverBin:z,fallbackFormat:St,topClearance:Q=0,minRightReserve:ct,hbinDefs:yt,sbinDefs:st,metadataFields:bt,showTitle:rt=!0}=F,O=Math.floor(m.clientWidth||m.width),E=Math.floor(m.clientHeight||m.height),Lt=O>=BIN_LEGEND_MIN_CANVAS_W&&E>=BIN_LEGEND_MIN_CANVAS_H,kt=H&&Lt&&oo.has(e.plotMode)&&e.passFailDisplay==="off",ft=H&&Lt&&no.has(e.plotMode),tt=H&&Lt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),ht=ft||tt,_t=ft&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[c])=>o-c):[],Bt=ft&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Je)].map(o=>[o,e.metadataCounts.get(o)??0]):[],et=[];if(tt&&e.passFailDisplay==="test"){const o=e.passFailCounts;et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),et.push({key:-2,color:Pe,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(tt){const o=e.specCounts,c=Re(e.testDefs,e.activeTest);et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),c?.limitHigh!==void 0&&et.push({key:-2,color:Pe,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),c?.limitLow!==void 0&&et.push({key:-3,color:Qe,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const S=tt?et.length:e.plotMode==="metadata"?Bt.length:_t.length,L=(m.ownerDocument.defaultView??window).devicePixelRatio??1;if(O<=0||E<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const $=j!=="default"?j:O<BIN_LEGEND_ADAPT_FLOATING?"floating":O<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",re=$==="default"||$==="compact",fe=$==="left",zt=$==="bottom",Pt=$==="top",Wt=$==="floating",Dt=$==="compact"||$==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,he=Math.floor((E-2*h)/D),de=S>he?he-1:S,ge=ht&&zt?de*D:0,Jt=ht&&Pt?de*D:0,Zt=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",jt=Re(e.testDefs,e.activeTest),Ne=Zt?"Count":jt?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),Ee=Zt?void 0:jt?.unit,[Ot,It]=e.valueRange,{tickFmt:we}=ve(It,Ne,Ee,St),Ft=e.allIntegerValues?o=>String(Math.round(o)):we;let Qt=0;if(kt){const o=m.getContext("2d");o.font=Z();const c=[Ft(Ot),Ft(It)];Ot<0&&c.push(Ft(-Math.max(Math.abs(Ot),Math.abs(It))));for(const s of c)Qt=Math.max(Qt,o.measureText(s).width)}const me=Math.max(lo,Math.ceil(Qt)+Ie+Gt+so-h),vt=kt?P+me+8:ht&&re?Dt:0,te=ht&&fe?Dt:0,ee=Mt?32:0,Nt=Mt?36:0,Ye=ct!=null?Math.max(vt,ct):vt,He=O-2*h-Ye-Nt-te,ue=E-2*h-ee-ge-Jt;m.width=Math.round(O*L),m.height=Math.round(E*L);const t=m.getContext("2d");t.scale(L,L),t.fillStyle=pt,t.fillRect(0,0,O,E);const G=e.hoverPoints;if(!G.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Et=e.rectangles[0],oe=Et?Et.width/2:0,ne=Et?Et.height/2:0,wt=e.dieBounds,pe=(wt?.minX??0)-oe,Xe=(wt?.maxX??0)+oe,$e=(wt?.minY??0)-ne,xe=(wt?.maxY??0)+ne,Me=Xe-pe,ye=xe-$e;let ot,nt,k;if(q)({originX:ot,originY:nt,ppm:k}=q);else{const c=e.notchDir,s=c&&c.y>.1?13:0,a=c&&c.y<-.1?13:0,r=c&&c.x<-.1?13:0,f=c&&c.x>.1?13:0,d=He-r-f,i=ue-Q-s-a;k=Math.min(d/Me,i/ye),ot=h+Nt+te+r+(d-Me*k)/2-pe*k,nt=h+Q+Jt+s+(i-ye*k)/2+xe*k}const Yt=q?.snapDist??Math.max(oe,ne,1)*1.5,Ht=ot+e.waferCenter.x*k,Ge=nt-e.waferCenter.y*k,se=e.waferRadius*k,lt=o=>{const c=Math.abs(o-Ge);return c>=se?0:Math.sqrt(se*se-c*c)},it=(o,c,s,a,r,f,d=io(),i=M.text)=>{if(!o)return;t.save(),t.fillStyle=i,t.font=d,t.textAlign=a,t.textBaseline=r;const p=a==="right"?c-f:f-c;let l=o;if(p>8&&t.measureText(l).width>p){for(;l.length>1&&t.measureText(l+"\u2026").width>p;)l=l.slice(0,-1);l=l+"\u2026"}p>8&&t.fillText(l,c,s),t.restore()};if(t.save(),t.setTransform(k*L,0,0,-k*L,ot*L,nt*L),e.rectangles.length>0){const o=new Map;for(const s of e.rectangles){const a=String(s.fill);let r=o.get(a);r||(r=[],o.set(a,r)),r.push(s)}for(const[s,a]of o){t.beginPath();for(const r of a)t.rect(r.x-r.width/2,r.y-r.height/2,r.width,r.height);t.fillStyle=s,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(k*L),t.beginPath();for(const s of e.rectangles)t.rect(s.x-s.width/2,s.y-s.height/2,s.width,s.height);if(t.stroke(),X){const s=e.rectangles.filter(a=>a.binFail);if(s.length>0){const a=new Map;for(const r of s){const f=We(String(r.fill));let d=a.get(f);d||(d=[],a.set(f,d)),d.push(r)}t.save(),t.lineCap="butt";for(const[r,f]of a){t.strokeStyle=r,t.globalAlpha=.55,t.lineWidth=Math.max(.6/(k*L),Math.min(f[0].width,f[0].height)*.1);for(const d of f){const i=d.width/2,p=d.height/2,l=Math.max(1.6/(k*L),Math.min(d.width,d.height)/3);t.save(),t.beginPath(),t.rect(d.x-i,d.y-p,d.width,d.height),t.clip(),t.beginPath();for(let b=-(i+p);b<=i+p;b+=l)t.moveTo(d.x-i+b,d.y-p),t.lineTo(d.x-i+b+d.height,d.y+p);t.stroke(),t.restore()}}t.restore()}}const c=e.rectangles.filter(s=>s.specMark);if(c.length>0){const s=new Map;for(const r of c){const f=We(String(r.fill)),d=`${r.specMark}|${f}`;let i=s.get(d);i||(i=[],s.set(d,i)),i.push(r)}const a=2.5/(k*L);t.lineJoin="round";for(const[r,f]of s){const[d,i]=r.split("|"),p=i==="#000000"?"#ffffff":"#000000",l=d==="failHigh"?1:-1,b=Math.min(f[0].width,f[0].height),w=Math.max(2.5/(k*L),b*.3);t.beginPath();for(const A of f)Oe(t,A.x,A.y,w,l);t.strokeStyle=p,t.lineWidth=a,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const c of o.points){for(let s=0;s<c.length;s++)s===0?t.moveTo(c[s].x,c[s].y):t.lineTo(c[s].x,c[s].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3/(k*L),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(k*L),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(k*L),t.stroke())}if(t.restore(),e.notchDir){const o=ot+e.waferCenter.x*k,c=nt-e.waferCenter.y*k,s=e.notchDir.x,a=-e.notchDir.y,r=e.waferRadius*k,f=4,d=9,i=5,p=o+s*(r+f),l=c+a*(r+f),b=p+s*d,w=l+a*d,A={x:-a,y:s},W=h+Nt+te,U=O-h-vt,K=h+Q+Jt,C=E-h-ge-ee;t.save(),t.beginPath(),t.rect(W,K,U-W,C-K),t.clip(),t.beginPath(),t.moveTo(p,l),t.lineTo(b+A.x*i,w+A.y*i),t.lineTo(b-A.x*i,w-A.y*i),t.closePath(),t.fillStyle=M.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let be=0;if(e.rectangles.length>0){let o=1;for(const f of e.texts)f.role!=="indicator"&&f.text.length>o&&(o=f.text.length);const c=e.rectangles[0].width*k,s=e.rectangles[0].height*k,a=Math.min(c,s),r=c/o;be=Math.max(8,Math.min(64,Math.round(Math.min(a*.55,r*1.8))))}for(const o of e.texts){const c=ot+o.x*k,s=nt-o.y*k;t.font=`${o.role==="indicator"?o.fontSize:be}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,c,s)}if(t.restore(),Mt&&fo(t,O,E,ot,nt,k,h,ee,Nt,V,e.gridToScreen,e.rotation,M),kt){const o=Ze(e.valueColorScheme),c=me,s=ue-Q,a=Math.round(s*.75),r=h+Q+Math.round((s-a)/2),f=O-h-P-c,d=Ot,i=It,p=i-d,l=e.plotMode==="stackedSoftBins"?st:yt,{primary:b,secondary:w}=rt?Ce(e,St,l):{primary:"",secondary:""};if(rt){const n=Math.max(r-6,h+Q+11),y=Ht+Math.max(lt(n),lt(n-12))+8;it(b,O-h,n,"right","bottom",y)}let A=r+a+4;const W=n=>Ht+Math.max(lt(n),lt(n+12))+8,U=e.logScale&&d>0?Math.log10(d):0,K=e.logScale&&i>0?Math.log10(i)-U:1,C=n=>e.logScale?(1-(Math.log10(n)-U)/K)*a:(1-(n-d)/p)*a;for(let n=0;n<Ut;n++){const y=1-n/(Ut-1),u=r+n/Ut*a,g=a/Ut+1;t.fillStyle=o.forValue(y),t.fillRect(f,u,P,g)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(f,r,P,a),t.fillStyle=M.text,t.font=Z(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const _=Ie,Rt=36,v=14,I=e.logScale&&K>0?ho(d,i,a,Rt,v,U,K):e.allIntegerValues?(()=>{const n=Math.max(1,qt(p*Rt/a)),y=[],u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(Math.round(g))}return y})():(()=>{const n=p>0?qt(p*Rt/a):0,y=[];if(n>0){const u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(g)}}return y})(),R=jt,x=Zt,T=Ft;t.textBaseline="middle";for(const n of I){const y=r+C(n);t.beginPath(),t.moveTo(f+P,y),t.lineTo(f+P+_,y),t.stroke(),t.fillText(T(n),f+P+_+Gt,y)}if(t.beginPath(),t.moveTo(f+P,r),t.lineTo(f+P+_,r),t.stroke(),t.textBaseline="top",t.fillText(T(i),f+P+_+Gt,r),t.beginPath(),t.moveTo(f+P,r+a),t.lineTo(f+P+_,r+a),t.stroke(),t.textBaseline="bottom",t.fillText(T(d),f+P+_+Gt,r+a),!x&&R&&(R.limitLow!==void 0||R.limitHigh!==void 0)){const n=[],y=e.colorbarRangeMode==="spec";for(const[u,g]of[[R.limitLow,"LSL"],[R.limitHigh,"USL"]]){if(u===void 0||e.logScale&&u<=0)continue;const B=C(u);!y&&(B<-v||B>a+v)||n.push({value:u,label:g,py:Math.max(0,Math.min(a,B))})}if(n.length>0){t.save(),t.font=Z(),t.textAlign="right",t.textBaseline="middle";for(const{py:u,label:g}of n){const B=r+u;y||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke()),t.fillStyle=M.text,t.fillText(g,f-3,B);const dt=g==="USL"?-1:1,gt=4,Tt=f-3-t.measureText(g).width-gt-4;t.beginPath(),Oe(t,Tt,B,gt,dt),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=M.text,t.fill()}t.restore()}}if(!x){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=M.text,t.font=ao(),t.textAlign="right",t.textBaseline="top",t.fillText(n,O-h,A),t.restore(),A+=15)}rt&&w&&it(w,O-h,A,"right","top",W(A),Vt(),M.text)}const le=[];let J;if(ht){const o=$==="compact",c=e.plotMode==="softBin"?st:yt,s=c?new Map(c.map(l=>[l.bin,l])):null,a=e.plotMode==="softBin"?e.binColors.soft:e.binColors.hard,r=l=>a.get(l)??je,f=(l,b)=>{const w=t.measureText(l).width,A=o?0:t.measureText(String(b)).width,W=Y+mt+w+(A?Kt:0);return{labelWidth:w,countWidth:A,totalWidth:W}},d=bt?.find(l=>l.key===e.activeMetadataKey),i=tt?et.map(l=>{const b=o?l.compactLabel:l.label;return{key:l.key,color:l.color,count:l.count,label:b,tooltipLabel:l.tooltip,...f(b,l.count)}}):e.plotMode==="metadata"?Bt.map(([l,b])=>{const A=d?.values?.find(K=>K.value===l)?.label??l,W=o?l:A,U=e.metadataColorMap?.get(l)??"#d6d9dd";return{key:l,color:U,count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}):_t.map(([l,b])=>{const w=s?.get(l),A=w?.name?`${l} \xB7 ${w.name}`:`Bin ${l}`,W=o?String(l):A;return{key:l,color:r(l),count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}),p=O-h*2;if(i.length>0){const l=Math.max(1,Math.floor((E-2*h)/D));let b=i.length,w=1,A=b*D,W=[],U=0;const K=zt||Pt;if(K){const I=Math.max(...i.map(x=>x.totalWidth)),R=Math.max(1,Math.min(i.length,Math.floor((p+8)/(I+8))));for(let x=R;x>=1;x--){const T=Math.ceil(i.length/x);if(T>l)continue;const n=new Array(x).fill(0);for(let u=0;u<i.length;u++){const g=u%x;n[g]=Math.max(n[g],i[u].totalWidth)}if(n.reduce((u,g)=>u+g,0)+(x-1)*8<=p||x===1){w=x,W=n,b=T,A=T*D;break}}}else b=Math.min(i.length,l),A=b*D,i.length>l&&(U=i.length-(l-1)),W=[Dt];let C,_;if(Wt){const I=Math.max(...i.map(g=>Y+mt+t.measureText(g.label).width+Kt)),R=Math.ceil(I);W=[R];const x=rt?ro:0,T=R+ut*2,n=A+x+ut*2,y=xt?.x??0,u=xt?.y??0;C=Math.min(Math.max(O-h-T+y,h),O-h-T),_=Math.min(Math.max(E-h-n+u,h),E-h-n),J={x:C,y:_,w:T,h:n},t.save(),t.globalAlpha=.92,t.fillStyle=M.surface,t.fillRect(C,_,T,n),t.globalAlpha=1,t.strokeStyle=M.axisLine,t.lineWidth=1,t.strokeRect(C,_,T,n),t.restore(),C+=ut,_+=ut+x}else zt?(C=h,_=E-h-A):Pt?(C=h,_=h+Q):fe?(C=h+4,_=h+Math.round((E-2*h-A)/2)):(C=O-h-Dt+4,_=h+Math.round((E-2*h-A)/2));if(rt){const I=e.plotMode==="softBin"?st:yt,{primary:R,secondary:x}=Ce(e,St,I),T=6,n=g=>Ht-Math.max(lt(g),lt(g-12))-8,y=g=>re?O-h:n(g),u=Wt?J.y+J.h:_+A;if(Pt){const g=u+T;it(R,C,g,"left","top",Ht-Math.max(lt(g),lt(g+12))-8),x&&it(x,C,g+16,"left","top",n(g+16),Vt(),M.text)}else if(Wt)it(R,J.x+ut,J.y+ut,"left","top",J.x+J.w-ut),x&&it(x,J.x,u+T,"left","top",J.x+J.w,Vt(),M.text);else{const g=Math.max(_-T,h+Q+12);if(it(R,C,g,"left","bottom",y(g)),x){const B=u+T;it(x,C,B,"left","top",y(B),Vt(),M.text)}}}t.save(),t.font=Z();const Rt=K?8:0,v=(I,R)=>{if(t.measureText(I).width<=R)return I;let x=0,T=I.length;const n="\u2026",y=t.measureText(n).width;for(;x<T;){const u=x+T+1>>1;t.measureText(I.slice(0,u)).width+y<=R?x=u:T=u-1}return x===0?n:I.slice(0,x)+n};if(K){let I=0;for(let R=0;R<b;R++){let x=C;for(let T=0;T<w;T++){const n=i[I++];if(!n)break;const y=n.key===N,u=!y&&n.key===z,g=x,B=x+Y+mt,dt=_+R*D+D/2,gt=_+R*D+Math.round((D-Y)/2),Tt=W[T]-Y-mt-Kt;u&&(t.fillStyle=M.hoverRow,t.fillRect(x,_+R*D,W[T],D)),t.fillStyle=n.color,t.fillRect(g,gt,Y,Y),t.strokeStyle=y?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=y?2:.75,t.strokeRect(g,gt,Y,Y),t.fillStyle=y?M.accent:M.text,t.font=y?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(n.label,Tt),B,dt),t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(n.count),x+W[T]-2,dt),le.push({bin:n.key,x,y:_+R*D,w:W[T],h:D,label:n.tooltipLabel}),x+=W[T]+Rt}}}else{const I=W[0],R=$!=="compact",x=I-Y-mt-(R?Kt:0),T=C+I-2;let n=i;U>0&&(n=i.slice(0,l-1));let y=_;for(const u of n){const g=u.key===N,B=!g&&u.key===z,dt=C,gt=C+Y+mt,Tt=y+D/2,Ae=y+Math.round((D-Y)/2),qe=u.label;B&&(t.fillStyle=M.hoverRow,t.fillRect(C-3,y,I+3,D)),t.fillStyle=u.color,t.fillRect(dt,Ae,Y,Y),t.strokeStyle=g?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=g?2:.75,t.strokeRect(dt,Ae,Y,Y),t.fillStyle=g?M.accent:M.text,t.font=g?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(qe,x),gt,Tt),(R||Wt)&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(u.count),T,Tt)),le.push({bin:u.key,x:C,y,w:I,h:D,label:u.tooltipLabel}),y+=D}U>0&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${U} more`,C+Y+mt,y+D/2))}}i.length>0&&t.restore()}const Ve={originX:ot,originY:nt,ppm:k,snapDist:Yt},Te=e.rectangles[0]?.width??1,Se=e.rectangles[0]?.height??1,at=e.dieBounds,Xt=at?at.minX:G.length?Math.min(...G.map(o=>o.x)):0,$t=at?at.minY:G.length?Math.min(...G.map(o=>o.y)):0,Ue=at?at.maxX:G.length?Math.max(...G.map(o=>o.x)):1,Ke=at?at.maxY:G.length?Math.max(...G.map(o=>o.y)):1,{cellW:ie,cellH:ae,nCols:At,nRows:ce}=eo(Ue-Xt,Ke-$t,Te*1.5,Se*1.5,G.length),Le=Array.from({length:At*ce},()=>[]);for(let o=0;o<G.length;o++){const c=Math.floor((G[o].x-Xt)/ie),s=Math.floor((G[o].y-$t)/ae),a=Number.isFinite(c)?Math.max(0,Math.min(At-1,c)):0,r=Number.isFinite(s)?Math.max(0,Math.min(ce-1,s)):0;Le[r*At+a].push(o)}function ke(o,c,s){const a=Math.max(0,Math.floor((o-s-Xt)/ie)),r=Math.min(At-1,Math.floor((o+s-Xt)/ie)),f=Math.max(0,Math.floor((c-s-$t)/ae)),d=Math.min(ce-1,Math.floor((c+s-$t)/ae)),i=[];for(let p=f;p<=d;p++)for(let l=a;l<=r;l++)for(const b of Le[p*At+l])i.push(b);return i}return{hitTarget:{getDieAtPoint(o,c){const s=(o-ot)/k,a=(nt-c)/k,r=Math.max(Te,Se);for(const i of ke(s,a,r)){const p=e.rectangles[i];if(p&&Math.abs(s-p.x)<=p.width/2&&Math.abs(a-p.y)<=p.height/2)return e.dies[i]??null}let f=null,d=Yt*Yt;for(const i of ke(s,a,Yt)){const p=G[i].x-s,l=G[i].y-a,b=p*p+l*l;b<d&&(d=b,f=e.dies[i]??null)}return f}},viewport:Ve,binLegendRows:le,legendBox:J}}function fo(m,e,F,M,h,H,X,P,pt,j,xt,Mt,V){m.save(),m.font=co(),m.fillStyle=V.text,m.strokeStyle=V.axisLine,m.lineWidth=.5;const q=F-P+4,N=X+pt-4,z=ze(xt),St=_e(z,1,0),Q=_e(z,0,1),ct=1e-9;function yt(S){return j?Math.abs(S.y)<ct&&Math.abs(S.x)>ct?{pitch:j.x,sign:Math.sign(S.x)}:Math.abs(S.x)<ct&&Math.abs(S.y)>ct?{pitch:j.y,sign:Math.sign(S.y)}:null:null}const st=yt(St),bt=yt(Q);function rt(S){return st?Math.round(S*st.sign/st.pitch):S}function O(S){return bt?Math.round(S*bt.sign/bt.pitch):S}function E(S){if(!S)return qt(50/H);const L=50/(S*H);return Math.max(1,Math.round(L))*S}const Lt=st?.pitch,kt=bt?.pitch,ft=E(Lt),tt=E(kt);m.textAlign="center",m.textBaseline="top";const ht=Math.ceil((X-M)/H/ft)*ft,_t=(e-X-M)/H;for(let S=ht;S<=_t;S+=ft){const L=M+S*H;if(L<X||L>e-X)continue;m.beginPath(),m.moveTo(L,q-Fe),m.lineTo(L,q),m.stroke();const $=j?String(rt(S)):De(S);m.fillText($,L,q+2)}m.textAlign="right",m.textBaseline="middle";const Bt=Math.ceil((h-(F-X))/H/tt)*tt,et=(h-X)/H;for(let S=Bt;S<=et;S+=tt){const L=h-S*H;if(L<X||L>F-X)continue;m.beginPath(),m.moveTo(N,L),m.lineTo(N+Fe,L),m.stroke();const $=j?String(O(S)):De(S);m.fillText($,N-2,L)}m.restore()}function qt(m){const e=Math.pow(10,Math.floor(Math.log10(m))),F=m/e;return(F<1.5?1:F<3.5?2:F<7.5?5:10)*e}function ho(m,e,F,M,h,H,X){const P=[],pt=X;if(pt<1){const V=qt((e-m)*M/F);if(V>0){const q=Math.ceil(m/V)*V;for(let N=q;N<=e+V*1e-6;N+=V){if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}}return P}const j=pt<3?[1,2,5]:[1],xt=Math.floor(Math.log10(m)),Mt=Math.ceil(Math.log10(e));for(let V=xt;V<=Mt;V++)for(const q of j){const N=q*Math.pow(10,V);if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}return P}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";
1
+ import{fontPx as Ct}from"./toolbar.js";import{findTestDef as Re,buildMapTitle as Ce}from"../renderer/buildView.js";import{affineInvert as ze,affineVector as _e}from"../core/transforms.js";import{compareNatural as Je}from"../core/utils.js";import{resolveValueColorFn as Ze}from"../renderer/colorSchemes.js";import{NO_DATA_FILL as je}from"../renderer/colorMap.js";import{SPEC_PASS_FILL as Be,SPEC_FAIL_LOW as Qe,SPEC_FAIL_HIGH as Pe,contrastTextColor as We}from"../renderer/colorMap.js";import{fmt as De,fmtColorbarAxis as ve}from"../renderer/fmt.js";import{resolveCanvasTheme as to}from"./canvasTheme.js";import{hitGridDims as eo}from"./hitGrid.js";function Oe(m,e,I,M,h){m.moveTo(e,I+h*M),m.lineTo(e-M*.9,I-h*M*.6),m.lineTo(e+M*.9,I-h*M*.6),m.closePath()}const oo=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),no=new Set(["hardBin","softBin","metadata"]),Z=()=>`${Ct(-2)}px system-ui, sans-serif`,Fe=3,Gt=2,so=6,lo=20,io=()=>`600 ${Ct()}px system-ui, sans-serif`,Vt=()=>`${Ct(-1)}px system-ui, sans-serif`,ao=()=>`600 ${Ct(-1)}px system-ui, sans-serif`,Ut=128,co=()=>`${Ct(-2)}px system-ui, sans-serif`,Ie=4,D=17,w=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const Kt=28,mt=5,ut=8,ro=15;export function toCanvas(m,e,I={}){const M=to(m.parentElement??m),{padding:h=16,showColorbar:H=!0,markFailingDies:X=!1,colorbarWidth:P=16,background:pt=M.background,legendPosition:j="default",legendOffset:xt,showAxes:Mt=!1,diePitchMm:V,viewport:q,activeBin:N,hoverBin:z,fallbackFormat:St,topClearance:Q=0,minRightReserve:ct,hbinDefs:yt,sbinDefs:st,metadataFields:bt,showTitle:rt=!0}=I,O=Math.floor(m.clientWidth||m.width),E=Math.floor(m.clientHeight||m.height),Lt=O>=BIN_LEGEND_MIN_CANVAS_W&&E>=BIN_LEGEND_MIN_CANVAS_H,kt=H&&Lt&&oo.has(e.plotMode)&&e.passFailDisplay==="off",ft=H&&Lt&&no.has(e.plotMode),tt=H&&Lt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),ht=ft||tt,_t=ft&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[c])=>o-c):[],Bt=ft&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Je)].map(o=>[o,e.metadataCounts.get(o)??0]):[],et=[];if(tt&&e.passFailDisplay==="test"){const o=e.passFailCounts;et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),et.push({key:-2,color:Pe,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(tt){const o=e.specCounts,c=Re(e.testDefs,e.activeTest);et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),c?.limitHigh!==void 0&&et.push({key:-2,color:Pe,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),c?.limitLow!==void 0&&et.push({key:-3,color:Qe,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const S=tt?et.length:e.plotMode==="metadata"?Bt.length:_t.length,L=(m.ownerDocument.defaultView??window).devicePixelRatio??1;if(O<=0||E<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const $=j!=="default"?j:O<BIN_LEGEND_ADAPT_FLOATING?"floating":O<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",re=$==="default"||$==="compact",fe=$==="left",zt=$==="bottom",Pt=$==="top",Wt=$==="floating",Dt=$==="compact"||$==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,he=Math.floor((E-2*h)/D),de=S>he?he-1:S,ge=ht&&zt?de*D:0,Jt=ht&&Pt?de*D:0,Zt=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",jt=Re(e.testDefs,e.activeTest),Ne=Zt?"Count":jt?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),Ee=Zt?void 0:jt?.unit,[Ot,Ft]=e.valueRange,{tickFmt:Ye}=ve(Ft,Ne,Ee,St),It=e.allIntegerValues?o=>String(Math.round(o)):Ye;let Qt=0;if(kt){const o=m.getContext("2d");o.font=Z();const c=[It(Ot),It(Ft)];Ot<0&&c.push(It(-Math.max(Math.abs(Ot),Math.abs(Ft))));for(const s of c)Qt=Math.max(Qt,o.measureText(s).width)}const me=Math.max(lo,Math.ceil(Qt)+Fe+Gt+so-h),vt=kt?P+me+8:ht&&re?Dt:0,te=ht&&fe?Dt:0,ee=Mt?32:0,Nt=Mt?36:0,we=ct!=null?Math.max(vt,ct):vt,He=O-2*h-we-Nt-te,ue=E-2*h-ee-ge-Jt;m.width=Math.round(O*L),m.height=Math.round(E*L);const t=m.getContext("2d");t.scale(L,L),t.fillStyle=pt,t.fillRect(0,0,O,E);const G=e.hoverPoints;if(!G.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Et=e.rectangles[0],oe=Et?Et.width/2:0,ne=Et?Et.height/2:0,Yt=e.dieBounds,pe=(Yt?.minX??0)-oe,Xe=(Yt?.maxX??0)+oe,$e=(Yt?.minY??0)-ne,xe=(Yt?.maxY??0)+ne,Me=Xe-pe,ye=xe-$e;let ot,nt,k;if(q)({originX:ot,originY:nt,ppm:k}=q);else{const c=e.notchDir,s=c&&c.y>.1?13:0,a=c&&c.y<-.1?13:0,r=c&&c.x<-.1?13:0,f=c&&c.x>.1?13:0,d=He-r-f,i=ue-Q-s-a;k=Math.min(d/Me,i/ye),ot=h+Nt+te+r+(d-Me*k)/2-pe*k,nt=h+Q+Jt+s+(i-ye*k)/2+xe*k}const wt=q?.snapDist??Math.max(oe,ne,1)*1.5,Ht=ot+e.waferCenter.x*k,Ge=nt-e.waferCenter.y*k,se=e.waferRadius*k,lt=o=>{const c=Math.abs(o-Ge);return c>=se?0:Math.sqrt(se*se-c*c)},it=(o,c,s,a,r,f,d=io(),i=M.text)=>{if(!o)return;t.save(),t.fillStyle=i,t.font=d,t.textAlign=a,t.textBaseline=r;const p=a==="right"?c-f:f-c;let l=o;if(p>8&&t.measureText(l).width>p){for(;l.length>1&&t.measureText(l+"\u2026").width>p;)l=l.slice(0,-1);l=l+"\u2026"}p>8&&t.fillText(l,c,s),t.restore()};if(t.save(),t.setTransform(k*L,0,0,-k*L,ot*L,nt*L),e.rectangles.length>0){const o=new Map;for(const s of e.rectangles){const a=String(s.fill);let r=o.get(a);r||(r=[],o.set(a,r)),r.push(s)}for(const[s,a]of o){t.beginPath();for(const r of a)t.rect(r.x-r.width/2,r.y-r.height/2,r.width,r.height);t.fillStyle=s,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(k*L),t.beginPath();for(const s of e.rectangles)t.rect(s.x-s.width/2,s.y-s.height/2,s.width,s.height);if(t.stroke(),X){const s=e.rectangles.filter(a=>a.binFail);if(s.length>0){const a=new Map;for(const r of s){const f=We(String(r.fill));let d=a.get(f);d||(d=[],a.set(f,d)),d.push(r)}t.save(),t.lineCap="butt";for(const[r,f]of a){t.strokeStyle=r,t.globalAlpha=.55,t.lineWidth=Math.max(.6/(k*L),Math.min(f[0].width,f[0].height)*.1);for(const d of f){const i=d.width/2,p=d.height/2,l=Math.max(1.6/(k*L),Math.min(d.width,d.height)/3);t.save(),t.beginPath(),t.rect(d.x-i,d.y-p,d.width,d.height),t.clip(),t.beginPath();for(let b=-(i+p);b<=i+p;b+=l)t.moveTo(d.x-i+b,d.y-p),t.lineTo(d.x-i+b+d.height,d.y+p);t.stroke(),t.restore()}}t.restore()}}const c=e.rectangles.filter(s=>s.specMark);if(c.length>0){const s=new Map;for(const r of c){const f=We(String(r.fill)),d=`${r.specMark}|${f}`;let i=s.get(d);i||(i=[],s.set(d,i)),i.push(r)}const a=2.5/(k*L);t.lineJoin="round";for(const[r,f]of s){const[d,i]=r.split("|"),p=i==="#000000"?"#ffffff":"#000000",l=d==="failHigh"?1:-1,b=Math.min(f[0].width,f[0].height),Y=Math.max(2.5/(k*L),b*.3);t.beginPath();for(const A of f)Oe(t,A.x,A.y,Y,l);t.strokeStyle=p,t.lineWidth=a,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const c of o.points){for(let s=0;s<c.length;s++)s===0?t.moveTo(c[s].x,c[s].y):t.lineTo(c[s].x,c[s].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3/(k*L),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(k*L),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(k*L),t.stroke())}if(t.restore(),e.notchDir){const o=ot+e.waferCenter.x*k,c=nt-e.waferCenter.y*k,s=e.notchDir.x,a=-e.notchDir.y,r=e.waferRadius*k,f=4,d=9,i=5,p=o+s*(r+f),l=c+a*(r+f),b=p+s*d,Y=l+a*d,A={x:-a,y:s},W=h+Nt+te,U=O-h-vt,K=h+Q+Jt,C=E-h-ge-ee;t.save(),t.beginPath(),t.rect(W,K,U-W,C-K),t.clip(),t.beginPath(),t.moveTo(p,l),t.lineTo(b+A.x*i,Y+A.y*i),t.lineTo(b-A.x*i,Y-A.y*i),t.closePath(),t.fillStyle=M.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let be=0;if(e.rectangles.length>0){let o=1;for(const f of e.texts)f.role!=="indicator"&&f.text.length>o&&(o=f.text.length);const c=e.rectangles[0].width*k,s=e.rectangles[0].height*k,a=Math.min(c,s),r=c/o;be=Math.max(8,Math.min(64,Math.round(Math.min(a*.55,r*1.8))))}for(const o of e.texts){const c=ot+o.x*k,s=nt-o.y*k;t.font=`${o.role==="indicator"?o.fontSize:be}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,c,s)}if(t.restore(),Mt&&fo(t,O,E,ot,nt,k,h,ee,Nt,V,e.gridToScreen,e.rotation,M),kt){const o=Ze(e.valueColorScheme,e.reverseValueScheme),c=me,s=ue-Q,a=Math.round(s*.75),r=h+Q+Math.round((s-a)/2),f=O-h-P-c,d=Ot,i=Ft,p=i-d,l=e.plotMode==="stackedSoftBins"?st:yt,{primary:b,secondary:Y}=rt?Ce(e,St,l):{primary:"",secondary:""};if(rt){const n=Math.max(r-6,h+Q+11),y=Ht+Math.max(lt(n),lt(n-12))+8;it(b,O-h,n,"right","bottom",y)}let A=r+a+4;const W=n=>Ht+Math.max(lt(n),lt(n+12))+8,U=e.logScale&&d>0?Math.log10(d):0,K=e.logScale&&i>0?Math.log10(i)-U:1,C=n=>e.logScale?(1-(Math.log10(n)-U)/K)*a:(1-(n-d)/p)*a;for(let n=0;n<Ut;n++){const y=1-n/(Ut-1),u=r+n/Ut*a,g=a/Ut+1;t.fillStyle=o(y),t.fillRect(f,u,P,g)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(f,r,P,a),t.fillStyle=M.text,t.font=Z(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const _=Fe,Rt=36,v=14,F=e.logScale&&K>0?ho(d,i,a,Rt,v,U,K):e.allIntegerValues?(()=>{const n=Math.max(1,qt(p*Rt/a)),y=[],u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(Math.round(g))}return y})():(()=>{const n=p>0?qt(p*Rt/a):0,y=[];if(n>0){const u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(g)}}return y})(),R=jt,x=Zt,T=It;t.textBaseline="middle";for(const n of F){const y=r+C(n);t.beginPath(),t.moveTo(f+P,y),t.lineTo(f+P+_,y),t.stroke(),t.fillText(T(n),f+P+_+Gt,y)}if(t.beginPath(),t.moveTo(f+P,r),t.lineTo(f+P+_,r),t.stroke(),t.textBaseline="top",t.fillText(T(i),f+P+_+Gt,r),t.beginPath(),t.moveTo(f+P,r+a),t.lineTo(f+P+_,r+a),t.stroke(),t.textBaseline="bottom",t.fillText(T(d),f+P+_+Gt,r+a),!x&&R&&(R.limitLow!==void 0||R.limitHigh!==void 0)){const n=[],y=e.colorbarRangeMode==="spec";for(const[u,g]of[[R.limitLow,"LSL"],[R.limitHigh,"USL"]]){if(u===void 0||e.logScale&&u<=0)continue;const B=C(u);!y&&(B<-v||B>a+v)||n.push({value:u,label:g,py:Math.max(0,Math.min(a,B))})}if(n.length>0){t.save(),t.font=Z(),t.textAlign="right",t.textBaseline="middle";for(const{py:u,label:g}of n){const B=r+u;y||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke()),t.fillStyle=M.text,t.fillText(g,f-3,B);const dt=g==="USL"?-1:1,gt=4,Tt=f-3-t.measureText(g).width-gt-4;t.beginPath(),Oe(t,Tt,B,gt,dt),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=M.text,t.fill()}t.restore()}}if(!x){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=M.text,t.font=ao(),t.textAlign="right",t.textBaseline="top",t.fillText(n,O-h,A),t.restore(),A+=15)}rt&&Y&&it(Y,O-h,A,"right","top",W(A),Vt(),M.text)}const le=[];let J;if(ht){const o=$==="compact",c=e.plotMode==="softBin"?st:yt,s=c?new Map(c.map(l=>[l.bin,l])):null,a=e.plotMode==="softBin"?e.binColors.soft:e.binColors.hard,r=l=>a.get(l)??je,f=(l,b)=>{const Y=t.measureText(l).width,A=o?0:t.measureText(String(b)).width,W=w+mt+Y+(A?Kt:0);return{labelWidth:Y,countWidth:A,totalWidth:W}},d=bt?.find(l=>l.key===e.activeMetadataKey),i=tt?et.map(l=>{const b=o?l.compactLabel:l.label;return{key:l.key,color:l.color,count:l.count,label:b,tooltipLabel:l.tooltip,...f(b,l.count)}}):e.plotMode==="metadata"?Bt.map(([l,b])=>{const A=d?.values?.find(K=>K.value===l)?.label??l,W=o?l:A,U=e.metadataColorMap?.get(l)??"#d6d9dd";return{key:l,color:U,count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}):_t.map(([l,b])=>{const Y=s?.get(l),A=Y?.name?`${l} \xB7 ${Y.name}`:`Bin ${l}`,W=o?String(l):A;return{key:l,color:r(l),count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}),p=O-h*2;if(i.length>0){const l=Math.max(1,Math.floor((E-2*h)/D));let b=i.length,Y=1,A=b*D,W=[],U=0;const K=zt||Pt;if(K){const F=Math.max(...i.map(x=>x.totalWidth)),R=Math.max(1,Math.min(i.length,Math.floor((p+8)/(F+8))));for(let x=R;x>=1;x--){const T=Math.ceil(i.length/x);if(T>l)continue;const n=new Array(x).fill(0);for(let u=0;u<i.length;u++){const g=u%x;n[g]=Math.max(n[g],i[u].totalWidth)}if(n.reduce((u,g)=>u+g,0)+(x-1)*8<=p||x===1){Y=x,W=n,b=T,A=T*D;break}}}else b=Math.min(i.length,l),A=b*D,i.length>l&&(U=i.length-(l-1)),W=[Dt];let C,_;if(Wt){const F=Math.max(...i.map(g=>w+mt+t.measureText(g.label).width+Kt)),R=Math.ceil(F);W=[R];const x=rt?ro:0,T=R+ut*2,n=A+x+ut*2,y=xt?.x??0,u=xt?.y??0;C=Math.min(Math.max(O-h-T+y,h),O-h-T),_=Math.min(Math.max(E-h-n+u,h),E-h-n),J={x:C,y:_,w:T,h:n},t.save(),t.globalAlpha=.92,t.fillStyle=M.surface,t.fillRect(C,_,T,n),t.globalAlpha=1,t.strokeStyle=M.axisLine,t.lineWidth=1,t.strokeRect(C,_,T,n),t.restore(),C+=ut,_+=ut+x}else zt?(C=h,_=E-h-A):Pt?(C=h,_=h+Q):fe?(C=h+4,_=h+Math.round((E-2*h-A)/2)):(C=O-h-Dt+4,_=h+Math.round((E-2*h-A)/2));if(rt){const F=e.plotMode==="softBin"?st:yt,{primary:R,secondary:x}=Ce(e,St,F),T=6,n=g=>Ht-Math.max(lt(g),lt(g-12))-8,y=g=>re?O-h:n(g),u=Wt?J.y+J.h:_+A;if(Pt){const g=u+T;it(R,C,g,"left","top",Ht-Math.max(lt(g),lt(g+12))-8),x&&it(x,C,g+16,"left","top",n(g+16),Vt(),M.text)}else if(Wt)it(R,J.x+ut,J.y+ut,"left","top",J.x+J.w-ut),x&&it(x,J.x,u+T,"left","top",J.x+J.w,Vt(),M.text);else{const g=Math.max(_-T,h+Q+12);if(it(R,C,g,"left","bottom",y(g)),x){const B=u+T;it(x,C,B,"left","top",y(B),Vt(),M.text)}}}t.save(),t.font=Z();const Rt=K?8:0,v=(F,R)=>{if(t.measureText(F).width<=R)return F;let x=0,T=F.length;const n="\u2026",y=t.measureText(n).width;for(;x<T;){const u=x+T+1>>1;t.measureText(F.slice(0,u)).width+y<=R?x=u:T=u-1}return x===0?n:F.slice(0,x)+n};if(K){let F=0;for(let R=0;R<b;R++){let x=C;for(let T=0;T<Y;T++){const n=i[F++];if(!n)break;const y=n.key===N,u=!y&&n.key===z,g=x,B=x+w+mt,dt=_+R*D+D/2,gt=_+R*D+Math.round((D-w)/2),Tt=W[T]-w-mt-Kt;u&&(t.fillStyle=M.hoverRow,t.fillRect(x,_+R*D,W[T],D)),t.fillStyle=n.color,t.fillRect(g,gt,w,w),t.strokeStyle=y?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=y?2:.75,t.strokeRect(g,gt,w,w),t.fillStyle=y?M.accent:M.text,t.font=y?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(n.label,Tt),B,dt),t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(n.count),x+W[T]-2,dt),le.push({bin:n.key,x,y:_+R*D,w:W[T],h:D,label:n.tooltipLabel}),x+=W[T]+Rt}}}else{const F=W[0],R=$!=="compact",x=F-w-mt-(R?Kt:0),T=C+F-2;let n=i;U>0&&(n=i.slice(0,l-1));let y=_;for(const u of n){const g=u.key===N,B=!g&&u.key===z,dt=C,gt=C+w+mt,Tt=y+D/2,Ae=y+Math.round((D-w)/2),qe=u.label;B&&(t.fillStyle=M.hoverRow,t.fillRect(C-3,y,F+3,D)),t.fillStyle=u.color,t.fillRect(dt,Ae,w,w),t.strokeStyle=g?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=g?2:.75,t.strokeRect(dt,Ae,w,w),t.fillStyle=g?M.accent:M.text,t.font=g?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(qe,x),gt,Tt),(R||Wt)&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(u.count),T,Tt)),le.push({bin:u.key,x:C,y,w:F,h:D,label:u.tooltipLabel}),y+=D}U>0&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${U} more`,C+w+mt,y+D/2))}}i.length>0&&t.restore()}const Ve={originX:ot,originY:nt,ppm:k,snapDist:wt},Te=e.rectangles[0]?.width??1,Se=e.rectangles[0]?.height??1,at=e.dieBounds,Xt=at?at.minX:G.length?Math.min(...G.map(o=>o.x)):0,$t=at?at.minY:G.length?Math.min(...G.map(o=>o.y)):0,Ue=at?at.maxX:G.length?Math.max(...G.map(o=>o.x)):1,Ke=at?at.maxY:G.length?Math.max(...G.map(o=>o.y)):1,{cellW:ie,cellH:ae,nCols:At,nRows:ce}=eo(Ue-Xt,Ke-$t,Te*1.5,Se*1.5,G.length),Le=Array.from({length:At*ce},()=>[]);for(let o=0;o<G.length;o++){const c=Math.floor((G[o].x-Xt)/ie),s=Math.floor((G[o].y-$t)/ae),a=Number.isFinite(c)?Math.max(0,Math.min(At-1,c)):0,r=Number.isFinite(s)?Math.max(0,Math.min(ce-1,s)):0;Le[r*At+a].push(o)}function ke(o,c,s){const a=Math.max(0,Math.floor((o-s-Xt)/ie)),r=Math.min(At-1,Math.floor((o+s-Xt)/ie)),f=Math.max(0,Math.floor((c-s-$t)/ae)),d=Math.min(ce-1,Math.floor((c+s-$t)/ae)),i=[];for(let p=f;p<=d;p++)for(let l=a;l<=r;l++)for(const b of Le[p*At+l])i.push(b);return i}return{hitTarget:{getDieAtPoint(o,c){const s=(o-ot)/k,a=(nt-c)/k,r=Math.max(Te,Se);for(const i of ke(s,a,r)){const p=e.rectangles[i];if(p&&Math.abs(s-p.x)<=p.width/2&&Math.abs(a-p.y)<=p.height/2)return e.dies[i]??null}let f=null,d=wt*wt;for(const i of ke(s,a,wt)){const p=G[i].x-s,l=G[i].y-a,b=p*p+l*l;b<d&&(d=b,f=e.dies[i]??null)}return f}},viewport:Ve,binLegendRows:le,legendBox:J}}function fo(m,e,I,M,h,H,X,P,pt,j,xt,Mt,V){m.save(),m.font=co(),m.fillStyle=V.text,m.strokeStyle=V.axisLine,m.lineWidth=.5;const q=I-P+4,N=X+pt-4,z=ze(xt),St=_e(z,1,0),Q=_e(z,0,1),ct=1e-9;function yt(S){return j?Math.abs(S.y)<ct&&Math.abs(S.x)>ct?{pitch:j.x,sign:Math.sign(S.x)}:Math.abs(S.x)<ct&&Math.abs(S.y)>ct?{pitch:j.y,sign:Math.sign(S.y)}:null:null}const st=yt(St),bt=yt(Q);function rt(S){return st?Math.round(S*st.sign/st.pitch):S}function O(S){return bt?Math.round(S*bt.sign/bt.pitch):S}function E(S){if(!S)return qt(50/H);const L=50/(S*H);return Math.max(1,Math.round(L))*S}const Lt=st?.pitch,kt=bt?.pitch,ft=E(Lt),tt=E(kt);m.textAlign="center",m.textBaseline="top";const ht=Math.ceil((X-M)/H/ft)*ft,_t=(e-X-M)/H;for(let S=ht;S<=_t;S+=ft){const L=M+S*H;if(L<X||L>e-X)continue;m.beginPath(),m.moveTo(L,q-Ie),m.lineTo(L,q),m.stroke();const $=j?String(rt(S)):De(S);m.fillText($,L,q+2)}m.textAlign="right",m.textBaseline="middle";const Bt=Math.ceil((h-(I-X))/H/tt)*tt,et=(h-X)/H;for(let S=Bt;S<=et;S+=tt){const L=h-S*H;if(L<X||L>I-X)continue;m.beginPath(),m.moveTo(N,L),m.lineTo(N+Ie,L),m.stroke();const $=j?String(O(S)):De(S);m.fillText($,N-2,L)}m.restore()}function qt(m){const e=Math.pow(10,Math.floor(Math.log10(m))),I=m/e;return(I<1.5?1:I<3.5?2:I<7.5?5:10)*e}function ho(m,e,I,M,h,H,X){const P=[],pt=X;if(pt<1){const V=qt((e-m)*M/I);if(V>0){const q=Math.ceil(m/V)*V;for(let N=q;N<=e+V*1e-6;N+=V){if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*I;z>h&&z<I-h&&P.push(N)}}return P}const j=pt<3?[1,2,5]:[1],xt=Math.floor(Math.log10(m)),Mt=Math.ceil(Math.log10(e));for(let V=xt;V<=Mt;V++)for(const q of j){const N=q*Math.pow(10,V);if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*I;z>h&&z<I-h&&P.push(N)}return P}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";
@@ -717,6 +717,7 @@ export interface PaletteState {
717
717
  plotMode: PlotMode;
718
718
  binColorScheme?: string;
719
719
  valueColorScheme?: string;
720
+ reverseValueScheme?: boolean;
720
721
  useDefinedBinColors?: boolean;
721
722
  }
722
723
  /**
@@ -737,6 +738,7 @@ export interface PaletteState {
737
738
  export declare function makePaletteBtn(helpers: ToolbarHelpers, getState: () => PaletteState, hasDefinedBinColors: () => boolean, apply: (partial: {
738
739
  binColorScheme?: string;
739
740
  valueColorScheme?: string;
741
+ reverseValueScheme?: boolean;
740
742
  useDefinedBinColors?: boolean;
741
743
  }) => void): {
742
744
  btn: HTMLButtonElement;