@wafertools/wafermap 0.24.2 → 0.24.3

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 (38) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/packages/canvas-adapter/charts/barPanel.d.ts +5 -0
  3. package/dist/packages/canvas-adapter/charts/barPanel.js +1 -1
  4. package/dist/packages/canvas-adapter/charts/binCluster.d.ts +5 -0
  5. package/dist/packages/canvas-adapter/charts/binCluster.js +1 -1
  6. package/dist/packages/canvas-adapter/charts/boxplot.d.ts +5 -0
  7. package/dist/packages/canvas-adapter/charts/boxplot.js +1 -1
  8. package/dist/packages/canvas-adapter/charts/capability.d.ts +5 -0
  9. package/dist/packages/canvas-adapter/charts/capability.js +1 -1
  10. package/dist/packages/canvas-adapter/charts/chartShell.d.ts +8 -5
  11. package/dist/packages/canvas-adapter/charts/chartShell.js +1 -1
  12. package/dist/packages/canvas-adapter/charts/correlation.d.ts +5 -0
  13. package/dist/packages/canvas-adapter/charts/correlation.js +1 -1
  14. package/dist/packages/canvas-adapter/charts/histogram.d.ts +5 -0
  15. package/dist/packages/canvas-adapter/charts/histogram.js +1 -1
  16. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.d.ts +5 -0
  17. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.js +1 -1
  18. package/dist/packages/canvas-adapter/charts/scatter.d.ts +5 -0
  19. package/dist/packages/canvas-adapter/charts/scatter.js +1 -1
  20. package/dist/packages/canvas-adapter/dieList.d.ts +9 -0
  21. package/dist/packages/canvas-adapter/dieList.js +6 -6
  22. package/dist/packages/canvas-adapter/insightsTab.d.ts +5 -0
  23. package/dist/packages/canvas-adapter/insightsTab.js +1 -1
  24. package/dist/packages/canvas-adapter/metadataBadge.d.ts +4 -0
  25. package/dist/packages/canvas-adapter/metadataBadge.js +1 -1
  26. package/dist/packages/canvas-adapter/renderWaferGallery.js +6 -6
  27. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
  28. package/dist/packages/canvas-adapter/summaryPanel.d.ts +1 -1
  29. package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
  30. package/dist/packages/canvas-adapter/toolbar.d.ts +4 -2
  31. package/dist/packages/canvas-adapter/toolbar.js +2 -2
  32. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
  33. package/dist/packages/canvas-adapter/userGuideHtml.js +1 -1
  34. package/dist/packages/canvas-adapter/version.d.ts +2 -2
  35. package/dist/packages/canvas-adapter/version.js +1 -1
  36. package/dist/packages/canvas-adapter/warnings.d.ts +1 -1
  37. package/dist/packages/canvas-adapter/warnings.js +1 -1
  38. package/package.json +2 -2
@@ -1 +1 @@
1
- import{getColorScheme as ht}from"../../renderer/colorSchemes.js";import{categorical as gt}from"./palette.js";import{buildScatterData as bt,buildScatterDataGrouped as yt}from"../../stats/scatter.js";import{buildFacetTable as St}from"../../stats/facets.js";import{CLR as M}from"../toolbar.js";import{cardShell as Mt,observeResize as Tt,makeTooltip as wt,makeTestSelect as kt,makeWaferSelect as vt,chartFillHeight as Lt,applyCanvasFlow as Ct,drawAxisUnit as At,resolveChartCanvasColors as Bt,makeAxisFormat as nt}from"./chartShell.js";const r=52,Ot=16,l=16,Et=44;export function renderScatterPanel(j){const{title:ot="Test scatter",items:B,testDefs:_,colorScheme:it="default",onSaveImage:lt,groups:P}=j,{card:T,body:C,controlsRow:X}=Mt(ot,lt),R=_.filter(e=>e.testNumber!==void 0),b=!!(P&&P.length>0),Y=(P??[]).map(e=>e.key),at=new Map(Y.map((e,n)=>[e,n]));let m=j.xTestNumber??R[0]?.testNumber??null,f=j.yTestNumber??R[1]?.testNumber??m,O=null;const q=()=>O!==null?B[O]?[B[O]]:[]:B;function K(e,n,o){const i=document.createElement("label");Object.assign(i.style,{display:"inline-flex",alignItems:"center",gap:"4px",fontSize:"11px",color:M.label});const d=document.createElement("span");d.textContent=e;const p=kt(R,n,o,{maxWidth:"180px",emptyText:"No tests"});return i.append(d,p),{wrap:i,select:p}}const{wrap:st,select:rt}=K("X:",m,e=>{m=e,H()}),{wrap:ct,select:dt}=K("Y:",f,e=>{f=e,H()});X.append(st,ct),!b&&B.length>1&&X.appendChild(vt(B,O,e=>{O=e,H()}));const E=document.createElement("div");Object.assign(E.style,{color:M.warnText,background:M.warnBg,border:`1px solid ${M.warnBorder}`,borderRadius:"4px",padding:"4px 8px",fontSize:"11px",marginBottom:"4px",display:"none"}),T.insertBefore(E,C);function J(){const e=b?[]:St(q(),{facetableOnly:!0}).filter(n=>n.splittable).map(n=>n.label);e.length>0?(E.textContent=`\u26A0 Mixed ${e.join(", ")} across these points \u2014 trends here may be confounded (Simpson's paradox). Use Group by, or the Wafer picker, to narrow to a like-for-like set.`,E.style.display=""):E.style.display="none"}J();const D=document.createElement("div");D.textContent=b?"One point per die \xB7 coloured by group \xB7 click legend to filter":"One point per die across all wafers \xB7 coloured by hard bin \xB7 click legend to filter",Object.assign(D.style,{color:M.label,fontSize:"11px",marginBottom:"4px"}),T.insertBefore(D,C);const pt=ht(it),{forBin:mt}=pt,G=e=>b?e.group??"\u2014":String(e.hbin??0),Q=e=>b?gt(at.get(e)??0):mt(Number(e)),V=e=>b?e:e==="0"?"No bin data":`Bin ${e}`,g=new Set,A=document.createElement("div");Object.assign(A.style,{display:"flex",flexWrap:"wrap",gap:"4px",marginBottom:"6px"}),C.appendChild(A);const u=document.createElement("canvas");u.style.display="block",u.style.cursor="crosshair",C.appendChild(u);const F=window.devicePixelRatio||1,Ht=wt(T);let h=[],w=0,I=1,k=0,N=1;function $(e){const n=_.find(o=>o.testNumber===e);return{unit:n?.unit,limitLow:n?.limitLow,limitHigh:n?.limitHigh}}function xt(){const e=C.clientWidth,n=Math.max(200,Math.min(400,e*.65)),o=Lt(T,C,u,n);return{w:e,h:o,plotW:Math.max(10,e-r-Ot),plotH:Math.max(10,o-l-Et)}}function Z(){for(const e of A.querySelectorAll("[data-cat]")){const n=e.dataset.cat,o=g.size===0||g.has(n);e.style.opacity=o?"1":"0.35";const i=g.has(n);e.style.boxShadow=i?`0 0 0 2px ${M.text}`:"none",e.setAttribute("aria-pressed",i?"true":"false")}}function tt(e){A.innerHTML="",g.clear();for(const n of e){const o=document.createElement("button");o.type="button",o.dataset.cat=n,o.title=`${V(n)} \u2014 click to filter`;const i=Q(n);Object.assign(o.style,{display:"inline-flex",alignItems:"center",gap:"4px",padding:"2px 7px",borderRadius:"10px",border:`1px solid ${M.menuBorder}`,background:"none",cursor:"pointer",fontSize:"11px",color:M.text,whiteSpace:"nowrap"});const d=document.createElement("span");Object.assign(d.style,{display:"inline-block",width:"9px",height:"9px",borderRadius:"50%",background:i,flexShrink:"0"}),o.append(d,document.createTextNode(V(n))),o.addEventListener("click",()=>{g.has(n)?g.delete(n):g.add(n),Z(),z()}),A.appendChild(o)}Z()}function z(){Ct(u,A.offsetHeight);const e=Bt(T),n=I-w,o=N-k,{w:i,h:d,plotW:p,plotH:c}=xt();u.width=Math.max(1,Math.floor(i*F)),u.height=Math.max(1,Math.floor(d*F)),u.style.width=`${i}px`,u.style.height=`${d}px`;const t=u.getContext("2d");if(t.setTransform(F,0,0,F,0,0),t.clearRect(0,0,i,d),h.length===0){t.font="12px system-ui, sans-serif",t.fillStyle=e.textMuted,t.textAlign="center",t.textBaseline="middle",t.fillText("No data \u2014 select two parametric tests with values.",i/2,d/2);return}const y=4,v=nt(Math.max(Math.abs(w),Math.abs(I)),m!==null?$(m).unit:void 0),U=nt(Math.max(Math.abs(k),Math.abs(N)),f!==null?$(f).unit:void 0);t.font="10px system-ui, sans-serif",t.strokeStyle=e.border,t.lineWidth=.5,t.fillStyle=e.textMuted;for(let a=0;a<=y;a++){const S=w+n*a/y,s=r+a/y*p;t.beginPath(),t.moveTo(s,l),t.lineTo(s,l+c),t.stroke(),t.textAlign="center",t.textBaseline="top",t.fillText(v.tick(S),s,l+c+4);const L=k+o*a/y,x=l+(1-a/y)*c;t.beginPath(),t.moveTo(r,x),t.lineTo(r+p,x),t.stroke(),t.textAlign="right",t.textBaseline="middle",t.fillText(U.tick(L),r-4,x)}v.unitLabel&&At(t,v.unitLabel,r+p/2,l+c+24,e.textMuted),U.unitLabel&&(t.save(),t.font="10px system-ui, sans-serif",t.fillStyle=e.textMuted,t.textAlign="center",t.textBaseline="middle",t.translate(6,l+c/2),t.rotate(-Math.PI/2),t.fillText(`(${U.unitLabel})`,0,0),t.restore());const W=g.size===0?h:h.filter(a=>g.has(G(a))),et=W.length>5e3?Math.ceil(W.length/5e3):1;t.globalAlpha=Math.max(.15,Math.min(.7,200/(W.length/et)));for(let a=0;a<W.length;a+=et){const S=W[a],s=r+(S.x-w)/n*p,L=l+(1-(S.y-k)/o)*c;t.beginPath(),t.arc(s,L,2.5,0,Math.PI*2),t.fillStyle=Q(G(S)),t.fill()}if(t.globalAlpha=1,m!==null&&f!==null){const a=$(m),S=$(f);t.strokeStyle=e.textMuted,t.fillStyle=e.textMuted,t.lineWidth=1,t.setLineDash([4,3]),t.font="9px system-ui, sans-serif",t.textBaseline="top";for(const[s,L]of[[a.limitLow,"LSL"],[a.limitHigh,"USL"]]){if(s===void 0||s<w||s>I)continue;const x=r+(s-w)/n*p;t.beginPath(),t.moveTo(x,l),t.lineTo(x,l+c),t.stroke(),t.textAlign="left",t.fillText(L,x+2,l+2)}for(const[s,L]of[[S.limitLow,"LSL"],[S.limitHigh,"USL"]]){if(s===void 0||s<k||s>N)continue;const x=l+(1-(s-k)/o)*c;t.beginPath(),t.moveTo(r,x),t.lineTo(r+p,x),t.stroke(),t.textAlign="left",t.fillText(L,r+3,x+2)}t.setLineDash([])}t.strokeStyle=e.border,t.lineWidth=1,t.beginPath(),t.moveTo(r,l),t.lineTo(r,l+c),t.moveTo(r,l+c),t.lineTo(r+p,l+c),t.stroke()}function H(){if(J(),R.length<2||m===null||f===null){h=[],tt([]),z();return}h=b?yt(P,m,f):bt(q(),m,f);let e;if(b){const n=new Set(h.map(G));e=Y.filter(o=>n.has(o))}else e=Array.from(new Set(h.map(n=>n.hbin??0))).sort((n,o)=>n-o).map(String);if(tt(e),h.length>0){const n=h.map(v=>v.x),o=h.map(v=>v.y),i=Math.min(...n),d=Math.max(...n),p=Math.min(...o),c=Math.max(...o),t=(d-i)*.05||1,y=(c-p)*.05||1;w=i-t,I=d+t,k=p-y,N=c+y}z()}const ft=Tt(T,()=>z());H();function ut(e,n){m=e,f=n,rt.value=String(e),dt.value=String(n),H()}return{card:T,setXY:ut,destroy:()=>ft.disconnect()}}
1
+ import{getColorScheme as he}from"../../renderer/colorSchemes.js";import{categorical as ge}from"./palette.js";import{buildScatterData as be,buildScatterDataGrouped as ye}from"../../stats/scatter.js";import{buildFacetTable as we}from"../../stats/facets.js";import{CLR as M}from"../toolbar.js";import{cardShell as Se,observeResize as Me,makeTooltip as Te,makeTestSelect as ke,makeWaferSelect as ve,chartFillHeight as Le,applyCanvasFlow as Ce,drawAxisUnit as Ae,resolveChartCanvasColors as De,makeAxisFormat as ne}from"./chartShell.js";const c=52,Be=16,a=16,Oe=44;export function renderScatterPanel(W){const{title:oe="Test scatter",items:D,testDefs:_,colorScheme:ie="default",onSaveImage:le,groups:P}=W,{card:i,body:C,controlsRow:X}=Se(oe,le,W.ownerDocument),R=_.filter(t=>t.testNumber!==void 0),y=!!(P&&P.length>0),Y=(P??[]).map(t=>t.key),ae=new Map(Y.map((t,n)=>[t,n]));let x=W.xTestNumber??R[0]?.testNumber??null,f=W.yTestNumber??R[1]?.testNumber??x,B=null;const q=()=>B!==null?D[B]?[D[B]]:[]:D;function K(t,n,o){const l=i.ownerDocument.createElement("label");Object.assign(l.style,{display:"inline-flex",alignItems:"center",gap:"4px",fontSize:"11px",color:M.label});const p=i.ownerDocument.createElement("span");p.textContent=t;const m=ke(R,n,o,{maxWidth:"180px",emptyText:"No tests",ownerDocument:i.ownerDocument});return l.append(p,m),{wrap:l,select:m}}const{wrap:se,select:re}=K("X:",x,t=>{x=t,E()}),{wrap:ce,select:de}=K("Y:",f,t=>{f=t,E()});X.append(se,ce),!y&&D.length>1&&X.appendChild(ve(D,B,t=>{B=t,E()},{ownerDocument:i.ownerDocument}));const O=i.ownerDocument.createElement("div");Object.assign(O.style,{color:M.warnText,background:M.warnBg,border:`1px solid ${M.warnBorder}`,borderRadius:"4px",padding:"4px 8px",fontSize:"11px",marginBottom:"4px",display:"none"}),i.insertBefore(O,C);function J(){const t=y?[]:we(q(),{facetableOnly:!0}).filter(n=>n.splittable).map(n=>n.label);t.length>0?(O.textContent=`\u26A0 Mixed ${t.join(", ")} across these points \u2014 trends here may be confounded (Simpson's paradox). Use Group by, or the Wafer picker, to narrow to a like-for-like set.`,O.style.display=""):O.style.display="none"}J();const j=i.ownerDocument.createElement("div");j.textContent=y?"One point per die \xB7 coloured by group \xB7 click legend to filter":"One point per die across all wafers \xB7 coloured by hard bin \xB7 click legend to filter",Object.assign(j.style,{color:M.label,fontSize:"11px",marginBottom:"4px"}),i.insertBefore(j,C);const pe=he(ie),{forBin:me}=pe,G=t=>y?t.group??"\u2014":String(t.hbin??0),Q=t=>y?ge(ae.get(t)??0):me(Number(t)),V=t=>y?t:t==="0"?"No bin data":`Bin ${t}`,b=new Set,A=i.ownerDocument.createElement("div");Object.assign(A.style,{display:"flex",flexWrap:"wrap",gap:"4px",marginBottom:"6px"}),C.appendChild(A);const h=i.ownerDocument.createElement("canvas");h.style.display="block",h.style.cursor="crosshair",C.appendChild(h);const F=window.devicePixelRatio||1,Ee=Te(i);let g=[],T=0,I=1,k=0,N=1;function $(t){const n=_.find(o=>o.testNumber===t);return{unit:n?.unit,limitLow:n?.limitLow,limitHigh:n?.limitHigh}}function xe(){const t=C.clientWidth,n=Math.max(200,Math.min(400,t*.65)),o=Le(i,C,h,n);return{w:t,h:o,plotW:Math.max(10,t-c-Be),plotH:Math.max(10,o-a-Oe)}}function Z(){for(const t of A.querySelectorAll("[data-cat]")){const n=t.dataset.cat,o=b.size===0||b.has(n);t.style.opacity=o?"1":"0.35";const l=b.has(n);t.style.boxShadow=l?`0 0 0 2px ${M.text}`:"none",t.setAttribute("aria-pressed",l?"true":"false")}}function ee(t){A.innerHTML="",b.clear();for(const n of t){const o=i.ownerDocument.createElement("button");o.type="button",o.dataset.cat=n,o.title=`${V(n)} \u2014 click to filter`;const l=Q(n);Object.assign(o.style,{display:"inline-flex",alignItems:"center",gap:"4px",padding:"2px 7px",borderRadius:"10px",border:`1px solid ${M.menuBorder}`,background:"none",cursor:"pointer",fontSize:"11px",color:M.text,whiteSpace:"nowrap"});const p=i.ownerDocument.createElement("span");Object.assign(p.style,{display:"inline-block",width:"9px",height:"9px",borderRadius:"50%",background:l,flexShrink:"0"}),o.append(p,i.ownerDocument.createTextNode(V(n))),o.addEventListener("click",()=>{b.has(n)?b.delete(n):b.add(n),Z(),z()}),A.appendChild(o)}Z()}function z(){Ce(h,A.offsetHeight);const t=De(i),n=I-T,o=N-k,{w:l,h:p,plotW:m,plotH:d}=xe();h.width=Math.max(1,Math.floor(l*F)),h.height=Math.max(1,Math.floor(p*F)),h.style.width=`${l}px`,h.style.height=`${p}px`;const e=h.getContext("2d");if(e.setTransform(F,0,0,F,0,0),e.clearRect(0,0,l,p),g.length===0){e.font="12px system-ui, sans-serif",e.fillStyle=t.textMuted,e.textAlign="center",e.textBaseline="middle",e.fillText("No data \u2014 select two parametric tests with values.",l/2,p/2);return}const w=4,v=ne(Math.max(Math.abs(T),Math.abs(I)),x!==null?$(x).unit:void 0),U=ne(Math.max(Math.abs(k),Math.abs(N)),f!==null?$(f).unit:void 0);e.font="10px system-ui, sans-serif",e.strokeStyle=t.border,e.lineWidth=.5,e.fillStyle=t.textMuted;for(let s=0;s<=w;s++){const S=T+n*s/w,r=c+s/w*m;e.beginPath(),e.moveTo(r,a),e.lineTo(r,a+d),e.stroke(),e.textAlign="center",e.textBaseline="top",e.fillText(v.tick(S),r,a+d+4);const L=k+o*s/w,u=a+(1-s/w)*d;e.beginPath(),e.moveTo(c,u),e.lineTo(c+m,u),e.stroke(),e.textAlign="right",e.textBaseline="middle",e.fillText(U.tick(L),c-4,u)}v.unitLabel&&Ae(e,v.unitLabel,c+m/2,a+d+24,t.textMuted),U.unitLabel&&(e.save(),e.font="10px system-ui, sans-serif",e.fillStyle=t.textMuted,e.textAlign="center",e.textBaseline="middle",e.translate(6,a+d/2),e.rotate(-Math.PI/2),e.fillText(`(${U.unitLabel})`,0,0),e.restore());const H=b.size===0?g:g.filter(s=>b.has(G(s))),te=H.length>5e3?Math.ceil(H.length/5e3):1;e.globalAlpha=Math.max(.15,Math.min(.7,200/(H.length/te)));for(let s=0;s<H.length;s+=te){const S=H[s],r=c+(S.x-T)/n*m,L=a+(1-(S.y-k)/o)*d;e.beginPath(),e.arc(r,L,2.5,0,Math.PI*2),e.fillStyle=Q(G(S)),e.fill()}if(e.globalAlpha=1,x!==null&&f!==null){const s=$(x),S=$(f);e.strokeStyle=t.textMuted,e.fillStyle=t.textMuted,e.lineWidth=1,e.setLineDash([4,3]),e.font="9px system-ui, sans-serif",e.textBaseline="top";for(const[r,L]of[[s.limitLow,"LSL"],[s.limitHigh,"USL"]]){if(r===void 0||r<T||r>I)continue;const u=c+(r-T)/n*m;e.beginPath(),e.moveTo(u,a),e.lineTo(u,a+d),e.stroke(),e.textAlign="left",e.fillText(L,u+2,a+2)}for(const[r,L]of[[S.limitLow,"LSL"],[S.limitHigh,"USL"]]){if(r===void 0||r<k||r>N)continue;const u=a+(1-(r-k)/o)*d;e.beginPath(),e.moveTo(c,u),e.lineTo(c+m,u),e.stroke(),e.textAlign="left",e.fillText(L,c+3,u+2)}e.setLineDash([])}e.strokeStyle=t.border,e.lineWidth=1,e.beginPath(),e.moveTo(c,a),e.lineTo(c,a+d),e.moveTo(c,a+d),e.lineTo(c+m,a+d),e.stroke()}function E(){if(J(),R.length<2||x===null||f===null){g=[],ee([]),z();return}g=y?ye(P,x,f):be(q(),x,f);let t;if(y){const n=new Set(g.map(G));t=Y.filter(o=>n.has(o))}else t=Array.from(new Set(g.map(n=>n.hbin??0))).sort((n,o)=>n-o).map(String);if(ee(t),g.length>0){const n=g.map(v=>v.x),o=g.map(v=>v.y),l=Math.min(...n),p=Math.max(...n),m=Math.min(...o),d=Math.max(...o),e=(p-l)*.05||1,w=(d-m)*.05||1;T=l-e,I=p+e,k=m-w,N=d+w}z()}const ue=Me(i,()=>z());E();function fe(t,n){x=t,f=n,re.value=String(t),de.value=String(n),E()}return{card:i,setXY:fe,destroy:()=>ue.disconnect()}}
@@ -98,6 +98,15 @@ export interface DieListOptions extends DieListDisplayOptions {
98
98
  waferMetadata?: WaferMetadata;
99
99
  /** Label/order hints for die metadata columns, e.g. `WaferMapResult.metadataFields`. */
100
100
  metadataFields?: MetadataFieldDef[];
101
+ /**
102
+ * Document to build elements and inject the shared `<style>` block into.
103
+ * Default `document`. Pass the anchor's `ownerDocument` when the table may
104
+ * be mounted into a different document than the bare global — e.g. a
105
+ * gallery card detached into its own popup window — otherwise the table's
106
+ * cells build in the wrong document and the injected font-size rule never
107
+ * reaches the document the table actually renders in.
108
+ */
109
+ ownerDocument?: Document;
101
110
  }
