@wafertools/wafermap 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +751 -0
  2. package/LICENSE +21 -0
  3. package/README.md +79 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.js +1 -0
  6. package/dist/packages/canvas-adapter/canvasTheme.d.ts +28 -0
  7. package/dist/packages/canvas-adapter/canvasTheme.js +1 -0
  8. package/dist/packages/canvas-adapter/charts/barPanel.d.ts +52 -0
  9. package/dist/packages/canvas-adapter/charts/barPanel.js +1 -0
  10. package/dist/packages/canvas-adapter/charts/binCluster.d.ts +17 -0
  11. package/dist/packages/canvas-adapter/charts/binCluster.js +1 -0
  12. package/dist/packages/canvas-adapter/charts/boxplot.d.ts +45 -0
  13. package/dist/packages/canvas-adapter/charts/boxplot.js +1 -0
  14. package/dist/packages/canvas-adapter/charts/capability.d.ts +41 -0
  15. package/dist/packages/canvas-adapter/charts/capability.js +1 -0
  16. package/dist/packages/canvas-adapter/charts/chartShell.d.ts +156 -0
  17. package/dist/packages/canvas-adapter/charts/chartShell.js +1 -0
  18. package/dist/packages/canvas-adapter/charts/correlation.d.ts +35 -0
  19. package/dist/packages/canvas-adapter/charts/correlation.js +1 -0
  20. package/dist/packages/canvas-adapter/charts/histogram.d.ts +30 -0
  21. package/dist/packages/canvas-adapter/charts/histogram.js +1 -0
  22. package/dist/packages/canvas-adapter/charts/index.d.ts +16 -0
  23. package/dist/packages/canvas-adapter/charts/index.js +1 -0
  24. package/dist/packages/canvas-adapter/charts/palette.d.ts +26 -0
  25. package/dist/packages/canvas-adapter/charts/palette.js +1 -0
  26. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.d.ts +18 -0
  27. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.js +1 -0
  28. package/dist/packages/canvas-adapter/charts/scatter.d.ts +37 -0
  29. package/dist/packages/canvas-adapter/charts/scatter.js +1 -0
  30. package/dist/packages/canvas-adapter/icons.d.ts +2 -0
  31. package/dist/packages/canvas-adapter/icons.js +42 -0
  32. package/dist/packages/canvas-adapter/index.d.ts +12 -0
  33. package/dist/packages/canvas-adapter/index.js +1 -0
  34. package/dist/packages/canvas-adapter/insightsTab.d.ts +76 -0
  35. package/dist/packages/canvas-adapter/insightsTab.js +1 -0
  36. package/dist/packages/canvas-adapter/metadataBadge.d.ts +26 -0
  37. package/dist/packages/canvas-adapter/metadataBadge.js +1 -0
  38. package/dist/packages/canvas-adapter/renderWaferGallery.d.ts +181 -0
  39. package/dist/packages/canvas-adapter/renderWaferGallery.js +20 -0
  40. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +316 -0
  41. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -0
  42. package/dist/packages/canvas-adapter/summaryPanel.d.ts +262 -0
  43. package/dist/packages/canvas-adapter/summaryPanel.js +3 -0
  44. package/dist/packages/canvas-adapter/toCanvas.d.ts +106 -0
  45. package/dist/packages/canvas-adapter/toCanvas.js +1 -0
  46. package/dist/packages/canvas-adapter/toolbar.d.ts +496 -0
  47. package/dist/packages/canvas-adapter/toolbar.js +9 -0
  48. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +2 -0
  49. package/dist/packages/canvas-adapter/userGuideHtml.js +968 -0
  50. package/dist/packages/canvas-adapter/version.d.ts +3 -0
  51. package/dist/packages/canvas-adapter/version.js +1 -0
  52. package/dist/packages/core/aggregates.d.ts +54 -0
  53. package/dist/packages/core/aggregates.js +1 -0
  54. package/dist/packages/core/classify.d.ts +24 -0
  55. package/dist/packages/core/classify.js +1 -0
  56. package/dist/packages/core/dies.d.ts +92 -0
  57. package/dist/packages/core/dies.js +1 -0
  58. package/dist/packages/core/index.d.ts +13 -0
  59. package/dist/packages/core/index.js +1 -0
  60. package/dist/packages/core/inference/grid.d.ts +35 -0
  61. package/dist/packages/core/inference/grid.js +1 -0
  62. package/dist/packages/core/inference/index.d.ts +7 -0
  63. package/dist/packages/core/inference/index.js +1 -0
  64. package/dist/packages/core/inference/pitch.d.ts +26 -0
  65. package/dist/packages/core/inference/pitch.js +1 -0
  66. package/dist/packages/core/inference/wafer.d.ts +30 -0
  67. package/dist/packages/core/inference/wafer.js +1 -0
  68. package/dist/packages/core/metadata.d.ts +31 -0
  69. package/dist/packages/core/metadata.js +1 -0
  70. package/dist/packages/core/probe.d.ts +16 -0
  71. package/dist/packages/core/probe.js +1 -0
  72. package/dist/packages/core/reticle.d.ts +68 -0
  73. package/dist/packages/core/reticle.js +1 -0
  74. package/dist/packages/core/transforms.d.ts +142 -0
  75. package/dist/packages/core/transforms.js +1 -0
  76. package/dist/packages/core/utils.d.ts +60 -0
  77. package/dist/packages/core/utils.js +1 -0
  78. package/dist/packages/core/wafer.d.ts +45 -0
  79. package/dist/packages/core/wafer.js +1 -0
  80. package/dist/packages/renderer/buildView.d.ts +420 -0
  81. package/dist/packages/renderer/buildView.js +1 -0
  82. package/dist/packages/renderer/buildWaferMap.d.ts +543 -0
  83. package/dist/packages/renderer/buildWaferMap.js +1 -0
  84. package/dist/packages/renderer/colorMap.d.ts +46 -0
  85. package/dist/packages/renderer/colorMap.js +1 -0
  86. package/dist/packages/renderer/colorSchemes.d.ts +40 -0
  87. package/dist/packages/renderer/colorSchemes.js +1 -0
  88. package/dist/packages/renderer/fmt.d.ts +30 -0
  89. package/dist/packages/renderer/fmt.js +1 -0
  90. package/dist/packages/renderer/index.d.ts +7 -0
  91. package/dist/packages/renderer/index.js +1 -0
  92. package/dist/packages/stats/analyzeWaferLot.d.ts +5 -0
  93. package/dist/packages/stats/analyzeWaferLot.js +1 -0
  94. package/dist/packages/stats/analyzeWaferMap.d.ts +13 -0
  95. package/dist/packages/stats/analyzeWaferMap.js +1 -0
  96. package/dist/packages/stats/binPareto.d.ts +49 -0
  97. package/dist/packages/stats/binPareto.js +1 -0
  98. package/dist/packages/stats/boxplot.d.ts +39 -0
  99. package/dist/packages/stats/boxplot.js +1 -0
  100. package/dist/packages/stats/capability.d.ts +55 -0
  101. package/dist/packages/stats/capability.js +1 -0
  102. package/dist/packages/stats/clusterDetection.d.ts +18 -0
  103. package/dist/packages/stats/clusterDetection.js +1 -0
  104. package/dist/packages/stats/correlation.d.ts +55 -0
  105. package/dist/packages/stats/correlation.js +1 -0
  106. package/dist/packages/stats/facets.d.ts +74 -0
  107. package/dist/packages/stats/facets.js +1 -0
  108. package/dist/packages/stats/filterFindings.d.ts +9 -0
  109. package/dist/packages/stats/filterFindings.js +1 -0
  110. package/dist/packages/stats/findingsNarrative.d.ts +3 -0
  111. package/dist/packages/stats/findingsNarrative.js +1 -0
  112. package/dist/packages/stats/histogram.d.ts +42 -0
  113. package/dist/packages/stats/histogram.js +1 -0
  114. package/dist/packages/stats/index.d.ts +27 -0
  115. package/dist/packages/stats/index.js +1 -0
  116. package/dist/packages/stats/math.d.ts +10 -0
  117. package/dist/packages/stats/math.js +1 -0
  118. package/dist/packages/stats/patternClassification.d.ts +107 -0
  119. package/dist/packages/stats/patternClassification.js +1 -0
  120. package/dist/packages/stats/regions.d.ts +57 -0
  121. package/dist/packages/stats/regions.js +1 -0
  122. package/dist/packages/stats/renderFindingsReport.d.ts +7 -0
  123. package/dist/packages/stats/renderFindingsReport.js +41 -0
  124. package/dist/packages/stats/renderSummaryReport.d.ts +60 -0
  125. package/dist/packages/stats/renderSummaryReport.js +68 -0
  126. package/dist/packages/stats/reportHtml.d.ts +42 -0
  127. package/dist/packages/stats/reportHtml.js +301 -0
  128. package/dist/packages/stats/scatter.d.ts +24 -0
  129. package/dist/packages/stats/scatter.js +1 -0
  130. package/dist/packages/stats/types.d.ts +269 -0
  131. package/dist/packages/stats/types.js +1 -0
  132. package/dist/packages/stats/yield.d.ts +56 -0
  133. package/dist/packages/stats/yield.js +1 -0
  134. package/dist/packages/worker/index.d.ts +44 -0
  135. package/dist/packages/worker/index.js +1 -0
  136. package/dist/packages/worker/wafermap.worker.d.ts +44 -0
  137. package/dist/packages/worker/wafermap.worker.js +1 -0
  138. package/package.json +122 -0