102
111
  /**
103
112
  * Build a scrollable die-list table + "Export CSV" button. Returns `null`
@@ -1,13 +1,13 @@
1
- import{hasPosition as k}from"../core/dies.js";import{isParametricTest as H}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as R}from"../stats/metadataColumns.js";import{CLR as a,saveTextFile as E}from"./toolbar.js";import{csvField as y}from"./summaryPanel.js";import{fmt as M}from"../renderer/fmt.js";const T=5e4;let $=!1;function B(){if($)return;$=!0;const n=document.createElement("style");n.textContent=`
1
+ import{hasPosition as H}from"../core/dies.js";import{isParametricTest as R}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as E}from"../stats/metadataColumns.js";import{CLR as o,saveTextFile as M}from"./toolbar.js";import{csvField as $}from"./summaryPanel.js";import{fmt as T}from"../renderer/fmt.js";const B=5e4,N=new WeakSet;function F(n){if(N.has(n))return;N.add(n);const s=n.createElement("style");s.textContent=`
2
2
  .wmap-dielist-table { width: 100%; border-collapse: collapse; font-size: 11px; }
3
3
  .wmap-dielist-th {
4
4
  text-align: left; padding: 4px 8px; position: sticky; top: 0;
5
- background: ${a.panelBg}; color: ${a.label}; font-weight: 600;
6
- border-bottom: 1px solid ${a.menuBorder}; white-space: nowrap;
5
+ background: ${o.panelBg}; color: ${o.label}; font-weight: 600;
6
+ border-bottom: 1px solid ${o.menuBorder}; white-space: nowrap;
7
7
  }
8
8
  .wmap-dielist-td {
9
- padding: 3px 8px; color: ${a.text};
10
- border-bottom: 1px solid ${a.menuBorder}; white-space: nowrap;
9
+ padding: 3px 8px; color: ${o.text};
10
+ border-bottom: 1px solid ${o.menuBorder}; white-space: nowrap;
11
11
  }
12
- `,document.head.appendChild(n)}function o(n,s,t){const i=document.createElement(n);return s&&Object.assign(i.style,s),t!==void 0&&(i.textContent=t),i}function F(n){return k(n)?`(${n.x}, ${n.y})`:"\u2014"}function P(n,s){if(s?.length)return s.filter(H);const t=new Map;for(const i of n)for(const d of Object.keys(i.testValues??{})){const r=Number(d);t.has(r)||t.set(r,{testNumber:r,name:`Test ${r}`})}return[...t.values()].sort((i,d)=>i.testNumber-d.testNumber)}export function buildDieListSection(n,s,t={}){if(!n.length)return null;B();const i=P(n,s),d=t.maxRows??T,r=Math.max(0,n.length-d),N=r>0?n.slice(0,d):n,u=o("div",{display:"flex",flexDirection:"column",gap:"8px",flex:"1",minHeight:"0",minWidth:"0"}),h=o("div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});h.appendChild(o("div",{fontSize:"10px",fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:a.label},t.title??`Die list (${n.length})`));const b=o("button",{fontSize:"11px",padding:"3px 8px",borderRadius:"4px",border:`1px solid ${a.menuBorder}`,background:a.menuBg,color:a.text,cursor:"pointer"},"Export CSV");b.type="button",h.appendChild(b),u.appendChild(h),t.note&&u.appendChild(o("div",{fontSize:"11px",color:a.label,lineHeight:"1.4",flexShrink:"0"},t.note));const L=[...t.extraColumn?[t.extraColumn.label]:[],"Position","Site","Hard bin","Soft bin",...i.map(e=>e.name)],{columns:j,truncatedKeys:f}=R({dies:n,waferMetadata:t.waferMetadata,metadataFields:t.metadataFields,dieKeys:t.metadataColumns,waferKeys:t.waferMetadataColumns==="none"?"none":void 0,waferPlacement:t.waferMetadataColumns??"csv",reservedLabels:L}),x=[...t.extraColumn?[{label:t.extraColumn.label,get:e=>t.extraColumn.get(e)??""}]:[],{label:"Position",get:F},{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...i.map(e=>({label:e.name,get:l=>{const c=l.testValues?.[e.testNumber];if(c!==void 0)return M(c,e.unit);const m=l.testPass?.[e.testNumber];return m===void 0?"":m?"PASS":"FAIL"}})),...j.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],g=x.filter(e=>!e.csvOnly),C=o("div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${a.menuBorder}`,borderRadius:"4px",...t.maxHeight?{maxHeight:t.maxHeight}:{}}),p=document.createElement("table");p.className="wmap-dielist-table",p.setAttribute("aria-label",t.title??`Die list (${n.length} dies)`);const w=o("thead"),S=o("tr");for(const e of g){const l=document.createElement("th");l.className="wmap-dielist-th",l.scope="col",l.textContent=e.label,S.appendChild(l)}w.appendChild(S),p.appendChild(w);const v=o("tbody");for(const e of N){const l=o("tr");for(const c of g){const m=document.createElement("td");m.className="wmap-dielist-td",m.textContent=c.get(e),l.appendChild(m)}v.appendChild(l)}if(p.appendChild(v),C.appendChild(p),u.appendChild(C),r>0||f.length>0){const e=[];r>0&&e.push(`Showing the first ${d.toLocaleString()} of ${n.length.toLocaleString()} dies. The CSV export contains all ${n.length.toLocaleString()}.`),f.length>0&&e.push(`${f.length} further metadata field${f.length===1?"":"s"} not shown.`),u.appendChild(o("div",{fontSize:"11px",color:a.label,lineHeight:"1.4",flexShrink:"0"},e.join(" ")))}return b.addEventListener("click",()=>{const e=[x.map(l=>y(l.label)).join(",")];for(const l of n)e.push(x.map(c=>y(c.get(l))).join(","));E(e.join(`
12
+ `,n.head.appendChild(s)}function i(n,s,t,l){const r=n.createElement(s);return t&&Object.assign(r.style,t),l!==void 0&&(r.textContent=l),r}function P(n){return H(n)?`(${n.x}, ${n.y})`:"\u2014"}function D(n,s){if(s?.length)return s.filter(R);const t=new Map;for(const l of n)for(const r of Object.keys(l.testValues??{})){const d=Number(r);t.has(d)||t.set(d,{testNumber:d,name:`Test ${d}`})}return[...t.values()].sort((l,r)=>l.testNumber-r.testNumber)}export function buildDieListSection(n,s,t={}){if(!n.length)return null;const l=t.ownerDocument??document;F(l);const r=D(n,s),d=t.maxRows??B,h=Math.max(0,n.length-d),k=h>0?n.slice(0,d):n,u=i(l,"div",{display:"flex",flexDirection:"column",gap:"8px",flex:"1",minHeight:"0",minWidth:"0"}),b=i(l,"div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});b.appendChild(i(l,"div",{fontSize:"10px",fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:o.label},t.title??`Die list (${n.length})`));const x=i(l,"button",{fontSize:"11px",padding:"3px 8px",borderRadius:"4px",border:`1px solid ${o.menuBorder}`,background:o.menuBg,color:o.text,cursor:"pointer"},"Export CSV");x.type="button",b.appendChild(x),u.appendChild(b),t.note&&u.appendChild(i(l,"div",{fontSize:"11px",color:o.label,lineHeight:"1.4",flexShrink:"0"},t.note));const L=[...t.extraColumn?[t.extraColumn.label]:[],"Position","Site","Hard bin","Soft bin",...r.map(e=>e.name)],{columns:j,truncatedKeys:f}=E({dies:n,waferMetadata:t.waferMetadata,metadataFields:t.metadataFields,dieKeys:t.metadataColumns,waferKeys:t.waferMetadataColumns==="none"?"none":void 0,waferPlacement:t.waferMetadataColumns??"csv",reservedLabels:L}),g=[...t.extraColumn?[{label:t.extraColumn.label,get:e=>t.extraColumn.get(e)??""}]:[],{label:"Position",get:P},{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...r.map(e=>({label:e.name,get:a=>{const c=a.testValues?.[e.testNumber];if(c!==void 0)return T(c,e.unit);const m=a.testPass?.[e.testNumber];return m===void 0?"":m?"PASS":"FAIL"}})),...j.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],C=g.filter(e=>!e.csvOnly),w=i(l,"div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${o.menuBorder}`,borderRadius:"4px",...t.maxHeight?{maxHeight:t.maxHeight}:{}}),p=l.createElement("table");p.className="wmap-dielist-table",p.setAttribute("aria-label",t.title??`Die list (${n.length} dies)`);const S=i(l,"thead"),v=i(l,"tr");for(const e of C){const a=l.createElement("th");a.className="wmap-dielist-th",a.scope="col",a.textContent=e.label,v.appendChild(a)}S.appendChild(v),p.appendChild(S);const y=i(l,"tbody");for(const e of k){const a=i(l,"tr");for(const c of C){const m=l.createElement("td");m.className="wmap-dielist-td",m.textContent=c.get(e),a.appendChild(m)}y.appendChild(a)}if(p.appendChild(y),w.appendChild(p),u.appendChild(w),h>0||f.length>0){const e=[];h>0&&e.push(`Showing the first ${d.toLocaleString()} of ${n.length.toLocaleString()} dies. The CSV export contains all ${n.length.toLocaleString()}.`),f.length>0&&e.push(`${f.length} further metadata field${f.length===1?"":"s"} not shown.`),u.appendChild(i(l,"div",{fontSize:"11px",color:o.label,lineHeight:"1.4",flexShrink:"0"},e.join(" ")))}return x.addEventListener("click",()=>{const e=[g.map(a=>$(a.label)).join(",")];for(const a of n)e.push(g.map(c=>$(c.get(a))).join(","));M(e.join(`
13
13
  `),t.csvFilename??"dies.csv","text/csv",t.onSaveText)}),u}
@@ -63,6 +63,11 @@ export interface InsightsTabDeps {
63
63
  * renderWaferGallery.ts's `rebuildLegend`/`setInsightsOpen`.
64
64
  */
65
65
  showMetadataStrip?: boolean;
66
+ /** Document to build this tab's DOM into. Default `document` — pass the
67
+ * render's own `ownerDocument` when the container might live in a
68
+ * different document (e.g. a gallery card detached into its own popup
69
+ * window). */
70
+ ownerDocument?: Document;
66
71
  }
67
72
  export interface InsightsTabHandle {
68
73
  /** Append this wherever the tab's content should live; starts hidden (`display: none`). */
@@ -1 +1 @@
1
- import{buildFacetTable as de,facetValueOf as ce,FACET_NONE_VALUE as pe}from"../stats/facets.js";import{isParametricTest as ue}from"../renderer/buildWaferMap.js";import{getColorScheme as me}from"../renderer/colorSchemes.js";import{CLR as C}from"./toolbar.js";import{renderCapabilityPanel as fe}from"./charts/capability.js";import{renderBoxplotPanel as be}from"./charts/boxplot.js";import{renderHistogramPanel as ye}from"./charts/histogram.js";import{renderCorrelationPanel as he}from"./charts/correlation.js";import{renderScatterPanel as ge}from"./charts/scatter.js";import{renderBarPanel as q}from"./charts/barPanel.js";import{renderBinClusterPanel as Ce}from"./charts/binCluster.js";import{QUANTITY as xe}from"./charts/palette.js";import{makeChartGridWrap as j,makeLabeledSelect as Se}from"./charts/chartShell.js";import{buildYieldData as A,buildYieldDataCombined as we}from"../stats/yield.js";import{buildBinParetoData as Be}from"../stats/binPareto.js";import{buildLotTestSection as ke,buildLotFunctionalSection as ve,buildMetadataStripBox as Te}from"./summaryPanel.js";import{buildRegionYieldData as N,buildRingRegions as $e,buildQuadrantRegions as Ee}from"../stats/regions.js";import{renderRegionYieldDiagram as z}from"./charts/regionYieldDiagram.js";const Oe=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}];export function createInsightsTab(v){const{getItems:H,getLotStats:Q,getColorSchemeName:h,passBins:f,getRingCount:K,onSaveImage:y,onSaveText:M,openWafer:D}=v,U=v.showMetadataStrip??!0,S=document.createElement("div");Object.assign(S.style,{display:"none",flexDirection:"column",gap:"10px",width:"100%"});const L=document.createElement("div"),x=document.createElement("div");Object.assign(x.style,{display:"flex",gap:"4px",borderBottom:`1px solid ${C.menuBorder}`,marginBottom:"2px"}),x.setAttribute("role","tablist"),x.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const t=Array.from(x.querySelectorAll('[role="tab"]')),a=t.indexOf(document.activeElement);if(a===-1)return;e.preventDefault();const r=t[(a+(e.key==="ArrowRight"?1:-1)+t.length)%t.length];r.focus(),r.click()});const T=document.createElement("div");Object.assign(T.style,{display:"flex",flexDirection:"column",gap:"10px"}),S.appendChild(L),S.appendChild(x),S.appendChild(T);let $=v.defaultView??"overview",w,O=[];function V(e,t,a){D?.(e,t,a)}function _(){return H().map((e,t)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:e.label??String(e.wafer.metadata?.waferId??""),waferIndex:t,statsSummary:e.statsSummary}).filter(e=>e!=null)}function F(e,t){Object.assign(e.style,{background:"none",border:"none",borderBottom:t?`2px solid ${C.iconActive}`:"2px solid transparent",color:t?C.iconActive:C.label,fontWeight:t?"700":"500",fontSize:"12px",padding:"6px 10px 8px",cursor:"pointer",marginBottom:"-1px"})}function X(e,t){const a=document.createElement("button");a.type="button",a.textContent=t;const r=e===$;return F(a,r),a.dataset.wmapInsightsTab=e,a.setAttribute("role","tab"),a.setAttribute("aria-selected",r?"true":"false"),a.tabIndex=r?0:-1,a.addEventListener("click",()=>{$!==e&&($=e,R())}),a}function J(e){const t=document.createElement("button");return t.type="button",t.textContent=`\u2039 ${e.label}`,F(t,!1),t.dataset.wmapInsightsBack="1",t.addEventListener("click",e.onBack),t}function Z(e,t,a,r=!0){const l=j(),s=me(h());let p="label";const d=a??"group",n=f.length===1?`bin ${f[0]}`:`bins ${f.join(", ")}`,u=Q?.(),m=new Map(u?.lotYieldSeries.map(o=>[o.waferIndex,o.yieldPercent])),c=o=>({...o,label:o.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:m.get(o.waferIndex),key:o.waferIndex}),B=e.map(c),g=t?.map(o=>({key:o.key,items:o.items.map(c)})),k=()=>g?we(g,f,p):A(B,f,p),i={title:t?`Yield by ${d} (pass: ${n})`:`Yield by wafer (pass: ${n})`,data:k(),selfControl:{current:p,options:[["yield","Sort: yield"],["label",t?`Sort: ${d}`:"Sort: wafer ID"]],onChange:o=>(p=o,{data:k()})},barColor:()=>xe,valueLabel:o=>`${o.percent.toFixed(1)}%`,drill:g?{onOpenGroup:o=>{const P=g.find(E=>E.key===o.label)?.items??[];return{data:A(P,f,p),title:`Yield by wafer \u2014 ${d}: ${o.label} (pass: ${n})`}},onBack:()=>({data:k(),title:`Yield by ${d} (pass: ${n})`}),groupLabelText:d}:void 0,onOpen:D?o=>{typeof o.key=="number"&&V(o.key,`Wafer ${o.label}`)}:void 0};let b=null;if(r&&(b=q(i,y),b.card.style.minHeight="360px",l.appendChild(b.card)),t){const o=Ce({title:"Hard bin pareto",groups:t.map(P=>({key:P.key,items:P.items.map(E=>({dies:E.dies,hardBinCounts:E.statsSummary?.stats.hardBinCounts,softBinCounts:E.statsSummary?.stats.softBinCounts}))})),colorScheme:h(),onSaveImage:y});return o.card.style.minHeight="360px",l.appendChild(o.card),{card:l,destroy:()=>{b?.destroy(),o.destroy()}}}let I="hbin";const ie=s.forBin,le=e.map(o=>({dies:o.dies,hardBinCounts:o.statsSummary?.stats.hardBinCounts,softBinCounts:o.statsSummary?.stats.softBinCounts})),G=()=>Be(le,I),se={title:"Hard bin pareto",data:G(),selfControl:{current:I,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:o=>(I=o,{data:G(),title:`${I==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:o=>ie(o.binCode??0)},Y=q(se,y);return Y.card.style.minHeight="360px",l.appendChild(Y.card),{card:l,destroy:()=>{b?.destroy(),Y.destroy()}}}function W(){const e=document.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{display:"flex",flexDirection:"column",gap:"10px",minWidth:"0",background:C.menuBg,border:`1px solid ${C.menuBorder}`,borderRadius:"6px",padding:"12px"}),e}function ee(e){if(L.innerHTML="",!U)return;const t=Te(e.map(a=>({metadata:a.metadata})),void 0,{facetableOnly:!1});t&&(t.style.marginBottom="0",L.appendChild(t))}function te(e,t,a){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const r=e.map(i=>i.wafer),l=e.map(i=>i.dies),s=e.flatMap(i=>i.dies),p=e.map(i=>i.statsSummary),d=p.every(i=>i!==void 0)?p:void 0,n=K?.()??4,u=[],m=[],c=N(l,r,n,f,$e);if(c.length){const i=z({title:"Ring yield",mode:"ring",rows:c,colorScheme:h(),onSaveImage:y});u.push(i.card),m.push(i.destroy)}const B=N(l,r,n,f,Ee);if(B.length){const i=z({title:"Quadrant yield",mode:"quadrant",rows:B,colorScheme:h(),onSaveImage:y});u.push(i.card),m.push(i.destroy)}let g=null;if(t.length){const i=ke(s,t,void 0,d,M);if(i){const b=W();b.appendChild(i),g=b}}let k=null;if(a.length){const i=ve(s,a,d,M);if(i){const b=W();b.appendChild(i),k=b}}return{elements:u,testValuesCard:g,functionalCard:k,destroy:()=>{for(const i of m)i()}}}function ne(e){const t=f.length===1?`bin ${f[0]}`:`bins ${f.join(", ")}`,a=A([{...e,key:e.waferIndex}],f)[0]?.percent,r=W();Object.assign(r.style,{flexDirection:"row",flexWrap:"wrap",gap:"8px"});function l(s,p){const d=document.createElement("div");Object.assign(d.style,{border:`1px solid ${C.menuBorder}`,borderRadius:"6px",padding:"8px 16px",textAlign:"center",minWidth:"110px"});const n=document.createElement("div");n.textContent=s,Object.assign(n.style,{fontSize:"20px",fontWeight:"700",color:C.value,lineHeight:"1.2"});const u=document.createElement("div");return u.textContent=p,Object.assign(u.style,{fontSize:"10px",color:C.label,marginTop:"2px"}),d.append(n,u),d}return a!==void 0&&r.appendChild(l(`${a.toFixed(1)}%`,`Yield \xB7 pass: ${t}`)),r.appendChild(l(String(e.dies.length),"Total dies")),r}function ae(e,t,a,r,l){const s=document.createElement("div");Object.assign(s.style,{display:"flex",flexDirection:"column",gap:"10px"});const p=e.length===1&&!r;p&&s.appendChild(ne(e[0]));const d=Z(e,r,l,!p);s.appendChild(d.card);const n=te(e,t,a);for(const u of n.elements)d.card.appendChild(u);return n.testValuesCard&&s.appendChild(n.testValuesCard),n.functionalCard&&s.appendChild(n.functionalCard),{card:s,destroy:()=>{d.destroy(),n.destroy()}}}function oe(e,t,a,r){const l=j(),s=c=>({...c,testStats:c.statsSummary?.stats.perTestStats}),p=e.map(s),d=a?.map(c=>({key:c.key,items:c.items.map(s)})),n=be({title:"Test value distribution",items:p,testDefs:t,groups:d,groupLabelText:r,colorScheme:h(),onSaveImage:y,onOpen:D?(c,B)=>V(c,`Wafer ${e.find(g=>g.waferIndex===c)?.label??c}`,B):void 0}),u=ye({title:"Value histogram",items:e,testDefs:t,groups:a,colorScheme:h(),onSaveImage:y}),m=fe({title:"Process capability",items:e,testDefs:t,groups:a,colorScheme:h(),onSaveImage:y,onSelectTest:c=>{n.setTest(c),u.setTest(c)}});return l.append(m.card,n.card,u.card),{card:l,destroy:()=>{m.destroy(),n.destroy(),u.destroy()}}}function re(e,t,a){const r=j(),l=ge({title:"Test scatter",items:e,testDefs:t,groups:a,colorScheme:h(),onSaveImage:y}),s=he({title:"Test correlation matrix",items:e,testDefs:t,groups:a,colorScheme:h(),onSaveImage:y,onSelectPair:(p,d)=>l.setXY(p,d)});return r.append(s.card,l.card),{card:r,destroy:()=>{s.destroy(),l.destroy()}}}function R(){for(const n of O)n.destroy();O=[],T.innerHTML="",x.innerHTML="",v.backTab&&x.appendChild(J(v.backTab));for(const n of Oe)x.appendChild(X(n.key,n.label));const e=_();ee(e);const t=de(e,{facetableOnly:!0}).filter(n=>n.splittable),a=document.createElement("div");Object.assign(a.style,{display:"flex",gap:"8px",alignItems:"center"});let r;t.length>0?(a.appendChild(Se("Group by:",[{value:"",label:"None"},...t.map(n=>({value:n.key,label:`${n.label} (${n.values.length})`}))],w??"",n=>{w=n||void 0,R()},{hook:"group-by"})),r=t.find(n=>n.key===w)?.label):w=void 0,T.appendChild(a);const l=H().find(n=>n?.testDefs?.length)?.testDefs??[],s=l.filter(ue);let p;if(w){const n=new Map,u=[];for(const m of e){const c=ce(m.metadata,w)??pe;n.has(c)||(n.set(c,[]),u.push(c)),n.get(c).push(m)}p=u.map(m=>({key:m,items:n.get(m)}))}const d=$==="overview"?ae(e,s,l,p,r):$==="distributions"?oe(e,s,p,r):re(e,s,p);O.push(d),T.appendChild(d.card)}return{el:S,render:R,destroy:()=>{for(const e of O)e.destroy();S.remove()}}}
1
+ import{buildFacetTable as ce,facetValueOf as pe,FACET_NONE_VALUE as ue}from"../stats/facets.js";import{isParametricTest as me}from"../renderer/buildWaferMap.js";import{getColorScheme as fe}from"../renderer/colorSchemes.js";import{CLR as x}from"./toolbar.js";import{renderCapabilityPanel as be}from"./charts/capability.js";import{renderBoxplotPanel as ye}from"./charts/boxplot.js";import{renderHistogramPanel as he}from"./charts/histogram.js";import{renderCorrelationPanel as ge}from"./charts/correlation.js";import{renderScatterPanel as Ce}from"./charts/scatter.js";import{renderBarPanel as N}from"./charts/barPanel.js";import{renderBinClusterPanel as xe}from"./charts/binCluster.js";import{QUANTITY as Se}from"./charts/palette.js";import{makeChartGridWrap as A,makeLabeledSelect as we}from"./charts/chartShell.js";import{buildYieldData as H,buildYieldDataCombined as Be}from"../stats/yield.js";import{buildBinParetoData as ke}from"../stats/binPareto.js";import{buildLotTestSection as ve,buildLotFunctionalSection as Te,buildMetadataStripBox as De}from"./summaryPanel.js";import{buildRegionYieldData as z,buildRingRegions as $e,buildQuadrantRegions as Ee}from"../stats/regions.js";import{renderRegionYieldDiagram as Q}from"./charts/regionYieldDiagram.js";const Oe=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}];export function createInsightsTab(w){const{getItems:M,getLotStats:K,getColorSchemeName:g,passBins:b,getRingCount:U,onSaveImage:h,onSaveText:V,openWafer:L}=w,_=w.showMetadataStrip??!0,i=w.ownerDocument??document,B=i.createElement("div");Object.assign(B.style,{display:"none",flexDirection:"column",gap:"10px",width:"100%"});const W=i.createElement("div"),S=i.createElement("div");Object.assign(S.style,{display:"flex",gap:"4px",borderBottom:`1px solid ${x.menuBorder}`,marginBottom:"2px"}),S.setAttribute("role","tablist"),S.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const t=Array.from(S.querySelectorAll('[role="tab"]')),o=t.indexOf(i.activeElement);if(o===-1)return;e.preventDefault();const r=t[(o+(e.key==="ArrowRight"?1:-1)+t.length)%t.length];r.focus(),r.click()});const D=i.createElement("div");Object.assign(D.style,{display:"flex",flexDirection:"column",gap:"10px"}),B.appendChild(W),B.appendChild(S),B.appendChild(D);let $=w.defaultView??"overview",k,O=[];function F(e,t,o){L?.(e,t,o)}function X(){return M().map((e,t)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:e.label??String(e.wafer.metadata?.waferId??""),waferIndex:t,statsSummary:e.statsSummary}).filter(e=>e!=null)}function G(e,t){Object.assign(e.style,{background:"none",border:"none",borderBottom:t?`2px solid ${x.iconActive}`:"2px solid transparent",color:t?x.iconActive:x.label,fontWeight:t?"700":"500",fontSize:"12px",padding:"6px 10px 8px",cursor:"pointer",marginBottom:"-1px"})}function J(e,t){const o=i.createElement("button");o.type="button",o.textContent=t;const r=e===$;return G(o,r),o.dataset.wmapInsightsTab=e,o.setAttribute("role","tab"),o.setAttribute("aria-selected",r?"true":"false"),o.tabIndex=r?0:-1,o.addEventListener("click",()=>{$!==e&&($=e,Y())}),o}function Z(e){const t=i.createElement("button");return t.type="button",t.textContent=`\u2039 ${e.label}`,G(t,!1),t.dataset.wmapInsightsBack="1",t.addEventListener("click",e.onBack),t}function ee(e,t,o,r=!0){const s=A(i),d=fe(g());let u="label";const c=o??"group",n=b.length===1?`bin ${b[0]}`:`bins ${b.join(", ")}`,m=K?.(),f=new Map(m?.lotYieldSeries.map(a=>[a.waferIndex,a.yieldPercent])),p=a=>({...a,label:a.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:f.get(a.waferIndex),key:a.waferIndex}),v=e.map(p),C=t?.map(a=>({key:a.key,items:a.items.map(p)})),T=()=>C?Be(C,b,u):H(v,b,u),l={title:t?`Yield by ${c} (pass: ${n})`:`Yield by wafer (pass: ${n})`,data:T(),selfControl:{current:u,options:[["yield","Sort: yield"],["label",t?`Sort: ${c}`:"Sort: wafer ID"]],onChange:a=>(u=a,{data:T()})},barColor:()=>Se,valueLabel:a=>`${a.percent.toFixed(1)}%`,drill:C?{onOpenGroup:a=>{const P=C.find(E=>E.key===a.label)?.items??[];return{data:H(P,b,u),title:`Yield by wafer \u2014 ${c}: ${a.label} (pass: ${n})`}},onBack:()=>({data:T(),title:`Yield by ${c} (pass: ${n})`}),groupLabelText:c}:void 0,onOpen:L?a=>{typeof a.key=="number"&&F(a.key,`Wafer ${a.label}`)}:void 0,ownerDocument:i};let y=null;if(r&&(y=N(l,h),y.card.style.minHeight="360px",s.appendChild(y.card)),t){const a=xe({title:"Hard bin pareto",groups:t.map(P=>({key:P.key,items:P.items.map(E=>({dies:E.dies,hardBinCounts:E.statsSummary?.stats.hardBinCounts,softBinCounts:E.statsSummary?.stats.softBinCounts}))})),colorScheme:g(),onSaveImage:h,ownerDocument:i});return a.card.style.minHeight="360px",s.appendChild(a.card),{card:s,destroy:()=>{y?.destroy(),a.destroy()}}}let I="hbin";const le=d.forBin,se=e.map(a=>({dies:a.dies,hardBinCounts:a.statsSummary?.stats.hardBinCounts,softBinCounts:a.statsSummary?.stats.softBinCounts})),q=()=>ke(se,I),de={title:"Hard bin pareto",data:q(),selfControl:{current:I,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:a=>(I=a,{data:q(),title:`${I==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:a=>le(a.binCode??0),ownerDocument:i},j=N(de,h);return j.card.style.minHeight="360px",s.appendChild(j.card),{card:s,destroy:()=>{y?.destroy(),j.destroy()}}}function R(){const e=i.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{display:"flex",flexDirection:"column",gap:"10px",minWidth:"0",background:x.menuBg,border:`1px solid ${x.menuBorder}`,borderRadius:"6px",padding:"12px"}),e}function te(e){if(W.innerHTML="",!_)return;const t=De(e.map(o=>({metadata:o.metadata})),void 0,{facetableOnly:!1});t&&(t.style.marginBottom="0",W.appendChild(t))}function ne(e,t,o){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const r=e.map(l=>l.wafer),s=e.map(l=>l.dies),d=e.flatMap(l=>l.dies),u=e.map(l=>l.statsSummary),c=u.every(l=>l!==void 0)?u:void 0,n=U?.()??4,m=[],f=[],p=z(s,r,n,b,$e);if(p.length){const l=Q({title:"Ring yield",mode:"ring",rows:p,colorScheme:g(),onSaveImage:h,ownerDocument:i});m.push(l.card),f.push(l.destroy)}const v=z(s,r,n,b,Ee);if(v.length){const l=Q({title:"Quadrant yield",mode:"quadrant",rows:v,colorScheme:g(),onSaveImage:h,ownerDocument:i});m.push(l.card),f.push(l.destroy)}let C=null;if(t.length){const l=ve(d,t,void 0,c,V);if(l){const y=R();y.appendChild(l),C=y}}let T=null;if(o.length){const l=Te(d,o,c,V);if(l){const y=R();y.appendChild(l),T=y}}return{elements:m,testValuesCard:C,functionalCard:T,destroy:()=>{for(const l of f)l()}}}function oe(e){const t=b.length===1?`bin ${b[0]}`:`bins ${b.join(", ")}`,o=H([{...e,key:e.waferIndex}],b)[0]?.percent,r=R();Object.assign(r.style,{flexDirection:"row",flexWrap:"wrap",gap:"8px"});function s(d,u){const c=i.createElement("div");Object.assign(c.style,{border:`1px solid ${x.menuBorder}`,borderRadius:"6px",padding:"8px 16px",textAlign:"center",minWidth:"110px"});const n=i.createElement("div");n.textContent=d,Object.assign(n.style,{fontSize:"20px",fontWeight:"700",color:x.value,lineHeight:"1.2"});const m=i.createElement("div");return m.textContent=u,Object.assign(m.style,{fontSize:"10px",color:x.label,marginTop:"2px"}),c.append(n,m),c}return o!==void 0&&r.appendChild(s(`${o.toFixed(1)}%`,`Yield \xB7 pass: ${t}`)),r.appendChild(s(String(e.dies.length),"Total dies")),r}function ae(e,t,o,r,s){const d=i.createElement("div");Object.assign(d.style,{display:"flex",flexDirection:"column",gap:"10px"});const u=e.length===1&&!r;u&&d.appendChild(oe(e[0]));const c=ee(e,r,s,!u);d.appendChild(c.card);const n=ne(e,t,o);for(const m of n.elements)c.card.appendChild(m);return n.testValuesCard&&d.appendChild(n.testValuesCard),n.functionalCard&&d.appendChild(n.functionalCard),{card:d,destroy:()=>{c.destroy(),n.destroy()}}}function re(e,t,o,r){const s=A(i),d=p=>({...p,testStats:p.statsSummary?.stats.perTestStats}),u=e.map(d),c=o?.map(p=>({key:p.key,items:p.items.map(d)})),n=ye({title:"Test value distribution",items:u,testDefs:t,groups:c,groupLabelText:r,colorScheme:g(),onSaveImage:h,onOpen:L?(p,v)=>F(p,`Wafer ${e.find(C=>C.waferIndex===p)?.label??p}`,v):void 0,ownerDocument:i}),m=he({title:"Value histogram",items:e,testDefs:t,groups:o,colorScheme:g(),onSaveImage:h,ownerDocument:i}),f=be({title:"Process capability",items:e,testDefs:t,groups:o,colorScheme:g(),onSaveImage:h,onSelectTest:p=>{n.setTest(p),m.setTest(p)},ownerDocument:i});return s.append(f.card,n.card,m.card),{card:s,destroy:()=>{f.destroy(),n.destroy(),m.destroy()}}}function ie(e,t,o){const r=A(i),s=Ce({title:"Test scatter",items:e,testDefs:t,groups:o,colorScheme:g(),onSaveImage:h,ownerDocument:i}),d=ge({title:"Test correlation matrix",items:e,testDefs:t,groups:o,colorScheme:g(),onSaveImage:h,onSelectPair:(u,c)=>s.setXY(u,c),ownerDocument:i});return r.append(d.card,s.card),{card:r,destroy:()=>{d.destroy(),s.destroy()}}}function Y(){for(const n of O)n.destroy();O=[],D.innerHTML="",S.innerHTML="",w.backTab&&S.appendChild(Z(w.backTab));for(const n of Oe)S.appendChild(J(n.key,n.label));const e=X();te(e);const t=ce(e,{facetableOnly:!0}).filter(n=>n.splittable),o=i.createElement("div");Object.assign(o.style,{display:"flex",gap:"8px",alignItems:"center"});let r;t.length>0?(o.appendChild(we("Group by:",[{value:"",label:"None"},...t.map(n=>({value:n.key,label:`${n.label} (${n.values.length})`}))],k??"",n=>{k=n||void 0,Y()},{hook:"group-by",ownerDocument:i})),r=t.find(n=>n.key===k)?.label):k=void 0,D.appendChild(o);const s=M().find(n=>n?.testDefs?.length)?.testDefs??[],d=s.filter(me);let u;if(k){const n=new Map,m=[];for(const f of e){const p=pe(f.metadata,k)??ue;n.has(p)||(n.set(p,[]),m.push(p)),n.get(p).push(f)}u=m.map(f=>({key:f,items:n.get(f)}))}const c=$==="overview"?ae(e,d,s,u,r):$==="distributions"?re(e,d,u,r):ie(e,d,u);O.push(c),D.appendChild(c.card)}return{el:B,render:Y,destroy:()=>{for(const e of O)e.destroy();B.remove()}}}
@@ -9,6 +9,10 @@ export interface MetadataBadgeOptions {
9
9
  * method instead of a (nonexistent) single waferId, per this project's
10
10
  * requirement that stacked maps always self-identify as such. */
11
11
  lotStack?: MetadataBadgeLotStack;
12
+ /** Document to build the badge into. Default `document` — pass the render's
13
+ * own `ownerDocument` when the container might live in a different
14
+ * document (e.g. a gallery card detached into its own popup window). */
15
+ ownerDocument?: Document;
12
16
  }
13
17
  export interface MetadataBadgeController {
14
18
  el: HTMLDivElement;
@@ -1 +1 @@
1
- import{metadataEntries as m,buildCompactMetadataRows as b}from"./summaryPanel.js";import{CLR as c,Z_BASE as h,wireExpandToggle as w}from"./toolbar.js";function y(n,r){if(r)return r.aggrMethod?`${r.lotSize} wafers \xB7 ${r.aggrMethod}`:`${r.lotSize} wafers`;if(n.lot&&n.waferId!==void 0&&n.waferId!==""){const t=String(n.lot),e=String(n.waferId);return e.includes(t)?e:`${t} \xB7 ${e}`}for(const t of["lot","waferId","product","testProgram"]){const e=n[t];if(e!=null&&e!=="")return String(e)}}export function createMetadataBadge(n,r={}){let t=n??{},e=r.lotStack,a=!1;const o=document.createElement("div");Object.assign(o.style,{position:"absolute",bottom:"4px",left:"4px",zIndex:h,background:c.menuBg,border:`1px solid ${c.menuBorder}`,borderRadius:"4px",boxShadow:"0 1px 4px rgba(0,0,0,0.12)",padding:"3px 8px",fontSize:"11px",color:c.value,cursor:"pointer",maxWidth:"260px",pointerEvents:"auto"});const l=document.createElement("div");Object.assign(l.style,{display:"flex",alignItems:"center",gap:"6px",whiteSpace:"nowrap"});const s=document.createElement("span");s.style.overflow="hidden",s.style.textOverflow="ellipsis";const f=document.createElement("span");Object.assign(f.style,{fontSize:"12px",lineHeight:"1",color:c.label,flexShrink:"0"}),l.appendChild(s),l.appendChild(f);const i=document.createElement("div");Object.assign(i.style,{marginTop:"5px",display:"none"}),o.appendChild(l),o.appendChild(i);function u(){const d=y(t,e)??"Wafer info";if(s.textContent=d,f.textContent=a?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(a)),o.setAttribute("aria-label",`Wafer info: ${d}. ${a?"Click to collapse.":"Click to expand."}`),i.innerHTML="",i.style.display=a?"block":"none",!a)return;if(e){const g=document.createElement("div");Object.assign(g.style,{fontWeight:"600",marginBottom:"3px"}),g.textContent=e.aggrMethod?`${e.lotSize} wafers stacked \xB7 ${e.aggrMethod}`:`${e.lotSize} wafers stacked`,i.appendChild(g)}const p=b(t);p&&i.appendChild(p)}const x=w(o,d=>{a=d,u()});return u(),{el:o,update(d,p){t=d??{},e=p,u()},isEmpty(){return!e&&m(t).length===0},destroy(){x.destroy(),o.remove()}}}
1
+ import{metadataEntries as b,buildCompactMetadataRows as h}from"./summaryPanel.js";import{CLR as f,Z_BASE as w,wireExpandToggle as y}from"./toolbar.js";function C(n,o){if(o)return o.aggrMethod?`${o.lotSize} wafers \xB7 ${o.aggrMethod}`:`${o.lotSize} wafers`;if(n.lot&&n.waferId!==void 0&&n.waferId!==""){const t=String(n.lot),e=String(n.waferId);return e.includes(t)?e:`${t} \xB7 ${e}`}for(const t of["lot","waferId","product","testProgram"]){const e=n[t];if(e!=null&&e!=="")return String(e)}}export function createMetadataBadge(n,o={}){let t=n??{},e=o.lotStack,a=!1;const i=o.ownerDocument??document,r=i.createElement("div");Object.assign(r.style,{position:"absolute",bottom:"4px",left:"4px",zIndex:w,background:f.menuBg,border:`1px solid ${f.menuBorder}`,borderRadius:"4px",boxShadow:"0 1px 4px rgba(0,0,0,0.12)",padding:"3px 8px",fontSize:"11px",color:f.value,cursor:"pointer",maxWidth:"260px",pointerEvents:"auto"});const s=i.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",gap:"6px",whiteSpace:"nowrap"});const p=i.createElement("span");p.style.overflow="hidden",p.style.textOverflow="ellipsis";const g=i.createElement("span");Object.assign(g.style,{fontSize:"12px",lineHeight:"1",color:f.label,flexShrink:"0"}),s.appendChild(p),s.appendChild(g);const d=i.createElement("div");Object.assign(d.style,{marginTop:"5px",display:"none"}),r.appendChild(s),r.appendChild(d);function u(){const l=C(t,e)??"Wafer info";if(p.textContent=l,g.textContent=a?"\u25B4":"\u25BE",r.setAttribute("aria-expanded",String(a)),r.setAttribute("aria-label",`Wafer info: ${l}. ${a?"Click to collapse.":"Click to expand."}`),d.innerHTML="",d.style.display=a?"block":"none",!a)return;if(e){const x=i.createElement("div");Object.assign(x.style,{fontWeight:"600",marginBottom:"3px"}),x.textContent=e.aggrMethod?`${e.lotSize} wafers stacked \xB7 ${e.aggrMethod}`:`${e.lotSize} wafers stacked`,d.appendChild(x)}const c=h(t);c&&d.appendChild(c)}const m=y(r,l=>{a=l,u()});return u(),{el:r,update(l,c){t=l??{},e=c,u()},isEmpty(){return!e&&b(t).length===0},destroy(){m.destroy(),r.remove()}}}
@@ -1,20 +1,20 @@
1
- import{getUniqueTestNumbers as yn,resolveTestNumber as xn,findTestDef as wn}from"../renderer/buildView.js";import{getColorScheme as vn}from"../renderer/colorSchemes.js";import{metadataValueColor as Cn}from"../renderer/colorMap.js";import{resolveCanvasTheme as Sn}from"./canvasTheme.js";import{ICONS as pe}from"./icons.js";import{CLR as m,sevColor as Mt,BIN_LEGEND_MODES as Mn,STACKED_MODES as ue,Z_ABOVE as kt,applyOverlayZ as kn,getTooltip as Bn,hideTooltip as Bt,createToolbarHelpers as En,buildModeMenuEl as On,openDetachWindow as Dn,openFloatingWindow as Tn,openModal as Wn,copyWmapThemeTokens as Ln,syncWmapPopupTheme as In,openUserGuideWindow as Rn,makePaletteBtn as Pn,makeLogScaleBtn as An,makeLegendStyleBtn as Fn,makeOverlaysBtn as Hn,makeOrientationBtn as $n,overlayRootFor as Et,saveImageBlob as jn,markMenuTrigger as me,wireMenuA11y as Ot,wireExpandToggle as Dt,passFailMenuRows as zn,requestedPassFailDisplay as Ge,logWmapVersionOnce as Nn,buildDataModeEntries as Vn,metadataKeyHasData as _n,metadataModeEntry as Gn}from"./toolbar.js";import{aggregateValues as Kn,aggregateBinCounts as Tt}from"../core/aggregates.js";import{renderWaferMap as Ke}from"./renderWaferMap.js";import{classifyChanged as qn}from"./renderWaferMap.js";import{buildWaferMap as Xn,getTestPassStatus as Un,isParametricTest as Wt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Ee}from"../stats/analyzeWaferMap.js";import{collectWarnings as Yn,buildWarningsMenuEl as Qn,severityOf as Zn}from"./warnings.js";import{compareNatural as Jn}from"../core/utils.js";import{createSummaryPanelEl as qe,buildMetadataStripRow as ei,buildCompactMetadataRows as Lt,metadataEntries as It,renderLotSummaryContent as ti}from"./summaryPanel.js";import"../stats/facets.js";import{openHtmlReport as ni}from"../stats/renderFindingsReport.js";import{escHtml as ge,renderSection as ii,renderSeverityBadge as ai,reportStyles as oi}from"../stats/reportHtml.js";import{createInsightsTab as li}from"./insightsTab.js";import{getDieKey as si,hasPosition as ri}from"../core/dies.js";function Oe(S){const B=new Set;return S.filter(p=>B.has(p.bin)?!1:(B.add(p.bin),!0))}function Rt(S,B){const p=document.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:"2px 4px",borderRadius:"3px"});const Y=document.createElement("span");Object.assign(Y.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:B.color,border:B.isActive?`2px solid ${m.iconActive}`:`1px solid ${m.menuBorder}`,borderRadius:"2px",boxSizing:"border-box"});const te=document.createElement("span");te.textContent=B.label,Object.assign(te.style,{fontWeight:B.isActive?"700":"400",color:B.isActive?m.iconActive:m.text,whiteSpace:"nowrap"}),p.appendChild(Y),p.appendChild(te),p.setAttribute("role","button"),p.setAttribute("aria-pressed",B.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=m.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=m.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",B.onClick),p.addEventListener("keydown",L=>{(L.key==="Enter"||L.key===" ")&&(L.preventDefault(),B.onClick())}),S.appendChild(p)}export function renderWaferGallery(S,B,p={}){Nn();const Y=p.cardPadding??6,te=p.downloadFilename??"wafer-gallery";let L=p.columns;const Pt=p.showPlotModeSelector??!0,At=p.showHelpButton??!1,Ft=p.userGuideExtension,Xe=p.insights?.enabled??!1,Ht=kn(p.zIndex),Q=p.summaryPanel,Ue=p.passBins??[1];let he=p.fallbackFormat,D=p.lotStatsSummary,ne=p.legendPosition??"default",d={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},w=[],q=[],Z=[],M=[],y=B.map(e=>typeof e=="function"?null:e),De=0,be=0;const R=new Map;let $t=0,T=null,ie=null,Ye=new Set,u=null,ae="lot",jt={};function Qe(e){return y[e]?.statsSummary??D?.perWafer.find(t=>t.waferIndex===e)?.summary}function ye(){return!!(y.some(e=>e?.statsSummary?.findings.length)||D?.perWafer.some(e=>e.summary.findings.length))}const zt=Bn(),J=En(zt),{makeBtn:V,setActive:oe,makeSep:P,makeMenuRow:Nt,makeMenuSection:Vt,makeDropdown:Ze,makeCheckMenuBtn:di,closeOpenMenu:xe,getOpenMenu:le,setOpenMenu:se}=J;S.ownerDocument.addEventListener("click",xe,!0);const Je=()=>Bt();window.addEventListener("blur",Je);function Te(e){Ye=new Set(e);const t=[...O.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((i,s)=>{const c=Ye.has(s);i.style.outline=c?`3px solid ${m.findingHighlight}`:"",i.style.outlineOffset=c?"-3px":"",c&&n===void 0&&(n=i)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function We(){Te([])}function Le(){for(const e of w)e&&e.clearSelection()}function Ie(e,t){const n=new Set(e),i=t??w.map((s,c)=>c);for(const s of i){const c=M[s],a=w[s];if(!c||!a)continue;const r=c.dies.filter(o=>n.has(si(o)));a.setSelection(r)}}function et(){const e=document.createElement("div");Object.assign(e.style,{display:"flex",gap:"4px",marginBottom:"10px",borderBottom:`1px solid ${m.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=ae===t;Object.assign(n.style,{border:"none",borderRadius:"4px",padding:"2px 8px",fontSize:"11px",cursor:"pointer",fontWeight:i?"600":"400",background:i?m.bgActive:"transparent",color:i?m.iconHover:m.icon}),n.addEventListener("click",()=>{ae=t,We(),Le(),I()}),e.appendChild(n)}return e}function _t(){if(!u)return;u.innerHTML="",D&&u.appendChild(et());const e=[];for(let n=0;n<y.length;n++){const i=y[n];if(!i)continue;const s=Qe(n)?.findings??[];if(!s.length)continue;const c=s.filter(r=>r.severity==="unusual").length,a=s.filter(r=>r.severity==="notable").length;e.push({index:n,item:i,unusualCount:c,notableCount:a,totalCount:s.length})}if(e.length>0){const n=document.createElement("button");n.type="button",n.textContent="Findings report",Object.assign(n.style,{border:`1px solid ${m.menuBorder}`,borderRadius:"4px",padding:"3px 8px",marginBottom:"10px",fontSize:"10px",color:m.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":""}`,s=new Date().toLocaleString(),c=e.map(({item:r,index:o})=>{const l=Qe(o),f=r.label??`W${o+1}`,h=l.findings.map(g=>`<li>${ai(g.severity)} ${ge(g.summary)}</li>`).join("");return ii(ge(f),`<ul style="margin:0;padding-left:18px;list-style:none">${h}</ul>`)}).join(`
2
- `),a=`<!DOCTYPE html>
1
+ import{getUniqueTestNumbers as yn,resolveTestNumber as xn,findTestDef as wn}from"../renderer/buildView.js";import{getColorScheme as vn}from"../renderer/colorSchemes.js";import{metadataValueColor as Cn}from"../renderer/colorMap.js";import{resolveCanvasTheme as Sn}from"./canvasTheme.js";import{ICONS as pe}from"./icons.js";import{CLR as g,sevColor as Mt,BIN_LEGEND_MODES as Mn,STACKED_MODES as ue,Z_ABOVE as kt,applyOverlayZ as kn,getTooltip as Dn,hideTooltip as Dt,createToolbarHelpers as Bn,buildModeMenuEl as En,openDetachWindow as On,openFloatingWindow as Tn,openModal as Wn,copyWmapThemeTokens as Ln,syncWmapPopupTheme as In,openUserGuideWindow as Rn,makePaletteBtn as Pn,makeLogScaleBtn as An,makeLegendStyleBtn as Fn,makeOverlaysBtn as Hn,makeOrientationBtn as $n,overlayRootFor as Bt,saveImageBlob as jn,markMenuTrigger as me,wireMenuA11y as Et,wireExpandToggle as Ot,passFailMenuRows as zn,requestedPassFailDisplay as Ge,logWmapVersionOnce as Nn,buildDataModeEntries as Vn,metadataKeyHasData as _n,metadataModeEntry as Gn}from"./toolbar.js";import{aggregateValues as Kn,aggregateBinCounts as Tt}from"../core/aggregates.js";import{renderWaferMap as Ke}from"./renderWaferMap.js";import{classifyChanged as qn}from"./renderWaferMap.js";import{buildWaferMap as Xn,getTestPassStatus as Un,isParametricTest as Wt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Be}from"../stats/analyzeWaferMap.js";import{collectWarnings as Yn,buildWarningsMenuEl as Qn,severityOf as Zn}from"./warnings.js";import{compareNatural as Jn}from"../core/utils.js";import{createSummaryPanelEl as qe,buildMetadataStripRow as eo,buildCompactMetadataRows as Lt,metadataEntries as It,renderLotSummaryContent as to}from"./summaryPanel.js";import"../stats/facets.js";import{openHtmlReport as no}from"../stats/renderFindingsReport.js";import{escHtml as ge,renderSection as oo,renderSeverityBadge as io,reportStyles as ao}from"../stats/reportHtml.js";import{createInsightsTab as lo}from"./insightsTab.js";import{getDieKey as so,hasPosition as ro}from"../core/dies.js";function Ee(m){const D=new Set;return m.filter(p=>D.has(p.bin)?!1:(D.add(p.bin),!0))}function Rt(m,D){const p=m.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:"2px 4px",borderRadius:"3px"});const Y=m.ownerDocument.createElement("span");Object.assign(Y.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:D.color,border:D.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:"2px",boxSizing:"border-box"});const te=m.ownerDocument.createElement("span");te.textContent=D.label,Object.assign(te.style,{fontWeight:D.isActive?"700":"400",color:D.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),p.appendChild(Y),p.appendChild(te),p.setAttribute("role","button"),p.setAttribute("aria-pressed",D.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=g.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=g.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",D.onClick),p.addEventListener("keydown",L=>{(L.key==="Enter"||L.key===" ")&&(L.preventDefault(),D.onClick())}),m.appendChild(p)}export function renderWaferGallery(m,D,p={}){Nn();const Y=p.cardPadding??6,te=p.downloadFilename??"wafer-gallery";let L=p.columns;const Pt=p.showPlotModeSelector??!0,At=p.showHelpButton??!1,Ft=p.userGuideExtension,Xe=p.insights?.enabled??!1,Ht=kn(p.zIndex),Q=p.summaryPanel,Ue=p.passBins??[1];let he=p.fallbackFormat,O=p.lotStatsSummary,ne=p.legendPosition??"default",d={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},v=[],q=[],Z=[],M=[],x=D.map(e=>typeof e=="function"?null:e),Oe=0,be=0;const R=new Map;let $t=0,T=null,oe=null,Ye=new Set,u=null,ie="lot",jt={};function Qe(e){return x[e]?.statsSummary??O?.perWafer.find(t=>t.waferIndex===e)?.summary}function ye(){return!!(x.some(e=>e?.statsSummary?.findings.length)||O?.perWafer.some(e=>e.summary.findings.length))}const zt=Dn(),J=Bn(zt),{makeBtn:V,setActive:ae,makeSep:P,makeMenuRow:Nt,makeMenuSection:Vt,makeDropdown:Ze,makeCheckMenuBtn:co,closeOpenMenu:xe,getOpenMenu:le,setOpenMenu:se}=J;m.ownerDocument.addEventListener("click",xe,!0);const Je=()=>Dt();window.addEventListener("blur",Je);function Te(e){Ye=new Set(e);const t=[...E.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,s)=>{const c=Ye.has(s);o.style.outline=c?`3px solid ${g.findingHighlight}`:"",o.style.outlineOffset=c?"-3px":"",c&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function We(){Te([])}function Le(){for(const e of v)e&&e.clearSelection()}function Ie(e,t){const n=new Set(e),o=t??v.map((s,c)=>c);for(const s of o){const c=M[s],i=v[s];if(!c||!i)continue;const r=c.dies.filter(a=>n.has(so(a)));i.setSelection(r)}}function et(){const e=m.ownerDocument.createElement("div");Object.assign(e.style,{display:"flex",gap:"4px",marginBottom:"10px",borderBottom:`1px solid ${g.menuBorder}`,paddingBottom:"8px"});for(const t of["lot","wafers"]){const n=m.ownerDocument.createElement("button");n.type="button",n.textContent=t==="lot"?"Lot":"Wafers";const o=ie===t;Object.assign(n.style,{border:"none",borderRadius:"4px",padding:"2px 8px",fontSize:"11px",cursor:"pointer",fontWeight:o?"600":"400",background:o?g.bgActive:"transparent",color:o?g.iconHover:g.icon}),n.addEventListener("click",()=>{ie=t,We(),Le(),I()}),e.appendChild(n)}return e}function _t(){if(!u)return;u.innerHTML="",O&&u.appendChild(et());const e=[];for(let n=0;n<x.length;n++){const o=x[n];if(!o)continue;const s=Qe(n)?.findings??[];if(!s.length)continue;const c=s.filter(r=>r.severity==="unusual").length,i=s.filter(r=>r.severity==="notable").length;e.push({index:n,item:o,unusualCount:c,notableCount:i,totalCount:s.length})}if(e.length>0){const n=m.ownerDocument.createElement("button");n.type="button",n.textContent="Findings report",Object.assign(n.style,{border:`1px solid ${g.menuBorder}`,borderRadius:"4px",padding:"3px 8px",marginBottom:"10px",fontSize:"10px",color:g.iconHover,background:"none",cursor:"pointer",display:"block",width:"100%",textAlign:"left"}),n.addEventListener("click",()=>{const o=`Findings report \u2014 ${e.length} wafer${e.length>1?"s":""}`,s=new Date().toLocaleString(),c=e.map(({item:r,index:a})=>{const l=Qe(a),f=r.label??`W${a+1}`,b=l.findings.map(h=>`<li>${io(h.severity)} ${ge(h.summary)}</li>`).join("");return oo(ge(f),`<ul style="margin:0;padding-left:18px;list-style:none">${b}</ul>`)}).join(`
2
+ `),i=`<!DOCTYPE html>
3
3
  <html lang="en">
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
- <title>${ge(i)}</title>
6
+ <title>${ge(o)}</title>
7
7
  <style>
8
- ${oi()}
8
+ ${ao()}
9
9
  </style>
10
10
  </head>
11
11
  <body>
12
12
  <main class="report">
13
13
  <header class="report-header">
14
- <h1>${ge(i)}</h1>
14
+ <h1>${ge(o)}</h1>
15
15
  <p class="report-subtitle">Generated ${ge(s)}</p>
16
16
  </header>
17
17
  ${c}
18
18
  </main>
19
19
  </body>
20
- </html>`;ni(a)}),u.appendChild(n)}if(e.length===0){const n=document.createElement("div");Object.assign(n.style,{color:m.icon,fontSize:"11px",padding:"4px 0"}),n.textContent="No findings on any wafer.",u.appendChild(n)}else for(const{index:n,item:i,unusualCount:s,notableCount:c,totalCount:a}of e){const r=s?"unusual":c?"notable":"info",o=s+c||a,l=document.createElement("button");l.type="button",Object.assign(l.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:"4px",border:"none",borderLeft:`3px solid ${Mt(r)}`,borderRadius:"3px",background:m.bgHover,cursor:"pointer",fontSize:"11px",textAlign:"left",boxSizing:"border-box"}),l.addEventListener("mouseover",()=>{l.style.background=m.bgActive}),l.addEventListener("mouseout",()=>{l.style.background=m.bgHover});const f=document.createElement("span");f.textContent=i.label??`W${n+1}`,Object.assign(f.style,{color:m.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const h=document.createElement("span");h.textContent=String(o),Object.assign(h.style,{marginLeft:"6px",flexShrink:"0",background:Mt(r),color:"#fff",borderRadius:"8px",padding:"1px 5px",fontSize:"10px",fontWeight:"600"}),l.appendChild(f),l.appendChild(h),l.addEventListener("click",()=>ke(n,i)),u.appendChild(l)}const t=document.createElement("div");t.style.height="12px",u.appendChild(t)}function I(){if(u)if(ae==="lot"&&D){const e=Oe(y.flatMap(n=>n?.hbinDefs??[])),t=Oe(y.flatMap(n=>n?.sbinDefs??[]));ti(u,{lotSummary:D,items:y,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:y.find(n=>n?.testDefs?.length)?.testDefs,passBins:Ue,ringCount:d.ringCount,colorScheme:d.colorScheme,fallbackFormat:he,activeFindingId:ie,warnings:p.warnings?.display??!0?_:[],findingsFilter:jt,onFindingsFilterChange:I,onSaveText:p.onSaveText,onFindingClick:(n,i)=>{ie===n.id?Re():Gt(n,i),I()},onWaferClick:n=>{Te([n])},dieListOptions:p.dieList}),ye()&&u.insertBefore(et(),u.firstChild)}else _t()}function tt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}function Re(){ie=null,We(),Le(),v({highlightBin:void 0},{fireCallback:!1})}function Gt(e,t){if(ie===e.id){Re();return}ie=e.id,t.style.background=m.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}),We(),Le();const s=e.highlight;if(s.kind==="wafer"){Te(s.waferIndices);const c=tt(e);for(const a of s.waferIndices){const l=M[a]?.statsSummary?.findings.find(f=>tt(f)===c)?.highlight?.dieKeys;l?.length&&Ie(l,[a])}}else s.kind==="bin"?s.dieKeys?.length&&Ie(s.dieKeys):(s.kind==="region"||s.kind==="dies")&&s.dieKeys?.length&&Ie(s.dieKeys)}function X(){if(!T)return;const e=!!u;T.style.display=(D||ye())&&e&&!Ae?"flex":"none";const t=u?u.style.display!=="none":!1;(D?.hasNotableFindings||y.some(i=>i?.statsSummary?.hasNotableFindings))&&!t?T.style.color=m.findingIndicator:T.dataset.active||(T.style.color=m.icon)}const E=document.createElement("div");E.dataset.wmapToolbar="gallery",Object.assign(E.style,{display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:m.menuBg,border:`1px solid ${m.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 nt=()=>{const e=le();e&&(e.remove(),se(null)),me($,!1)},$=V("mode","Plot mode",()=>{if(le()){nt();return}const e=y.flatMap(g=>g?.dies??[]),t=y.find(g=>g?.testDefs?.length)?.testDefs,{testEntries:n,binEntries:i,stackedEntries:s}=Vn(e,t,{includeStacked:!0}),c=d.plotMode??"hardBin",a=d.activeTest??0;function r(g){return g.plotMode!==c?!1:g.plotMode==="value"?a===(g.activeTest??0):g.plotMode==="metadata"?d.activeMetadataKey===g.activeMetadataKey:!0}function o(g,k){g.activeTest!==void 0?v({plotMode:"value",activeTest:g.activeTest,activeMetadataKey:void 0,logScale:g.logScale}):g.activeMetadataKey!==void 0?v({plotMode:g.plotMode,activeTest:void 0,activeMetadataKey:g.activeMetadataKey,passFailDisplay:"off"}):v({plotMode:g.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),k.remove(),se(null),me($,!1)}const l=new Set,f=y.flatMap(g=>g?.metadataFields??[]).filter(g=>!l.has(g.key)&&l.add(g.key)).filter(g=>_n(e,g.key)).map(Gn),h=On($.getBoundingClientRect(),n,i,s,r,o,{makeMenuRow:Nt,makeMenuSection:Vt},c,$.ownerDocument.defaultView??window,f);Et($).appendChild(h),se(h),me($,!0),Ot(h,$,nt)});me($,!1);const Kt=()=>M.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:qt,sync:it}=Pn(J,()=>d.plotMode??"hardBin",()=>d.colorScheme??"default",Kt,e=>v({colorScheme:e}));it();const Xt=B.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Pe(){const e=y.find(n=>n?.testDefs?.length)?.testDefs,{testNumber:t}=xn(d.activeTest??0,e);return{testNumber:t,td:wn(e,t)}}function at(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=Pe();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function re(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=Pe();return e!==void 0&&!Wt(e)}function Ut(){if((d.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Pe();return y.some(n=>n?.dies?.some(i=>Un(i,e,t)!==void 0))}const Yt=Hn(J,()=>[{label:"Ring boundaries",active:!!d.showRingBoundaries,onClick:()=>v({showRingBoundaries:!d.showRingBoundaries})},{label:"Quadrant lines",active:!!d.showQuadrantBoundaries,onClick:()=>v({showQuadrantBoundaries:!d.showQuadrantBoundaries})},{label:"Die labels",active:!!d.showDieLabels,onClick:()=>v({showDieLabels:!d.showDieLabels})},{label:"Reticle grid",active:!!d.showReticle,enabled:Xt,onClick:()=>v({showReticle:!d.showReticle})},{label:"XY indicator",active:!!d.showXYIndicator,onClick:()=>v({showXYIndicator:!d.showXYIndicator})},...zn({functionalActive:re(),hasLimits:at()&&!re(),hasRecorded:Ut()&&!re(),display:Ge(d)},e=>v({passFailDisplay:e}))],()=>!!(d.showRingBoundaries||d.showQuadrantBoundaries||d.showDieLabels||d.showReticle||d.showXYIndicator||Ge(d)!=="off")),{btn:Qt,sync:ot}=Fn(J,()=>({plotMode:d.plotMode,legendPosition:ne}),e=>{ne=e;for(const t of w)t&&t.setOptions({legendPosition:ne})});ot();const Zt=[{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"}],lt=Ze("aggr","Aggregation method",()=>Zt,()=>d.aggregationMethod??"mean",e=>v({aggregationMethod:e}));function st(){const e=d.plotMode==="stackedValues";lt.style.display=e?"":"none"}st();const{btn:Jt,sync:rt}=An(J,()=>({...d,functionalActive:re()}),e=>v(e));rt();const we=V("specRange","Colorbar range: spec limits",()=>{const e=d.colorbarRangeMode==="data"?"spec":"data";v({colorbarRangeMode:e})});function dt(){const e=(d.plotMode??"hardBin")==="value"&&at()&&Ge(d)==="off"&&!re();we.style.display=e?"":"none";const t=(d.colorbarRangeMode??"spec")==="spec";oe(we,t),we.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}dt();const en=$n(J,()=>d,e=>v(e)),tn=V("downloadAll","Download gallery PNG",hn),nn=Ze("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"}],()=>L!=null?String(L):"auto",e=>xt(e==="auto"?void 0:Number(e))),C=document.createElement("div");Object.assign(C.style,{display:"inline-flex",alignItems:"center",gap:"0"}),E.appendChild(C),Pt&&C.appendChild($),C.appendChild(qt),C.appendChild(lt),C.appendChild(Jt),C.appendChild(we),C.appendChild(P()),C.appendChild(Yt),C.appendChild(P()),C.appendChild(Qt),C.appendChild(P()),C.appendChild(en),C.appendChild(P()),C.appendChild(nn),C.appendChild(P()),C.appendChild(tn),(D||ye())&&(T=V("findings","Summary panel",()=>{if(!u)return;const e=u.style.display!=="none";e||I(),u.style.display=e?"none":"flex",oe(T,!e),X()}),E.appendChild(P()),E.appendChild(T));let j=null,ve=null,_=[],ct=!1;function ft(){const e=Yn({lotStatsSummary:D,result:{warnings:y.flatMap(n=>n?.warnings??[])}}),t=e.length!==_.length||e.some((n,i)=>n.code!==_[i]?.code||n.message!==_[i]?.message);_=e,(t||!ct)&&(ct=!0,p.warnings?.onWarning?.(e)),an()}function an(){if(!j||!ve)return;const e=_.length,t=e>0;if(j.style.display=t?"flex":"none",ve.style.display=t?"":"none",!t)return;const n=Zn(_[0]),i=`${e} data ${e===1?"warning":"warnings"}`;j.style.color=n==="error"?m.errText:m.warnText,j.ariaLabel=n==="error"?`${i} \u2014 wafers in this lot may be positionally wrong`:i}(p.warnings?.display??!0)&&(ve=P(),j=V("warning","Data warnings",()=>{const e=le();if(xe(new MouseEvent("click")),e)return;const t=Qn(j.getBoundingClientRect(),_);Et(S).appendChild(t),se(t),Ot(t,j,()=>xe(new MouseEvent("click")))}),me(j,!1),E.appendChild(ve),E.appendChild(j)),ft();let U=null;Xe&&(U=V("analysis","Insights",()=>{const e=ee?.style.display!=="none";ut(!e)}),U.dataset.wmapInsightsBtn="1",E.appendChild(P()),E.appendChild(U));function pt(){import("./userGuideHtml.js").then(e=>Rn({buildWaferMap:Xn,renderWaferMap:Ke,renderWaferGallery,analyzeWaferMap:Ee},e.USER_GUIDE_HTML,Ft,S))}At&&(E.appendChild(P()),E.appendChild(V("help","User guide",()=>pt())));const G=document.createElement("div");Object.assign(G.style,{display:"flex",flexDirection:"column",gap:"6px",background:m.menuBg,border:`1px solid ${m.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 de=null,ee=null;Xe&&(de=li({getItems:()=>y,getLotStats:()=>D,getColorSchemeName:()=>d.colorScheme??"default",passBins:Ue,getRingCount:()=>d.ringCount??4,defaultView:p.insights?.defaultView,backTab:{label:"Gallery",onBack:()=>ut(!1)},showMetadataStrip:!1,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,openWafer:(e,t,n)=>{const i=y[e];if(!i)return;let s=null;const c=Wn({title:t,onClose:()=>s?.destroy(),anchor:S});vt(c,t,i.wafer.metadata??void 0),s=ze(c.contentWrap,i,n)}}),ee=de.el);let Ae=!1;function ut(e){!de||!ee||(Ae=e,ee.style.display=e?"flex":"none",A.style.display=e?"none":"flex",C.style.display=e?"none":"inline-flex",U&&(oe(U,e),U.innerHTML=e?pe.wafer:pe.analysis,U.ariaLabel=e?"Back to gallery view":"Insights"),X(),Me(),e&&de.render())}const on=4,Fe=240,mt=480,ln=720,sn=1.25,gt=p.maxSize;let z=gt??mt;function ht(e){const t=Y*2+110+2;let n=null;for(const i of e){if(i==null||!i.dies?.length)continue;const s=i.dies[0].width;if(!(s>0))continue;const c=i.wafer.radius*2*(on/s),a=Math.ceil(c+t);(n==null||a>n)&&(n=a)}return n}function rn(e){const t=ht(e);return t==null?Fe:Math.min(z,Math.max(Fe,t))}function dn(e){if(gt!=null)return!1;const t=ht(e);if(t==null)return!1;const n=Math.min(ln,Math.max(mt,t));return n<=z?!1:(z=n,!0)}function cn(){for(const e of Array.from(O.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${z}px`,e.style.maxHeight=`${z}px`)}let Ce=Fe,bt=0;function yt(e){const t=dn(e);if(t&&cn(),L!=null){t&&Se();return}const n=rn(e);n>Ce&&(Ce=n),Se()}function xt(e){L=e,Se()}function He(e){return`repeat(${e}, minmax(0, ${z}px))`}function Se(){if(L!=null){O.style.gridTemplateColumns=He(L);return}const e=Math.max(1,bt),t=12,n=O.clientWidth||0,i=c=>(n-t*(c-1))/c;let s=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){for(;s>1&&i(s)<Ce;)s--;const c=Math.min(z,Ce*sn);for(;s<e&&i(s+1)>=c;)s++}O.style.gridTemplateColumns=He(s)}const O=document.createElement("div");if(Object.assign(O.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:He(1),gap:"12px",justifyContent:"start",alignContent:"start"}),ae=D?"lot":"wafers",Q?.placement){const e=Q.placement;u=qe(e),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.display="flex",u.style.flexDirection="column"}else if(D||ye()){const e=!!Q?.defaultOpen;u=qe("right"),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.flexDirection="column",u.style.display=e?"flex":"none",I()}X(),u?.style.display!=="none"&&T&&oe(T,!0),(Q?.placement??"right")==="left"?(u&&A.appendChild(u),A.appendChild(O)):(A.appendChild(O),u&&A.appendChild(u)),S.appendChild(E),S.appendChild(G),S.appendChild(A),ee&&S.appendChild(ee);function Me(){G.innerHTML="";const e=d.plotMode??"hardBin",t=!Ae&&Mn.has(e),n=M.filter(b=>b!=null),i=n.find(b=>b.isLotStack),s=ei(n.map(b=>({metadata:b.wafer.metadata??void 0})),i?{lotSize:i.lotSize??n.length,aggrMethod:i.aggrMethod}:void 0),c=e==="metadata",a=d.activeMetadataKey,r=new Set;if(t&&!c)for(const b of n)for(const W of b.dies){if(W.partial)continue;const x=e==="softBin"?W.sbin:W.hbin;x!=null&&r.add(x)}const o=t&&!c?[...r].sort((b,W)=>b-W):[],l=new Set;if(t&&c&&a)for(const b of n)for(const W of b.dies){if(W.partial)continue;const x=W.metadata?.[a];x!=null&&(typeof x=="string"||typeof x=="number"||typeof x=="boolean")&&l.add(String(x))}const f=t&&c?[...l].sort(Jn):[];if(!s&&!o.length&&!f.length){G.style.display="none";return}if(G.style.display="flex",s&&G.appendChild(s),!o.length&&!f.length)return;const h=document.createElement("div");Object.assign(h.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"6px 14px"}),s&&Object.assign(h.style,{borderTop:`1px solid ${m.separator}`,paddingTop:"6px"}),G.appendChild(h);const g=vn(d.colorScheme),k=d.highlightBin;if(c){const b=d.highlightMetadataValue,W=M.flatMap(x=>x?.metadataFields??[]).find(x=>x.key===a);f.forEach((x,Ne)=>{const Ve=b===x,St=W?.values?.find(_e=>_e.value===x),bn=St?.color??Cn(Ne);Rt(h,{color:bn,isActive:Ve,label:St?.label??x,onClick:()=>{const _e=d.highlightMetadataValue===x?void 0:x;v({highlightMetadataValue:_e})}})});return}const F=e==="softBin"?M.flatMap(b=>b?.sbinDefs??[]):M.flatMap(b=>b?.hbinDefs??[]),H=new Set,K=[];for(const b of F)H.has(b.bin)||(H.add(b.bin),K.push(b));const fe=K.length>0?new Map(K.map(b=>[b.bin,b])):null;for(const b of o){const W=k===b,x=fe?.get(b),Ne=(d.colorScheme==="custom"?x?.color:void 0)??g.forBin(b);Rt(h,{color:Ne,isActive:W,label:x?.name?`${b} \xB7 ${x.name}`:`Bin ${b}`,onClick:()=>{const Ve=d.highlightBin===b?void 0:b;v({highlightBin:Ve})}})}}function ce(e){const t=y.filter(r=>r!==null);if(!t.length)return[];const n=t.map(r=>r.dies.filter(ri)),i=t[0].wafer,s=t.length,c=i.metadata?{...i,metadata:(({wafer:r,waferId:o,...l})=>l)(i.metadata)}:i;function a(r,o){return{...r,stats:{...r.stats,isLotStack:!0,aggregationMethod:o,lotSize:s}}}if(e==="stackedValues"){const r=t.find(f=>f.testDefs?.length)?.testDefs;let o=r?.filter(Wt);if(r?.length||(o=yn(t.flatMap(h=>h.dies)).map(h=>({testNumber:h,name:`Test ${h}`}))),!o?.length)return[];const l=d.aggregationMethod??"mean";return o.map(f=>{const h=Kn(n,l,f.testNumber),g={testNumber:0,name:f.name,unit:f.unit};return{wafer:c,dies:h,testDefs:[g],label:`${f.name} \xB7 ${l}`,isLotStack:!0,aggrMethod:l,lotSize:s,statsSummary:a(Ee({wafer:c,dies:h,testDefs:[g]},{testNumbers:[0]}),l)}})}if(e==="stackedBins"){let r=Oe(t.flatMap(o=>o.hbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(l=>l.dies.map(f=>f.hbin).filter(f=>f!=null)))].sort((l,f)=>l-f).map(l=>({bin:l,name:`Bin ${l}`}))),r.map(o=>{const l=Tt(n,o.bin,"hard"),f=[{bin:o.bin,name:o.name}];return{wafer:c,dies:l,hbinDefs:f,label:`${o.bin} \xB7 ${o.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:a(Ee({wafer:c,dies:l,hbinDefs:f}),"countBin")}})}if(e==="stackedSoftBins"){let r=Oe(t.flatMap(o=>o.sbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(l=>l.dies.map(f=>f.sbin).filter(f=>f!=null)))].sort((l,f)=>l-f).map(l=>({bin:l,name:`Bin ${l}`}))),r.map(o=>{const l=Tt(n,o.bin,"soft"),f=[{bin:o.bin,name:o.name}];return{wafer:c,dies:l,sbinDefs:f,label:`${o.bin} \xB7 ${o.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:a(Ee({wafer:c,dies:l,sbinDefs:f}),"countBin")}})}return t}function $e(e){const t=y.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:d.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const fn=new Set(["default","accessible","custom"]);function v(e,{fireCallback:t=!0}={}){const n=d.plotMode;d={...d,...e};const i=d.plotMode,s=ue.has(i),c=n!==void 0&&ue.has(n),a=be>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(i==="hardBin"||i==="softBin")&&!fn.has(d.colorScheme??"")&&(d={...d,colorScheme:"default"}),e.plotMode!==void 0)if(s){const o=$e(i);if(d={...d,...o},a)for(const l of w)l&&l.setOptions(e);else N(ce(i))}else if(c){const{valueRange:o,lotSize:l,aggregationMethod:f,...h}=d;if(d=h,a)for(const g of w)g&&g.setOptions(e);else N(y.filter(g=>g!==null))}else for(const o of w)o&&o.setOptions(e);else if(e.aggregationMethod!==void 0&&i==="stackedValues")if(a)for(const o of w)o&&o.setOptions(e);else N(ce("stackedValues"));else for(const o of w)o&&o.setOptions(e);Me(),st(),ot(),it();const r=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||r)&&I(),rt(),dt(),t){const o=Object.keys(e);p.onViewOptionsChange?.(d,o,qn(o))}}function wt(e,t,n){const i=e.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0"});const s=e.createElement("span");s.textContent=t,Object.assign(s.style,{fontWeight:"700",fontSize:"13px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),i.appendChild(s);const c=It(n??{});let a=null;if(c.length>0){const r=e.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:m.label,flexShrink:"0"}),r.textContent="\u25BE",i.appendChild(r),Object.assign(i.style,{cursor:"pointer"}),a=e.createElement("div"),a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:kt,background:m.menuBg,borderBottom:`1px solid ${m.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const o=Lt(n??{});o&&a.appendChild(o),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Dt(i,l=>{r.textContent=l?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(l)),a&&(a.style.display=l?"block":"none")})}return{wrap:i,metaPanel:a}}function vt(e,t,n){const i=e.box.querySelector("[data-wmap-window-title]"),s=It(n??{});if(!i||s.length===0)return;const c=i.parentElement,a=document.createElement("div");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0",cursor:"pointer"}),c?.insertBefore(a,i),a.appendChild(i);const r=document.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:m.label,flexShrink:"0"}),r.textContent="\u25BE",a.appendChild(r);const o=document.createElement("div");o.dataset.wmapCardMetaPanel="1",Object.assign(o.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:kt,background:m.menuBg,borderBottom:`1px solid ${m.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const l=Lt(n??{});l&&o.appendChild(l),e.contentWrap.style.position="relative",e.contentWrap.appendChild(o),a.setAttribute("aria-expanded","false"),a.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Dt(a,f=>{r.textContent=f?"\u25B4":"\u25BE",a.setAttribute("aria-expanded",String(f)),o.style.display=f?"block":"none"})}function je(e,t,n){const i=document.createElement("div");i.className="wmap-gallery-card",Object.assign(i.style,{background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:"10px",overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${z}px`,maxHeight:`${z}px`});const s=document.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${m.menuBorder}`,flexShrink:"0",gap:"6px"});const{wrap:c,metaPanel:a}=wt(document,e.label??"",e.wafer.metadata??void 0);s.appendChild(c);const r=document.createElement("button");r.dataset.wmapExpandBtn="1",r.title="Open full view",r.innerHTML=pe.expand,Object.assign(r.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${m.menuBorder}`,borderRadius:"4px",background:m.panelBg,color:m.label,padding:"2px",cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),s.appendChild(r),i.appendChild(s);const o=document.createElement("div");Object.assign(o.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),i.appendChild(o),a&&o.appendChild(a),O.appendChild(i);const l=Ke(o,e,{viewOptions:e.viewOptions?{...d,...e.viewOptions}:d,toolbarControls:"full",showTooltip:!0,padding:Y,legendPosition:ne,fallbackFormat:he,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>ke(t,e),showMetadataBadge:!1});return l.setViewControlsVisible(!1),l.setSummaryVisible(!1),r.onclick=()=>ke(t,e),{card:i,ctrl:l,canvasWrapper:o,expandBtn:r}}function pn(e){const t=Z[e];if(!t)return;const n=[...R.values()].find(i=>i.cardIndex===e);n?(t.innerHTML=pe.minimize,t.title="Reattach to gallery",t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>mn(n.id)):(t.innerHTML=pe.expand,t.title="Open full view",t.setAttribute("aria-label","Open full view"),t.onclick=()=>ke(e,M[e]))}function N(e){gn(),le()?.remove(),se(null),Re(),M=[];for(const a of w)a&&a.destroy();w=[],q=[],Z=[],be=0,O.innerHTML="",bt=e.length,yt(e.map(a=>typeof a=="function"?null:a));const t=[];for(let a=0;a<e.length;a++){const r=e[a];if(typeof r=="function"){const o=document.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:"10px",aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const l=document.createElement("span");l.textContent="\u2026",Object.assign(l.style,{color:m.label,fontSize:"18px"}),o.appendChild(l),O.appendChild(o),M.push(null),w.push(null),q.push(null),Z.push(null),t.push({index:a,factory:r,placeholder:o}),be++}else{const{ctrl:o,canvasWrapper:l,expandBtn:f}=je(r,a,e.length);M.push(r),w.push(o),q.push(l),Z.push(f)}}M.flatMap(a=>a?[...a.hbinDefs??[],...a.sbinDefs??[]]:[]).some(a=>a.color)&&!p.viewOptions?.colorScheme&&(d={...d,colorScheme:"custom"}),Me();const i=++De;let s=0;function c(){if(i!==De)return;if(s>=t.length){if(ue.has(d.plotMode)){const F=d.plotMode;N(ce(F))}return}const{index:a,factory:r,placeholder:o}=t[s++],l=r();M[a]=l,y[a]=l,yt([l]);const{card:f,ctrl:h,canvasWrapper:g,expandBtn:k}=je(l,a,e.length);w[a]=h,q[a]=g,Z[a]=k,be--,o.replaceWith(f),Me(),!u&&!Q?.placement&&l.statsSummary?.findings.length?(D||(ae="wafers"),u=qe("right"),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.flexDirection="column",u.style.display="none",(Q?.placement??"right")==="left"?A.insertBefore(u,O):A.appendChild(u),I(),T||(T=V("findings","Summary panel",()=>{if(!u)return;const H=u.style.display!=="none";H||I(),u.style.display=H?"none":"flex",oe(T,!H),X()}),E.appendChild(P()),E.appendChild(T)),X()):u&&u.style.display!=="none"&&I(),X(),setTimeout(c,0)}t.length>0&&setTimeout(c,0)}if(ue.has(d.plotMode)&&y.length>0){const e=$e(d.plotMode);d={...d,...e},N(ce(d.plotMode))}else N(B);const Ct=new ResizeObserver(()=>{L==null&&Se()});Ct.observe(O),u&&I();function un(e){const t=q[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:m.label,fontSize:"12px",textAlign:"center",padding:"0 12px"}),t.appendChild(n)}function ke(e,t){for(const a of R.values())if(a.cardIndex===e)return;const n=t.label??"Wafer map",i=$t++,s=w[e]?.getOptions(),c=Dn(n);if(c){const a=c.document;a.title=n,Object.assign(a.documentElement.style,{height:"100%"}),Object.assign(a.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),Ln(S,a.documentElement);const r=In(S,a.documentElement,()=>F.setOptions({})),o=a.createElement("div");o.dataset.wmapWindowBanner="1",o.textContent=n,Object.assign(o.style,{display:"none",padding:"6px 12px",fontSize:"12px",fontWeight:"700",background:m.warnBg,color:m.warnText,borderBottom:`1px solid ${m.warnBorder}`,flexShrink:"0"}),a.body.appendChild(o);const l=a.createElement("div");Object.assign(l.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),a.body.appendChild(l);const{wrap:f,metaPanel:h}=wt(a,n,t.wafer.metadata??void 0),g=a.createElement("div");Object.assign(g.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${m.menuBorder}`,flexShrink:"0",gap:"6px"}),g.appendChild(f),l.appendChild(g);const k=a.createElement("div");Object.assign(k.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),h&&k.appendChild(h),l.appendChild(k);const F=ze(k,t,void 0,s),H=setInterval(()=>{c.closed&&Be(i)},400);c.addEventListener("pagehide",()=>Be(i)),R.set(i,{id:i,ctrl:F,cardIndex:e,label:n,closePollId:H,stopThemeSync:r,close:()=>{c.closed||c.close()},setTitle:K=>{a.title=K,o.textContent=K,o.style.display="block"}})}else{const a=Tn({title:n,onClose:()=>Be(i),anchor:S});a.contentWrap.style.flexDirection="column",vt(a,n,t.wafer.metadata??void 0);const r=ze(a.contentWrap,t,void 0,s);R.set(i,{id:i,ctrl:r,cardIndex:e,label:n,closePollId:null,close:()=>a.close(),setTitle:o=>{const l=a.box.querySelector("[data-wmap-window-title]");l&&(l.textContent=o,l.title=o)}})}w[e]?.destroy(),w[e]=null,un(e),pn(e)}function ze(e,t,n,i){const s=t.viewOptions?{...d,...t.viewOptions}:d,c=i?{...s,...i}:s,a=n!==void 0?{...c,plotMode:"value",activeTest:n}:c,r=Ke(e,t,{viewOptions:a,toolbarControls:"full",showTooltip:!0,padding:Y,legendPosition:ne,fallbackFormat:he,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showMetadataBadge:!1});return r.setViewControlsVisible(!0),r.setSummaryVisible(!0),r.setExpandVisible(!1),r}function Be(e){const t=R.get(e);if(!t)return;R.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,s=M[i];if(!s)return;const c={...s,viewOptions:n};M[i]=c;const{card:a,ctrl:r,canvasWrapper:o,expandBtn:l}=je(c,i,M.length);q[i]?.parentElement?.replaceWith(a),w[i]=r,q[i]=o,Z[i]=l}function mn(e){const t=R.get(e);t&&(t.close(),Be(e))}function gn(){for(const e of R.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function hn(){const e=[...O.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),i=Math.ceil(t/n),s=e[0].width,c=e[0].height,a=8,r=window.devicePixelRatio||1,o=Math.round(26*r),l=Math.round(12*r),f=document.createElement("canvas");f.width=n*s+(n-1)*a,f.height=i*(c+o)+(i-1)*a;const h=f.getContext("2d"),g=Sn(O);h.fillStyle=g.background,h.fillRect(0,0,f.width,f.height),e.forEach((k,F)=>{const H=F%n,K=Math.floor(F/n),fe=H*(s+a),b=K*(c+o+a),W=k.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";h.fillStyle=g.surface,h.fillRect(fe,b,s,o),h.fillStyle=g.text,h.font=`700 ${l}px system-ui, sans-serif`,h.textAlign="left",h.textBaseline="middle",h.fillText(W,fe+Math.round(10*r),b+o/2,s-Math.round(20*r)),h.drawImage(k,fe,b+o)}),f.toBlob(k=>{k&&jn(k,te,p.onSaveImage)})}return{setItems(e){y=e.map(n=>typeof n=="function"?null:n);const t=d.plotMode;if(ue.has(t))if(e.some(i=>typeof i=="function"))N(e);else{const i=$e(t);d={...d,...i},N(ce(t))}else N(e)},setOptions(e){v(e,{fireCallback:!1})},getOptions(){return{...d}},setFallbackFormat(e){he=e;for(const t of w)t&&t.setFallbackFormat(e)},setLotStatsSummary(e){D=e,ft(),u&&I(),X()},setColumns(e){xt(e)},openUserGuide:pt,destroy(){De++;for(const e of[...R.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();R.clear();for(const e of w)e&&e.destroy();w=[],le()?.remove(),Ct.disconnect(),S.ownerDocument.removeEventListener("click",xe,!0),window.removeEventListener("blur",Je),Ht(),Bt(),E.remove(),G.remove(),A.remove(),u?.remove(),de?.destroy()}}}
20
+ </html>`;no(i)}),u.appendChild(n)}if(e.length===0){const n=m.ownerDocument.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:"11px",padding:"4px 0"}),n.textContent="No findings on any wafer.",u.appendChild(n)}else for(const{index:n,item:o,unusualCount:s,notableCount:c,totalCount:i}of e){const r=s?"unusual":c?"notable":"info",a=s+c||i,l=m.ownerDocument.createElement("button");l.type="button",Object.assign(l.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:"4px",border:"none",borderLeft:`3px solid ${Mt(r)}`,borderRadius:"3px",background:g.bgHover,cursor:"pointer",fontSize:"11px",textAlign:"left",boxSizing:"border-box"}),l.addEventListener("mouseover",()=>{l.style.background=g.bgActive}),l.addEventListener("mouseout",()=>{l.style.background=g.bgHover});const f=m.ownerDocument.createElement("span");f.textContent=o.label??`W${n+1}`,Object.assign(f.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const b=m.ownerDocument.createElement("span");b.textContent=String(a),Object.assign(b.style,{marginLeft:"6px",flexShrink:"0",background:Mt(r),color:"#fff",borderRadius:"8px",padding:"1px 5px",fontSize:"10px",fontWeight:"600"}),l.appendChild(f),l.appendChild(b),l.addEventListener("click",()=>ke(n,o)),u.appendChild(l)}const t=m.ownerDocument.createElement("div");t.style.height="12px",u.appendChild(t)}function I(){if(u)if(ie==="lot"&&O){const e=Ee(x.flatMap(n=>n?.hbinDefs??[])),t=Ee(x.flatMap(n=>n?.sbinDefs??[]));to(u,{lotSummary:O,items:x,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:x.find(n=>n?.testDefs?.length)?.testDefs,passBins:Ue,ringCount:d.ringCount,colorScheme:d.colorScheme,fallbackFormat:he,activeFindingId:oe,warnings:p.warnings?.display??!0?_:[],findingsFilter:jt,onFindingsFilterChange:I,onSaveText:p.onSaveText,onFindingClick:(n,o)=>{oe===n.id?Re():Gt(n,o),I()},onWaferClick:n=>{Te([n])},dieListOptions:p.dieList}),ye()&&u.insertBefore(et(),u.firstChild)}else _t()}function tt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}function Re(){oe=null,We(),Le(),C({highlightBin:void 0},{fireCallback:!1})}function Gt(e,t){if(oe===e.id){Re();return}oe=e.id,t.style.background=g.bgActive,t.style.fontWeight="600";const{kind:n,index:o}=e.variable;n==="test"?C({plotMode:"value",activeTest:o??0,highlightBin:void 0},{fireCallback:!1}):n==="softBin"?C({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):C({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1}),We(),Le();const s=e.highlight;if(s.kind==="wafer"){Te(s.waferIndices);const c=tt(e);for(const i of s.waferIndices){const l=M[i]?.statsSummary?.findings.find(f=>tt(f)===c)?.highlight?.dieKeys;l?.length&&Ie(l,[i])}}else s.kind==="bin"?s.dieKeys?.length&&Ie(s.dieKeys):(s.kind==="region"||s.kind==="dies")&&s.dieKeys?.length&&Ie(s.dieKeys)}function X(){if(!T)return;const e=!!u;T.style.display=(O||ye())&&e&&!Ae?"flex":"none";const t=u?u.style.display!=="none":!1;(O?.hasNotableFindings||x.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?T.style.color=g.findingIndicator:T.dataset.active||(T.style.color=g.icon)}const B=m.ownerDocument.createElement("div");B.dataset.wmapToolbar="gallery",Object.assign(B.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 nt=()=>{const e=le();e&&(e.remove(),se(null)),me(j,!1)},j=V("mode","Plot mode",()=>{if(le()){nt();return}const e=x.flatMap(h=>h?.dies??[]),t=x.find(h=>h?.testDefs?.length)?.testDefs,{testEntries:n,binEntries:o,stackedEntries:s}=Vn(e,t,{includeStacked:!0}),c=d.plotMode??"hardBin",i=d.activeTest??0;function r(h){return h.plotMode!==c?!1:h.plotMode==="value"?i===(h.activeTest??0):h.plotMode==="metadata"?d.activeMetadataKey===h.activeMetadataKey:!0}function a(h,k){h.activeTest!==void 0?C({plotMode:"value",activeTest:h.activeTest,activeMetadataKey:void 0,logScale:h.logScale}):h.activeMetadataKey!==void 0?C({plotMode:h.plotMode,activeTest:void 0,activeMetadataKey:h.activeMetadataKey,passFailDisplay:"off"}):C({plotMode:h.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),k.remove(),se(null),me(j,!1)}const l=new Set,f=x.flatMap(h=>h?.metadataFields??[]).filter(h=>!l.has(h.key)&&l.add(h.key)).filter(h=>_n(e,h.key)).map(Gn),b=En(j.getBoundingClientRect(),n,o,s,r,a,{makeMenuRow:Nt,makeMenuSection:Vt},c,j.ownerDocument.defaultView??window,f);Bt(j).appendChild(b),se(b),me(j,!0),Et(b,j,nt)});me(j,!1);const Kt=()=>M.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:qt,sync:ot}=Pn(J,()=>d.plotMode??"hardBin",()=>d.colorScheme??"default",Kt,e=>C({colorScheme:e}));ot();const Xt=D.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Pe(){const e=x.find(n=>n?.testDefs?.length)?.testDefs,{testNumber:t}=xn(d.activeTest??0,e);return{testNumber:t,td:wn(e,t)}}function it(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=Pe();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function re(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=Pe();return e!==void 0&&!Wt(e)}function Ut(){if((d.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Pe();return x.some(n=>n?.dies?.some(o=>Un(o,e,t)!==void 0))}const Yt=Hn(J,()=>[{label:"Ring boundaries",active:!!d.showRingBoundaries,onClick:()=>C({showRingBoundaries:!d.showRingBoundaries})},{label:"Quadrant lines",active:!!d.showQuadrantBoundaries,onClick:()=>C({showQuadrantBoundaries:!d.showQuadrantBoundaries})},{label:"Die labels",active:!!d.showDieLabels,onClick:()=>C({showDieLabels:!d.showDieLabels})},{label:"Reticle grid",active:!!d.showReticle,enabled:Xt,onClick:()=>C({showReticle:!d.showReticle})},{label:"XY indicator",active:!!d.showXYIndicator,onClick:()=>C({showXYIndicator:!d.showXYIndicator})},...zn({functionalActive:re(),hasLimits:it()&&!re(),hasRecorded:Ut()&&!re(),display:Ge(d)},e=>C({passFailDisplay:e}))],()=>!!(d.showRingBoundaries||d.showQuadrantBoundaries||d.showDieLabels||d.showReticle||d.showXYIndicator||Ge(d)!=="off")),{btn:Qt,sync:at}=Fn(J,()=>({plotMode:d.plotMode,legendPosition:ne}),e=>{ne=e;for(const t of v)t&&t.setOptions({legendPosition:ne})});at();const Zt=[{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"}],lt=Ze("aggr","Aggregation method",()=>Zt,()=>d.aggregationMethod??"mean",e=>C({aggregationMethod:e}));function st(){const e=d.plotMode==="stackedValues";lt.style.display=e?"":"none"}st();const{btn:Jt,sync:rt}=An(J,()=>({...d,functionalActive:re()}),e=>C(e));rt();const we=V("specRange","Colorbar range: spec limits",()=>{const e=d.colorbarRangeMode==="data"?"spec":"data";C({colorbarRangeMode:e})});function dt(){const e=(d.plotMode??"hardBin")==="value"&&it()&&Ge(d)==="off"&&!re();we.style.display=e?"":"none";const t=(d.colorbarRangeMode??"spec")==="spec";ae(we,t),we.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}dt();const en=$n(J,()=>d,e=>C(e)),tn=V("downloadAll","Download gallery PNG",hn),nn=Ze("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"}],()=>L!=null?String(L):"auto",e=>xt(e==="auto"?void 0:Number(e))),S=m.ownerDocument.createElement("div");Object.assign(S.style,{display:"inline-flex",alignItems:"center",gap:"0"}),B.appendChild(S),Pt&&S.appendChild(j),S.appendChild(qt),S.appendChild(lt),S.appendChild(Jt),S.appendChild(we),S.appendChild(P()),S.appendChild(Yt),S.appendChild(P()),S.appendChild(Qt),S.appendChild(P()),S.appendChild(en),S.appendChild(P()),S.appendChild(nn),S.appendChild(P()),S.appendChild(tn),(O||ye())&&(T=V("findings","Summary panel",()=>{if(!u)return;const e=u.style.display!=="none";e||I(),u.style.display=e?"none":"flex",ae(T,!e),X()}),B.appendChild(P()),B.appendChild(T));let A=null,ve=null,_=[],ct=!1;function ft(){const e=Yn({lotStatsSummary:O,result:{warnings:x.flatMap(n=>n?.warnings??[])}}),t=e.length!==_.length||e.some((n,o)=>n.code!==_[o]?.code||n.message!==_[o]?.message);_=e,(t||!ct)&&(ct=!0,p.warnings?.onWarning?.(e)),on()}function on(){if(!A||!ve)return;const e=_.length,t=e>0;if(A.style.display=t?"flex":"none",ve.style.display=t?"":"none",!t)return;const n=Zn(_[0]),o=`${e} data ${e===1?"warning":"warnings"}`;A.style.color=n==="error"?g.errText:g.warnText,A.ariaLabel=n==="error"?`${o} \u2014 wafers in this lot may be positionally wrong`:o}(p.warnings?.display??!0)&&(ve=P(),A=V("warning","Data warnings",()=>{const e=le();if(xe(new MouseEvent("click")),e)return;const t=Qn(A.getBoundingClientRect(),_,A.ownerDocument.defaultView??window);Bt(m).appendChild(t),se(t),Et(t,A,()=>xe(new MouseEvent("click")))}),me(A,!1),B.appendChild(ve),B.appendChild(A)),ft();let U=null;Xe&&(U=V("analysis","Insights",()=>{const e=ee?.style.display!=="none";ut(!e)}),U.dataset.wmapInsightsBtn="1",B.appendChild(P()),B.appendChild(U));function pt(){import("./userGuideHtml.js").then(e=>Rn({buildWaferMap:Xn,renderWaferMap:Ke,renderWaferGallery,analyzeWaferMap:Be},e.USER_GUIDE_HTML,Ft,m))}At&&(B.appendChild(P()),B.appendChild(V("help","User guide",()=>pt())));const G=m.ownerDocument.createElement("div");Object.assign(G.style,{display:"flex",flexDirection:"column",gap:"6px",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"6px",padding:"6px 10px",marginBottom:"10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"});const F=m.ownerDocument.createElement("div");Object.assign(F.style,{display:"flex",flexDirection:"row",gap:"12px",alignItems:"flex-start"});let de=null,ee=null;Xe&&(de=lo({getItems:()=>x,getLotStats:()=>O,getColorSchemeName:()=>d.colorScheme??"default",passBins:Ue,getRingCount:()=>d.ringCount??4,defaultView:p.insights?.defaultView,backTab:{label:"Gallery",onBack:()=>ut(!1)},showMetadataStrip:!1,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,ownerDocument:m.ownerDocument,openWafer:(e,t,n)=>{const o=x[e];if(!o)return;let s=null;const c=Wn({title:t,onClose:()=>s?.destroy(),anchor:m});vt(c,t,o.wafer.metadata??void 0),s=ze(c.contentWrap,o,n)}}),ee=de.el);let Ae=!1;function ut(e){!de||!ee||(Ae=e,ee.style.display=e?"flex":"none",F.style.display=e?"none":"flex",S.style.display=e?"none":"inline-flex",U&&(ae(U,e),U.innerHTML=e?pe.wafer:pe.analysis,U.ariaLabel=e?"Back to gallery view":"Insights"),X(),Me(),e&&de.render())}const an=4,Fe=240,mt=480,ln=720,sn=1.25,gt=p.maxSize;let z=gt??mt;function ht(e){const t=Y*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const s=o.dies[0].width;if(!(s>0))continue;const c=o.wafer.radius*2*(an/s),i=Math.ceil(c+t);(n==null||i>n)&&(n=i)}return n}function rn(e){const t=ht(e);return t==null?Fe:Math.min(z,Math.max(Fe,t))}function dn(e){if(gt!=null)return!1;const t=ht(e);if(t==null)return!1;const n=Math.min(ln,Math.max(mt,t));return n<=z?!1:(z=n,!0)}function cn(){for(const e of Array.from(E.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${z}px`,e.style.maxHeight=`${z}px`)}let Ce=Fe,bt=0;function yt(e){const t=dn(e);if(t&&cn(),L!=null){t&&Se();return}const n=rn(e);n>Ce&&(Ce=n),Se()}function xt(e){L=e,Se()}function He(e){return`repeat(${e}, minmax(0, ${z}px))`}function Se(){if(L!=null){E.style.gridTemplateColumns=He(L);return}const e=Math.max(1,bt),t=12,n=E.clientWidth||0,o=c=>(n-t*(c-1))/c;let s=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){for(;s>1&&o(s)<Ce;)s--;const c=Math.min(z,Ce*sn);for(;s<e&&o(s+1)>=c;)s++}E.style.gridTemplateColumns=He(s)}const E=m.ownerDocument.createElement("div");if(Object.assign(E.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:He(1),gap:"12px",justifyContent:"start",alignContent:"start"}),ie=O?"lot":"wafers",Q?.placement){const e=Q.placement;u=qe(e,m.ownerDocument),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.display="flex",u.style.flexDirection="column"}else if(O||ye()){const e=!!Q?.defaultOpen;u=qe("right",m.ownerDocument),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.flexDirection="column",u.style.display=e?"flex":"none",I()}X(),u?.style.display!=="none"&&T&&ae(T,!0),(Q?.placement??"right")==="left"?(u&&F.appendChild(u),F.appendChild(E)):(F.appendChild(E),u&&F.appendChild(u)),m.appendChild(B),m.appendChild(G),m.appendChild(F),ee&&m.appendChild(ee);function Me(){G.innerHTML="";const e=d.plotMode??"hardBin",t=!Ae&&Mn.has(e),n=M.filter(y=>y!=null),o=n.find(y=>y.isLotStack),s=eo(n.map(y=>({metadata:y.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),c=e==="metadata",i=d.activeMetadataKey,r=new Set;if(t&&!c)for(const y of n)for(const W of y.dies){if(W.partial)continue;const w=e==="softBin"?W.sbin:W.hbin;w!=null&&r.add(w)}const a=t&&!c?[...r].sort((y,W)=>y-W):[],l=new Set;if(t&&c&&i)for(const y of n)for(const W of y.dies){if(W.partial)continue;const w=W.metadata?.[i];w!=null&&(typeof w=="string"||typeof w=="number"||typeof w=="boolean")&&l.add(String(w))}const f=t&&c?[...l].sort(Jn):[];if(!s&&!a.length&&!f.length){G.style.display="none";return}if(G.style.display="flex",s&&G.appendChild(s),!a.length&&!f.length)return;const b=m.ownerDocument.createElement("div");Object.assign(b.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"6px 14px"}),s&&Object.assign(b.style,{borderTop:`1px solid ${g.separator}`,paddingTop:"6px"}),G.appendChild(b);const h=vn(d.colorScheme),k=d.highlightBin;if(c){const y=d.highlightMetadataValue,W=M.flatMap(w=>w?.metadataFields??[]).find(w=>w.key===i);f.forEach((w,Ne)=>{const Ve=y===w,St=W?.values?.find(_e=>_e.value===w),bn=St?.color??Cn(Ne);Rt(b,{color:bn,isActive:Ve,label:St?.label??w,onClick:()=>{const _e=d.highlightMetadataValue===w?void 0:w;C({highlightMetadataValue:_e})}})});return}const H=e==="softBin"?M.flatMap(y=>y?.sbinDefs??[]):M.flatMap(y=>y?.hbinDefs??[]),$=new Set,K=[];for(const y of H)$.has(y.bin)||($.add(y.bin),K.push(y));const fe=K.length>0?new Map(K.map(y=>[y.bin,y])):null;for(const y of a){const W=k===y,w=fe?.get(y),Ne=(d.colorScheme==="custom"?w?.color:void 0)??h.forBin(y);Rt(b,{color:Ne,isActive:W,label:w?.name?`${y} \xB7 ${w.name}`:`Bin ${y}`,onClick:()=>{const Ve=d.highlightBin===y?void 0:y;C({highlightBin:Ve})}})}}function ce(e){const t=x.filter(r=>r!==null);if(!t.length)return[];const n=t.map(r=>r.dies.filter(ro)),o=t[0].wafer,s=t.length,c=o.metadata?{...o,metadata:(({wafer:r,waferId:a,...l})=>l)(o.metadata)}:o;function i(r,a){return{...r,stats:{...r.stats,isLotStack:!0,aggregationMethod:a,lotSize:s}}}if(e==="stackedValues"){const r=t.find(f=>f.testDefs?.length)?.testDefs;let a=r?.filter(Wt);if(r?.length||(a=yn(t.flatMap(b=>b.dies)).map(b=>({testNumber:b,name:`Test ${b}`}))),!a?.length)return[];const l=d.aggregationMethod??"mean";return a.map(f=>{const b=Kn(n,l,f.testNumber),h={testNumber:0,name:f.name,unit:f.unit};return{wafer:c,dies:b,testDefs:[h],label:`${f.name} \xB7 ${l}`,isLotStack:!0,aggrMethod:l,lotSize:s,statsSummary:i(Be({wafer:c,dies:b,testDefs:[h]},{testNumbers:[0]}),l)}})}if(e==="stackedBins"){let r=Ee(t.flatMap(a=>a.hbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(l=>l.dies.map(f=>f.hbin).filter(f=>f!=null)))].sort((l,f)=>l-f).map(l=>({bin:l,name:`Bin ${l}`}))),r.map(a=>{const l=Tt(n,a.bin,"hard"),f=[{bin:a.bin,name:a.name}];return{wafer:c,dies:l,hbinDefs:f,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Be({wafer:c,dies:l,hbinDefs:f}),"countBin")}})}if(e==="stackedSoftBins"){let r=Ee(t.flatMap(a=>a.sbinDefs??[]));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(l=>l.dies.map(f=>f.sbin).filter(f=>f!=null)))].sort((l,f)=>l-f).map(l=>({bin:l,name:`Bin ${l}`}))),r.map(a=>{const l=Tt(n,a.bin,"soft"),f=[{bin:a.bin,name:a.name}];return{wafer:c,dies:l,sbinDefs:f,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:s,statsSummary:i(Be({wafer:c,dies:l,sbinDefs:f}),"countBin")}})}return t}function $e(e){const t=x.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:d.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const fn=new Set(["default","accessible","custom"]);function C(e,{fireCallback:t=!0}={}){const n=d.plotMode;d={...d,...e};const o=d.plotMode,s=ue.has(o),c=n!==void 0&&ue.has(n),i=be>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(o==="hardBin"||o==="softBin")&&!fn.has(d.colorScheme??"")&&(d={...d,colorScheme:"default"}),e.plotMode!==void 0)if(s){const a=$e(o);if(d={...d,...a},i)for(const l of v)l&&l.setOptions(e);else N(ce(o))}else if(c){const{valueRange:a,lotSize:l,aggregationMethod:f,...b}=d;if(d=b,i)for(const h of v)h&&h.setOptions(e);else N(x.filter(h=>h!==null))}else for(const a of v)a&&a.setOptions(e);else if(e.aggregationMethod!==void 0&&o==="stackedValues")if(i)for(const a of v)a&&a.setOptions(e);else N(ce("stackedValues"));else for(const a of v)a&&a.setOptions(e);Me(),st(),at(),ot();const r=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||r)&&I(),rt(),dt(),t){const a=Object.keys(e);p.onViewOptionsChange?.(d,a,qn(a))}}function wt(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0"});const s=e.createElement("span");s.textContent=t,Object.assign(s.style,{fontWeight:"700",fontSize:"13px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(s);const c=It(n??{});let i=null;if(c.length>0){const r=e.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),r.textContent="\u25BE",o.appendChild(r),Object.assign(o.style,{cursor:"pointer"}),i=e.createElement("div"),i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:kt,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=Lt(n??{});a&&i.appendChild(a),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Ot(o,l=>{r.textContent=l?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(l)),i&&(i.style.display=l?"block":"none")})}return{wrap:o,metaPanel:i}}function vt(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),s=It(n??{});if(!o||s.length===0)return;const c=o.parentElement,i=m.ownerDocument.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",flex:"1",minWidth:"0",cursor:"pointer"}),c?.insertBefore(i,o),i.appendChild(o);const r=m.ownerDocument.createElement("span");Object.assign(r.style,{fontSize:"12px",lineHeight:"1",color:g.label,flexShrink:"0"}),r.textContent="\u25BE",i.appendChild(r);const a=m.ownerDocument.createElement("div");a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:kt,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:"0 2px 6px rgba(0,0,0,0.15)",padding:"8px 10px",fontSize:"11px",display:"none"});const l=Lt(n??{});l&&a.appendChild(l),e.contentWrap.style.position="relative",e.contentWrap.appendChild(a),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Ot(i,f=>{r.textContent=f?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(f)),a.style.display=f?"block":"none"})}function je(e,t,n){const o=m.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:"10px",overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${z}px`,maxHeight:`${z}px`});const s=m.ownerDocument.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",padding:"8px 10px 6px",borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:"6px"});const{wrap:c,metaPanel:i}=wt(document,e.label??"",e.wafer.metadata??void 0);s.appendChild(c);const r=m.ownerDocument.createElement("button");r.dataset.wmapExpandBtn="1",r.title="Open full view",r.innerHTML=pe.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"}),s.appendChild(r),o.appendChild(s);const a=m.ownerDocument.createElement("div");Object.assign(a.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(a),i&&a.appendChild(i),E.appendChild(o);const l=Ke(a,e,{viewOptions:e.viewOptions?{...d,...e.viewOptions}:d,toolbarControls:"full",showTooltip:!0,padding:Y,legendPosition:ne,fallbackFormat:he,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>ke(t,e),showMetadataBadge:!1});return l.setViewControlsVisible(!1),l.setSummaryVisible(!1),r.onclick=()=>ke(t,e),{card:o,ctrl:l,canvasWrapper:a,expandBtn:r}}function pn(e){const t=Z[e];if(!t)return;const n=[...R.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=pe.minimize,t.title="Reattach to gallery",t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>mn(n.id)):(t.innerHTML=pe.expand,t.title="Open full view",t.setAttribute("aria-label","Open full view"),t.onclick=()=>ke(e,M[e]))}function N(e){gn(),le()?.remove(),se(null),Re(),M=[];for(const i of v)i&&i.destroy();v=[],q=[],Z=[],be=0,E.innerHTML="",bt=e.length,yt(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const r=e[i];if(typeof r=="function"){const a=m.ownerDocument.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 l=m.ownerDocument.createElement("span");l.textContent="\u2026",Object.assign(l.style,{color:g.label,fontSize:"18px"}),a.appendChild(l),E.appendChild(a),M.push(null),v.push(null),q.push(null),Z.push(null),t.push({index:i,factory:r,placeholder:a}),be++}else{const{ctrl:a,canvasWrapper:l,expandBtn:f}=je(r,i,e.length);M.push(r),v.push(a),q.push(l),Z.push(f)}}M.flatMap(i=>i?[...i.hbinDefs??[],...i.sbinDefs??[]]:[]).some(i=>i.color)&&!p.viewOptions?.colorScheme&&(d={...d,colorScheme:"custom"}),Me();const o=++Oe;let s=0;function c(){if(o!==Oe)return;if(s>=t.length){if(ue.has(d.plotMode)){const H=d.plotMode;N(ce(H))}return}const{index:i,factory:r,placeholder:a}=t[s++],l=r();M[i]=l,x[i]=l,yt([l]);const{card:f,ctrl:b,canvasWrapper:h,expandBtn:k}=je(l,i,e.length);v[i]=b,q[i]=h,Z[i]=k,be--,a.replaceWith(f),Me(),!u&&!Q?.placement&&l.statsSummary?.findings.length?(O||(ie="wafers"),u=qe("right",m.ownerDocument),u.style.maxHeight="calc(100vh - 80px)",u.style.position="sticky",u.style.top="8px",u.style.flexDirection="column",u.style.display="none",(Q?.placement??"right")==="left"?F.insertBefore(u,E):F.appendChild(u),I(),T||(T=V("findings","Summary panel",()=>{if(!u)return;const $=u.style.display!=="none";$||I(),u.style.display=$?"none":"flex",ae(T,!$),X()}),B.appendChild(P()),B.appendChild(T)),X()):u&&u.style.display!=="none"&&I(),X(),setTimeout(c,0)}t.length>0&&setTimeout(c,0)}if(ue.has(d.plotMode)&&x.length>0){const e=$e(d.plotMode);d={...d,...e},N(ce(d.plotMode))}else N(D);const Ct=new ResizeObserver(()=>{L==null&&Se()});Ct.observe(E),u&&I();function un(e){const t=q[e];if(!t)return;t.innerHTML="",Object.assign(t.style,{alignItems:"center",justifyContent:"center"});const n=m.ownerDocument.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 ke(e,t){for(const i of R.values())if(i.cardIndex===e)return;const n=t.label??"Wafer map",o=$t++,s=v[e]?.getOptions(),c=On(n);if(c){const i=c.document;i.title=n,Object.assign(i.documentElement.style,{height:"100%"}),Object.assign(i.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),Ln(m,i.documentElement);const r=In(m,i.documentElement,()=>H.setOptions({})),a=i.createElement("div");a.dataset.wmapWindowBanner="1",a.textContent=n,Object.assign(a.style,{display:"none",padding:"6px 12px",fontSize:"12px",fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),i.body.appendChild(a);const l=i.createElement("div");Object.assign(l.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),i.body.appendChild(l);const{wrap:f,metaPanel:b}=wt(i,n,t.wafer.metadata??void 0),h=i.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(f),l.appendChild(h);const k=i.createElement("div");Object.assign(k.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),b&&k.appendChild(b),l.appendChild(k);const H=ze(k,t,void 0,s),$=setInterval(()=>{c.closed&&De(o)},400);c.addEventListener("pagehide",()=>De(o)),R.set(o,{id:o,ctrl:H,cardIndex:e,label:n,closePollId:$,stopThemeSync:r,close:()=>{c.closed||c.close()},setTitle:K=>{i.title=K,a.textContent=K,a.style.display="block"}})}else{const i=Tn({title:n,onClose:()=>De(o),anchor:m});i.contentWrap.style.flexDirection="column",vt(i,n,t.wafer.metadata??void 0);const r=ze(i.contentWrap,t,void 0,s);R.set(o,{id:o,ctrl:r,cardIndex:e,label:n,closePollId:null,close:()=>i.close(),setTitle:a=>{const l=i.box.querySelector("[data-wmap-window-title]");l&&(l.textContent=a,l.title=a)}})}v[e]?.destroy(),v[e]=null,un(e),pn(e)}function ze(e,t,n,o){const s=t.viewOptions?{...d,...t.viewOptions}:d,c=o?{...s,...o}:s,i=n!==void 0?{...c,plotMode:"value",activeTest:n}:c,r=Ke(e,t,{viewOptions:i,toolbarControls:"full",showTooltip:!0,padding:Y,legendPosition:ne,fallbackFormat:he,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showMetadataBadge:!1});return r.setViewControlsVisible(!0),r.setSummaryVisible(!0),r.setExpandVisible(!1),r}function De(e){const t=R.get(e);if(!t)return;R.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const o=t.cardIndex,s=M[o];if(!s)return;const c={...s,viewOptions:n};M[o]=c;const{card:i,ctrl:r,canvasWrapper:a,expandBtn:l}=je(c,o,M.length);q[o]?.parentElement?.replaceWith(i),v[o]=r,q[o]=a,Z[o]=l}function mn(e){const t=R.get(e);t&&(t.close(),De(e))}function gn(){for(const e of R.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function hn(){const e=[...E.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),s=e[0].width,c=e[0].height,i=8,r=window.devicePixelRatio||1,a=Math.round(26*r),l=Math.round(12*r),f=m.ownerDocument.createElement("canvas");f.width=n*s+(n-1)*i,f.height=o*(c+a)+(o-1)*i;const b=f.getContext("2d"),h=Sn(E);b.fillStyle=h.background,b.fillRect(0,0,f.width,f.height),e.forEach((k,H)=>{const $=H%n,K=Math.floor(H/n),fe=$*(s+i),y=K*(c+a+i),W=k.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";b.fillStyle=h.surface,b.fillRect(fe,y,s,a),b.fillStyle=h.text,b.font=`700 ${l}px system-ui, sans-serif`,b.textAlign="left",b.textBaseline="middle",b.fillText(W,fe+Math.round(10*r),y+a/2,s-Math.round(20*r)),b.drawImage(k,fe,y+a)}),f.toBlob(k=>{k&&jn(k,te,p.onSaveImage)})}return{setItems(e){x=e.map(n=>typeof n=="function"?null:n);const t=d.plotMode;if(ue.has(t))if(e.some(o=>typeof o=="function"))N(e);else{const o=$e(t);d={...d,...o},N(ce(t))}else N(e)},setOptions(e){C(e,{fireCallback:!1})},getOptions(){return{...d}},setFallbackFormat(e){he=e;for(const t of v)t&&t.setFallbackFormat(e)},setLotStatsSummary(e){O=e,ft(),u&&I(),X()},setColumns(e){xt(e)},openUserGuide:pt,destroy(){Oe++;for(const e of[...R.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();R.clear();for(const e of v)e&&e.destroy();v=[],le()?.remove(),Ct.disconnect(),m.ownerDocument.removeEventListener("click",xe,!0),window.removeEventListener("blur",Je),Ht(),Dt(),B.remove(),G.remove(),F.remove(),u?.remove(),de?.destroy()}}}