@@ -0,0 +1,20 @@
1
+ import{getUniqueTestNumbers as cn,resolveTestNumber as pn,findTestDef as fn}from"../renderer/buildView.js";import{getColorScheme as un}from"../renderer/colorSchemes.js";import{metadataValueColor as mn}from"../renderer/colorMap.js";import{resolveCanvasTheme as gn}from"./canvasTheme.js";import{ICONS as re}from"./icons.js";import{CLR as g,sevColor as xt,BIN_LEGEND_MODES as hn,STACKED_MODES as de,Z_ABOVE as vt,applyOverlayZ as bn,getTooltip as yn,hideTooltip as wt,createToolbarHelpers as xn,buildModeMenuEl as vn,openDetachWindow as wn,openFloatingWindow as Cn,openModal as Sn,copyWmapThemeTokens as Mn,syncWmapPopupTheme as kn,openUserGuideWindow as Bn,makePaletteBtn as En,makeLogScaleBtn as On,makeLegendStyleBtn as Dn,makeOverlaysBtn as Tn,makeOrientationBtn as Ln,overlayRootFor as In,saveImageBlob as Wn,markMenuTrigger as Ce,wireMenuA11y as Rn,wireExpandToggle as Ct,passFailMenuRows as Pn,requestedPassFailDisplay as ze,logWmapVersionOnce as An,buildDataModeEntries as Fn,metadataKeyHasData as Hn,metadataModeEntry as $n}from"./toolbar.js";import{aggregateValues as jn,aggregateBinCounts as St}from"../core/aggregates.js";import{renderWaferMap as Ne}from"./renderWaferMap.js";import{classifyChanged as zn}from"./renderWaferMap.js";import{buildWaferMap as Nn,getTestPassStatus as Vn,isParametricTest as Mt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Se}from"../stats/analyzeWaferMap.js";import{compareNatural as _n}from"../core/utils.js";import{createSummaryPanelEl as Ve,buildMetadataStripRow as Gn,buildCompactMetadataRows as kt,metadataEntries as Bt,renderLotSummaryContent as Kn}from"./summaryPanel.js";import"../stats/facets.js";import{openHtmlReport as qn}from"../stats/renderFindingsReport.js";import{escHtml as ce,renderSection as Xn,renderSeverityBadge as Un,reportStyles as Yn}from"../stats/reportHtml.js";import{createInsightsTab as Qn}from"./insightsTab.js";import{getDieKey as Zn}from"../core/dies.js";function Me(M){const k=new Set;return M.filter(m=>k.has(m.bin)?!1:(k.add(m.bin),!0))}function Et(M,k){const m=document.createElement("div");Object.assign(m.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:"2px 4px",borderRadius:"3px"});const K=document.createElement("span");Object.assign(K.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:k.color,border:k.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:"2px",boxSizing:"border-box"});const Z=document.createElement("span");Z.textContent=k.label,Object.assign(Z.style,{fontWeight:k.isActive?"700":"400",color:k.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),m.appendChild(K),m.appendChild(Z),m.setAttribute("role","button"),m.setAttribute("aria-pressed",k.isActive?"true":"false"),m.tabIndex=0,m.addEventListener("mouseenter",()=>{m.style.background=g.bgHover}),m.addEventListener("mouseleave",()=>{m.style.background="transparent"}),m.addEventListener("focus",()=>{m.style.background=g.bgHover}),m.addEventListener("blur",()=>{m.style.background="transparent"}),m.addEventListener("click",k.onClick),m.addEventListener("keydown",I=>{(I.key==="Enter"||I.key===" ")&&(I.preventDefault(),k.onClick())}),M.appendChild(m)}export function renderWaferGallery(M,k,m={}){An();const K=m.cardPadding??6,Z=m.downloadFilename??"wafer-gallery";let I=m.columns;const Ot=m.showPlotModeSelector??!0,Dt=m.showHelpButton??!1,Tt=m.userGuideExtension,_e=m.insights?.enabled??!1,Lt=bn(m.zIndex),q=m.summaryPanel,Ge=m.passBins??[1];let pe=m.fallbackFormat,T=m.lotStatsSummary,J=m.legendPosition??"default",c={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...m.viewOptions},w=[],V=[],X=[],S=[],x=k.map(e=>typeof e=="function"?null:e),ke=0,fe=0;const P=new Map;let It=0,E=null,ee=null,Ke=new Set,f=null,te="lot",Wt={};function qe(e){return x[e]?.statsSummary??T?.perWafer.find(t=>t.waferIndex===e)?.summary}function ue(){return!!(x.some(e=>e?.statsSummary?.findings.length)||T?.perWafer.some(e=>e.summary.findings.length))}const Rt=yn(),U=xn(Rt),{makeBtn:_,setActive:ne,makeSep:F,makeMenuRow:Pt,makeMenuSection:At,makeDropdown:Xe,makeCheckMenuBtn:Jn,closeOpenMenu:Ue,getOpenMenu:me,setOpenMenu:ge}=U;M.ownerDocument.addEventListener("click",Ue,!0);const Ye=()=>wt();window.addEventListener("blur",Ye);function Be(e){Ke=new Set(e);const t=[...B.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((i,l)=>{const o=Ke.has(l);i.style.outline=o?`3px solid ${g.findingHighlight}`:"",i.style.outlineOffset=o?"-3px":"",o&&n===void 0&&(n=i)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function Ee(){Be([])}function Oe(){for(const e of w)e&&e.clearSelection()}function De(e,t){const n=new Set(e),i=t??w.map((l,o)=>o);for(const l of i){const o=S[l],s=w[l];if(!o||!s)continue;const r=o.dies.filter(a=>n.has(Zn(a)));s.setSelection(r)}}function Qe(){const e=document.createElement("div");Object.assign(e.style,{display:"flex",gap:"4px",marginBottom:"10px",borderBottom:`1px solid ${g.menuBorder}`,paddingBottom:"8px"});for(const t of["lot","wafers"]){const n=document.createElement("button");n.type="button",n.textContent=t==="lot"?"Lot":"Wafers";const i=te===t;Object.assign(n.style,{border:"none",borderRadius:"4px",padding:"2px 8px",fontSize:"11px",cursor:"pointer",fontWeight:i?"600":"400",background:i?g.bgActive:"transparent",color:i?g.iconHover:g.icon}),n.addEventListener("click",()=>{te=t,Ee(),Oe(),W()}),e.appendChild(n)}return e}function Ft(){if(!f)return;f.innerHTML="",T&&f.appendChild(Qe());const e=[];for(let n=0;n<x.length;n++){const i=x[n];if(!i)continue;const l=qe(n)?.findings??[];if(!l.length)continue;const o=l.filter(r=>r.severity==="unusual").length,s=l.filter(r=>r.severity==="notable").length;e.push({index:n,item:i,unusualCount:o,notableCount:s,totalCount:l.length})}if(e.length>0){const n=document.createElement("button");n.type="button",n.textContent="Findings report",Object.assign(n.style,{border:`1px solid ${g.menuBorder}`,borderRadius:"4px",padding:"3px 8px",marginBottom:"10px",fontSize:"10px",color:g.iconHover,background:"none",cursor:"pointer",display:"block",width:"100%",textAlign:"left"}),n.addEventListener("click",()=>{const i=`Findings report \u2014 ${e.length} wafer${e.length>1?"s":""}`,l=new Date().toLocaleString(),o=e.map(({item:r,index:a})=>{const d=qe(a),p=r.label??`W${a+1}`,h=d.findings.map(u=>`<li>${Un(u.severity)} ${ce(u.summary)}</li>`).join("");return Xn(ce(p),`<ul style="margin:0;padding-left:18px;list-style:none">${h}</ul>`)}).join(`
2
+ `),s=`<!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>${ce(i)}</title>
7
+ <style>
8
+ ${Yn()}
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <main class="report">
13
+ <header class="report-header">
14
+ <h1>${ce(i)}</h1>
15
+ <p class="report-subtitle">Generated ${ce(l)}</p>
16
+ </header>
17
+ ${o}
18
+ </main>
19
+ </body>
20
+ </html>`;qn(s)}),f.appendChild(n)}if(e.length===0){const n=document.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:"11px",padding:"4px 0"}),n.textContent="No findings on any wafer.",f.appendChild(n)}else for(const{index:n,item:i,unusualCount:l,notableCount:o,totalCount:s}of e){const r=l?"unusual":o?"notable":"info",a=l+o||s,d=document.createElement("button");d.type="button",Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:"4px",border:"none",borderLeft:`3px solid ${xt(r)}`,borderRadius:"3px",background:g.bgHover,cursor:"pointer",fontSize:"11px",textAlign:"left",boxSizing:"border-box"}),d.addEventListener("mouseover",()=>{d.style.background=g.bgActive}),d.addEventListener("mouseout",()=>{d.style.background=g.bgHover});const p=document.createElement("span");p.textContent=i.label??`W${n+1}`,Object.assign(p.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const h=document.createElement("span");h.textContent=String(a),Object.assign(h.style,{marginLeft:"6px",flexShrink:"0",background:xt(r),color:"#fff",borderRadius:"8px",padding:"1px 5px",fontSize:"10px",fontWeight:"600"}),d.appendChild(p),d.appendChild(h),d.addEventListener("click",()=>ve(n,i)),f.appendChild(d)}const t=document.createElement("div");t.style.height="12px",f.appendChild(t)}function W(){if(f)if(te==="lot"&&T){const e=Me(x.flatMap(n=>n?.hbinDefs??[])),t=Me(x.flatMap(n=>n?.sbinDefs??[]));Kn(f,{lotSummary:T,items:x,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:x.find(n=>n?.testDefs?.length)?.testDefs,passBins:Ge,ringCount:c.ringCount,colorScheme:c.colorScheme,fallbackFormat:pe,activeFindingId:ee,findingsFilter:Wt,onFindingsFilterChange:W,onSaveText:m.onSaveText,onFindingClick:(n,i)=>{ee===n.id?Te():Ht(n,i),W()},onWaferClick:n=>{Be([n])}}),ue()&&f.insertBefore(Qe(),f.firstChild)}else Ft()}function Ze(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}function Te(){ee=null,Ee(),Oe(),v({highlightBin:void 0},{fireCallback:!1})}function Ht(e,t){if(ee===e.id){Te();return}ee=e.id,t.style.background=g.bgActive,t.style.fontWeight="600";const{kind:n,index:i}=e.variable;n==="test"?v({plotMode:"value",activeTest:i??0,highlightBin:void 0},{fireCallback:!1}):n==="softBin"?v({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):v({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1}),Ee(),Oe();const l=e.highlight;if(l.kind==="wafer"){Be(l.waferIndices);const o=Ze(e);for(const s of l.waferIndices){const d=S[s]?.statsSummary?.findings.find(p=>Ze(p)===o)?.highlight?.dieKeys;d?.length&&De(d,[s])}}else l.kind==="bin"?l.dieKeys?.length&&De(l.dieKeys):(l.kind==="region"||l.kind==="dies")&&l.dieKeys?.length&&De(l.dieKeys)}function G(){if(!E)return;const e=!!f;E.style.display=(T||ue())&&e&&!Ie?"flex":"none";const t=f?f.style.display!=="none":!1;(T?.hasNotableFindings||x.some(i=>i?.statsSummary?.hasNotableFindings))&&!t?E.style.color=g.findingIndicator:E.dataset.active||(E.style.color=g.icon)}const L=document.createElement("div");L.dataset.wmapToolbar="gallery",Object.assign(L.style,{display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"3px 4px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const Je=()=>{const e=me();e&&(e.remove(),ge(null)),Ce(H,!1)},H=_("mode","Plot mode",()=>{if(me()){Je();return}const e=x.flatMap(u=>u?.dies??[]),t=x.find(u=>u?.testDefs?.length)?.testDefs,{testEntries:n,binEntries:i,stackedEntries:l}=Fn(e,t,{includeStacked:!0}),o=c.plotMode??"hardBin",s=c.activeTest??0;function r(u){return u.plotMode!==o?!1:u.plotMode==="value"?s===(u.activeTest??0):u.plotMode==="metadata"?c.activeMetadataKey===u.activeMetadataKey:!0}function a(u,O){u.activeTest!==void 0?v({plotMode:"value",activeTest:u.activeTest,activeMetadataKey:void 0,logScale:u.logScale}):u.activeMetadataKey!==void 0?v({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:u.activeMetadataKey,passFailDisplay:"off"}):v({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),O.remove(),ge(null),Ce(H,!1)}const d=new Set,p=x.flatMap(u=>u?.metadataFields??[]).filter(u=>!d.has(u.key)&&d.add(u.key)).filter(u=>Hn(e,u.key)).map($n),h=vn(H.getBoundingClientRect(),n,i,l,r,a,{makeMenuRow:Pt,makeMenuSection:At},o,H.ownerDocument.defaultView??window,p);In(H).appendChild(h),ge(h),Ce(H,!0),Rn(h,H,Je)});Ce(H,!1);const $t=()=>S.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:jt,sync:et}=En(U,()=>c.plotMode??"hardBin",()=>c.colorScheme??"default",$t,e=>v({colorScheme:e}));et();const zt=k.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Le(){const e=x.find(n=>n?.testDefs?.length)?.testDefs,{testNumber:t}=pn(c.activeTest??0,e);return{testNumber:t,td:fn(e,t)}}function tt(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=Le();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function ie(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=Le();return e!==void 0&&!Mt(e)}function Nt(){if((c.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Le();return x.some(n=>n?.dies?.some(i=>Vn(i,e,t)!==void 0))}const Vt=Tn(U,()=>[{label:"Ring boundaries",active:!!c.showRingBoundaries,onClick:()=>v({showRingBoundaries:!c.showRingBoundaries})},{label:"Quadrant lines",active:!!c.showQuadrantBoundaries,onClick:()=>v({showQuadrantBoundaries:!c.showQuadrantBoundaries})},{label:"Die labels",active:!!c.showDieLabels,onClick:()=>v({showDieLabels:!c.showDieLabels})},{label:"Reticle grid",active:!!c.showReticle,enabled:zt,onClick:()=>v({showReticle:!c.showReticle})},{label:"XY indicator",active:!!c.showXYIndicator,onClick:()=>v({showXYIndicator:!c.showXYIndicator})},...Pn({functionalActive:ie(),hasLimits:tt()&&!ie(),hasRecorded:Nt()&&!ie(),display:ze(c)},e=>v({passFailDisplay:e}))],()=>!!(c.showRingBoundaries||c.showQuadrantBoundaries||c.showDieLabels||c.showReticle||c.showXYIndicator||ze(c)!=="off")),{btn:_t,sync:nt}=Dn(U,()=>({plotMode:c.plotMode,legendPosition:J}),e=>{J=e;for(const t of w)t&&t.setOptions({legendPosition:J})});nt();const Gt=[{value:"mean",label:"Mean"},{value:"median",label:"Median"},{value:"stddev",label:"Std Dev"},{value:"min",label:"Min"},{value:"max",label:"Max"},{value:"count",label:"Count"}],it=Xe("aggr","Aggregation method",()=>Gt,()=>c.aggregationMethod??"mean",e=>v({aggregationMethod:e}));function at(){const e=c.plotMode==="stackedValues";it.style.display=e?"":"none"}at();const{btn:Kt,sync:ot}=On(U,()=>({...c,functionalActive:ie()}),e=>v(e));ot();const he=_("specRange","Colorbar range: spec limits",()=>{const e=c.colorbarRangeMode==="data"?"spec":"data";v({colorbarRangeMode:e})});function lt(){const e=(c.plotMode??"hardBin")==="value"&&tt()&&ze(c)==="off"&&!ie();he.style.display=e?"":"none";const t=(c.colorbarRangeMode??"spec")==="spec";ne(he,t),he.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}lt();const qt=Ln(U,()=>c,e=>v(e)),Xt=_("downloadAll","Download gallery PNG",rn),Ut=Xe("columns","Columns",()=>[{value:"auto",label:"Auto"},{value:"1",label:"1 column"},{value:"2",label:"2 columns"},{value:"3",label:"3 columns"},{value:"4",label:"4 columns"},{value:"5",label:"5 columns"}],()=>I!=null?String(I):"auto",e=>mt(e==="auto"?void 0:Number(e))),C=document.createElement("div");Object.assign(C.style,{display:"inline-flex",alignItems:"center",gap:"0"}),L.appendChild(C),Ot&&C.appendChild(H),C.appendChild(jt),C.appendChild(it),C.appendChild(Kt),C.appendChild(he),C.appendChild(F()),C.appendChild(Vt),C.appendChild(F()),C.appendChild(_t),C.appendChild(F()),C.appendChild(qt),C.appendChild(F()),C.appendChild(Ut),C.appendChild(F()),C.appendChild(Xt),(T||ue())&&(E=_("findings","Summary panel",()=>{if(!f)return;const e=f.style.display!=="none";e||W(),f.style.display=e?"none":"flex",ne(E,!e),G()}),L.appendChild(F()),L.appendChild(E));let Y=null;_e&&(Y=_("analysis","Insights",()=>{const e=Q?.style.display!=="none";rt(!e)}),L.appendChild(F()),L.appendChild(Y));function st(){import("./userGuideHtml.js").then(e=>Bn({buildWaferMap:Nn,renderWaferMap:Ne,renderWaferGallery,analyzeWaferMap:Se},e.USER_GUIDE_HTML,Tt,M))}Dt&&(L.appendChild(F()),L.appendChild(_("help","User guide",()=>st())));const N=document.createElement("div");Object.assign(N.style,{display:"flex",flexDirection:"column",gap:"6px",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"6px 10px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"});const A=document.createElement("div");Object.assign(A.style,{display:"flex",flexDirection:"row",gap:"12px",alignItems:"flex-start"});let ae=null,Q=null;_e&&(ae=Qn({getItems:()=>x,getLotStats:()=>T,getColorSchemeName:()=>c.colorScheme??"default",passBins:Ge,getRingCount:()=>c.ringCount??4,defaultView:m.insights?.defaultView,backTab:{label:"Gallery",onBack:()=>rt(!1)},showMetadataStrip:!1,onSaveImage:m.onSaveImage,onSaveText:m.onSaveText,openWafer:(e,t,n)=>{const i=x[e];if(!i)return;let l=null;const o=Sn({title:t,onClose:()=>l?.destroy(),anchor:M});ht(o,t,i.wafer.metadata??void 0),l=Fe(o.contentWrap,i,n)}}),Q=ae.el);let Ie=!1;function rt(e){!ae||!Q||(Ie=e,Q.style.display=e?"flex":"none",A.style.display=e?"none":"flex",C.style.display=e?"none":"inline-flex",Y&&(ne(Y,e),Y.innerHTML=e?re.wafer:re.analysis,Y.ariaLabel=e?"Back to gallery view":"Insights"),G(),xe(),e&&ae.render())}const Yt=4,We=240,dt=480,Qt=720,Zt=1.25,ct=m.maxSize;let $=ct??dt;function pt(e){const t=K*2+110+2;let n=null;for(const i of e){if(i==null||!i.dies?.length)continue;const l=i.dies[0].width;if(!(l>0))continue;const o=i.wafer.radius*2*(Yt/l),s=Math.ceil(o+t);(n==null||s>n)&&(n=s)}return n}function Jt(e){const t=pt(e);return t==null?We:Math.min($,Math.max(We,t))}function en(e){if(ct!=null)return!1;const t=pt(e);if(t==null)return!1;const n=Math.min(Qt,Math.max(dt,t));return n<=$?!1:($=n,!0)}function tn(){for(const e of Array.from(B.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${$}px`,e.style.maxHeight=`${$}px`)}let be=We,ft=0;function ut(e){const t=en(e);if(t&&tn(),I!=null){t&&ye();return}const n=Jt(e);n>be&&(be=n),ye()}function mt(e){I=e,ye()}function Re(e){return`repeat(${e}, minmax(0, ${$}px))`}function ye(){if(I!=null){B.style.gridTemplateColumns=Re(I);return}const e=Math.max(1,ft),t=12,n=B.clientWidth||0,i=o=>(n-t*(o-1))/o;let l=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){for(;l>1&&i(l)<be;)l--;const o=Math.min($,be*Zt);for(;l<e&&i(l+1)>=o;)l++}B.style.gridTemplateColumns=Re(l)}const B=document.createElement("div");if(Object.assign(B.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:Re(1),gap:"12px",justifyContent:"start",alignContent:"start"}),te=T?"lot":"wafers",q?.placement){const e=q.placement;f=Ve(e),f.style.maxHeight="calc(100vh - 80px)",f.style.position="sticky",f.style.top="8px",f.style.display="flex",f.style.flexDirection="column"}else if(T||ue()){const e=!!q?.defaultOpen;f=Ve("right"),f.style.maxHeight="calc(100vh - 80px)",f.style.position="sticky",f.style.top="8px",f.style.flexDirection="column",f.style.display=e?"flex":"none",W()}G(),f?.style.display!=="none"&&E&&ne(E,!0),(q?.placement??"right")==="left"?(f&&A.appendChild(f),A.appendChild(B)):(A.appendChild(B),f&&A.appendChild(f)),M.appendChild(L),M.appendChild(N),M.appendChild(A),Q&&M.appendChild(Q);function xe(){N.innerHTML="";const e=c.plotMode??"hardBin",t=!Ie&&hn.has(e),n=S.filter(b=>b!=null),i=n.find(b=>b.isLotStack),l=Gn(n.map(b=>({metadata:b.wafer.metadata??void 0})),i?{lotSize:i.lotSize??n.length,aggrMethod:i.aggrMethod}:void 0),o=e==="metadata",s=c.activeMetadataKey,r=new Set;if(t&&!o)for(const b of n)for(const D of b.dies){if(D.partial)continue;const y=e==="softBin"?D.sbin:D.hbin;y!=null&&r.add(y)}const a=t&&!o?[...r].sort((b,D)=>b-D):[],d=new Set;if(t&&o&&s)for(const b of n)for(const D of b.dies){if(D.partial)continue;const y=D.metadata?.[s];y!=null&&(typeof y=="string"||typeof y=="number"||typeof y=="boolean")&&d.add(String(y))}const p=t&&o?[...d].sort(_n):[];if(!l&&!a.length&&!p.length){N.style.display="none";return}if(N.style.display="flex",l&&N.appendChild(l),!a.length&&!p.length)return;const h=document.createElement("div");Object.assign(h.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"6px 14px"}),l&&Object.assign(h.style,{borderTop:`1px solid ${g.separator}`,paddingTop:"6px"}),N.appendChild(h);const u=un(c.colorScheme),O=c.highlightBin;if(o){const b=c.highlightMetadataValue,D=S.flatMap(y=>y?.metadataFields??[]).find(y=>y.key===s);p.forEach((y,He)=>{const $e=b===y,yt=D?.values?.find(je=>je.value===y),dn=yt?.color??mn(He);Et(h,{color:dn,isActive:$e,label:yt?.label??y,onClick:()=>{const je=c.highlightMetadataValue===y?void 0:y;v({highlightMetadataValue:je})}})});return}const z=e==="softBin"?S.flatMap(b=>b?.sbinDefs??[]):S.flatMap(b=>b?.hbinDefs??[]),R=new Set,le=[];for(const b of z)R.has(b.bin)||(R.add(b.bin),le.push(b));const se=le.length>0?new Map(le.map(b=>[b.bin,b])):null;for(const b of a){const D=O===b,y=se?.get(b),He=(c.colorScheme==="custom"?y?.color:void 0)??u.forBin(b);Et(h,{color:He,isActive:D,label:y?.name?`${b} \xB7 ${y.name}`:`Bin ${b}`,onClick:()=>{const $e=c.highlightBin===b?void 0:b;v({highlightBin:$e})}})}}function oe(e){const t=x.filter(r=>r!==null);if(!t.length)return[];const n=t.map(r=>r.dies),i=t[0].wafer,l=t.length,o=i.metadata?{...i,metadata:(({wafer:r,waferId:a,...d})=>d)(i.metadata)}:i;function s(r,a){return{...r,stats:{...r.stats,isLotStack:!0,aggregationMethod:a,lotSize:l}}}if(e==="stackedValues"){const r=t.find(p=>p.testDefs?.length)?.testDefs;let a=r?.filter(Mt);if(r?.length||(a=cn(t.flatMap(h=>h.dies)).map(h=>({testNumber:h,name:`Test ${h}`}))),!a?.length)return[];const d=c.aggregationMethod??"mean";return a.map(p=>{const h=jn(n,d,p.testNumber),u={testNumber:0,name:p.name,unit:p.unit};return{wafer:o,dies:h,testDefs:[u],label:`${p.name} \xB7 ${d}`,isLotStack:!0,aggrMethod:d,lotSize:l,statsSummary:s(Se({wafer:o,dies:h,testDefs:[u]},{testNumbers:[0]}),d)}})}if(e==="stackedBins"){let r=Me(t.flatMap(a=>a.hbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(d=>d.dies.map(p=>p.hbin).filter(p=>p!=null)))].sort((d,p)=>d-p).map(d=>({bin:d,name:`Bin ${d}`}))),r.map(a=>{const d=St(n,a.bin,"hard"),p=[{bin:a.bin,name:a.name}];return{wafer:o,dies:d,hbinDefs:p,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:l,statsSummary:s(Se({wafer:o,dies:d,hbinDefs:p}),"countBin")}})}if(e==="stackedSoftBins"){let r=Me(t.flatMap(a=>a.sbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(d=>d.dies.map(p=>p.sbin).filter(p=>p!=null)))].sort((d,p)=>d-p).map(d=>({bin:d,name:`Bin ${d}`}))),r.map(a=>{const d=St(n,a.bin,"soft"),p=[{bin:a.bin,name:a.name}];return{wafer:o,dies:d,sbinDefs:p,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:l,statsSummary:s(Se({wafer:o,dies:d,sbinDefs:p}),"countBin")}})}return t}function Pe(e){const t=x.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:c.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const nn=new Set(["default","accessible","custom"]);function v(e,{fireCallback:t=!0}={}){const n=c.plotMode;c={...c,...e};const i=c.plotMode,l=de.has(i),o=n!==void 0&&de.has(n),s=fe>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(i==="hardBin"||i==="softBin")&&!nn.has(c.colorScheme??"")&&(c={...c,colorScheme:"default"}),e.plotMode!==void 0)if(l){const a=Pe(i);if(c={...c,...a},s)for(const d of w)d&&d.setOptions(e);else j(oe(i))}else if(o){const{valueRange:a,lotSize:d,aggregationMethod:p,...h}=c;if(c=h,s)for(const u of w)u&&u.setOptions(e);else j(x.filter(u=>u!==null))}else for(const a of w)a&&a.setOptions(e);else if(e.aggregationMethod!==void 0&&i==="stackedValues")if(s)for(const a of w)a&&a.setOptions(e);else j(oe("stackedValues"));else for(const a of w)a&&a.setOptions(e);xe(),at(),nt(),et();const r=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||r)&&W(),ot(),lt(),t){const a=Object.keys(e);m.onViewOptionsChange?.(c,a,zn(a))}}function gt(e,t,n){const i=e.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0"});const l=e.createElement("span");l.textContent=t,Object.assign(l.style,{fontWeight:"700",fontSize:"13px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),i.appendChild(l);const o=Bt(n??{});let s=null;if(o.length>0){const r=e.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),r.textContent="\u25BE",i.appendChild(r),Object.assign(i.style,{cursor:"pointer"}),s=e.createElement("div"),s.dataset.wmapCardMetaPanel="1",Object.assign(s.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:vt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const a=kt(n??{});a&&s.appendChild(a),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Ct(i,d=>{r.textContent=d?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(d)),s&&(s.style.display=d?"block":"none")})}return{wrap:i,metaPanel:s}}function ht(e,t,n){const i=e.box.querySelector("[data-wmap-window-title]"),l=Bt(n??{});if(!i||l.length===0)return;const o=i.parentElement,s=document.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0",cursor:"pointer"}),o?.insertBefore(s,i),s.appendChild(i);const r=document.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),r.textContent="\u25BE",s.appendChild(r);const a=document.createElement("div");a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:vt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const d=kt(n??{});d&&a.appendChild(d),e.contentWrap.style.position="relative",e.contentWrap.appendChild(a),s.setAttribute("aria-expanded","false"),s.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Ct(s,p=>{r.textContent=p?"\u25B4":"\u25BE",s.setAttribute("aria-expanded",String(p)),a.style.display=p?"block":"none"})}function Ae(e,t,n){const i=document.createElement("div");i.className="wmap-gallery-card",Object.assign(i.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${$}px`,maxHeight:`${$}px`});const l=document.createElement("div");Object.assign(l.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"});const{wrap:o,metaPanel:s}=gt(document,e.label??"",e.wafer.metadata??void 0);l.appendChild(o);const r=document.createElement("button");r.dataset.wmapExpandBtn="1",r.title="Open full view",r.innerHTML=re.expand,Object.assign(r.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${g.menuBorder}`,borderRadius:"4px",background:g.panelBg,color:g.label,padding:"2px",cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),l.appendChild(r),i.appendChild(l);const a=document.createElement("div");Object.assign(a.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),i.appendChild(a),s&&a.appendChild(s),B.appendChild(i);const d=Ne(a,e,{viewOptions:e.viewOptions?{...c,...e.viewOptions}:c,toolbarControls:"full",showTooltip:!0,padding:K,legendPosition:J,fallbackFormat:pe,statsSummary:e.statsSummary,onSaveImage:m.onSaveImage,onSaveText:m.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>ve(t,e),showMetadataBadge:!1});return d.setViewControlsVisible(!1),d.setSummaryVisible(!1),r.onclick=()=>ve(t,e),{card:i,ctrl:d,canvasWrapper:a,expandBtn:r}}function an(e){const t=X[e];if(!t)return;const n=[...P.values()].find(i=>i.cardIndex===e);n?(t.innerHTML=re.minimize,t.title="Reattach to gallery",t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>ln(n.id)):(t.innerHTML=re.expand,t.title="Open full view",t.setAttribute("aria-label","Open full view"),t.onclick=()=>ve(e,S[e]))}function j(e){sn(),me()?.remove(),ge(null),Te(),S=[];for(const s of w)s&&s.destroy();w=[],V=[],X=[],fe=0,B.innerHTML="",ft=e.length,ut(e.map(s=>typeof s=="function"?null:s));const t=[];for(let s=0;s<e.length;s++){const r=e[s];if(typeof r=="function"){const a=document.createElement("div");a.className="wmap-gallery-card",Object.assign(a.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const d=document.createElement("span");d.textContent="\u2026",Object.assign(d.style,{color:g.label,fontSize:"18px"}),a.appendChild(d),B.appendChild(a),S.push(null),w.push(null),V.push(null),X.push(null),t.push({index:s,factory:r,placeholder:a}),fe++}else{const{ctrl:a,canvasWrapper:d,expandBtn:p}=Ae(r,s,e.length);S.push(r),w.push(a),V.push(d),X.push(p)}}S.flatMap(s=>s?[...s.hbinDefs??[],...s.sbinDefs??[]]:[]).some(s=>s.color)&&!m.viewOptions?.colorScheme&&(c={...c,colorScheme:"custom"}),xe();const i=++ke;let l=0;function o(){if(i!==ke)return;if(l>=t.length){if(de.has(c.plotMode)){const z=c.plotMode;j(oe(z))}return}const{index:s,factory:r,placeholder:a}=t[l++],d=r();S[s]=d,x[s]=d,ut([d]);const{card:p,ctrl:h,canvasWrapper:u,expandBtn:O}=Ae(d,s,e.length);w[s]=h,V[s]=u,X[s]=O,fe--,a.replaceWith(p),xe(),!f&&!q?.placement&&d.statsSummary?.findings.length?(T||(te="wafers"),f=Ve("right"),f.style.maxHeight="calc(100vh - 80px)",f.style.position="sticky",f.style.top="8px",f.style.flexDirection="column",f.style.display="none",(q?.placement??"right")==="left"?A.insertBefore(f,B):A.appendChild(f),W(),E||(E=_("findings","Summary panel",()=>{if(!f)return;const R=f.style.display!=="none";R||W(),f.style.display=R?"none":"flex",ne(E,!R),G()}),L.appendChild(F()),L.appendChild(E)),G()):f&&f.style.display!=="none"&&W(),G(),setTimeout(o,0)}t.length>0&&setTimeout(o,0)}if(de.has(c.plotMode)&&x.length>0){const e=Pe(c.plotMode);c={...c,...e},j(oe(c.plotMode))}else j(k);const bt=new ResizeObserver(()=>{I==null&&ye()});bt.observe(B),f&&W();function on(e){const t=V[e];if(!t)return;t.innerHTML="",Object.assign(t.style,{alignItems:"center",justifyContent:"center"});const n=document.createElement("span");n.textContent="Detached \u2014 open in its own window",Object.assign(n.style,{color:g.label,fontSize:"12px",textAlign:"center",padding:"0 12px"}),t.appendChild(n)}function ve(e,t){for(const o of P.values())if(o.cardIndex===e)return;const n=t.label??"Wafer map",i=It++,l=wn(n);if(l){const o=l.document;o.title=n,Object.assign(o.documentElement.style,{height:"100%"}),Object.assign(o.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),Mn(M,o.documentElement);const s=kn(M,o.documentElement,()=>O.setOptions({})),r=o.createElement("div");r.dataset.wmapWindowBanner="1",r.textContent=n,Object.assign(r.style,{display:"none",padding:"6px 12px",fontSize:"12px",fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),o.body.appendChild(r);const a=o.createElement("div");Object.assign(a.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),o.body.appendChild(a);const{wrap:d,metaPanel:p}=gt(o,n,t.wafer.metadata??void 0),h=o.createElement("div");Object.assign(h.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"}),h.appendChild(d),a.appendChild(h);const u=o.createElement("div");Object.assign(u.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),p&&u.appendChild(p),a.appendChild(u);const O=Fe(u,t),z=setInterval(()=>{l.closed&&we(i)},400);l.addEventListener("pagehide",()=>we(i)),P.set(i,{id:i,ctrl:O,cardIndex:e,label:n,closePollId:z,stopThemeSync:s,close:()=>{l.closed||l.close()},setTitle:R=>{o.title=R,r.textContent=R,r.style.display="block"}})}else{const o=Cn({title:n,onClose:()=>we(i),anchor:M});o.contentWrap.style.flexDirection="column",ht(o,n,t.wafer.metadata??void 0);const s=Fe(o.contentWrap,t);P.set(i,{id:i,ctrl:s,cardIndex:e,label:n,closePollId:null,close:()=>o.close(),setTitle:r=>{const a=o.box.querySelector("[data-wmap-window-title]");a&&(a.textContent=r,a.title=r)}})}w[e]?.destroy(),w[e]=null,on(e),an(e)}function Fe(e,t,n){const i=t.viewOptions?{...c,...t.viewOptions}:c,l=n!==void 0?{...i,plotMode:"value",activeTest:n}:i,o=Ne(e,t,{viewOptions:l,toolbarControls:"full",showTooltip:!0,padding:K,legendPosition:J,fallbackFormat:pe,statsSummary:t.statsSummary,onSaveImage:m.onSaveImage,onSaveText:m.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showMetadataBadge:!1});return o.setViewControlsVisible(!0),o.setSummaryVisible(!0),o.setExpandVisible(!1),o}function we(e){const t=P.get(e);if(!t)return;P.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const i=t.cardIndex,l=S[i];if(!l)return;const o={...l,viewOptions:n};S[i]=o;const{card:s,ctrl:r,canvasWrapper:a,expandBtn:d}=Ae(o,i,S.length);V[i]?.parentElement?.replaceWith(s),w[i]=r,V[i]=a,X[i]=d}function ln(e){const t=P.get(e);t&&(t.close(),we(e))}function sn(){for(const e of P.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function rn(){const e=[...B.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),i=Math.ceil(t/n),l=e[0].width,o=e[0].height,s=8,r=window.devicePixelRatio||1,a=Math.round(26*r),d=Math.round(12*r),p=document.createElement("canvas");p.width=n*l+(n-1)*s,p.height=i*(o+a)+(i-1)*s;const h=p.getContext("2d"),u=gn(B);h.fillStyle=u.background,h.fillRect(0,0,p.width,p.height),e.forEach((O,z)=>{const R=z%n,le=Math.floor(z/n),se=R*(l+s),b=le*(o+a+s),D=O.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";h.fillStyle=u.surface,h.fillRect(se,b,l,a),h.fillStyle=u.text,h.font=`700 ${d}px system-ui, sans-serif`,h.textAlign="left",h.textBaseline="middle",h.fillText(D,se+Math.round(10*r),b+a/2,l-Math.round(20*r)),h.drawImage(O,se,b+a)}),p.toBlob(O=>{O&&Wn(O,Z,m.onSaveImage)})}return{setItems(e){x=e.map(n=>typeof n=="function"?null:n);const t=c.plotMode;if(de.has(t))if(e.some(i=>typeof i=="function"))j(e);else{const i=Pe(t);c={...c,...i},j(oe(t))}else j(e)},setOptions(e){v(e,{fireCallback:!1})},getOptions(){return{...c}},setFallbackFormat(e){pe=e;for(const t of w)t&&t.setFallbackFormat(e)},setLotStatsSummary(e){T=e,f&&W(),G()},setColumns(e){mt(e)},openUserGuide:st,destroy(){ke++;for(const e of[...P.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();P.clear();for(const e of w)e&&e.destroy();w=[],me()?.remove(),bt.disconnect(),M.ownerDocument.removeEventListener("click",Ue,!0),window.removeEventListener("blur",Ye),Lt(),wt(),L.remove(),N.remove(),A.remove(),f?.remove(),ae?.destroy()}}}
@@ -0,0 +1,316 @@
1
+ import type { PlotMode } from '../renderer/buildView.js';
2
+ import type { Die } from '../core/dies.js';
3
+ import { type ToCanvasOptions } from './toCanvas.js';
4
+ import type { WaferMapResult } from '../renderer/buildWaferMap.js';
5
+ import type { StatsSummary } from '../stats/types.js';
6
+ import { type SaveImageHandler, type SaveTextHandler, type UserGuideExtension } from './toolbar.js';
7
+ import type { SummaryPanelOptions } from './summaryPanel.js';
8
+ import { type InsightsOptions } from './insightsTab.js';
9
+ /**
10
+ * Stable display preferences — worth persisting to localStorage or a user profile.
11
+ * These describe how the user wants to view wafer maps in general.
12
+ */
13
+ export interface WaferPreferences {
14
+ colorScheme?: string;
15
+ /** Interactive rotation in degrees (0 | 90 | 180 | 270). */
16
+ rotation?: 0 | 90 | 180 | 270;
17
+ flipX?: boolean;
18
+ flipY?: boolean;
19
+ showDieLabels?: boolean;
20
+ showRingBoundaries?: boolean;
21
+ showQuadrantBoundaries?: boolean;
22
+ showReticle?: boolean;
23
+ showXYIndicator?: boolean;
24
+ ringCount?: number;
25
+ /** Legend position for bin modes. Default 'default'. */
26
+ legendPosition?: 'default' | 'compact' | 'bottom' | 'top' | 'left' | 'floating';
27
+ /**
28
+ * When true, apply log₁₀ scale to value normalization and the colorbar.
29
+ * Overrides the per-test TestDef.logScale default.
30
+ * Falls back to linear when vMin ≤ 0.
31
+ */
32
+ logScale?: boolean;
33
+ /**
34
+ * Controls the default colorbar range when the active testDef has spec limits.
35
+ * `'spec'` (default): colorbar spans [limitLow, limitHigh]; out-of-spec dies show fail colors.
36
+ * `'data'`: colorbar spans actual data min/max; out-of-spec coloring still applies.
37
+ */
38
+ colorbarRangeMode?: 'spec' | 'data';
39
+ /**
40
+ * When true (default), partial (edge) dies are rendered in muted grey.
41
+ * Set to false to hide them entirely, matching real prober behaviour where
42
+ * positions outside the wafer circle are never tested.
43
+ */
44
+ showPartialDies?: boolean;
45
+ }
46
+ /**
47
+ * Transient display state — describes the current view session, not worth persisting.
48
+ * Changes frequently as the user navigates tests and modes.
49
+ */
50
+ export interface WaferDisplayState {
51
+ plotMode?: PlotMode;
52
+ /**
53
+ * Requested pass/fail display for `value` mode — `'spec'` (spec-limit judgement),
54
+ * `'test'` (the tester's recorded verdict from `die.testPass`), or `'off'` (gradient).
55
+ * The library resolves the effective display from the data; a functional active
56
+ * test always renders as `'test'`. Toggled by the Overlays toolbar menu.
57
+ */
58
+ passFailDisplay?: 'off' | 'spec' | 'test';
59
+ /**
60
+ * Which test number to display in `value` plot mode. Default `0`.
61
+ * Controlled by the mode dropdown when the result has testDefs.
62
+ */
63
+ activeTest?: number;
64
+ /**
65
+ * Which `die.metadata` key to display in `'metadata'` plot mode. Must match
66
+ * a `key` in the result's `metadataFields`. Controlled by the mode dropdown
67
+ * when the result has `metadataFields`.
68
+ */
69
+ activeMetadataKey?: string;
70
+ highlightBin?: number;
71
+ /** Dim every die except this metadata value in `'metadata'` mode — the analogue of `highlightBin`. */
72
+ highlightMetadataValue?: string;
73
+ /**
74
+ * Explicit value colour normalization range.
75
+ *
76
+ * - Tuple `[min, max]`: applied to whichever test is active (caller owns the
77
+ * coupling with `activeTest`).
78
+ * - Object `{ test, range }`: applied only when `test` matches the active
79
+ * test; ignored (auto-scale) on mismatch, so one test's data can never be
80
+ * coloured against another test's range. Prefer this when the range was
81
+ * computed for a specific test.
82
+ *
83
+ * When omitted, the range is auto-computed from the die values present.
84
+ */
85
+ valueRange?: [number, number] | {
86
+ test: number;
87
+ range: [number, number];
88
+ };
89
+ /**
90
+ * Aggregation method for `stackedValues` mode.
91
+ * Drives both the per-die aggregation and the hover tooltip label.
92
+ * Accepted values: `'mean'` | `'median'` | `'stddev'` | `'min'` | `'max'` | `'count'`.
93
+ * Defaults to `'mean'` when not set.
94
+ */
95
+ aggregationMethod?: string;
96
+ /**
97
+ * Total number of wafers in the lot — used to compute bin occurrence percentage
98
+ * in `stackedBins` hover tooltips.
99
+ */
100
+ lotSize?: number;
101
+ }
102
+ /**
103
+ * All scene-level options that the toolbar can control.
104
+ * Combines stable {@link WaferPreferences} with transient {@link WaferDisplayState}.
105
+ * The flat shape is unchanged — callers set any field directly.
106
+ * Use the `category` hint in {@link RenderOptions.onViewOptionsChange} to decide
107
+ * whether a change is worth persisting.
108
+ */
109
+ export type WaferViewOptions = WaferPreferences & WaferDisplayState;
110
+ export interface RenderOptions extends Omit<ToCanvasOptions, 'viewport' | 'hbinDefs' | 'sbinDefs'> {
111
+ /** Initial scene display options. All are overridable via the toolbar. */
112
+ viewOptions?: WaferViewOptions;
113
+ /** Called when the user hovers over a die. Null when leaving a die. */
114
+ onHover?: (die: Die | null, event: MouseEvent) => void;
115
+ /** Called when the user clicks a die. */
116
+ onClick?: (die: Die, event: MouseEvent) => void;
117
+ /** Called when the user completes a box-select. */
118
+ onSelect?: (dies: Die[]) => void;
119
+ /**
120
+ * Called whenever the toolbar changes a scene option.
121
+ * `changed` lists the keys that changed.
122
+ * `category` is `'preference'` when all changed keys are {@link WaferPreferences},
123
+ * `'state'` when all are {@link WaferDisplayState}, or `'mixed'` when both.
124
+ * Use `category !== 'state'` to decide whether to persist the new options.
125
+ */
126
+ onViewOptionsChange?: (opts: WaferViewOptions, changed: (keyof WaferViewOptions)[], category: 'preference' | 'state' | 'mixed') => void;
127
+ /** Show built-in floating tooltip on hover. Default true. */
128
+ showTooltip?: boolean;
129
+ /** Show the built-in toolbar. Default true. */
130
+ showToolbar?: boolean;
131
+ /**
132
+ * Show a small always-visible metadata badge (lot, wafer ID, product, test
133
+ * program, temperature, etc.) overlaid bottom-left on the canvas. Default
134
+ * true. Independent of `showToolbar` and the Insights tab — this exists so
135
+ * basic wafer/lot identity is never hidden behind a mode or toggle, without
136
+ * costing any layout space (it's an overlay, not a layout element). Renders
137
+ * nothing when the result has no metadata at all. Collapsed by default to a
138
+ * single identifying line; click/Enter/Space expands in place to the full
139
+ * field set.
140
+ */
141
+ showMetadataBadge?: boolean;
142
+ /** Optional precomputed wafer-level stats summary. Enables the summary panel toggle button in the toolbar. */
143
+ statsSummary?: StatsSummary;
144
+ /**
145
+ * Bin numbers treated as pass for yield calculation in the summary panel.
146
+ * Defaults to `[1]`. Must match the `passBins` passed to `analyzeWaferMap` / `buildWaferMap`
147
+ * to ensure the summary panel yield label is consistent with the rest of the display.
148
+ */
149
+ passBins?: number[];
150
+ /**
151
+ * 'full' (default) shows all toolbar controls.
152
+ * 'view-only' shows only zoom, reset, box-select, and download — used by gallery cards.
153
+ */
154
+ toolbarControls?: 'full' | 'view-only';
155
+ /**
156
+ * Show the plot mode selector in the toolbar. Default true.
157
+ * Set to false when the host application manages mode switching itself.
158
+ */
159
+ showPlotModeSelector?: boolean;
160
+ /** Minimum zoom relative to fit. Default 0.4. */
161
+ minZoom?: number;
162
+ /** Maximum zoom relative to fit. Default 20. */
163
+ maxZoom?: number;
164
+ /** Filename for the PNG download (without extension). Default `'wafermap'`. */
165
+ downloadFilename?: string;
166
+ /**
167
+ * Host hook for persisting the rendered PNG. When provided, the toolbar's save
168
+ * action calls `onSaveImage(blob, suggestedName)` instead of triggering a
169
+ * browser `<a download>` — letting embedded hosts (Tauri, Electron, WebView2)
170
+ * route the image through a native save dialog. `suggestedName` includes the
171
+ * `.png` extension and is derived from `downloadFilename`. When omitted, the
172
+ * default browser download behaviour is unchanged.
173
+ */
174
+ onSaveImage?: SaveImageHandler;
175
+ /**
176
+ * Host hook for saving the Summary/Insights test-values table's "Export CSV"
177
+ * button. Mirrors `onSaveImage` — when provided, called with
178
+ * `(text, suggestedName, mimeType)` instead of triggering a browser
179
+ * `<a download>` (a silent no-op in Tauri/Electron/WebView2). When omitted,
180
+ * the default browser download behaviour is unchanged.
181
+ */
182
+ onSaveText?: SaveTextHandler;
183
+ /**
184
+ * Options for the always-available Summary panel — a docked panel
185
+ * (metadata, yield, bin breakdown, ring/quadrant yield, test values, and
186
+ * findings with severity/kind/region filters, click-to-highlight on the
187
+ * map) toggled via the toolbar's "Summary" button whenever `statsSummary`
188
+ * is supplied. Independent of `insights` below: this always shows/hides
189
+ * its own toolbar button regardless of whether Insights is open, since
190
+ * Insights has no map for a finding to highlight against.
191
+ */
192
+ summaryPanel?: SummaryPanelOptions;
193
+ /**
194
+ * Custom tooltip renderer. When provided, replaces the built-in tooltip content.
195
+ * Return a string (set as innerHTML), an HTMLElement (appended directly), or null to suppress the tooltip.
196
+ * The built-in tooltip wrapper (positioning, show/hide behaviour) is preserved.
197
+ */
198
+ renderTooltip?: (die: Die) => string | HTMLElement | null;
199
+ /**
200
+ * Show a help button in the toolbar that opens the built-in end-user guide in a modal.
201
+ * Default false. Enable in applications that want to surface the guide without linking externally.
202
+ */
203
+ showHelpButton?: boolean;
204
+ /**
205
+ * Host-supplied content inserted into the built-in end-user guide window
206
+ * (see `showHelpButton`) — e.g. a host app's own documentation, so the user
207
+ * has one help button instead of two. See `UserGuideExtension`.
208
+ */
209
+ userGuideExtension?: UserGuideExtension;
210
+ /** Override the expand action for both the expand button and the E key. Used by the gallery to route through its own modal logic. */
211
+ onExpand?: () => void;
212
+ /**
213
+ * Show the toolbar expand button and enable the E-key shortcut. Default true.
214
+ * Set false when the host already renders the map inside its own expanded/modal
215
+ * context, where wmap's built-in expand modal would be redundant.
216
+ */
217
+ showExpandButton?: boolean;
218
+ /**
219
+ * Intrinsic height for the map. `renderWaferMap` fills its container, which
220
+ * therefore must have a resolved height — in a plain document a bare `<div>`
221
+ * has none and the map collapses to zero. Set this and the library sizes its
222
+ * own wrapper instead, so the map renders with no container CSS required.
223
+ * Accepts a number (px) or any CSS length (e.g. `'600px'`, `'70vh'`).
224
+ * Omit it when the container already has a height (flex/grid child, absolute
225
+ * inset, or an explicit CSS height). Width always comes from the container.
226
+ */
227
+ height?: number | string;
228
+ /**
229
+ * Cap the map's rendered width and height at this many CSS pixels. When
230
+ * the container is larger, the map sits top-left aligned within it rather
231
+ * than stretching to fill it. Number only (a fixed pixel ceiling, not a
232
+ * responsive length like `height`). Omit for no cap (fills the container,
233
+ * current behaviour). The expand button/E-key still opens the map at full
234
+ * size, unaffected by this cap.
235
+ */
236
+ maxSize?: number;
237
+ /**
238
+ * Base `z-index` for wmap's transient overlays — toolbar menus, the die
239
+ * tooltip, the expand modal, and the user-guide modal. wmap layers its own
240
+ * overlays from this value upward (tooltip and the modal box sit one or two
241
+ * above it). Set this when embedding a map inside your own modal/overlay so
242
+ * wmap's menus and tooltips appear above it.
243
+ *
244
+ * Omit it and wmap defaults overlays to a high value (above typical app modal
245
+ * layers), so they appear on top with no configuration. The value is applied
246
+ * for the lifetime of this render and restored on `destroy()`.
247
+ */
248
+ zIndex?: number;
249
+ /**
250
+ * Show an "Insights" tab in the toolbar (see `InsightsOptions`). Selecting
251
+ * it replaces the canvas with wmap's own chart suite, computed over this
252
+ * one wafer's dies (the same suite `renderWaferGallery`'s own `insights`
253
+ * shows for a whole lot, minus grouping — a single wafer has nothing to
254
+ * group by).
255
+ */
256
+ insights?: InsightsOptions;
257
+ }
258
+ export interface WaferMapController {
259
+ /** Update the die data (e.g. after a data reload) — rebuilds scene, preserves zoom/pan. */
260
+ setDies(dies: Die[]): void;
261
+ /** Replace the wafer map result entirely — updates both wafer geometry and die data, preserves zoom/pan. */
262
+ setResult(result: WaferMapResult): void;
263
+ /** Merge scene option overrides — rebuilds scene, preserves zoom/pan. */
264
+ setOptions(opts: Partial<WaferViewOptions>): void;
265
+ /** Return current scene options snapshot. */
266
+ getOptions(): WaferViewOptions;
267
+ /** Programmatically set the selected dies (renders highlight overlay). */
268
+ setSelection(dies: Die[]): void;
269
+ /** Clear the current selection. */
270
+ clearSelection(): void;
271
+ /** Reset zoom and pan to fitted view. */
272
+ resetZoom(): void;
273
+ /** Update the fallback format for unitless values and re-render. */
274
+ setFallbackFormat(format: 'si' | 'engineering'): void;
275
+ /** Replace the current stats summary used by the built-in Summary panel. */
276
+ setStatsSummary(summary: StatsSummary | undefined): void;
277
+ /** Show or hide the Summary toolbar button without affecting the panel's content. */
278
+ setSummaryVisible(visible: boolean): void;
279
+ /** Show or hide the scene-control toolbar buttons (mode, orientation, etc). */
280
+ setViewControlsVisible(visible: boolean): void;
281
+ /** Show or hide the expand toolbar button. */
282
+ setExpandVisible(visible: boolean): void;
283
+ /** Show or hide the help toolbar button. */
284
+ setHelpButtonVisible(visible: boolean): void;
285
+ /** Show or hide the metadata badge without affecting its content. */
286
+ setMetadataBadgeVisible(visible: boolean): void;
287
+ /**
288
+ * Opens the built-in end-user guide window — the same action the help
289
+ * toolbar button performs, but callable directly. Works regardless of
290
+ * `showHelpButton`/`setHelpButtonVisible`'s current value, so a host that
291
+ * hides wmap's own help button (e.g. to fold it into its own combined help
292
+ * menu) can still trigger the guide without a DOM query against wmap's
293
+ * internal button markup.
294
+ */
295
+ openUserGuide(): void;
296
+ /** Close the auto-mounted Summary panel if it is open. No-op if no panel exists. */
297
+ closeSummaryPanel(): void;
298
+ /** Programmatically open/close the Insights tab. No-op if `insights.enabled` was not set. */
299
+ setInsightsOpen(open: boolean): void;
300
+ /** Move the floating tooltip into a different parent (e.g. a maximized modal box). */
301
+ setTooltipParent(parent: HTMLElement): void;
302
+ /**
303
+ * Returns the current legend entries in `hardBin`/`softBin`/`metadata` modes, `null` in other
304
+ * modes. Each entry includes the bin number (or metadata value string), display name, and color.
305
+ */
306
+ getActiveLegend(): Array<{
307
+ bin: number | string;
308
+ name: string;
309
+ color: string;
310
+ }> | null;
311
+ /** Remove all event listeners and DOM elements. */
312
+ destroy(): void;
313
+ }
314
+ export declare function classifyChanged(keys: (keyof WaferViewOptions)[]): 'preference' | 'state' | 'mixed';
315
+ export declare function renderWaferMap(container: HTMLElement, result: WaferMapResult, options?: RenderOptions): WaferMapController;
316
+ //# sourceMappingURL=renderWaferMap.d.ts.map
@@ -0,0 +1 @@
1
+ import{buildView as Vn,buildHoverText as _n,findTestDef as vt,resolveTestNumber as bt}from"../renderer/buildView.js";import{toCanvas as Gn,BIN_LEGEND_W as dn,BIN_LEGEND_W_COMPACT as Zn,BIN_LEGEND_ADAPT_COMPACT as Qn,BIN_LEGEND_ADAPT_FLOATING as jn}from"./toCanvas.js";import{buildWaferMap as Un,getTestPassStatus as $n,isParametricTest as cn}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as qn}from"../stats/analyzeWaferMap.js";import{CLR as q,Z_BASE as Jn,applyOverlayZ as ei,getTooltip as pn,hideTooltip as $e,reparentTooltip as ti,positionTooltip as xt,createToolbarHelpers as ni,buildModeMenuEl as ii,openReparentedModal as oi,openUserGuideWindow as ai,makePaletteBtn as si,makeLogScaleBtn as li,makeLegendStyleBtn as ri,makeOverlaysBtn as di,makeOrientationBtn as ci,overlayRootFor as pi,saveImageBlob as fi,markMenuTrigger as qe,wireMenuA11y as ui,nextFrame as wt,passFailMenuRows as hi,requestedPassFailDisplay as Mt,logWmapVersionOnce as gi,buildDataModeEntries as mi,metadataKeyHasData as yi,metadataModeEntry as vi}from"./toolbar.js";import{createSummaryPanelEl as St,wrapWithSummaryPanel as Ct,renderWaferSummaryContent as bi}from"./summaryPanel.js";import"../stats/facets.js";import{ICONS as fn}from"./icons.js";import{hardBinColor as xi,softBinColor as wi,metadataValueColor as Mi}from"../renderer/colorMap.js";import{createInsightsTab as Si}from"./insightsTab.js";import{createMetadataBadge as Ci}from"./metadataBadge.js";import{getDieKey as Me}from"../core/dies.js";const un=new Set(["colorScheme","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","ringCount","legendPosition","logScale","colorbarRangeMode"]);export function classifyChanged(z){const w=z.some(R=>un.has(R)),M=z.some(R=>!un.has(R));return w&&M?"mixed":w?"preference":"state"}export function renderWaferMap(z,w,M={}){gi();const R=z.ownerDocument,_=R.defaultView??window;_.getComputedStyle(z).position==="static"&&(z.style.position="relative");const hn=z.clientHeight;M.height!=null&&(z.style.height=typeof M.height=="number"?`${M.height}px`:M.height);const J=document.createElement("div");Object.assign(J.style,{position:"relative",width:"100%",height:"100%"}),M.maxSize!=null&&(J.style.maxWidth=`${M.maxSize}px`,J.style.maxHeight=`${M.maxSize}px`),z.appendChild(J);const x=document.createElement("div");Object.assign(x.style,{position:"relative",width:"100%",height:"100%"});const a=document.createElement("canvas");Object.assign(a.style,{width:"100%",height:"100%",display:"block"}),x.appendChild(a),J.appendChild(x);const{onHover:Ye,onClick:gn,onSelect:oe,onViewOptionsChange:mn,showTooltip:yn=!0,showToolbar:fe=!0,showMetadataBadge:vn=!0,toolbarControls:Et="full",showPlotModeSelector:bn=!0,minZoom:xn=.4,maxZoom:wn=20,summaryPanel:Se,renderTooltip:Bt,passBins:kt=[1],showHelpButton:Mn=!1,userGuideExtension:Sn,onExpand:Dt,showExpandButton:Lt=!0,zIndex:Cn,insights:Pt,viewOptions:En={},...ae}=M,Bn=Pt?.enabled??!1,kn=ei(Cn);let Ce=ae.fallbackFormat,se=M.statsSummary,Je=w,ee=w.wafer,le=w.dies,S=new Set,Q=w.hbinDefs,j=w.sbinDefs,U=w.testDefs,Ee=w.metadataFields,Tt=w.reticles?.length?w.reticles:void 0,Ot=w.reticleConfig,Rt=w.view?.dataAxisFlip,et=w.isLotStack,tt=w.aggrMethod,nt=w.lotSize,It=!1,k=null;vn&&(k=Ci(ee.metadata,{lotStack:At()}),k.isEmpty()||x.appendChild(k.el));function At(){return et?{lotSize:nt??1,aggrMethod:tt}:void 0}function Dn(){if(!k)return;k.update(ee.metadata,At());const e=k.el.isConnected;k.isEmpty()&&e?k.el.remove():!k.isEmpty()&&!e&&x.appendChild(k.el)}const Ft=[...Q??[],...j??[]].some(e=>e.color);let s={plotMode:"hardBin",colorScheme:Ft?"custom":"default",showDieLabels:!1,showPartialDies:!0,showRingBoundaries:!1,showQuadrantBoundaries:!1,showReticle:!1,showXYIndicator:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,legendPosition:ae.legendPosition??"default",...En},te=null,ue=!1;Bn&&(te=Si({getItems:()=>[{wafer:ee,dies:le,hbinDefs:Q,sbinDefs:j,testDefs:U,label:String(ee.metadata?.waferId??""),statsSummary:se}],getColorSchemeName:()=>s.colorScheme??"default",passBins:kt,getRingCount:()=>s.ringCount??4,onSaveImage:M.onSaveImage,onSaveText:M.onSaveText,defaultView:Pt?.defaultView,backTab:{label:"Map",onBack:()=>it(!1)}}),Object.assign(te.el.style,{position:"absolute",inset:"0",background:q.panelBg,overflowY:"auto",paddingTop:fe?"44px":"0"}),J.appendChild(te.el));function it(e){te&&(ue=e,te.el.style.display=e?"flex":"none",F&&(F.style.display=e?"none":"flex"),E&&(E.style.display=e?"none":"flex"),G&&(G.style.display=e?"none":"flex"),k&&(k.el.style.display=e||It?"none":""),Ne(),Y&&(Y.innerHTML=e?fn.wafer:fn.analysis,Y.ariaLabel=e?"Back to wafer view":"Insights"),e&&te.render())}let h,Yt,I=null,D=null,ot=[],Be=null,at=ae.legendOffset??{x:0,y:0},ke=!1,he=!1,De={x:0,y:0},st={x:0,y:0},re=!1,ge=!1,H="pan",me={x:0,y:0},He={x:0,y:0},L={x:0,y:0},P={x:0,y:0},Le=!1,ye=!1;function Pe(){const e=s;h=Vn(ee,le,{plotMode:e.plotMode,colorScheme:e.colorScheme,showDieLabels:e.showDieLabels,showPartialDies:e.showPartialDies,showRingBoundaries:e.showRingBoundaries,showQuadrantBoundaries:e.showQuadrantBoundaries,showReticle:e.showReticle,showXYIndicator:e.showXYIndicator,reticles:Tt,ringCount:e.ringCount,highlightBin:e.highlightBin,highlightMetadataValue:e.highlightMetadataValue,activeTest:e.activeTest,activeMetadataKey:e.activeMetadataKey,testDefs:U,valueRange:e.valueRange,logScale:e.logScale,isLotStack:et,aggregationMethod:tt??e.aggregationMethod,lotSize:nt??e.lotSize,dataAxisFlip:Rt,colorbarRangeMode:e.colorbarRangeMode,passFailDisplay:e.passFailDisplay,fallbackFormat:Ce,interactiveTransform:{rotation:e.rotation??0,flipX:e.flipX??!1,flipY:e.flipY??!1}},{hbinDefs:Q,sbinDefs:j,metadataFields:Ee}),Yt=new Map(h.dies.map((t,n)=>[Me(t),n]))}Pe();let X=null,de=null,Xe=null,Ln={},T=null,$=null;function Pn(e){const{kind:t,index:n}=e.variable;v(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"?(ft(i.dieKeys),v({highlightBin:i.bin})):(i.kind==="region"||i.kind==="dies")&&ft(i.dieKeys)}function Ht(e){bi(e,{wafer:ee,dies:le,yieldSummary:Je.yield,dataCoverage:Je.dataCoverage,hbinDefs:Q,sbinDefs:j,testDefs:U,statsSummary:se,passBins:kt,ringCount:s.ringCount??4,colorScheme:s.colorScheme,fallbackFormat:Ce,activeFindingId:Xe,findingsFilter:Ln,onFindingsFilterChange:ce,onSaveText:M.onSaveText,onFindingClick:(t,n)=>{Xe===t.id?(Xe=null,ft([]),v({highlightBin:void 0})):(Xe=t.id,Pn(t)),ce()}})}function ce(){X&&Ht(X)}function We(){T&&Ht(T)}function Xt(e,t){fe&&(t==="right"||t==="top")&&(e.style.paddingTop="44px")}if(Se?.placement){const e=Se.placement;X=St(e),Xt(X,e);const t=x.parentElement,n=x.nextSibling;de=Ct(x,X,e),t?.insertBefore(de,n),ce()}else if(se){const e=Se?.defaultOpen??!fe;T=St("right"),Xt(T,"right"),T.style.display=e?"block":"none";const t=x.parentElement,n=x.nextSibling;$=Ct(x,T,"right"),t?.insertBefore($,n),We()}const m=yn?pn(R):null;let C=null,A=null,F=null,E=null,ze=null,O=null,G=null,Ke=null,Y=null;const Tn=24;let ve=null,lt=null,Wt=null,rt=null,dt=null,ct=null,pt=null;function ft(e){S=new Set(e??[]),oe&&oe(mt()),y()}function Ne(){if(!O)return;const e=!!(X??T);O.style.display=se&&e&&!ue?"flex":"none";const t=X??T,n=t?t.style.display!=="none":!1;se?.hasNotableFindings&&!n?O.style.color=q.findingIndicator:O.dataset.active||(O.style.color=q.icon)}if(fe){let ne=function(Z){H=Z,i(K,Z==="zoom"),i(Oe,Z==="pan"),ze&&i(ze,Z==="select"),a.style.cursor=Z==="pan"?"grab":"crosshair"},Ge=function(){ve&&(clearTimeout(ve),ve=null),C&&(C.style.opacity="1")},Ze=function(){ve=setTimeout(()=>{C&&(C.style.opacity="0.35")},600)};C=document.createElement("div"),C.dataset.wmapToolbar="single",Object.assign(C.style,{position:"absolute",top:"4px",right:"4px",display:"flex",flexDirection:"row",alignItems:"center",background:q.menuBg,border:`1px solid ${q.menuBorder}`,borderRadius:"4px",boxShadow:"0 1px 4px rgba(0,0,0,0.12)",zIndex:Jn,opacity:"0.35",transition:"opacity 0.2s ease",pointerEvents:"auto"});const e=pn(R),t=ni(e),{makeBtn:n,setActive:i,makeSep:o,makeMenuRow:f,makeMenuSection:g,makeDropdown:l,makeCheckMenuBtn:p,closeOpenMenu:d,getOpenMenu:r,setOpenMenu:u}=t;lt=d,Wt=r,R.addEventListener("click",d,!0),F=document.createElement("div"),Object.assign(F.style,{display:"flex",alignItems:"center",gap:"0"}),C.appendChild(F);const we=n("download","Download PNG",In);F.appendChild(we),F.appendChild(o());const K=n("zoomMode","Zoom (drag to zoom region)",()=>ne("zoom")),ie=n("zoomIn","Zoom in",()=>xe(a.clientWidth/2,a.clientHeight/2,1.2)),B=n("zoomOut","Zoom out",()=>xe(a.clientWidth/2,a.clientHeight/2,1/1.2)),N=n("reset","Reset zoom (double-click)",()=>_e());F.appendChild(K),F.appendChild(ie),F.appendChild(B),F.appendChild(N),F.appendChild(o());const Oe=n("pan","Pan (drag to move)",()=>ne("pan"));if(F.appendChild(Oe),ze=n("boxSelect","Select (drag to select dies)",()=>ne("select")),F.appendChild(ze),i(Oe,!0),Et!=="view-only"){let Z=function(c){return c.plotMode!==(s.plotMode??"hardBin")?!1:c.plotMode==="value"?(s.activeTest??0)===(c.activeTest??0):c.plotMode==="metadata"?s.activeMetadataKey===c.activeMetadataKey:!0},Re=function(c,b){c.activeTest!==void 0?v({plotMode:c.plotMode,activeTest:c.activeTest,activeMetadataKey:void 0,logScale:c.logScale}):c.activeMetadataKey!==void 0?v({plotMode:c.plotMode,activeTest:void 0,activeMetadataKey:c.activeMetadataKey,passFailDisplay:"off"}):v({plotMode:c.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),b.remove(),u(null),qe(V,!1)};A=document.createElement("div"),Object.assign(A.style,{display:"flex",alignItems:"center",gap:"0"}),C.appendChild(A),E=document.createElement("div"),Object.assign(E.style,{display:"flex",alignItems:"center",gap:"0"}),A.appendChild(E),E.appendChild(o());const Qe=()=>{const c=r();c&&(c.remove(),u(null)),qe(V,!1)},V=n("mode","Plot mode",()=>{if(r()){Qe();return}const c=h.dies,b=h.testDefs,{testEntries:Ue,binEntries:pe,stackedEntries:Ie}=mi(c,b,{includeStacked:h.isLotStack}),yt=(Ee??[]).filter(Fe=>yi(c,Fe.key)).map(vi),Ae=ii(V.getBoundingClientRect(),Ue,pe,Ie,Z,Re,{makeMenuRow:f,makeMenuSection:g},s.plotMode??"hardBin",V.ownerDocument.defaultView??window,yt);pi(V).appendChild(Ae),u(Ae),qe(V,!0),ui(Ae,V,Qe)});qe(V,!1);const{btn:An,sync:Fn}=si(t,()=>s.plotMode??"hardBin",()=>s.colorScheme??"default",()=>Ft,c=>v({colorScheme:c}));dt=Fn,dt();const Yn=di(t,()=>{const c=!!h.hasReticle,b=(s.plotMode??"hardBin")==="value",{testNumber:Ue}=bt(s.activeTest??0,h.testDefs),pe=vt(h.testDefs,Ue),Ie=b&&pe!==void 0&&!cn(pe),yt=b&&!Ie&&(pe?.limitLow!==void 0||pe?.limitHigh!==void 0),Ae=b&&!Ie&&h.dies.some(Fe=>$n(Fe,Ue,pe)!==void 0);return[{label:"Ring boundaries",active:!!s.showRingBoundaries,onClick:()=>v({showRingBoundaries:!s.showRingBoundaries})},{label:"Quadrant lines",active:!!s.showQuadrantBoundaries,onClick:()=>v({showQuadrantBoundaries:!s.showQuadrantBoundaries})},{label:"Die labels",active:!!s.showDieLabels,onClick:()=>v({showDieLabels:!s.showDieLabels})},{label:"Reticle grid",active:!!s.showReticle,enabled:c,onClick:()=>v({showReticle:!s.showReticle})},{label:"XY indicator",active:!!s.showXYIndicator,onClick:()=>v({showXYIndicator:!s.showXYIndicator})},...hi({functionalActive:Ie,hasLimits:yt,hasRecorded:Ae,display:Mt(s)},Fe=>v({passFailDisplay:Fe}))]},()=>!!(s.showRingBoundaries||s.showQuadrantBoundaries||s.showDieLabels||s.showReticle||s.showXYIndicator||Mt(s)!=="off")),{btn:Hn,sync:Xn}=ri(t,()=>s,c=>v({legendPosition:c}));rt=Xn,rt();const rn=()=>{const{testNumber:c}=bt(s.activeTest??0,U),b=vt(U,c);return b!==void 0&&!cn(b)},{btn:Wn,sync:zn}=li(t,()=>({...s,functionalActive:rn()}),c=>v(c));ct=zn,ct();const Kn=()=>{const{testNumber:c}=bt(s.activeTest??0,U),b=vt(U,c);return b!==void 0&&(b.limitLow!==void 0||b.limitHigh!==void 0)},je=n("specRange","Colorbar range: spec limits",()=>{const c=s.colorbarRangeMode==="data"?"spec":"data";v({colorbarRangeMode:c})});pt=()=>{const c=s.plotMode==="value"&&Kn()&&Mt(s)==="off"&&!rn();je.style.display=c?"":"none";const b=(s.colorbarRangeMode??"spec")==="spec";i(je,b),je.ariaLabel=b?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"},pt();const Nn=ci(t,()=>s,c=>v(c));bn&&E.appendChild(V),E.appendChild(An),E.appendChild(Wn),E.appendChild(je),E.appendChild(o()),E.appendChild(Yn),E.appendChild(o()),E.appendChild(Hn),E.appendChild(o()),E.appendChild(Nn),se&&(O=n("findings","Summary panel",()=>{const c=X??T;if(!c)return;const b=c.style.display!=="none";c.style.display=b?"none":"block",i(O,!b),Ne()}),A.appendChild(o()),A.appendChild(O),T?.style.display!=="none"&&i(O,!0),Ne()),Lt&&(A.appendChild(o()),G=n("expand","Expand (E)",Dt??zt),A.appendChild(G)),te&&(A.appendChild(o()),Y=n("analysis","Insights",()=>{it(!ue),i(Y,ue)}),A.appendChild(Y)),Mn&&(A.appendChild(o()),Ke=n("help","User guide",()=>ln()),A.appendChild(Ke))}J.appendChild(C),a.addEventListener("mouseenter",Ge),a.addEventListener("mouseleave",Ze),C.addEventListener("mouseenter",Ge),C.addEventListener("mouseleave",Ze)}let be=null;function zt(){be&&(be.close(),be=null);const e=de??$??x;e.style.flex="1",e.style.minWidth="0",e.style.minHeight="0";const t=oi(C?[e,C]:[e],{ownerDocument:R,onClosed:()=>{be=null,G&&(G.style.display="flex"),a.focus({preventScroll:!0})}});t&&(C&&(t.contentWrap.style.position="relative"),be=t,G&&(G.style.display="none"))}function Kt(e){const t=s.plotMode;if(s={...s,...e},e.plotMode!==void 0&&e.plotMode!==t){I=null;const o=s.plotMode;(o==="hardBin"||o==="softBin")&&!new Set(["default","accessible","custom"]).has(s.colorScheme??"")&&(s={...s,colorScheme:"default"})}Object.keys(e).every(o=>o==="legendPosition")||Pe(),rt?.(),dt?.(),ct?.(),pt?.(),y();const i=e.plotMode!==void 0&&e.plotMode!==t;(e.colorScheme!==void 0||i)&&(ce(),We())}function v(e){Kt(e);const t=Object.keys(e);mn?.(s,t,classifyChanged(t))}let ut=!1;function ht(){ut||(ut=!0,wt(()=>{ut=!1,y()},_))}function y(){const e=D??void 0,t=h.dies[0],n=t?{x:t.width,y:t.height}:ae.diePitchMm,i=Math.floor(a.clientWidth||a.width),o=!!(Q?.length||j?.length||h.dies.some(r=>r.hbin!=null||r.sbin!=null)),f=s.legendPosition??"default",g=f==="default"||f==="compact",l=(ae.colorbarWidth??16)+28,p=o&&g?f!=="default"?Math.max(dn,l):i<jn?0:i<Qn?Math.max(Zn,l):Math.max(dn,l):void 0,d=Gn(a,h,{...ae,topClearance:fe?Tn:0,minRightReserve:p,legendPosition:f,legendOffset:at,diePitchMm:n,fallbackFormat:Ce,showAxes:ae.showAxes??D!==null,viewport:e,activeBin:s.plotMode==="metadata"?s.highlightMetadataValue:s.highlightBin,hbinDefs:Q,sbinDefs:j,metadataFields:Ee});ot=d.binLegendRows,Be=d.legendBox??null,I||(I=d.viewport),S.size>0&&On(),ge&&Rn()}function On(){const e=W();if(!e)return;const t=a.getContext("2d"),n=h.hoverPoints,i=h.rectangles[0],o=i?i.width/2*e.ppm:e.ppm*.5,f=i?i.height/2*e.ppm:e.ppm*.5,g=Math.max(1,Math.min(3,o*.08)),l=o-g,p=f-g,d=[];for(const r of S){const u=Yt.get(r);u!==void 0&&d.push({sx:e.originX+n[u].x*e.ppm,sy:e.originY-n[u].y*e.ppm})}if(d.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:r,sy:u}of d)t.rect(r-l,u-p,l*2,p*2);t.fill(),t.strokeStyle="rgba(255,255,255,0.9)",t.lineWidth=3,t.beginPath();for(const{sx:r,sy:u}of d)t.rect(r-l,u-p,l*2,p*2);t.stroke(),t.strokeStyle="rgba(0,0,0,0.9)",t.lineWidth=1.5,t.beginPath();for(const{sx:r,sy:u}of d)t.rect(r-l,u-p,l*2,p*2);t.stroke(),t.restore()}}function Rn(){const e=a.getContext("2d"),t=Math.min(L.x,P.x),n=Math.min(L.y,P.y),i=Math.abs(P.x-L.x),o=Math.abs(P.y-L.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 In(){a.toBlob(e=>{e&&fi(e,M.downloadFilename??"wafermap",M.onSaveImage)})}function Nt(e){return I?Math.max(I.ppm*xn,Math.min(I.ppm*wn,e)):e}function xe(e,t,n){const i=D??I;if(!i)return;const o=Nt(i.ppm*n),f=o/i.ppm,g=e-(e-i.originX)*f,l=t-(t-i.originY)*f,p=(I?.snapDist??1)/(o/(I?.ppm??o));D={originX:g,originY:l,ppm:o,snapDist:p},y()}function W(){return D??I}function Vt(e){if(e.ctrlKey||e.metaKey){e.preventDefault();const t=a.getBoundingClientRect(),n=e.deltaY<0?1.12:1/1.12;xe(e.clientX-t.left,e.clientY-t.top,n)}else if(D!==null){e.preventDefault();const t=W(),n=D.snapDist;D={originX:t.originX-e.deltaX,originY:t.originY-e.deltaY,ppm:t.ppm,snapDist:n},y()}}function _t(e,t,n){return e>=n.x&&e<n.x+n.w&&t>=n.y&&t<n.y+n.h}function Gt(e){if(e.button!==0||!W())return;a.focus({preventScroll:!0}),a.setPointerCapture(e.pointerId);const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(Be&&s.legendPosition==="floating"&&_t(n,i,Be)){he=!0,De={x:n,y:i},st={...at};return}if(Le&&H!=="pan"){ye=!0,re=!0,me={x:n,y:i},He={x:W().originX,y:W().originY},a.style.cursor="grabbing";return}if(H==="zoom"||H==="select"){ge=!0,L=P={x:n,y:i};return}re=!0,me={x:n,y:i},He={x:W().originX,y:W().originY},a.style.cursor="grabbing"}function Zt(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(ge){P={x:n,y:i},ht();return}if(he){const r=n-De.x,u=i-De.y;r*r+u*u>16&&(he=!1,ke=!0,a.style.cursor="grabbing")}if(ke){at={x:st.x+(n-De.x),y:st.y+(i-De.y)},ht();return}if(re){const r=W(),u=D?.snapDist??I?.snapDist??1;D={originX:He.x+(n-me.x),originY:He.y+(i-me.y),ppm:r.ppm,snapDist:u},ht();return}const o=W();if(!o)return;const f=(n-o.originX)/o.ppm,g=(o.originY-i)/o.ppm,p=$t(f,g,o.snapDist)?.die??null,d=ot.find(r=>n>=r.x&&n<r.x+r.w&&i>=r.y&&i<r.y+r.h);if(d){a.style.cursor="pointer",m&&(m.innerHTML=d.label??`Bin ${d.bin}`,m.style.display="block",xt(m,a,e.clientX,e.clientY)),Ye?.(null,e);return}if(H==="pan"&&(a.style.cursor=p?"crosshair":"grab"),m)if(p)if(Bt){const r=Bt(p);r===null?m.style.display="none":(typeof r=="string"?m.innerHTML=r:(m.innerHTML="",m.appendChild(r)),m.style.display="block",xt(m,a,e.clientX,e.clientY))}else m.innerHTML=_n(p,h.plotMode,{testDefs:U,hbinDefs:Q,sbinDefs:j,fallbackFormat:Ce,aggrMethod:h.aggrMethod,lotSize:h.lotSize,waferMeta:ee.metadata,activeTest:h.activeTest,reticleConfig:Ot}),m.style.display="block",xt(m,a,e.clientX,e.clientY);else m.style.display="none";Ye?.(p,e)}function Qt(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top,o=e.ctrlKey||e.metaKey;if(m&&(n<0||i<0||n>t.width||i>t.height)&&(m.style.display="none"),ge){ge=!1,P={x:n,y:i};const l=n-L.x,p=i-L.y,d=W();if(H==="zoom"){if(l*l+p*p<25)xe(n,i,2);else if(d){const r=Math.min(L.x,P.x),u=Math.max(L.x,P.x),ne=Math.min(L.y,P.y),we=Math.max(L.y,P.y),K=u-r,ie=we-ne;if(K>4&&ie>4){const B=a.clientWidth,N=a.clientHeight,Oe=B/K,Ge=N/ie,Ze=Math.min(Oe,Ge),Z=Nt(d.ppm*Ze),Re=Z/d.ppm,Qe=(r+u)/2,V=(ne+we)/2;D={originX:B/2-(Qe-d.originX)*Re,originY:N/2-(V-d.originY)*Re,ppm:Z,snapDist:d.snapDist/Re}}}y(),a.style.cursor="crosshair";return}if(l*l+p*p<25)gt(n,i,o,e);else if(d){const r=(Math.min(L.x,P.x)-d.originX)/d.ppm,u=(Math.max(L.x,P.x)-d.originX)/d.ppm,ne=(d.originY-Math.max(L.y,P.y))/d.ppm,we=(d.originY-Math.min(L.y,P.y))/d.ppm,K=h.hoverPoints,ie=[];for(let B=0;B<K.length;B++)if(K[B].x>=r&&K[B].x<=u&&K[B].y>=ne&&K[B].y<=we){const N=h.dies[B];N&&ie.push(N)}if(o)for(const B of ie){const N=Me(B);S.has(N)?S.delete(N):S.add(N)}else S=new Set(ie.map(B=>Me(B)));oe?.(mt())}y(),a.style.cursor="crosshair";return}if(he){he=!1,gt(n,i,o,e);return}if(ke){ke=!1,a.style.cursor="grab";return}if(!re)return;if(re=!1,ye){ye=!1,a.style.cursor=Le||H==="pan"?"grab":"crosshair";return}a.style.cursor=H==="pan"?"grab":"crosshair";const f=n-me.x,g=i-me.y;f*f+g*g<25&&gt(n,i,o,e)}function gt(e,t,n,i){for(const l of ot)if(e>=l.x&&e<l.x+l.w&&t>=l.y&&t<l.y+l.h){if(typeof l.bin=="number"){const p=s.highlightBin===l.bin?void 0:l.bin;v({highlightBin:p})}else{const p=s.highlightMetadataValue===l.bin?void 0:l.bin;v({highlightMetadataValue:p})}return}if(Be&&_t(e,t,Be))return;const o=W();if(!o)return;const g=$t((e-o.originX)/o.ppm,(o.originY-t)/o.ppm,o.snapDist)?.die??null;if(g){gn?.(g,i);const l=Me(g);n?S.has(l)?S.delete(l):S.add(l):S=new Set([l]),oe?.(mt()),y()}else n||(S=new Set,oe?.([]),y())}function mt(){const e=[],t=h.hoverPoints;for(let n=0;n<t.length;n++){const i=h.dies[n];i&&S.has(Me(i))&&e.push(i)}return e}function jt(){m&&$e(R),Ye?.(null,new MouseEvent("mouseleave")),a.style.cursor=H==="pan"?"grab":"crosshair"}function Ut(){re=!1,ye=!1,ge=!1,he=!1,ke=!1,m&&$e(R),Ye?.(null,new MouseEvent("mouseleave")),a.style.cursor=H==="pan"?"grab":"crosshair",y()}function $t(e,t,n){const i=h.hoverPoints,o=h.rectangles;for(let p=0;p<o.length;p++){const d=o[p];if(Math.abs(e-d.x)<=d.width/2&&Math.abs(t-d.y)<=d.height/2){const r=h.dies[p];return r?{die:r,index:p}:null}}let f=null,g=-1,l=n*n;for(let p=0;p<i.length;p++){const d=i[p].x-e,r=i[p].y-t,u=d*d+r*r;u<l&&(l=u,f=h.dies[p]??null,g=p)}return f?{die:f,index:g}:null}const qt=new _.ResizeObserver(()=>{I=null,D=null,y()});qt.observe(a),M.height==null&&hn<=0&&wt(()=>wt(()=>{z.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 Te=_.matchMedia(`(resolution: ${_.devicePixelRatio}dppx)`);const Ve=()=>{Te.removeEventListener("change",Ve),Te=_.matchMedia(`(resolution: ${_.devicePixelRatio}dppx)`),Te.addEventListener("change",Ve),y()};Te.addEventListener("change",Ve);const Jt=_.matchMedia("(prefers-color-scheme: dark)"),en=()=>y();Jt.addEventListener("change",en);const tn=()=>{m&&$e(R)};_.addEventListener("blur",tn);function nn(e){if(e.key==="Escape"&&S.size>0&&(S=new Set,oe?.([]),y()),(e.key==="e"||e.key==="E")&&Et!=="view-only"&&Lt&&!ue&&(e.stopPropagation(),(Dt??zt)()),(e.ctrlKey||e.metaKey)&&(e.key==="="||e.key==="+"?(e.preventDefault(),xe(a.clientWidth/2,a.clientHeight/2,1.2)):e.key==="-"?(e.preventDefault(),xe(a.clientWidth/2,a.clientHeight/2,1/1.2)):e.key==="0"&&(e.preventDefault(),_e())),!e.ctrlKey&&!e.metaKey&&!e.shiftKey){const n=W();if(n){const i=D?.snapDist??I?.snapDist??1;let o=0,f=0;e.key==="ArrowLeft"&&(o=20,e.preventDefault()),e.key==="ArrowRight"&&(o=-20,e.preventDefault()),e.key==="ArrowUp"&&(f=20,e.preventDefault()),e.key==="ArrowDown"&&(f=-20,e.preventDefault()),(o||f)&&(D={originX:n.originX+o,originY:n.originY+f,ppm:n.ppm,snapDist:i},y())}e.key===" "&&!Le&&(e.preventDefault(),Le=!0,H!=="pan"&&(a.style.cursor="grab"))}}function on(e){e.key===" "&&(Le=!1,ye&&(re=!1,ye=!1),a.style.cursor=H==="pan"?"grab":"crosshair")}a.style.cursor="grab",a.setAttribute("tabindex","0"),a.addEventListener("wheel",Vt,{passive:!1}),a.addEventListener("pointerdown",Gt),a.addEventListener("pointermove",Zt),a.addEventListener("pointerup",Qt),a.addEventListener("pointerleave",jt),a.addEventListener("pointercancel",Ut);const an=()=>_e();a.addEventListener("dblclick",an),a.addEventListener("keydown",nn),a.addEventListener("keyup",on);const sn=e=>{e.stopPropagation()};a.addEventListener("click",sn),a.clientWidth,y();function _e(){I=null,D=null,y()}function ln(){import("./userGuideHtml.js").then(e=>ai({buildWaferMap:Un,renderWaferMap,renderWaferGallery:void 0,analyzeWaferMap:qn},e.USER_GUIDE_HTML,Sn,z))}return{setDies(e){le=e,Pe(),y(),X&&ce()},setResult(e){Je=e,ee=e.wafer,le=e.dies,Q=e.hbinDefs,j=e.sbinDefs,U=e.testDefs,Ee=e.metadataFields,Tt=e.reticles?.length?e.reticles:void 0,Ot=e.reticleConfig,Rt=e.view?.dataAxisFlip,et=e.isLotStack,tt=e.aggrMethod,nt=e.lotSize,Dn(),Pe(),y(),X&&ce()},setOptions(e){Kt(e)},getOptions(){return{...s}},resetZoom:_e,setSelection(e){S=new Set(e.map(t=>Me(t))),y()},clearSelection(){S=new Set,oe?.([]),y()},setFallbackFormat(e){Ce=e,Pe(),y()},setStatsSummary(e){if(se=e,X)ce();else if(T)We();else if(e&&!Se?.placement){const t=Se?.defaultOpen??!fe;T=St("right"),T.style.display=t?"block":"none";const n=x.parentElement,i=x.nextSibling;$=Ct(x,T,"right"),n?.insertBefore($,i),We()}Ne()},setSummaryVisible(e){O&&(O.style.display=e?"flex":"none")},setViewControlsVisible(e){A&&(A.style.display=e?"flex":"none")},setExpandVisible(e){G&&(G.style.display=e?"flex":"none")},setHelpButtonVisible(e){Ke&&(Ke.style.display=e?"flex":"none")},setMetadataBadgeVisible(e){It=!e,k&&(k.el.style.display=e&&!ue?"":"none")},openUserGuide:ln,setInsightsOpen(e){it(e),Y&&(e?(Y.dataset.active="1",Y.style.background=q.bgActive,Y.style.color=q.iconActive):(delete Y.dataset.active,Y.style.background="transparent",Y.style.color=q.icon))},closeSummaryPanel(){const e=X??T;!e||e.style.display==="none"||(e.style.display="none",O&&(delete O.dataset.active,O.style.background="transparent",O.style.color=q.icon))},setTooltipParent(e){m&&ti(e)},getActiveLegend(){const e=s.plotMode;if(e==="metadata"){const o=s.activeMetadataKey;if(!o)return null;const f=Ee?.find(l=>l.key===o),g=[...new Set(le.map(l=>l.metadata?.[o]).filter(l=>l!=null&&(typeof l=="string"||typeof l=="number"||typeof l=="boolean")).map(String))].sort();return g.length?g.map((l,p)=>{const d=f?.values?.find(u=>u.value===l),r=d?.color??Mi(p);return{bin:l,name:d?.label??l,color:r}}):null}if(e!=="hardBin"&&e!=="softBin")return null;const t=e==="hardBin",n=t?Q:j,i=[...new Set(le.map(o=>t?o.hbin:o.sbin).filter(o=>o!==void 0))].sort((o,f)=>o-f);return i.length?i.map(o=>{const f=n?.find(l=>l.bin===o),g=f?.color??(t?xi(o):wi(o));return{bin:o,name:f?.name??`Bin ${o}`,color:g}}):null},destroy(){be?.close(),ve&&clearTimeout(ve),Wt?.()?.remove(),lt&&R.removeEventListener("click",lt,!0),a.removeEventListener("wheel",Vt),a.removeEventListener("pointerdown",Gt),a.removeEventListener("pointermove",Zt),a.removeEventListener("pointerup",Qt),a.removeEventListener("pointerleave",jt),a.removeEventListener("pointercancel",Ut),a.removeEventListener("dblclick",an),a.removeEventListener("keydown",nn),a.removeEventListener("keyup",on),a.removeEventListener("click",sn),qt.disconnect(),Te.removeEventListener("change",Ve),Jt.removeEventListener("change",en),_.removeEventListener("blur",tn),kn(),m&&$e(R),C?.remove(),de&&(de.parentElement?.insertBefore(x,de),de.remove()),$&&($.parentElement?.insertBefore(x,$),$.remove()),x.remove(),a.style.cursor="",te?.destroy(),k?.destroy(),J.remove()}}}