@wafertools/wafermap 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/AGENTS.md +13 -13
  2. package/CHANGELOG.md +334 -1
  3. package/README.md +3 -3
  4. package/dist/packages/canvas-adapter/charts/chartShell.d.ts +2 -12
  5. package/dist/packages/canvas-adapter/charts/chartShell.js +1 -1
  6. package/dist/packages/canvas-adapter/dieList.js +7 -7
  7. package/dist/packages/canvas-adapter/drilldown.js +1 -1
  8. package/dist/packages/canvas-adapter/insightsTab.js +1 -1
  9. package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
  10. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +47 -4
  11. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
  12. package/dist/packages/canvas-adapter/summaryPanel.d.ts +22 -3
  13. package/dist/packages/canvas-adapter/summaryPanel.js +4 -3
  14. package/dist/packages/canvas-adapter/toCanvas.d.ts +23 -2
  15. package/dist/packages/canvas-adapter/toCanvas.js +1 -1
  16. package/dist/packages/canvas-adapter/toolbar.d.ts +54 -1
  17. package/dist/packages/canvas-adapter/toolbar.js +2 -2
  18. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
  19. package/dist/packages/canvas-adapter/userGuideHtml.js +100 -27
  20. package/dist/packages/canvas-adapter/version.d.ts +2 -2
  21. package/dist/packages/canvas-adapter/version.js +1 -1
  22. package/dist/packages/core/aggregates.d.ts +6 -0
  23. package/dist/packages/core/aggregates.js +1 -1
  24. package/dist/packages/core/compact.d.ts +205 -0
  25. package/dist/packages/core/compact.js +3 -0
  26. package/dist/packages/core/dieTable.d.ts +137 -0
  27. package/dist/packages/core/dieTable.js +1 -0
  28. package/dist/packages/core/dies.d.ts +22 -0
  29. package/dist/packages/core/dies.js +1 -1
  30. package/dist/packages/core/passBins.d.ts +6 -0
  31. package/dist/packages/core/passBins.js +1 -1
  32. package/dist/packages/core/utils.d.ts +14 -0
  33. package/dist/packages/core/utils.js +1 -1
  34. package/dist/packages/renderer/axisTicks.d.ts +14 -0
  35. package/dist/packages/renderer/axisTicks.js +1 -1
  36. package/dist/packages/renderer/buildView.d.ts +29 -4
  37. package/dist/packages/renderer/buildView.js +1 -1
  38. package/dist/packages/renderer/buildWaferMap.d.ts +29 -11
  39. package/dist/packages/renderer/buildWaferMap.js +1 -1
  40. package/dist/packages/renderer/columnarInput.d.ts +87 -0
  41. package/dist/packages/renderer/columnarInput.js +1 -0
  42. package/dist/packages/renderer/compactView.d.ts +22 -0
  43. package/dist/packages/renderer/compactView.js +1 -0
  44. package/dist/packages/renderer/derivedTests/apply.d.ts +8 -6
  45. package/dist/packages/renderer/derivedTests/apply.js +1 -1
  46. package/dist/packages/renderer/index.d.ts +1 -0
  47. package/dist/packages/renderer/spec.d.ts +3 -7
  48. package/dist/packages/renderer/spec.js +1 -1
  49. package/dist/packages/renderer/xyIndicator.d.ts +27 -0
  50. package/dist/packages/renderer/xyIndicator.js +1 -0
  51. package/dist/packages/stats/analyzeWaferLot.d.ts +28 -0
  52. package/dist/packages/stats/analyzeWaferLot.js +1 -1
  53. package/dist/packages/stats/analyzeWaferMap.d.ts +169 -2
  54. package/dist/packages/stats/analyzeWaferMap.js +1 -1
  55. package/dist/packages/stats/binRows.d.ts +38 -0
  56. package/dist/packages/stats/binRows.js +1 -0
  57. package/dist/packages/stats/boxplot.js +1 -1
  58. package/dist/packages/stats/capability.d.ts +7 -7
  59. package/dist/packages/stats/capability.js +1 -1
  60. package/dist/packages/stats/clusterDetection.js +1 -1
  61. package/dist/packages/stats/connectedComponents.js +1 -1
  62. package/dist/packages/stats/correlation.js +1 -1
  63. package/dist/packages/stats/filterFindings.d.ts +30 -0
  64. package/dist/packages/stats/filterFindings.js +1 -1
  65. package/dist/packages/stats/findingText.d.ts +9 -0
  66. package/dist/packages/stats/findingText.js +2 -0
  67. package/dist/packages/stats/histogram.js +1 -1
  68. package/dist/packages/stats/lotDrift.d.ts +16 -0
  69. package/dist/packages/stats/lotDrift.js +1 -0
  70. package/dist/packages/stats/lotPattern.d.ts +33 -0
  71. package/dist/packages/stats/lotPattern.js +1 -0
  72. package/dist/packages/stats/math.d.ts +73 -6
  73. package/dist/packages/stats/math.js +1 -1
  74. package/dist/packages/stats/normalizeInput.js +1 -1
  75. package/dist/packages/stats/patternClassification.d.ts +34 -3
  76. package/dist/packages/stats/patternClassification.js +1 -1
  77. package/dist/packages/stats/presentation.d.ts +42 -0
  78. package/dist/packages/stats/presentation.js +1 -0
  79. package/dist/packages/stats/regions.d.ts +16 -0
  80. package/dist/packages/stats/regions.js +1 -1
  81. package/dist/packages/stats/renderSummaryReport.d.ts +15 -2
  82. package/dist/packages/stats/renderSummaryReport.js +32 -27
  83. package/dist/packages/stats/reportHtml.d.ts +54 -9
  84. package/dist/packages/stats/reportHtml.js +130 -47
  85. package/dist/packages/stats/scatter.js +1 -1
  86. package/dist/packages/stats/sweep.js +1 -1
  87. package/dist/packages/stats/synthesis.d.ts +66 -0
  88. package/dist/packages/stats/synthesis.js +2 -0
  89. package/dist/packages/stats/testPassRate.js +1 -1
  90. package/dist/packages/stats/trend.js +1 -1
  91. package/dist/packages/stats/types.d.ts +6 -1
  92. package/dist/packages/stats/yieldRows.d.ts +31 -0
  93. package/dist/packages/stats/yieldRows.js +1 -0
  94. package/dist/packages/worker/index.js +1 -1
  95. package/dist/packages/worker/wafermap.worker.d.ts +3 -0
  96. package/dist/packages/worker/wafermap.worker.js +1 -1
  97. package/llms.txt +1 -1
  98. package/package.json +1 -1
  99. package/dist/packages/stats/findingsNarrative.d.ts +0 -3
  100. package/dist/packages/stats/findingsNarrative.js +0 -1
@@ -1,13 +1,13 @@
1
- import{hasPosition as I,isPositionedDie as B}from"../core/dies.js";import{classifyDie as W}from"../core/classify.js";import{isParametricTest as G,getTestPassStatus as S}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as Y}from"../stats/metadataColumns.js";import{LEADING as N,TRACKING as _,wireControlHover as U,controlStyle as X,SPACE as Q,RADIUS as F,FONT as g,CLR as c,saveTextFile as q}from"./toolbar.js";import{csvField as H}from"./summaryPanel.js";import{fmt as P}from"../renderer/fmt.js";import{testLabel as E,markedTestLabel as j,derivedFields as J,derivedKeyText as Z,derivedTestSource as ee,isDerivedTest as te,DERIVED_KEY as ne}from"../renderer/testLabel.js";const L=(t,r)=>r?`${t} (${r})`:t,ie=5e4,M=new WeakSet;function le(t){if(M.has(t))return;M.add(t);const r=t.createElement("style");r.textContent=`
1
+ import{hasPosition as F,isPositionedDie as V}from"../core/dies.js";import{testsPresent as G,testValue as H}from"../core/dieTable.js";import{classifyDie as Y}from"../core/classify.js";import{isParametricTest as _,getTestPassStatus as S}from"../renderer/buildWaferMap.js";import{resolveMetadataColumns as U}from"../stats/metadataColumns.js";import{LEADING as N,TRACKING as X,wireControlHover as Q,controlStyle as q,SPACE as J,RADIUS as P,FONT as g,CLR as d,saveTextFile as Z}from"./toolbar.js";import{csvField as k}from"./summaryPanel.js";import{fmt as j}from"../renderer/fmt.js";import{testLabel as E,markedTestLabel as M,derivedFields as ee,derivedKeyText as te,derivedTestSource as ne,isDerivedTest as ie,DERIVED_KEY as le}from"../renderer/testLabel.js";const L=(t,a)=>a?`${t} (${a})`:t,ae=5e4,z=new WeakSet;function re(t){if(z.has(t))return;z.add(t);const a=t.createElement("style");a.textContent=`
2
2
  .wmap-dielist-table { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
3
3
  .wmap-dielist-th {
4
4
  text-align: left; padding: 4px 8px; position: sticky; top: 0;
5
- background: ${c.panelBg}; color: ${c.label}; font-weight: 600;
6
- border-bottom: 1px solid ${c.menuBorder}; white-space: nowrap;
5
+ background: ${d.panelBg}; color: ${d.label}; font-weight: 600;
6
+ border-bottom: 1px solid ${d.menuBorder}; white-space: nowrap;
7
7
  }
8
8
  .wmap-dielist-td {
9
- padding: 4px 8px; color: ${c.text};
10
- border-bottom: 1px solid ${c.menuBorder}; white-space: nowrap;
9
+ padding: 4px 8px; color: ${d.text};
10
+ border-bottom: 1px solid ${d.menuBorder}; white-space: nowrap;
11
11
  }
12
- `,t.head.appendChild(r)}function s(t,r,n,i){const a=t.createElement(r);return n&&Object.assign(a.style,n),i!==void 0&&(a.textContent=i),a}function ae(t){return I(t)?String(t.x):""}function re(t){return I(t)?String(t.y):""}function oe(t,r){if(r!==void 0)return r.filter(i=>i.testNumber!==void 0);const n=new Map;for(const i of t)for(const a of Object.keys(i.testValues??{})){const d=Number(a);n.has(d)||n.set(d,{testNumber:d,name:E(void 0,d)})}return[...n.values()].sort((i,a)=>i.testNumber-a.testNumber)}function se(t,r,n){if(!r)return;const i=new Map;for(const a of t){if(!B(a))continue;const d=r(a);d&&i.set(a,W(a,d,{ringCount:n}))}return i.size>0?i:void 0}export function buildDieListSection(t,r,n={}){if(!t.length)return null;const i=n.ownerDocument??document;le(i);const a=oe(t,r),d=n.maxRows??ie,C=Math.max(0,t.length-d),z=C>0?t.slice(0,d):t,f=s(i,"div",{display:"flex",flexDirection:"column",gap:Q.md,flex:"1",minHeight:"0",minWidth:"0"}),v=s(i,"div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});v.appendChild(s(i,"div",{fontSize:g.meta,fontWeight:"700",letterSpacing:_,textTransform:"uppercase",color:c.label},n.title??`Die list (${t.length})`));const h=s(i,"button",{fontSize:g.body,padding:"3px 8px",borderRadius:F.control,...X("outlined"),background:c.menuBg},"Export CSV");h.type="button",U(h),v.appendChild(h),f.appendChild(v),n.note&&f.appendChild(s(i,"div",{fontSize:g.body,color:c.label,lineHeight:N.base,flexShrink:"0"},n.note));const w=se(t,n.getWafer,n.ringCount??4),K=t.some(e=>e.edgeExcluded===!0),O=[...n.extraColumn?[n.extraColumn.label]:[],"X","Y","Ring","Quadrant","Edge excluded","Site","Hard bin","Soft bin",...a.map(e=>L(E(e,e.testNumber),e.unit))],{columns:V,truncatedKeys:x}=Y({dies:t,waferMetadata:n.waferMetadata,metadataFields:n.metadataFields,dieKeys:n.metadataColumns,waferKeys:n.waferMetadataColumns==="none"?"none":void 0,waferPlacement:n.waferMetadataColumns??"csv",reservedLabels:O}),y=[...n.extraColumn?[{label:n.extraColumn.label,get:e=>n.extraColumn.get(e)??""}]:[],{label:"X",get:ae},{label:"Y",get:re},...w?[{label:"Ring",get:e=>{const l=w.get(e);return l?String(l.ring):""}},{label:"Quadrant",get:e=>w.get(e)?.quadrant??""}]:[],...K?[{label:"Edge excluded",get:e=>e.edgeExcluded?"Yes":"No"}]:[],{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...a.map(e=>{const l=!G(e);return{label:L(j(e,e.testNumber),e.unit),...te(e)?{csvLabel:`${L(E(e,e.testNumber),e.unit)} [derived from ${ee(e)??ne}]`}:{},get:o=>{if(l){const p=S(o,e.testNumber,e);return p===void 0?"":p?"PASS":"FAIL"}const u=o.testValues?.[e.testNumber];if(u!==void 0)return P(u,e.unit);const b=S(o,e.testNumber,e);return b===void 0?"":b?"PASS":"FAIL"},csvGet:o=>{if(l){const p=S(o,e.testNumber,e);return p===void 0?"":p?"PASS":"FAIL"}const u=o.testValues?.[e.testNumber];if(u!==void 0)return P(u,void 0,"engineering");const b=S(o,e.testNumber,e);return b===void 0?"":b?"PASS":"FAIL"}}}),...V.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],$=y.filter(e=>!e.csvOnly),A=Z(a.map(e=>({label:j(e,e.testNumber),...J(e)})));A&&f.appendChild(s(i,"div",{fontSize:g.body,color:c.label,lineHeight:N.base,flexShrink:"0"},A));const D=s(i,"div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${c.menuBorder}`,borderRadius:F.control,...n.maxHeight?{maxHeight:n.maxHeight}:{}}),m=i.createElement("table");m.className="wmap-dielist-table",m.setAttribute("aria-label",n.title??`Die list (${t.length} dies)`);const R=s(i,"thead"),T=s(i,"tr");for(const e of $){const l=i.createElement("th");l.className="wmap-dielist-th",l.scope="col",l.textContent=e.label,T.appendChild(l)}R.appendChild(T),m.appendChild(R);const k=s(i,"tbody");for(const e of z){const l=s(i,"tr");for(const o of $){const u=i.createElement("td");u.className="wmap-dielist-td",u.textContent=o.get(e),l.appendChild(u)}k.appendChild(l)}if(m.appendChild(k),D.appendChild(m),f.appendChild(D),C>0||x.length>0){const e=[];C>0&&e.push(`Showing the first ${d.toLocaleString()} of ${t.length.toLocaleString()} dies. The CSV export contains all ${t.length.toLocaleString()}.`),x.length>0&&e.push(`${x.length} further metadata field${x.length===1?"":"s"} not shown.`),f.appendChild(s(i,"div",{fontSize:g.body,color:c.label,lineHeight:N.base,flexShrink:"0"},e.join(" ")))}return h.addEventListener("click",()=>{const e=[y.map(l=>H(l.csvLabel??l.label)).join(",")];for(const l of t)e.push(y.map(o=>H((o.csvGet??o.get)(l))).join(","));q(e.join(`
13
- `),"die-list.csv","text/csv",n.onSaveText)}),f}
12
+ `,t.head.appendChild(a)}function s(t,a,n,i){const r=t.createElement(a);return n&&Object.assign(r.style,n),i!==void 0&&(r.textContent=i),r}function oe(t){return F(t)?String(t.x):""}function se(t){return F(t)?String(t.y):""}function de(t,a){return a!==void 0?a.filter(n=>n.testNumber!==void 0):G(t,"values").map(n=>({testNumber:n,name:E(void 0,n)}))}function ce(t,a,n){if(!a)return;const i=new Map;for(const r of t){if(!V(r))continue;const u=a(r);u&&i.set(r,Y(r,u,{ringCount:n}))}return i.size>0?i:void 0}export function buildDieListSection(t,a,n={}){if(!t.length)return null;const i=n.ownerDocument??document;re(i);const r=de(t,a),u=n.maxRows??ae,C=Math.max(0,t.length-u),K=C>0?t.slice(0,u):t,m=s(i,"div",{display:"flex",flexDirection:"column",gap:J.md,flex:"1",minHeight:"0",minWidth:"0"}),v=s(i,"div",{display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:"0"});v.appendChild(s(i,"div",{fontSize:g.meta,fontWeight:"700",letterSpacing:X,textTransform:"uppercase",color:d.label},n.title??`Die list (${t.length})`));const h=s(i,"button",{fontSize:g.body,padding:"3px 8px",borderRadius:P.control,...q("outlined"),background:d.menuBg},"Export CSV");h.type="button",Q(h),v.appendChild(h),m.appendChild(v),n.note&&m.appendChild(s(i,"div",{fontSize:g.body,color:d.label,lineHeight:N.base,flexShrink:"0"},n.note));const w=ce(t,n.getWafer,n.ringCount??4),B=t.some(e=>e.edgeExcluded===!0),O=[...n.extraColumn?[n.extraColumn.label]:[],"X","Y","Ring","Quadrant","Edge excluded","Site","Hard bin","Soft bin",...r.map(e=>L(E(e,e.testNumber),e.unit))],{columns:W,truncatedKeys:x}=U({dies:t,waferMetadata:n.waferMetadata,metadataFields:n.metadataFields,dieKeys:n.metadataColumns,waferKeys:n.waferMetadataColumns==="none"?"none":void 0,waferPlacement:n.waferMetadataColumns??"csv",reservedLabels:O}),y=[...n.extraColumn?[{label:n.extraColumn.label,get:e=>n.extraColumn.get(e)??""}]:[],{label:"X",get:oe},{label:"Y",get:se},...w?[{label:"Ring",get:e=>{const l=w.get(e);return l?String(l.ring):""}},{label:"Quadrant",get:e=>w.get(e)?.quadrant??""}]:[],...B?[{label:"Edge excluded",get:e=>e.edgeExcluded?"Yes":"No"}]:[],{label:"Site",get:e=>e.siteNum!==void 0?String(e.siteNum):""},{label:"Hard bin",get:e=>e.hbin!==void 0?String(e.hbin):""},{label:"Soft bin",get:e=>e.sbin!==void 0?String(e.sbin):""},...r.map(e=>{const l=!_(e);return{label:L(M(e,e.testNumber),e.unit),...ie(e)?{csvLabel:`${L(E(e,e.testNumber),e.unit)} [derived from ${ne(e)??le}]`}:{},get:o=>{if(l){const p=S(o,e.testNumber,e);return p===void 0?"":p?"PASS":"FAIL"}const c=H(o,e.testNumber);if(c!==void 0)return j(c,e.unit);const b=S(o,e.testNumber,e);return b===void 0?"":b?"PASS":"FAIL"},csvGet:o=>{if(l){const p=S(o,e.testNumber,e);return p===void 0?"":p?"PASS":"FAIL"}const c=H(o,e.testNumber);if(c!==void 0)return j(c,void 0,"engineering");const b=S(o,e.testNumber,e);return b===void 0?"":b?"PASS":"FAIL"}}}),...W.map(e=>({label:e.label,get:e.get,csvOnly:e.csvOnly}))],$=y.filter(e=>!e.csvOnly),A=te(r.map(e=>({label:M(e,e.testNumber),...ee(e)})));A&&m.appendChild(s(i,"div",{fontSize:g.body,color:d.label,lineHeight:N.base,flexShrink:"0"},A));const D=s(i,"div",{overflow:"auto",flex:"1",minHeight:"0",minWidth:"0",border:`1px solid ${d.menuBorder}`,borderRadius:P.control,...n.maxHeight?{maxHeight:n.maxHeight}:{}}),f=i.createElement("table");f.className="wmap-dielist-table",f.setAttribute("aria-label",n.title??`Die list (${t.length} dies)`);const R=s(i,"thead"),T=s(i,"tr");for(const e of $){const l=i.createElement("th");l.className="wmap-dielist-th",l.scope="col",l.textContent=e.label,T.appendChild(l)}R.appendChild(T),f.appendChild(R);const I=s(i,"tbody");for(const e of K){const l=s(i,"tr");for(const o of $){const c=i.createElement("td");c.className="wmap-dielist-td",c.textContent=o.get(e),l.appendChild(c)}I.appendChild(l)}if(f.appendChild(I),D.appendChild(f),m.appendChild(D),C>0||x.length>0){const e=[];C>0&&e.push(`Showing the first ${u.toLocaleString()} of ${t.length.toLocaleString()} dies. The CSV export contains all ${t.length.toLocaleString()}.`),x.length>0&&e.push(`${x.length} further metadata field${x.length===1?"":"s"} not shown.`),m.appendChild(s(i,"div",{fontSize:g.body,color:d.label,lineHeight:N.base,flexShrink:"0"},e.join(" ")))}return h.addEventListener("click",()=>{const e=[y.map(l=>k(l.csvLabel??l.label)).join(",")];for(const l of t)e.push(y.map(o=>k((o.csvGet??o.get)(l))).join(","));Z(e.join(`
13
+ `),"die-list.csv","text/csv",n.onSaveText)}),m}
@@ -1 +1 @@
1
- import{isYieldEligibleDie as b}from"../core/dies.js";import{isParametricTest as y}from"../renderer/buildWaferMap.js";import{buildSweepData as T}from"../stats/sweep.js";import{renderSweepPanel as C}from"./charts/sweep.js";import{renderHistogramPanel as E}from"./charts/histogram.js";import{renderCapabilityPanel as $}from"./charts/capability.js";import{openChartExpandModal as M,populationPhrase as w}from"./charts/chartShell.js";import{buildCheckMenuEl as I,createToolbarHelpers as x,getTooltip as N,menuLayerFor as R,wireMenuA11y as L,CLR as V,FONT as k,SPACE as F}from"./toolbar.js";const P=30,v=e=>e.items.flatMap(t=>t.dies);function O(e){return e.items.map(t=>({...t,dies:t.dies.filter(a=>b(a))}))}function A(e,t,a){return(e.testDefs??[]).filter(y).map(s=>s.testNumber).filter(s=>{let o=0;for(const i of t){const n=i.testValues?.[s];if(n!==void 0&&Number.isFinite(n)&&++o>=a)return!0}return!1})}function S(e,t,a,s,o){const n=e.ownerDocument.createElement("div");n.textContent=a,n.dataset.wmapPopulation="1",Object.assign(n.style,{color:V.label,fontSize:k.body,marginBottom:F.sm});const r=e.querySelector("[data-wmap-chart-expand]")?.parentElement;r?.parentElement===e?r.after(n):e.prepend(n),M(e,t,{anchor:s,onClosed:o})}function H(e,t,a,s){const o=v(t);let i=t.notMeasuredReason??null;return!i&&!o.some(n=>b(n))&&(i="These dies are all partial or edge-excluded, which charts leave out"),i||T(o,t.testDefs,e).series.some(r=>r.points.some(d=>d.count>0))||(i="These dies have no values for this sweep\u2019s tests"),{section:"Sweep",label:e.title,unavailable:i,open:()=>{const n=C({spec:e,dies:o,population:t.population,testDefs:t.testDefs,onSaveImage:a.onSaveImage,ownerDocument:s.ownerDocument}),r=o.filter(d=>b(d)).length;M(n.card,`${e.title} \u2014 ${w(r,o.length,t.population)}`,{anchor:s,onClosed:()=>n.destroy()})}}}function W(e,t,a){const s=O(e),o=v(e).length,i=s.flatMap(l=>l.dies),n=w(i.length,o,e.population),r=(e.testDefs??[]).filter(y),d=a.ownerDocument,f=(l,m)=>e.notMeasuredReason?e.notMeasuredReason:i.length===0?"These dies are all partial or edge-excluded, which charts leave out":A(e,i,l).length>0?null:m,u={section:"Distributions",label:"Value histogram",unavailable:f(1,"These dies have no parametric test values"),open:()=>{const l=E({title:"Value histogram",items:s,testDefs:r,selectedTestNumber:e.activeTest,onSaveImage:t.onSaveImage,ownerDocument:d});S(l.card,`Value histogram \u2014 ${n}`,`Population: ${n}`,a,()=>l.destroy())}},h={section:"Distributions",label:"Process capability",unavailable:f(2,"Needs at least 2 of these dies with values for one test"),open:()=>{const l=$({title:"Process capability",items:s,testDefs:r,selectedTestNumber:e.activeTest,onSaveImage:t.onSaveImage,ownerDocument:d}),m=i.length<P?` \xB7 fewer than ${P} dies, so each Ppk is a rough estimate`:"";S(l.card,`Process capability \u2014 ${n}`,`Population: ${n}${m}`,a,()=>l.destroy())}};return[u,h]}function B(e,t,a){return[...W(e,t,a),...(t.sweeps??[]).map(s=>H(s,e,t,a))]}const g=new WeakMap;export function openDrilldownMenu(e,t,a,s){const o=t.ownerDocument,i=o.defaultView??window;g.get(o)?.();const n=B(a,s,t),r=[];let d;for(const p of n)p.section!==d&&(r.push({section:p.section}),d=p.section),r.push({label:p.label,active:!1,action:!0,enabled:p.unavailable===null,disabledHint:p.unavailable??void 0,onClick:()=>{c(),p.open()}});const{makeMenuSection:f}=x(N(o)),u=I(new DOMRect(e.x,e.y-4,0,0),r,{makeMenuSection:f},i),h=v(a).length;u.setAttribute("role","menu"),u.setAttribute("aria-label",`Open a chart of ${w(h,h,a.population)}`),u.dataset.wmapDrilldownMenu="1",R(t).appendChild(u);const l=u.getBoundingClientRect();l.bottom>i.innerHeight-4&&(u.style.top=`${Math.max(4,e.y-l.height)}px`),l.right>i.innerWidth-4&&(u.style.left=`${Math.max(4,i.innerWidth-l.width-4)}px`);let m=!1;function c(){m||(m=!0,u.remove(),o.removeEventListener("pointerdown",D,!0),i.removeEventListener("blur",c),g.get(o)===c&&g.delete(o))}function D(p){u.contains(p.target)||c()}return o.addEventListener("pointerdown",D,!0),i.addEventListener("blur",c),L(u,t,c),g.set(o,c),c}
1
+ import{isYieldEligibleDie as b}from"../core/dies.js";import{testValue as T}from"../core/dieTable.js";import{isParametricTest as y}from"../renderer/buildWaferMap.js";import{buildSweepData as C}from"../stats/sweep.js";import{renderSweepPanel as E}from"./charts/sweep.js";import{renderHistogramPanel as $}from"./charts/histogram.js";import{renderCapabilityPanel as I}from"./charts/capability.js";import{openChartExpandModal as M,populationPhrase as w}from"./charts/chartShell.js";import{buildCheckMenuEl as x,createToolbarHelpers as N,getTooltip as R,menuLayerFor as L,wireMenuA11y as V,CLR as k,FONT as F,SPACE as O}from"./toolbar.js";const P=30,v=e=>e.items.flatMap(t=>t.dies);function A(e){return e.items.map(t=>({...t,dies:t.dies.filter(a=>b(a))}))}function H(e,t,a){return(e.testDefs??[]).filter(y).map(s=>s.testNumber).filter(s=>{let o=0;for(const i of t){const n=T(i,s);if(n!==void 0&&Number.isFinite(n)&&++o>=a)return!0}return!1})}function S(e,t,a,s,o){const n=e.ownerDocument.createElement("div");n.textContent=a,n.dataset.wmapPopulation="1",Object.assign(n.style,{color:k.label,fontSize:F.body,marginBottom:O.sm});const r=e.querySelector("[data-wmap-chart-expand]")?.parentElement;r?.parentElement===e?r.after(n):e.prepend(n),M(e,t,{anchor:s,onClosed:o})}function W(e,t,a,s){const o=v(t);let i=t.notMeasuredReason??null;return!i&&!o.some(n=>b(n))&&(i="These dies are all partial or edge-excluded, which charts leave out"),i||C(o,t.testDefs,e).series.some(r=>r.points.some(d=>d.count>0))||(i="These dies have no values for this sweep\u2019s tests"),{section:"Sweep",label:e.title,unavailable:i,open:()=>{const n=E({spec:e,dies:o,population:t.population,testDefs:t.testDefs,onSaveImage:a.onSaveImage,ownerDocument:s.ownerDocument}),r=o.filter(d=>b(d)).length;M(n.card,`${e.title} \u2014 ${w(r,o.length,t.population)}`,{anchor:s,onClosed:()=>n.destroy()})}}}function B(e,t,a){const s=A(e),o=v(e).length,i=s.flatMap(l=>l.dies),n=w(i.length,o,e.population),r=(e.testDefs??[]).filter(y),d=a.ownerDocument,f=(l,c)=>e.notMeasuredReason?e.notMeasuredReason:i.length===0?"These dies are all partial or edge-excluded, which charts leave out":H(e,i,l).length>0?null:c,u={section:"Distributions",label:"Value histogram",unavailable:f(1,"These dies have no parametric test values"),open:()=>{const l=$({title:"Value histogram",items:s,testDefs:r,selectedTestNumber:e.activeTest,onSaveImage:t.onSaveImage,ownerDocument:d});S(l.card,`Value histogram \u2014 ${n}`,`Population: ${n}`,a,()=>l.destroy())}},h={section:"Distributions",label:"Process capability",unavailable:f(2,"Needs at least 2 of these dies with values for one test"),open:()=>{const l=I({title:"Process capability",items:s,testDefs:r,selectedTestNumber:e.activeTest,onSaveImage:t.onSaveImage,ownerDocument:d}),c=i.length<P?` \xB7 fewer than ${P} dies, so each Ppk is a rough estimate`:"";S(l.card,`Process capability \u2014 ${n}`,`Population: ${n}${c}`,a,()=>l.destroy())}};return[u,h]}function _(e,t,a){return[...B(e,t,a),...(t.sweeps??[]).map(s=>W(s,e,t,a))]}const g=new WeakMap;export function openDrilldownMenu(e,t,a,s){const o=t.ownerDocument,i=o.defaultView??window;g.get(o)?.();const n=_(a,s,t),r=[];let d;for(const p of n)p.section!==d&&(r.push({section:p.section}),d=p.section),r.push({label:p.label,active:!1,action:!0,enabled:p.unavailable===null,disabledHint:p.unavailable??void 0,onClick:()=>{m(),p.open()}});const{makeMenuSection:f}=N(R(o)),u=x(new DOMRect(e.x,e.y-4,0,0),r,{makeMenuSection:f},i),h=v(a).length;u.setAttribute("role","menu"),u.setAttribute("aria-label",`Open a chart of ${w(h,h,a.population)}`),u.dataset.wmapDrilldownMenu="1",L(t).appendChild(u);const l=u.getBoundingClientRect();l.bottom>i.innerHeight-4&&(u.style.top=`${Math.max(4,e.y-l.height)}px`),l.right>i.innerWidth-4&&(u.style.left=`${Math.max(4,i.innerWidth-l.width-4)}px`);let c=!1;function m(){c||(c=!0,u.remove(),o.removeEventListener("pointerdown",D,!0),i.removeEventListener("blur",m),g.get(o)===m&&g.delete(o))}function D(p){u.contains(p.target)||m()}return o.addEventListener("pointerdown",D,!0),i.addEventListener("blur",m),V(u,t,m),g.set(o,m),m}
@@ -1 +1 @@
1
- import{buildFacetTable as He,facetValueOf as Fe,FACET_NONE_VALUE as Ne}from"../stats/facets.js";import{mergeTestDefs as le}from"../stats/mergeTestDefs.js";import{isParametricTest as Ve}from"../renderer/buildWaferMap.js";import{waferDisplayLabel as _e,waferIdentityLabel as Ue}from"../core/waferLabel.js";import{hasDrilldownTargets as de,waferPopulation as ze}from"./chartPopulation.js";import{openDrilldownMenu as qe}from"./drilldown.js";import{INPUT_DEFAULT_PASS_BINS as R,itemPassBins as Qe,passBinsLabel as ce}from"../core/passBins.js";import{NO_DATA_FILL as pe}from"../renderer/colorMap.js";import{describeWaferPopulation as Ke,populationStat as Xe}from"../stats/population.js";import{LEADING as ue,ALPHA as Je,SPACE as C,EDGE_GUTTER as ee,FONT as W,CLR as k,RADIUS as fe,SHADOW as Ze,controlStyle as me,wireControlHover as te,wireTooltip as et}from"./toolbar.js";import{ICONS as tt}from"./icons.js";import{renderCapabilityPanel as nt}from"./charts/capability.js";import{renderBoxplotPanel as at}from"./charts/boxplot.js";import{renderTrendPanel as ot}from"./charts/trend.js";import{renderSweepPanel as st}from"./charts/sweep.js";import{sweepAppliesTo as rt}from"../stats/sweep.js";import{renderHistogramPanel as it}from"./charts/histogram.js";import{renderCorrelationPanel as lt}from"./charts/correlation.js";import{renderScatterPanel as dt}from"./charts/scatter.js";import{renderBarPanel as be}from"./charts/barPanel.js";import{renderBinClusterPanel as ct}from"./charts/binCluster.js";import{renderTestPassRatePanel as pt}from"./charts/testPassRate.js";import{QUANTITY as ut}from"./charts/palette.js";import{cardFrameStyle as ft,makeChartGridWrap as V,makeLabeledSelect as mt,makeLinkedGroupSelect as bt}from"./charts/chartShell.js";import{buildYieldData as _,buildYieldDataCombined as ge}from"../stats/yield.js";import{buildBinParetoData as gt}from"../stats/binPareto.js";import{buildLotTestSection as ht,buildLotFunctionalSection as yt,buildMetadataStripBox as wt}from"./summaryPanel.js";import{buildRegionYieldData as he,buildRingRegions as Ct,buildQuadrantRegions as xt}from"../stats/regions.js";import{renderRegionYieldDiagram as ye}from"./charts/regionYieldDiagram.js";const we=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}],St={key:"sweeps",label:"Sweeps"};export function createInsightsTab(x){const{getItems:Ce,getLotStats:xe,getBinColors:ne,getRingCount:Se,onSaveImage:T,onSaveText:U,openWafer:G,focusTest:ae}=x,ve=x.showMetadataStrip??!0,M=x.contentInset??ee,p=x.ownerDocument??document,I=p.createElement("div");Object.assign(I.style,{display:"none",flexDirection:"column",width:"100%",paddingTop:"0"});const Te=ee,O=p.createElement("div");Object.assign(O.style,{paddingLeft:Te});const B=p.createElement("div");Object.assign(B.style,{display:"flex",gap:C.xs,alignItems:"center",background:k.menuBg,border:`1px solid ${k.menuBorder}`,borderRadius:fe.container,boxShadow:Ze.panel,padding:`0 ${C.lg}`,marginBottom:C.lg,marginLeft:M,marginRight:M}),B.setAttribute("role","tablist"),B.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const t=Array.from(B.querySelectorAll('[role="tab"]')),a=t.indexOf(p.activeElement);if(a===-1)return;e.preventDefault();const s=t[(a+(e.key==="ArrowRight"?1:-1)+t.length)%t.length];s.focus(),s.click()});const j=p.createElement("div");Object.assign(j.style,{display:"flex",flexDirection:"column",gap:C.lg,marginTop:"0",paddingLeft:M,paddingRight:M}),I.appendChild(O),I.appendChild(B),I.appendChild(j);const oe=(x.sweeps?.length??0)>0,ke=oe?[...we,St]:we;let L=x.defaultView==="sweeps"&&!oe?"overview":x.defaultView??"overview",A,$=null,E=null,Y={includeLimits:void 0,clipOutliers:!1,limits:"both"};const z=new Map,se=(e,t)=>{Y=e;for(const a of z.values())for(const s of a)s!==t&&s.setAxisPrefs(e)},q=e=>{E!==e&&(E=e,F())};let H=new Map;function re(){for(const e of H.values())e.destroy();H=new Map}function Q(e,t,a){G?.(e,t,a)}function K(e){if(e.some(t=>de(t.testDefs,x.sweeps)))return(t,a,s)=>{const r=e.find(u=>u.waferIndex===t);if(!r||!de(r.testDefs,x.sweeps))return;s.preventDefault();const i=ze(r.dies,{waferLabel:r.identity,testDefs:r.testDefs,activeTest:a??$??void 0,waferIndex:t});qe({x:s.clientX,y:s.clientY},s.target,i,{sweeps:x.sweeps,onSaveImage:T})}}function De(e){return G?{open:(t,a)=>Q(t,`Wafer ${e.find(s=>s.waferIndex===t)?.label??t}`,a)}:ae&&e.length===1?{open:(t,a)=>ae(a),label:"show this test on the map"}:null}function Be(){return Ce().map((e,t)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:_e(e,t),identity:Ue(e),waferIndex:t,passBins:Qe(e),statsSummary:e.statsSummary,testDefs:e.testDefs}).filter(e=>e!=null)}function ie(e,t){Object.assign(e.style,{background:"none",border:"none",borderBottom:t?`2px solid ${k.iconActive}`:"2px solid transparent",color:t?k.iconActive:k.label,fontWeight:t?"700":"500",fontSize:W.body,padding:`${C.sm} ${ee} ${C.md}`,cursor:"pointer",marginBottom:"-1px"})}function $e(e,t){const a=p.createElement("button");a.type="button",a.textContent=t;const s=e===L;return ie(a,s),a.dataset.on=s?"true":"false",te(a,"bare"),a.dataset.wmapInsightsTab=e,a.setAttribute("role","tab"),a.setAttribute("aria-selected",s?"true":"false"),a.tabIndex=s?0:-1,a.addEventListener("click",()=>{L!==e&&(L=e,F({keepSections:!0}))}),a}function Ee(e){const t=p.createElement("button");return t.type="button",t.textContent=`\u2039 ${e.label}`,ie(t,!1),t.dataset.wmapInsightsBack="1",t.addEventListener("click",e.onBack),t}function Le(e,t,a,s=!0){const r=V(p),i=ne();let u="label";const f=a??"group",g=ce(e.map(l=>l.passBins)),d=xe?.(),m=new Map(d?.lotYieldSeries.map(l=>[l.waferIndex,l.yieldPercent])),h=l=>({...l,label:l.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:m.get(l.waferIndex),key:l.waferIndex}),b=e.map(h),y=t?.map(l=>({key:l.key,items:l.items.map(h)})),S=()=>y?ge(y,R,u):_(b,R,u),o={title:t?`Yield by ${f} (pass: ${g})`:`Yield by wafer (pass: ${g})`,data:S(),selfControl:{current:u,options:[["yield","Sort: yield"],["label",t?`Sort: ${f}`:"Sort: wafer ID"]],onChange:l=>(u=l,{data:S()})},barColor:()=>ut,valueLabel:l=>`${l.percent.toFixed(1)}%`,reference:l=>{if(l.length<3)return null;const D=l.map(Z=>Z.percent).sort((Z,Ge)=>Z-Ge),P=D.length%2?D[(D.length-1)/2]:(D[D.length/2-1]+D[D.length/2])/2;return{value:P,label:`median ${P.toFixed(1)}%`}},drill:y?{onOpenGroup:l=>{const D=y.find(P=>P.key===l.label)?.items??[];return{data:_(D,R,u),title:`Yield by wafer \u2014 ${f}: ${l.label} (pass: ${g})`}},onBack:()=>({data:S(),title:`Yield by ${f} (pass: ${g})`}),groupLabelText:f}:void 0,onOpen:G?l=>{typeof l.key=="number"&&Q(l.key,`Wafer ${l.label}`)}:void 0,onWaferContextMenu:K(e),ownerDocument:p};let n=null;if(s&&(n=be(o,T),n.card.style.minHeight="360px",r.appendChild(n.card)),t){const l=ct({title:"Hard bin pareto",groups:t.map(D=>({key:D.key,items:D.items.map(P=>({dies:P.dies,hardBinCounts:P.statsSummary?.stats.hardBinCounts,softBinCounts:P.statsSummary?.stats.softBinCounts}))})),onSaveImage:T,ownerDocument:p});return l.card.style.minHeight="360px",r.appendChild(l.card),{card:r,destroy:()=>{n?.destroy(),l.destroy()}}}let v="hbin";const c=l=>l===void 0?pe:(v==="hbin"?i.hard:i.soft).get(l)??pe,w=e.map(l=>({dies:l.dies,hardBinCounts:l.statsSummary?.stats.hardBinCounts,softBinCounts:l.statsSummary?.stats.softBinCounts})),N=()=>gt(w,v),Ye={title:"Hard bin pareto",data:N(),selfControl:{current:v,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:l=>(v=l,{data:N(),title:`${v==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:l=>c(l.binCode),ownerDocument:p},J=be(Ye,T);return J.card.style.minHeight="360px",r.appendChild(J.card),{card:r,destroy:()=>{n?.destroy(),J.destroy()}}}function X(){const e=p.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{...ft(),display:"flex",flexDirection:"column",gap:C.lg,minWidth:"0"}),e}function Pe(e){if(O.innerHTML="",O.style.marginBottom="0",!ve)return;const t=wt(e.map(a=>({metadata:a.metadata})),void 0,{facetableOnly:!1});t&&(t.style.marginBottom="0",O.appendChild(t),O.style.marginBottom=C.xs)}function Ie(e,t,a,s){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const r=e.map(c=>c.wafer),i=e.map(c=>c.dies),u=e.flatMap(c=>c.dies),f=e.map(c=>c.statsSummary),g=f.every(c=>c!==void 0)?f:void 0,d=Se?.()??4,m=[],h=[],y=pt({groups:(s??[{key:"",items:e}]).map(c=>({key:c.key,items:c.items.map(w=>({dies:w.dies,testSpecYield:w.statsSummary?.stats.testSpecYield,functionalYield:w.statsSummary?.stats.functionalYield}))})),testDefs:a,onSaveImage:T,ownerDocument:p});y.card.style.minHeight="300px",m.push(y.card),h.push(y.destroy);const S=he(i,r,d,c=>e[c].passBins,Ct);if(S.length){const c=ye({title:"Ring yield",mode:"ring",rows:S,onSaveImage:T,ownerDocument:p});m.push(c.card),h.push(c.destroy)}const o=he(i,r,d,c=>e[c].passBins,xt);if(o.length){const c=ye({title:"Quadrant yield",mode:"quadrant",rows:o,onSaveImage:T,ownerDocument:p});m.push(c.card),h.push(c.destroy)}let n=null;if(t.length){const c=ht(u,t,void 0,g,U,i.map(w=>({dies:w})),void 0,"full");if(c){const w=X();w.appendChild(c),n=w}}let v=null;if(a.length){const c=yt(u,a,g,U);if(c){const w=X();w.appendChild(c),v=w}}return{elements:m,testValuesCard:n,functionalCard:v,destroy:()=>{for(const c of h)c()}}}function Oe(e){const t=ce(e.map(d=>d.passBins)),a=e.length===1,s=e[0],r=X();Object.assign(r.style,{flexDirection:"row",flexWrap:"wrap",gap:C.md});const i=d=>{const m=d.lastElementChild;return m&&Object.assign(m.style,{borderRight:"none",paddingRight:"0",marginRight:"0"}),d};function u(d,m,h){const b=p.createElement("div");Object.assign(b.style,{display:"flex",alignItems:"baseline",gap:C.sm,paddingRight:C.xxl,marginRight:C.md,borderRight:`1px solid ${k.menuBorder}`});const y=p.createElement("div");y.textContent=d,Object.assign(y.style,{fontSize:W.heading,fontWeight:"700",color:k.value,lineHeight:ue.tight});const S=p.createElement("div");if(S.textContent=m,Object.assign(S.style,{fontSize:W.body,color:k.label}),b.append(y,S),h){const o=p.createElement("div");o.textContent=h,Object.assign(o.style,{fontSize:W.meta,color:k.label,opacity:Je.muted}),b.appendChild(o)}return b}if(a){const d=_([{...s,key:s.waferIndex}],R)[0]?.percent;return d!==void 0&&r.appendChild(u(`${d.toFixed(1)}%`,`Yield \xB7 pass: ${t}`)),r.appendChild(u(String(s.dies.length),"Total dies")),i(r)}r.appendChild(u(String(e.length),"Wafers"));const f=_(e.map(d=>({...d,key:d.waferIndex})),R).map(d=>d.percent).filter(d=>Number.isFinite(d));if(f.length){const d=f.reduce((b,y)=>b+y,0)/f.length,m=ge([{key:"all",items:e.map(b=>({...b,key:b.waferIndex}))}],R)[0]?.percent,h=m!==void 0&&m.toFixed(1)!==d.toFixed(1);r.appendChild(u(`${d.toFixed(1)}%`,`Mean per-wafer yield \xB7 pass: ${t}`,h?`${m.toFixed(1)}% by dies`:void 0))}const g=e.map(d=>d.statsSummary);if(g.every(d=>d!==void 0)){const d=g.reduce((h,b)=>h+b.stats.analyzedDies,0),m=g.reduce((h,b)=>h+b.stats.excludedDies,0);r.appendChild(u(d.toLocaleString(),"Dies analysed",m?`${m.toLocaleString()} excluded`:void 0))}else r.appendChild(u(e.reduce((d,m)=>d+m.dies.length,0).toLocaleString(),"Total dies"));return i(r)}function Ae(e,t,a,s,r){const i=p.createElement("div");Object.assign(i.style,{display:"flex",flexDirection:"column",gap:C.lg});const u=e.length===1&&!s;e.length&&!s&&i.appendChild(Oe(e));const f=Le(e,s,r,!u);i.appendChild(f.card);const g=Ie(e,t,a,s);for(const d of g.elements)f.card.appendChild(d);return g.testValuesCard&&i.appendChild(g.testValuesCard),g.functionalCard&&i.appendChild(g.functionalCard),{card:i,destroy:()=>{f.destroy(),g.destroy()}}}function Re(e,t,a,s){const r=V(p),i=De(e),u=o=>n=>se(n,o()),f=o=>({...o,testStats:o.statsSummary?.stats.perTestStats}),g=e.map(f),d=a?.map(o=>({key:o.key,items:o.items.map(f)})),m=at({title:"Test value distribution",axisPrefs:Y,onAxisPrefsChange:u(()=>m),onTestChange:o=>y(o),selectedTestNumber:$??void 0,items:g,testDefs:t,groups:d,groupLabelText:s,onSaveImage:T,onGroupChange:o=>q(o),onOpen:i?.open,openActionLabel:i?.label,onWaferContextMenu:K(e),ownerDocument:p}),h=it({title:"Value histogram",axisPrefs:Y,onAxisPrefsChange:u(()=>h),onTestChange:o=>y(o),selectedTestNumber:$??void 0,items:e,testDefs:t,groups:a,onGroupChange:o=>q(o),onSaveImage:T,ownerDocument:p}),b=ot({title:"Wafer-to-wafer trend",axisPrefs:Y,onAxisPrefsChange:u(()=>b),onTestChange:o=>y(o),selectedTestNumber:$??void 0,items:e.map(o=>({label:o.label,key:o.waferIndex,dies:o.dies,testStats:o.statsSummary?.stats.perTestStats})),testDefs:t,onSaveImage:T,centreLabel:Xe(Ke(e.map(o=>o.wafer.metadata)),"mean"),onOpen:G?(o,n)=>Q(o,`Wafer ${e.find(v=>v.waferIndex===o)?.label??o}`,n):void 0,onWaferContextMenu:K(e),ownerDocument:p}),y=o=>{$=o,m.setTest(o),h.setTest(o),b.setTest(o),S.setTest(o)};z.set("distribution",[m,h,b]);const S=nt({title:"Process capability",items:e,testDefs:t,onSaveImage:T,selectedTestNumber:$??void 0,onSelectTest:o=>y(o),ownerDocument:p});return r.append(S.card,m.card,h.card,b.card),{card:r,destroy:()=>{S.destroy(),m.destroy(),h.destroy(),b.destroy()}}}function We(e){const t=V(p),a=le(e).defs,s=e.flatMap(f=>f.dies),r=x.sweeps??[],i=r.filter(f=>!rt(f,a));i.length>0&&t.appendChild(Me(i,r.length));const u=r.map(f=>st({spec:f,dies:s,testDefs:a,onSaveImage:T,ownerDocument:p}));for(const f of u)t.appendChild(f.card);return{card:t,destroy:()=>{for(const f of u)f.destroy()}}}function Me(e,t){const a=p.createElement("div");a.setAttribute("role","status"),Object.assign(a.style,{gridColumn:"1 / -1",display:"flex",flexWrap:"wrap",alignItems:"center",gap:C.md,padding:`${C.sm} ${C.md}`,background:k.warnBg,border:`1px solid ${k.warnBorder}`,borderRadius:fe.container,color:k.warnText,fontSize:W.body,lineHeight:ue.base});const s=e.length,r=p.createElement("span");if(r.style.flex="1 1 24ch",r.textContent=(s===t?s===1?"This sweep names no test in this data":"None of these sweeps names a test in this data":`${s} of ${t} sweeps name no test in this data: ${e.map(i=>i.title).join(", ")}`)+` \u2014 ${s===1?"it":"they"} may belong to another test program.`,a.appendChild(r),x.onRemoveSweeps){const i=p.createElement("button");i.type="button",Object.assign(i.style,me("outlined")),i.textContent=s===1?"Remove this sweep":`Remove these ${s} sweeps`,te(i);const u=e.map(f=>f.id);i.addEventListener("click",()=>x.onRemoveSweeps(u)),a.appendChild(i)}return a}function je(e,t,a){const s=V(p),r=dt({title:"Test scatter",items:e,testDefs:t,groups:a,binColors:ne().hard,onSaveImage:T,axisPrefs:Y,onAxisPrefsChange:u=>se(u,r),ownerDocument:p});z.set("correlation",[r]);const i=lt({title:"Test correlation matrix",items:e,testDefs:t,onSaveImage:T,onSaveText:U,onSelectPair:(u,f)=>r.setXY(u,f),ownerDocument:p});return s.append(i.card,r.card),{card:s,destroy:()=>{i.destroy(),r.destroy()}}}function F(e){e?.keepSections||re(),j.innerHTML="",B.innerHTML="",x.backTab&&B.appendChild(Ee(x.backTab));for(const n of ke)B.appendChild($e(n.key,n.label));const t=Be();Pe(t);const a=He(t,{facetableOnly:!0}).filter(n=>n.splittable),s=p.createElement("div");Object.assign(s.style,{display:"flex",gap:C.md,alignItems:"center",marginLeft:C.xxl,paddingBottom:C.xs});let r;a.length>0?(s.appendChild(mt("Group by:",[{value:"",label:"None"},...a.map(n=>({value:n.key,label:`${n.label} (${n.values.length})`}))],A??"",n=>{A=n||void 0,E=null,F()},{hook:"group-by",ownerDocument:p})),r=a.find(n=>n.key===A)?.label):A=void 0;let i;if(A){const n=new Map,v=[];for(const c of t){const w=Fe(c.metadata,A)??Ne;n.has(w)||(n.set(w,[]),v.push(w)),n.get(w).push(c)}i=v.map(c=>({key:c,items:n.get(c)}))}E!==null&&!i?.some(n=>n.key===E)&&(E=null),i&&i.length>0&&s.appendChild(bt(i.map(n=>n.key),"Show:",E,n=>q(n),{ownerDocument:p}).el);let u=null;if(x.onOpenGuide){const n=p.createElement("button");n.type="button",n.innerHTML=tt.help,n.setAttribute("aria-label","User guide"),Object.assign(n.style,{...me("bare"),display:"inline-flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",flexShrink:"0"}),te(n,"bare"),et(n,"User guide"),n.addEventListener("click",()=>x.onOpenGuide()),Object.assign(n.style,{marginLeft:"auto"}),u=n}B.appendChild(s),u&&B.appendChild(u);const f=E!==null?i?.find(n=>n.key===E):void 0,g=f?.items??t,d=f?void 0:i,m=le(g),h=m.defs,b=h.filter(Ve);$!==null&&!b.some(n=>n.testNumber===$)&&($=null);const y=e?.keepSections?H.get(L):void 0,S=y??(L==="overview"?Ae(g,b,h,d,r):L==="distributions"?Re(g,b,d,r):L==="sweeps"?We(g):je(g,b,d));y||H.set(L,S);const o=m.conflicts.filter(n=>n.excluded);if(o.length>0){const n=p.createElement("div");Object.assign(n.style,{color:k.label,fontSize:W.body,padding:`0 ${M} ${C.sm}`});const v=o.slice(0,6).map(N=>N.testNumber).join(", "),c=o.length>6?`, and ${o.length-6} more`:"",w=o.length===1?"it":"them";n.textContent=`${o.length} test ${o.length===1?"number is":"numbers are"} hidden (${v}${c}) \u2014 the wafers in view describe ${w} differently, so their values cannot be pooled. `+(i&&i.length>0?`Pick one ${r??"group"} under "Show:" to analyse ${w}.`:"Load one test program at a time to analyse them."),n.dataset.wmapWithheldTests=String(o.length),j.appendChild(n)}j.appendChild(S.card)}return{el:I,render:F,destroy:()=>{re(),I.remove()}}}
1
+ import{MEAN_WAFER_YIELD_LABEL as He}from"../stats/presentation.js";import{buildFacetTable as Fe,facetValueOf as Ne,FACET_NONE_VALUE as _e}from"../stats/facets.js";import{mergeTestDefs as de}from"../stats/mergeTestDefs.js";import{isParametricTest as Ve}from"../renderer/buildWaferMap.js";import{waferDisplayLabel as ze,waferIdentityLabel as Ue}from"../core/waferLabel.js";import{hasDrilldownTargets as ce,waferPopulation as qe}from"./chartPopulation.js";import{openDrilldownMenu as Qe}from"./drilldown.js";import{INPUT_DEFAULT_PASS_BINS as M,itemPassBins as Ke,passBinsLabel as pe}from"../core/passBins.js";import{NO_DATA_FILL as ue}from"../renderer/colorMap.js";import{describeWaferPopulation as Xe,populationStat as Je}from"../stats/population.js";import{LEADING as fe,ALPHA as Ze,SPACE as w,EDGE_GUTTER as te,FONT as O,CLR as k,RADIUS as me,SHADOW as et,controlStyle as be,wireControlHover as ne,wireTooltip as tt}from"./toolbar.js";import{ICONS as nt}from"./icons.js";import{renderCapabilityPanel as ot}from"./charts/capability.js";import{renderBoxplotPanel as at}from"./charts/boxplot.js";import{renderTrendPanel as st}from"./charts/trend.js";import{renderSweepPanel as rt}from"./charts/sweep.js";import{sweepAppliesTo as it}from"../stats/sweep.js";import{renderHistogramPanel as lt}from"./charts/histogram.js";import{renderCorrelationPanel as dt}from"./charts/correlation.js";import{renderScatterPanel as ct}from"./charts/scatter.js";import{renderBarPanel as ge}from"./charts/barPanel.js";import{renderBinClusterPanel as pt}from"./charts/binCluster.js";import{renderTestPassRatePanel as ut}from"./charts/testPassRate.js";import{QUANTITY as ft}from"./charts/palette.js";import{cardFrameStyle as mt,makeChartGridWrap as V,makeLabeledSelect as bt,makeLinkedGroupSelect as gt}from"./charts/chartShell.js";import{buildYieldData as z,buildYieldDataCombined as he}from"../stats/yield.js";import{buildBinParetoData as ht}from"../stats/binPareto.js";import{buildLotTestSectionSteps as yt,buildLotFunctionalSection as wt,buildMetadataStripBox as Ct}from"./summaryPanel.js";import{runChunked as xt}from"./chunked.js";import{buildRegionYieldData as ye,buildRingRegions as St,buildQuadrantRegions as vt}from"../stats/regions.js";import{renderRegionYieldDiagram as we}from"./charts/regionYieldDiagram.js";const Ce=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}],Tt={key:"sweeps",label:"Sweeps"};export function createInsightsTab(x){const{getItems:xe,getLotStats:Se,getBinColors:oe,getRingCount:ve,onSaveImage:T,onSaveText:U,openWafer:F,focusTest:ae}=x,Te=x.showMetadataStrip??!0,Y=x.contentInset??te,p=x.ownerDocument??document,R=p.createElement("div");Object.assign(R.style,{display:"none",flexDirection:"column",width:"100%",paddingTop:"0"});const ke=te,W=p.createElement("div");Object.assign(W.style,{paddingLeft:ke});const $=p.createElement("div");Object.assign($.style,{display:"flex",gap:w.xs,alignItems:"center",background:k.menuBg,border:`1px solid ${k.menuBorder}`,borderRadius:me.container,boxShadow:et.panel,padding:`0 ${w.lg}`,marginBottom:w.lg,marginLeft:Y,marginRight:Y}),$.setAttribute("role","tablist"),$.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const t=Array.from($.querySelectorAll('[role="tab"]')),o=t.indexOf(p.activeElement);if(o===-1)return;e.preventDefault();const s=t[(o+(e.key==="ArrowRight"?1:-1)+t.length)%t.length];s.focus(),s.click()});const G=p.createElement("div");Object.assign(G.style,{display:"flex",flexDirection:"column",gap:w.lg,marginTop:"0",paddingLeft:Y,paddingRight:Y}),R.appendChild(W),R.appendChild($),R.appendChild(G);const se=(x.sweeps?.length??0)>0,De=se?[...Ce,Tt]:Ce;let P=x.defaultView==="sweeps"&&!se?"overview":x.defaultView??"overview",j,E=null,L=null,H={includeLimits:void 0,clipOutliers:!1,limits:"both"};const q=new Map,re=(e,t)=>{H=e;for(const o of q.values())for(const s of o)s!==t&&s.setAxisPrefs(e)},Q=e=>{L!==e&&(L=e,_())};let N=new Map;function ie(){for(const e of N.values())e.destroy();N=new Map}function K(e,t,o){F?.(e,t,o)}function X(e){if(e.some(t=>ce(t.testDefs,x.sweeps)))return(t,o,s)=>{const r=e.find(u=>u.waferIndex===t);if(!r||!ce(r.testDefs,x.sweeps))return;s.preventDefault();const i=qe(r.dies,{waferLabel:r.identity,testDefs:r.testDefs,activeTest:o??E??void 0,waferIndex:t});Qe({x:s.clientX,y:s.clientY},s.target,i,{sweeps:x.sweeps,onSaveImage:T})}}function Be(e){return F?{open:(t,o)=>K(t,`Wafer ${e.find(s=>s.waferIndex===t)?.label??t}`,o)}:ae&&e.length===1?{open:(t,o)=>ae(o),label:"show this test on the map"}:null}function $e(){return xe().map((e,t)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:ze(e,t),identity:Ue(e),waferIndex:t,passBins:Ke(e),statsSummary:e.statsSummary,testDefs:e.testDefs}).filter(e=>e!=null)}function le(e,t){Object.assign(e.style,{background:"none",border:"none",borderBottom:t?`2px solid ${k.iconActive}`:"2px solid transparent",color:t?k.iconActive:k.label,fontWeight:t?"700":"500",fontSize:O.body,padding:`${w.sm} ${te} ${w.md}`,cursor:"pointer",marginBottom:"-1px"})}function Ee(e,t){const o=p.createElement("button");o.type="button",o.textContent=t;const s=e===P;return le(o,s),o.dataset.on=s?"true":"false",ne(o,"bare"),o.dataset.wmapInsightsTab=e,o.setAttribute("role","tab"),o.setAttribute("aria-selected",s?"true":"false"),o.tabIndex=s?0:-1,o.addEventListener("click",()=>{P!==e&&(P=e,_({keepSections:!0}))}),o}function Le(e){const t=p.createElement("button");return t.type="button",t.textContent=`\u2039 ${e.label}`,le(t,!1),t.dataset.wmapInsightsBack="1",t.addEventListener("click",e.onBack),t}function Pe(e,t,o,s=!0){const r=V(p),i=oe();let u="label";const f=o??"group",g=pe(e.map(d=>d.passBins)),c=Se?.(),m=new Map(c?.lotYieldSeries.map(d=>[d.waferIndex,d.yieldPercent])),h=d=>({...d,label:d.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:m.get(d.waferIndex),key:d.waferIndex}),b=e.map(h),y=t?.map(d=>({key:d.key,items:d.items.map(h)})),S=()=>y?he(y,M,u):z(b,M,u),a={title:t?`Yield by ${f} (pass: ${g})`:`Yield by wafer (pass: ${g})`,data:S(),selfControl:{current:u,options:[["yield","Sort: yield"],["label",t?`Sort: ${f}`:"Sort: wafer ID"]],onChange:d=>(u=d,{data:S()})},barColor:()=>ft,valueLabel:d=>`${d.percent.toFixed(1)}%`,reference:d=>{if(d.length<3)return null;const D=d.map(ee=>ee.percent).sort((ee,Ge)=>ee-Ge),A=D.length%2?D[(D.length-1)/2]:(D[D.length/2-1]+D[D.length/2])/2;return{value:A,label:`median ${A.toFixed(1)}%`}},drill:y?{onOpenGroup:d=>{const D=y.find(A=>A.key===d.label)?.items??[];return{data:z(D,M,u),title:`Yield by wafer \u2014 ${f}: ${d.label} (pass: ${g})`}},onBack:()=>({data:S(),title:`Yield by ${f} (pass: ${g})`}),groupLabelText:f}:void 0,onOpen:F?d=>{typeof d.key=="number"&&K(d.key,`Wafer ${d.label}`)}:void 0,onWaferContextMenu:X(e),ownerDocument:p};let n=null;if(s&&(n=ge(a,T),n.card.style.minHeight="360px",r.appendChild(n.card)),t){const d=pt({title:"Hard bin pareto",groups:t.map(D=>({key:D.key,items:D.items.map(A=>({dies:A.dies,hardBinCounts:A.statsSummary?.stats.hardBinCounts,softBinCounts:A.statsSummary?.stats.softBinCounts}))})),onSaveImage:T,ownerDocument:p});return d.card.style.minHeight="360px",r.appendChild(d.card),{card:r,destroy:()=>{n?.destroy(),d.destroy()}}}let v="hbin";const l=d=>d===void 0?ue:(v==="hbin"?i.hard:i.soft).get(d)??ue,C=e.map(d=>({dies:d.dies,hardBinCounts:d.statsSummary?.stats.hardBinCounts,softBinCounts:d.statsSummary?.stats.softBinCounts})),I=()=>ht(C,v),B={title:"Hard bin pareto",data:I(),selfControl:{current:v,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:d=>(v=d,{data:I(),title:`${v==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:d=>l(d.binCode),ownerDocument:p},Z=ge(B,T);return Z.card.style.minHeight="360px",r.appendChild(Z.card),{card:r,destroy:()=>{n?.destroy(),Z.destroy()}}}function J(){const e=p.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{...mt(),display:"flex",flexDirection:"column",gap:w.lg,minWidth:"0"}),e}function Ae(e){if(W.innerHTML="",W.style.marginBottom="0",!Te)return;const t=Ct(e.map(o=>({metadata:o.metadata})),void 0,{facetableOnly:!1});t&&(t.style.marginBottom="0",W.appendChild(t),W.style.marginBottom=w.xs)}function Ie(e,t,o,s){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const r=e.map(l=>l.wafer),i=e.map(l=>l.dies),u=e.flatMap(l=>l.dies),f=e.map(l=>l.statsSummary),g=f.every(l=>l!==void 0)?f:void 0,c=ve?.()??4,m=[],h=[],y=ut({groups:(s??[{key:"",items:e}]).map(l=>({key:l.key,items:l.items.map(C=>({dies:C.dies,testSpecYield:C.statsSummary?.stats.testSpecYield,functionalYield:C.statsSummary?.stats.functionalYield}))})),testDefs:o,onSaveImage:T,ownerDocument:p});y.card.style.minHeight="300px",m.push(y.card),h.push(y.destroy);const S=ye(i,r,c,l=>e[l].passBins,St);if(S.length){const l=we({title:"Ring yield",mode:"ring",rows:S,onSaveImage:T,ownerDocument:p});m.push(l.card),h.push(l.destroy)}const a=ye(i,r,c,l=>e[l].passBins,vt);if(a.length){const l=we({title:"Quadrant yield",mode:"quadrant",rows:a,onSaveImage:T,ownerDocument:p});m.push(l.card),h.push(l.destroy)}let n=null;if(t.length){const l=J();let C=null;const I=xt(yt(u,t,void 0,g,U,i.map(B=>({dies:B})),void 0,"full"),{onDone:B=>{C=B,l.removeAttribute("aria-busy"),B?l.replaceChildren(B):l.remove()}});if(I.done)C&&(n=l);else{const B=p.createElement("div");B.textContent="Computing test statistics\u2026",Object.assign(B.style,{color:k.label,fontSize:O.body}),l.setAttribute("aria-busy","true"),l.appendChild(B),n=l,h.push(()=>I.cancel())}}let v=null;if(o.length){const l=wt(u,o,g,U);if(l){const C=J();C.appendChild(l),v=C}}return{elements:m,testValuesCard:n,functionalCard:v,destroy:()=>{for(const l of h)l()}}}function Oe(e){const t=pe(e.map(c=>c.passBins)),o=e.length===1,s=e[0],r=J();Object.assign(r.style,{flexDirection:"row",flexWrap:"wrap",gap:w.md});const i=c=>{const m=c.lastElementChild;return m&&Object.assign(m.style,{borderRight:"none",paddingRight:"0",marginRight:"0"}),c};function u(c,m,h){const b=p.createElement("div");Object.assign(b.style,{display:"flex",alignItems:"baseline",gap:w.sm,paddingRight:w.xxl,marginRight:w.md,borderRight:`1px solid ${k.menuBorder}`});const y=p.createElement("div");y.textContent=c,Object.assign(y.style,{fontSize:O.heading,fontWeight:"700",color:k.value,lineHeight:fe.tight});const S=p.createElement("div");if(S.textContent=m,Object.assign(S.style,{fontSize:O.body,color:k.label}),b.append(y,S),h){const a=p.createElement("div");a.textContent=h,Object.assign(a.style,{fontSize:O.meta,color:k.label,opacity:Ze.muted}),b.appendChild(a)}return b}if(o){const c=z([{...s,key:s.waferIndex}],M)[0]?.percent;return c!==void 0&&r.appendChild(u(`${c.toFixed(1)}%`,`Yield \xB7 pass: ${t}`)),r.appendChild(u(String(s.dies.length),"Total dies")),i(r)}r.appendChild(u(String(e.length),"Wafers"));const f=z(e.map(c=>({...c,key:c.waferIndex})),M).map(c=>c.percent).filter(c=>Number.isFinite(c));if(f.length){const c=f.reduce((b,y)=>b+y,0)/f.length,m=he([{key:"all",items:e.map(b=>({...b,key:b.waferIndex}))}],M)[0]?.percent,h=m!==void 0&&m.toFixed(1)!==c.toFixed(1);r.appendChild(u(`${c.toFixed(1)}%`,`${He} \xB7 pass: ${t}`,h?`${m.toFixed(1)}% by dies`:void 0))}const g=e.map(c=>c.statsSummary);if(g.every(c=>c!==void 0)){const c=g.reduce((h,b)=>h+b.stats.analyzedDies,0),m=g.reduce((h,b)=>h+b.stats.excludedDies,0);r.appendChild(u(c.toLocaleString(),"Dies analysed",m?`${m.toLocaleString()} excluded`:void 0))}else r.appendChild(u(e.reduce((c,m)=>c+m.dies.length,0).toLocaleString(),"Total dies"));return i(r)}function Re(e,t,o,s,r){const i=p.createElement("div");Object.assign(i.style,{display:"flex",flexDirection:"column",gap:w.lg});const u=e.length===1&&!s;e.length&&!s&&i.appendChild(Oe(e));const f=Pe(e,s,r,!u);i.appendChild(f.card);const g=Ie(e,t,o,s);for(const c of g.elements)f.card.appendChild(c);return g.testValuesCard&&i.appendChild(g.testValuesCard),g.functionalCard&&i.appendChild(g.functionalCard),{card:i,destroy:()=>{f.destroy(),g.destroy()}}}function We(e,t,o,s){const r=V(p),i=Be(e),u=a=>n=>re(n,a()),f=a=>({...a,testStats:a.statsSummary?.stats.perTestStats}),g=e.map(f),c=o?.map(a=>({key:a.key,items:a.items.map(f)})),m=at({title:"Test value distribution",axisPrefs:H,onAxisPrefsChange:u(()=>m),onTestChange:a=>y(a),selectedTestNumber:E??void 0,items:g,testDefs:t,groups:c,groupLabelText:s,onSaveImage:T,onGroupChange:a=>Q(a),onOpen:i?.open,openActionLabel:i?.label,onWaferContextMenu:X(e),ownerDocument:p}),h=lt({title:"Value histogram",axisPrefs:H,onAxisPrefsChange:u(()=>h),onTestChange:a=>y(a),selectedTestNumber:E??void 0,items:e,testDefs:t,groups:o,onGroupChange:a=>Q(a),onSaveImage:T,ownerDocument:p}),b=st({title:"Wafer-to-wafer trend",axisPrefs:H,onAxisPrefsChange:u(()=>b),onTestChange:a=>y(a),selectedTestNumber:E??void 0,items:e.map(a=>({label:a.label,key:a.waferIndex,dies:a.dies,testStats:a.statsSummary?.stats.perTestStats})),testDefs:t,onSaveImage:T,centreLabel:Je(Xe(e.map(a=>a.wafer.metadata)),"mean"),onOpen:F?(a,n)=>K(a,`Wafer ${e.find(v=>v.waferIndex===a)?.label??a}`,n):void 0,onWaferContextMenu:X(e),ownerDocument:p}),y=a=>{E=a,m.setTest(a),h.setTest(a),b.setTest(a),S.setTest(a)};q.set("distribution",[m,h,b]);const S=ot({title:"Process capability",items:e,testDefs:t,onSaveImage:T,selectedTestNumber:E??void 0,onSelectTest:a=>y(a),ownerDocument:p});return r.append(S.card,m.card,h.card,b.card),{card:r,destroy:()=>{S.destroy(),m.destroy(),h.destroy(),b.destroy()}}}function je(e){const t=V(p),o=de(e).defs,s=e.flatMap(f=>f.dies),r=x.sweeps??[],i=r.filter(f=>!it(f,o));i.length>0&&t.appendChild(Me(i,r.length));const u=r.map(f=>rt({spec:f,dies:s,testDefs:o,onSaveImage:T,ownerDocument:p}));for(const f of u)t.appendChild(f.card);return{card:t,destroy:()=>{for(const f of u)f.destroy()}}}function Me(e,t){const o=p.createElement("div");o.setAttribute("role","status"),Object.assign(o.style,{gridColumn:"1 / -1",display:"flex",flexWrap:"wrap",alignItems:"center",gap:w.md,padding:`${w.sm} ${w.md}`,background:k.warnBg,border:`1px solid ${k.warnBorder}`,borderRadius:me.container,color:k.warnText,fontSize:O.body,lineHeight:fe.base});const s=e.length,r=p.createElement("span");if(r.style.flex="1 1 24ch",r.textContent=(s===t?s===1?"This sweep names no test in this data":"None of these sweeps names a test in this data":`${s} of ${t} sweeps name no test in this data: ${e.map(i=>i.title).join(", ")}`)+` \u2014 ${s===1?"it":"they"} may belong to another test program.`,o.appendChild(r),x.onRemoveSweeps){const i=p.createElement("button");i.type="button",Object.assign(i.style,be("outlined")),i.textContent=s===1?"Remove this sweep":`Remove these ${s} sweeps`,ne(i);const u=e.map(f=>f.id);i.addEventListener("click",()=>x.onRemoveSweeps(u)),o.appendChild(i)}return o}function Ye(e,t,o){const s=V(p),r=ct({title:"Test scatter",items:e,testDefs:t,groups:o,binColors:oe().hard,onSaveImage:T,axisPrefs:H,onAxisPrefsChange:u=>re(u,r),ownerDocument:p});q.set("correlation",[r]);const i=dt({title:"Test correlation matrix",items:e,testDefs:t,onSaveImage:T,onSaveText:U,onSelectPair:(u,f)=>r.setXY(u,f),ownerDocument:p});return s.append(i.card,r.card),{card:s,destroy:()=>{i.destroy(),r.destroy()}}}function _(e){e?.keepSections||ie(),G.innerHTML="",$.innerHTML="",x.backTab&&$.appendChild(Le(x.backTab));for(const n of De)$.appendChild(Ee(n.key,n.label));const t=$e();Ae(t);const o=Fe(t,{facetableOnly:!0}).filter(n=>n.splittable),s=p.createElement("div");Object.assign(s.style,{display:"flex",gap:w.md,alignItems:"center",marginLeft:w.xxl,paddingBottom:w.xs});let r;o.length>0?(s.appendChild(bt("Group by:",[{value:"",label:"None"},...o.map(n=>({value:n.key,label:`${n.label} (${n.values.length})`}))],j??"",n=>{j=n||void 0,L=null,_()},{hook:"group-by",ownerDocument:p})),r=o.find(n=>n.key===j)?.label):j=void 0;let i;if(j){const n=new Map,v=[];for(const l of t){const C=Ne(l.metadata,j)??_e;n.has(C)||(n.set(C,[]),v.push(C)),n.get(C).push(l)}i=v.map(l=>({key:l,items:n.get(l)}))}L!==null&&!i?.some(n=>n.key===L)&&(L=null),i&&i.length>0&&s.appendChild(gt(i.map(n=>n.key),"Show:",L,n=>Q(n),{ownerDocument:p}).el);let u=null;if(x.onOpenGuide){const n=p.createElement("button");n.type="button",n.innerHTML=nt.help,n.setAttribute("aria-label","User guide"),Object.assign(n.style,{...be("bare"),display:"inline-flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",flexShrink:"0"}),ne(n,"bare"),tt(n,"User guide"),n.addEventListener("click",()=>x.onOpenGuide()),Object.assign(n.style,{marginLeft:"auto"}),u=n}$.appendChild(s),u&&$.appendChild(u);const f=L!==null?i?.find(n=>n.key===L):void 0,g=f?.items??t,c=f?void 0:i,m=de(g),h=m.defs,b=h.filter(Ve);E!==null&&!b.some(n=>n.testNumber===E)&&(E=null);const y=e?.keepSections?N.get(P):void 0,S=y??(P==="overview"?Re(g,b,h,c,r):P==="distributions"?We(g,b,c,r):P==="sweeps"?je(g):Ye(g,b,c));y||N.set(P,S);const a=m.conflicts.filter(n=>n.excluded);if(a.length>0){const n=p.createElement("div");Object.assign(n.style,{color:k.label,fontSize:O.body,padding:`0 ${Y} ${w.sm}`});const v=a.slice(0,6).map(I=>I.testNumber).join(", "),l=a.length>6?`, and ${a.length-6} more`:"",C=a.length===1?"it":"them";n.textContent=`${a.length} test ${a.length===1?"number is":"numbers are"} hidden (${v}${l}) \u2014 the wafers in view describe ${C} differently, so their values cannot be pooled. `+(i&&i.length>0?`Pick one ${r??"group"} under "Show:" to analyse ${C}.`:"Load one test program at a time to analyse them."),n.dataset.wmapWithheldTests=String(a.length),G.appendChild(n)}G.appendChild(S.card)}return{el:R,render:_,destroy:()=>{ie(),R.remove()}}}
@@ -1 +1 @@
1
- import{getUniqueTestNumbers as Mo,resolveTestNumber as Do,findTestDef as ko,collectMetadataValues as Eo}from"../renderer/buildView.js";import{metadataCategoricalValue as Bo}from"../core/metadata.js";import{resolveBinColorsForMaps as Oo,mergeBinDefs as Ye,binColorWarning as To,mixedPassBinsWarning as Lo,binColorsEqual as Ro}from"../renderer/binColors.js";import{itemPassBins as Io,INPUT_DEFAULT_PASS_BINS as Wo}from"../core/passBins.js";import{NO_DATA_FILL as $o}from"../renderer/colorMap.js";import{metadataValueColor as Ao}from"../renderer/colorMap.js";import{resolveCanvasTheme as Po}from"./canvasTheme.js";import{ICONS as We}from"./icons.js";import{SHADOW as $e,LEADING as Ze,TRACKING as Fo,controlStyle as Ho,wireControlHover as xt,SPACE as w,EDGE_GUTTER as oe,MAP_CHROME_INSET as jo,RADIUS as z,FONT as L,CLR as h,sevColor as gn,MODE_LABELS as Vo,BIN_LEGEND_MODES as hn,STACKED_MODES as be,Z_ABOVE as bn,applyOverlayZ as No,getTooltip as zo,hideTooltip as yn,createToolbarHelpers as _o,buildModeMenuEl as Go,openDetachWindow as Ko,openFloatingWindow as qo,openModal as Uo,openReportModal as Xo,copyWmapThemeTokens as Yo,syncWmapPopupTheme as Zo,openUserGuideWindow as Qo,makePaletteBtn as Jo,makeLogScaleBtn as ei,makeLegendStyleBtn as ti,makeOverlaysBtn as ni,makeOrientationBtn as oi,menuLayerFor as wn,saveImageBlob as ii,markMenuTrigger as Ae,wireMenuA11y as vn,wireExpandToggle as xn,wireTooltip as Cn,requestedPassFailDisplay as Sn,overlayMenuRows as ai,anyOverlayActive as li,logWmapVersionOnce as si,buildDataModeEntries as ri,metadataKeyHasData as di,metadataModeEntry as ci}from"./toolbar.js";import{waferDisplayLabel as Qe,waferIdentityLabel as Mn}from"../core/waferLabel.js";import{metadataDisplayValue as ui}from"../core/metadata.js";import{withExportContext as fi}from"./exportName.js";import{sortBinsForDisplay as pi}from"../stats/binPareto.js";import{diePassStatus as mi}from"../core/dies.js";import{aggregateValues as gi,aggregateBinCounts as Dn}from"../core/aggregates.js";import{renderWaferMap as hi,renderWaferMapCard as kn,toPublicViewOptions as En}from"./renderWaferMap.js";import{hasDrilldownTargets as bi,waferPopulation as yi}from"./chartPopulation.js";import{classifyChanged as wi,COLOR_KEYS as vi}from"./renderWaferMap.js";import{buildWaferMap as xi,getTestPassStatus as Bn,isParametricTest as Ct,getDieTestValue as Ci}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Je}from"../stats/analyzeWaferMap.js";import{collectWarnings as Si,buildWarningsMenuEl as Mi,severityOf as Di}from"./warnings.js";import{compareNatural as St,arrayEqual as On}from"../core/utils.js";import{createSummaryPanelEl as Mt,buildMetadataStripRow as ki,buildCompactMetadataRows as Tn,metadataEntries as Ln,renderLotSummaryContentSteps as Ei,reportMapsFromItems as Bi}from"./summaryPanel.js";import{renderLotReportHtml as Oi}from"../stats/renderSummaryReport.js";import{prettyKey as Ti}from"../stats/facets.js";import{testLabel as Li,markedTestLabel as Ri,derivedFields as Ii}from"../renderer/testLabel.js";import{mergeTestDefs as Wi}from"../stats/mergeTestDefs.js";import{getDieKey as $i,hasPosition as Ai}from"../core/dies.js";import{runChunked as Pi}from"./chunked.js";function Rn(f){if(typeof f!="number"||!Number.isFinite(f))return;const C=Math.round(f);return C>=1?C:void 0}const Dt=12;function Fi(f,C,p){let A=C;if(C.length>Dt){const k=C.slice(0,Dt-1),I=C.slice(Dt-1),H=I.reduce((X,ie)=>X+ie.count,0);A=[...k,{color:h.label,count:H,label:`Other (${I.length} bins)`}]}const D=f.createElement("div");Object.assign(D.style,{display:"flex",columnGap:"1px",width:"100%",height:"8px",borderRadius:z.control,overflow:"hidden",border:`1px solid ${h.menuBorder}`,boxSizing:"border-box",marginTop:w.xs,flexShrink:"0"}),D.setAttribute("role","img"),D.setAttribute("aria-label",`Population split: ${A.map(k=>`${k.label} ${et(k.count/p*100)}`).join(", ")}`);for(const k of A){const I=k.count/p*100,H=f.createElement("div");Object.assign(H.style,{flex:`${I} 1 0`,minWidth:I>0?"2px":"0",background:k.color}),Cn(H,`${k.label} \xB7 ${k.count.toLocaleString()} dies \xB7 ${et(I)}`),D.appendChild(H)}return D}function et(f){return f>0&&f<.1?"<0.1%":`${f.toFixed(1)}%`}function In(f,C,p){const A=new Map;let D=0,k=0;for(const I of f){const H=p?new Set(p(I)):void 0;for(const X of I.dies){if(X.partial||X.edgeExcluded)continue;const ie=C(X);ie!==void 0&&(A.set(ie,(A.get(ie)??0)+1),D++,H&&mi(X,H)&&k++)}}return{counts:A,total:D,pass:k}}function Wn(f,C){const p=f.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:`${w.xxs} ${w.xs}`,borderRadius:z.control});const A=f.ownerDocument.createElement("span");Object.assign(A.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:C.color,border:C.isActive?`2px solid ${h.iconActive}`:`1px solid ${h.menuBorder}`,borderRadius:z.control,boxSizing:"border-box"});const D=f.ownerDocument.createElement("span");if(D.textContent=C.label,Object.assign(D.style,{fontWeight:C.isActive?"700":"400",color:C.isActive?h.iconActive:h.text,whiteSpace:"nowrap"}),p.appendChild(A),p.appendChild(D),C.count!==void 0){const k=f.ownerDocument.createElement("span");if(k.textContent=C.count.toLocaleString(),Object.assign(k.style,{color:C.isActive?h.iconActive:h.text,fontWeight:C.isActive?"700":"400",whiteSpace:"nowrap"}),p.appendChild(k),C.percent!==void 0){const I=f.ownerDocument.createElement("span");I.textContent=et(C.percent),Object.assign(I.style,{color:h.label,whiteSpace:"nowrap"}),p.appendChild(I)}}p.setAttribute("role","button"),p.setAttribute("aria-pressed",C.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=h.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=h.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",C.onClick),p.addEventListener("keydown",k=>{(k.key==="Enter"||k.key===" ")&&(k.preventDefault(),C.onClick())}),f.appendChild(p)}export function renderWaferGallery(f,C,p={}){si();const A=6;let D=Rn(p.columns);const k=p.showHelpButton??!1,I=p.userGuideExtension,H=p.insights?.enabled??!1,X=p.insights?.sweeps?{sweeps:p.insights.sweeps}:void 0,ie=No(p.zIndex),re=p.summaryPanel,$n=e=>[...Io(e)],kt=()=>v.flatMap(e=>e?[e.ringCount??4]:[]),tt=()=>kt()[0]??4;function An(e){const t=[...new Set(e)].sort((n,o)=>n-o);return t.length<2?null:{code:"ring-count-mixed",severity:"warning",message:`These wafers were built with different ring counts (${t.join(", ")}). Each card and each wafer's findings use their own; the lot's ring yield in the Summary panel, report and Insights uses ${e[0]} rings.`}}let V=p.lotStatsSummary,ye=p.viewOptions?.legendPosition??"default",Pe=p.perCardLegend??!1;function we(){const e=c.plotMode??"hardBin";return hn.has(e)?null:c.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"These wafers have no shared colour bar for value mode, so each map keeps its own"}function Et(){const e=Pe||we()!==null;for(const t of S)t&&t.setOptions({showLegend:e})}let c={plotMode:"hardBin",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},S=[],ae=[],de=[],R=[];const Fe=fi(()=>{const e=R.filter(n=>n!=null),t=[...new Set(e.map(n=>ui(n.wafer.metadata?.lot)).filter(n=>n!==void 0))].sort(St);return{prefix:p.downloadFilename,lots:t,...e.length===1?{wafer:Mn(e[0])}:{waferCount:e.length}}},p.onSaveImage,p.onSaveText);let v=C.map(e=>typeof e=="function"?null:e);function Bt(){return Wi(v)}function ve(){if(v.some(e=>e?.testDefs?.length))return Bt().defs}let xe=0,He=0;const _=new Map;let Pn=0,P=null,Ce=null,Ot=new Set,b=null,Fn={};function Tt(e){return v[e]?.statsSummary??V?.perWafer.find(t=>t.waferIndex===e)?.summary}function nt(){return!!(v.some(e=>e?.statsSummary?.findings.length)||V?.perWafer.some(e=>e.summary.findings.length))}const Hn=zo(),ce=_o(Hn),{makeBtn:Q,setActive:Se,makeSep:G,makeMenuRow:jn,makeMenuSection:Vn,makeDropdown:Lt,closeOpenMenu:je,getOpenMenu:Me,setOpenMenu:De}=ce;f.ownerDocument.addEventListener("click",je,!0);const Rt=()=>yn();window.addEventListener("blur",Rt);let It=p.findingsNotice;function Wt(e){Ot=new Set(e);const t=[...$.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,d)=>{const l=Ot.has(d);o.style.outline=l?`3px solid ${h.findingHighlight}`:"",o.style.outlineOffset=l?"-3px":"",l&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function $t(){Wt([])}function At(){for(const e of S)e&&e.clearSelection()}function ot(e,t){const n=new Set(e),o=t??S.map((d,l)=>l);for(const d of o){const l=R[d],a=S[d];if(!l||!a)continue;const r=l.dies.filter(i=>n.has($i(i)));a.setSelection(r)}}function Nn(){const e=[];for(let t=0;t<v.length;t++){const n=v[t];if(!n)continue;const o=Tt(t)?.findings??[];o.length&&e.push({index:t,item:n,unusualCount:o.filter(d=>d.severity==="unusual").length,notableCount:o.filter(d=>d.severity==="notable").length,totalCount:o.length})}return e}function zn(e){const t=R[e]??v[e];t&&Ie(e,t)}function _n(e){const t=Tt(e)?.findings??[];if(t.length)return{total:t.length,unusual:t.filter(n=>n.severity==="unusual").length,notable:t.filter(n=>n.severity==="notable").length}}function Gn(){Xo(Oi(Bi(v,Wo,tt())),{anchor:f})}function Kn(){if(!b)return;b.innerHTML="";const e=Nn();if(v.length>0){const n=f.ownerDocument.createElement("div"),o=e.length,d=v.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${d} wafers`:`${o} of ${d} wafer${d===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:L.body,color:h.label,marginBottom:w.md}),b.appendChild(n)}if(e.length>0){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent="Summary report",Object.assign(n.style,{...Ho("outlined"),marginBottom:w.lg,display:"block",width:"100%",textAlign:"left"}),xt(n),n.addEventListener("click",Gn),b.appendChild(n)}if(e.length===0){const n=f.ownerDocument.createElement("div");Object.assign(n.style,{color:h.icon,fontSize:L.body,padding:"4px 0"}),n.textContent="No findings on any wafer.",b.appendChild(n)}else for(const{index:n,item:o,unusualCount:d,notableCount:l,totalCount:a}of e){const r=d?"unusual":l?"notable":"info",i=d+l||a,s=f.ownerDocument.createElement("button");s.type="button",Object.assign(s.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:w.xs,border:"none",borderLeft:`3px solid ${gn(r)}`,borderRadius:z.control,background:h.bgHover,cursor:"pointer",fontSize:L.body,textAlign:"left",boxSizing:"border-box"}),s.addEventListener("mouseover",()=>{s.style.background=h.bgActive}),s.addEventListener("mouseout",()=>{s.style.background=h.bgHover});const u=f.ownerDocument.createElement("span");u.textContent=Qe(o,n),Object.assign(u.style,{color:h.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const m=f.ownerDocument.createElement("span");m.textContent=String(i),s.setAttribute("aria-label",`${Qe(o,n)} \u2014 ${i} finding${i===1?"":"s"}${d?`, ${d} unusual`:""} \u2014 view wafer`),Object.assign(m.style,{marginLeft:w.sm,flexShrink:"0",background:gn(r),color:"#fff",borderRadius:z.container,padding:"1px 5px",fontSize:L.body,fontWeight:"600"}),s.appendChild(u),s.appendChild(m),s.addEventListener("click",()=>Ie(n,o)),b.appendChild(s)}const t=f.ownerDocument.createElement("div");t.style.height="12px",b.appendChild(t)}let ue=null,ke=null;function N(){if(b)if(ue?.cancel(),ue=null,V){const e=Ye(v.map(n=>n?.hbinDefs)),t=Ye(v.map(n=>n?.sbinDefs));ue=Pi(Ei(b,{lotSummary:V,items:v,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:ve(),ringCount:tt(),binColors:c.binColors,plotMode:c.plotMode??"hardBin",fallbackFormat:c.fallbackFormat,activeFindingId:Ce,warnings:p.warnings?.display??!0?J:[],findingsFilter:Fn,findingsNotice:It,onFindingsFilterChange:N,onSaveText:Fe.onSaveText,onFindingClick:(n,o)=>{Ce===n.id?it():Un(n,o),N()},onWaferClick:zn,findingsFor:_n,dieListOptions:p.dieList}),{onDone:()=>{const n=ke;ke=null,n?.()}})}else Kn()}function qn(e){const t=e.highlight;return t?.kind==="wafer"&&t.waferIndices?.length?t.waferIndices:null}function Pt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}let Ve=[];function Ft(){if(Ve.length!==0){for(const e of Ve)S[e]?.setOptions({plotMode:c.plotMode,activeTest:c.activeTest});Ve=[]}}function it(){Ce=null,$t(),At(),Ft(),T({highlightBin:void 0},{fireCallback:!1})}function Un(e,t){if(Ce===e.id){it();return}Ce=e.id,t.style.background=h.bgActive,t.style.fontWeight="600",Ft();const{kind:n,index:o}=e.variable;if(n==="test"){const l=o??0,a=ve();if(a===void 0||a.some(i=>i.testNumber===l))T({plotMode:"value",activeTest:l,highlightBin:void 0},{fireCallback:!1});else{T({highlightBin:void 0},{fireCallback:!1});const s=be.has(c.plotMode??"hardBin")?null:qn(e);if(s){for(const u of s)S[u]?.setOptions({plotMode:"value",activeTest:l});Ve=[...s]}}}else n==="softBin"?T({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):T({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1});$t(),At();const d=e.highlight;if(d.kind==="wafer"){Wt(d.waferIndices);const l=Pt(e);for(const a of d.waferIndices){const s=R[a]?.statsSummary?.findings.find(u=>Pt(u)===l)?.highlight?.dieKeys;s?.length&&ot(s,[a])}}else d.kind==="bin"?d.dieKeys?.length&&ot(d.dieKeys):(d.kind==="region"||d.kind==="dies")&&d.dieKeys?.length&&ot(d.dieKeys)}function le(){if(!P)return;const e=!!b;P.style.display=(V||nt())&&e&&!Te?"flex":"none";const t=b?b.style.display!=="none":!1;(V?.hasNotableFindings||v.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?P.style.color=h.findingIndicator:P.dataset.active||(P.style.color=h.icon)}const W=f.ownerDocument.createElement("div");W.dataset.wmapToolbar="gallery",Object.assign(W.style,{flexShrink:"0",marginLeft:"auto",display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:h.menuBg,border:`1px solid ${h.menuBorder}`,borderRadius:z.control,padding:"0",boxShadow:$e.panel,flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const Ht=()=>{const e=Me();e&&(e.remove(),De(null)),Ae(Y,!1)},Y=Q("mode","Plot mode",()=>{if(Me()){Ht();return}const e=v.flatMap(y=>y?.dies??[]),t=ve(),{testEntries:n,binEntries:o,stackedEntries:d}=ri(e,t,{includeStacked:!0}),l=v.filter(Boolean).length,a=y=>{if(y===void 0)return l;let B=0;for(const j of v)j?.dies?.some(U=>Bn(U,y)!==void 0||U.testValues?.[y]!==void 0)&&B++;return B},r=l<2?n:n.map(y=>{const B=a(y.activeTest);return B===l?y:{...y,label:`${y.label} \u2014 ${B} of ${l} wafers`}}),i=c.plotMode??"hardBin",s=c.activeTest??0;function u(y){return y.plotMode!==i?!1:y.plotMode==="value"?s===(y.activeTest??0):y.plotMode==="metadata"?c.activeMetadataKey===y.activeMetadataKey:!0}function m(y,B){y.activeTest!==void 0?T({plotMode:"value",activeTest:y.activeTest,activeMetadataKey:void 0,logScale:y.logScale}):y.activeMetadataKey!==void 0?T({plotMode:y.plotMode,activeTest:void 0,activeMetadataKey:y.activeMetadataKey,passFailDisplay:"off"}):T({plotMode:y.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),B.remove(),De(null),Ae(Y,!1)}const M=new Set,E=v.flatMap(y=>y?.metadataFields??[]).filter(y=>!M.has(y.key)&&M.add(y.key)).filter(y=>di(e,y.key)).map(ci),x=Go(Y.getBoundingClientRect(),r,o,d,u,m,{makeMenuRow:jn,makeMenuSection:Vn},i,Y.ownerDocument.defaultView??window,E);wn(Y).appendChild(x),De(x),Ae(Y,!0),vn(x,Y,Ht)});Ae(Y,!1);const Xn=()=>R.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:Yn,sync:jt}=Jo(ce,()=>({...c,plotMode:c.plotMode??"hardBin"}),Xn,e=>T(e));jt();const Zn=C.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Ne(){const e=ve(),{testNumber:t}=Do(c.activeTest??0,e);return{testNumber:t,td:ko(e,t)}}function Vt(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=Ne();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function Ee(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=Ne();return e!==void 0&&!Ct(e)}function Qn(){if((c.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Ne();return v.some(n=>n?.dies?.some(o=>Bn(o,e,t)!==void 0))}function Jn(e,t){if(!t||!Ct(t))return;const n=t.limitLow!==void 0||t.limitHigh!==void 0;if((Sn(c)==="spec"&&n?"spec":c.colorbarRangeMode??"spec")==="spec"&&n)return;let l=1/0,a=-1/0;for(const r of v)if(r)for(const i of r.dies){const s=Ci(i,e);s!==void 0&&(s<l&&(l=s),s>a&&(a=s))}if(isFinite(l))return l===a?[l,l+1]:[l,a]}function at(e,t,n){const o=c[e];if(o===t||o!=null&&t!=null&&n(o,t))return!1;c={...c,[e]:t};for(const d of S)d&&d.setOptions({[e]:t});return!0}function Nt(){if((c.plotMode??"hardBin")!=="metadata")return;const e=c.activeMetadataKey;if(!e)return;const t=new Set;for(const n of v)if(n)for(const o of Eo(n.dies,e))t.add(o);return{key:e,values:[...t].sort(St)}}function lt(){at("metadataValueOrder",Nt(),(e,t)=>e.key===t.key&&On(e.values,t.values))}function st(){if((c.plotMode??"hardBin")!=="value")return;const{testNumber:e,td:t}=Ne(),n=Jn(e,t);at("valueRange",n?{test:e,range:n}:void 0,(d,l)=>{const a=s=>Array.isArray(s)?{test:void 0,range:s}:{test:s.test,range:s.range},r=a(d),i=a(l);return r.test===i.test&&On(r.range,i.range)})}let rt=!1;function eo(){if(rt)return;rt=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{rt=!1,st(),lt(),_t()})}let dt=!1;function to(){if(dt)return;dt=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{dt=!1,qe()})}let zt=[];function fe(){const{colors:e,mixedHardBins:t}=Oo(v.filter(n=>n!=null),{binColorScheme:c.binColorScheme,useDefinedBinColors:c.useDefinedBinColors});return zt=t,e}function _t(){at("binColors",fe(),Ro),Be()}const no=ni(ce,()=>ai(c,Zn,{functionalActive:Ee(),hasLimits:Vt()&&!Ee(),hasRecorded:Qn()&&!Ee(),binMode:(c.plotMode??"hardBin")==="hardBin"||(c.plotMode??"hardBin")==="softBin"},e=>T(e)),()=>li(c)),{btn:oo,sync:Gt}=ti(ce,()=>({plotMode:c.plotMode,legendPosition:ye}),e=>{ye=e;for(const t of S)t&&t.setOptions({legendPosition:ye})},{get:()=>Pe,set:e=>{Pe=e,Et()},blockedReason:we});Gt();const io=[{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"}],Kt=Lt("aggr","Aggregation method",()=>io,()=>c.aggregationMethod??"mean",e=>T({aggregationMethod:e}));function qt(){const e=c.plotMode==="stackedValues";Kt.style.display=e?"":"none"}qt();const{btn:ao,sync:Ut}=ei(ce,()=>({...c,functionalActive:Ee()}),e=>T(e));Ut();const ze=Q("specRange","Colorbar range: test limits",()=>{const e=c.colorbarRangeMode==="data"?"spec":"data";T({colorbarRangeMode:e})});function Xt(){const e=(c.plotMode??"hardBin")==="value"&&Vt()&&Sn(c)==="off"&&!Ee();ze.style.display=e?"":"none";const t=(c.colorbarRangeMode??"spec")==="spec";Se(ze,t),ze.ariaLabel=t?"Colorbar range: test limits (click for data range)":"Colorbar range: data range (click for test limits)"}Xt();const lo=oi(ce,()=>c,e=>T(e)),so=Q("downloadAll","Download gallery PNG",xo),ro=Lt("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"}],()=>D!=null?String(D):"auto",e=>ln(e==="auto"?void 0:Number(e))),O=f.ownerDocument.createElement("div");Object.assign(O.style,{display:"inline-flex",alignItems:"center",gap:"0"}),W.appendChild(O),O.appendChild(Y),O.appendChild(Yn),O.appendChild(Kt),O.appendChild(ao),O.appendChild(ze),O.appendChild(G()),O.appendChild(no),O.appendChild(G()),O.appendChild(oo),O.appendChild(G()),O.appendChild(lo),O.appendChild(G()),O.appendChild(ro),O.appendChild(G()),O.appendChild(so),(V||nt())&&(P=Q("findings","Summary panel",()=>{if(!b)return;const e=b.style.display!=="none";e||N(),b.style.display=e?"none":"flex",Se(P,!e),le()}),W.appendChild(G()),W.appendChild(P));let K=null,_e=null,J=[],Yt=!1;function Be(){const e=Si({lotStatsSummary:V,result:{warnings:[...v.flatMap(n=>n?.warnings??[]),...Bt().warnings]},extra:[c.binColors&&To(c.binColors,c.plotMode),Lo(zt),An(kt())].filter(n=>!!n)}),t=e.length!==J.length||e.some((n,o)=>n.code!==J[o]?.code||n.message!==J[o]?.message);J=e,(t||!Yt)&&(Yt=!0,p.warnings?.onWarning?.(e)),co()}function co(){if(!K||!_e)return;const e=J.length,t=e>0;if(K.style.display=t?"flex":"none",_e.style.display=t?"":"none",!t)return;const n=Di(J[0]),o=`${e} data ${e===1?"warning":"warnings"}`;K.style.color=n==="error"?h.errText:h.warnText,K.ariaLabel=n==="error"?`${o} \u2014 some wafers may be positionally wrong`:o}(p.warnings?.display??!0)&&(_e=G(),K=Q("warning","Data warnings",()=>{const e=Me();if(je(new MouseEvent("click")),e)return;const t=Mi(K.getBoundingClientRect(),J,K.ownerDocument.defaultView??window);wn(f).appendChild(t),De(t),vn(t,K,()=>je(new MouseEvent("click")))}),Ae(K,!1),W.appendChild(_e),W.appendChild(K)),Be();let se=null;H&&(se=Q("analysis","Insights",()=>{Jt(!Te)}),se.dataset.wmapInsightsBtn="1",W.appendChild(G()),W.appendChild(se));function Zt(){import("./userGuideHtml.js").then(e=>Qo({buildWaferMap:xi,renderWaferMap:hi,renderWaferGallery,analyzeWaferMap:Je},e.USER_GUIDE_HTML,I,f))}k&&(W.appendChild(G()),W.appendChild(Q("help","User guide",()=>Zt())));const pe=f.ownerDocument.createElement("div");pe.dataset.wmapGalleryMeta="1",Object.assign(pe.style,{flex:"1",minWidth:"0",overflow:"hidden",display:"flex",alignItems:"center",padding:`${w.sm} ${w.lg}`,fontSize:L.sub,lineHeight:Ze.none,boxSizing:"border-box"});const Ge=f.ownerDocument.createElement("div");Object.assign(Ge.style,{background:h.canvasBg,display:"flex",alignItems:"stretch",gap:w.lg,paddingBottom:w.lg,minWidth:"0"});const ee=f.ownerDocument.createElement("div");ee.dataset.wmapGalleryLegend="1",Object.assign(ee.style,{display:"flex",flexDirection:"column",gap:w.sm,background:h.menuBg,border:`1px solid ${h.menuBorder}`,borderRadius:z.container,padding:`${w.sm} ${w.lg}`,marginBottom:w.lg,boxShadow:$e.panel,fontSize:L.body,lineHeight:Ze.none,boxSizing:"border-box",width:"100%",minWidth:"0"});const q=f.ownerDocument.createElement("div");Object.assign(q.style,{display:"flex",flexDirection:"row",alignItems:"flex-start"});let me=null,Oe=null,Qt=null;function uo(){return H?me?Promise.resolve(me):(Qt??=import("./insightsTab.js").then(({createInsightsTab:e})=>(me=e({getItems:()=>v,getLotStats:()=>V,getBinColors:()=>c.binColors??fe(),getRingCount:tt,defaultView:p.insights?.defaultView,sweeps:p.insights?.sweeps,onRemoveSweeps:p.insights?.onRemoveSweeps,onOpenGuide:void 0,showMetadataStrip:!1,onSaveImage:Fe.onSaveImage,onSaveText:Fe.onSaveText,ownerDocument:f.ownerDocument,openWafer:(t,n,o)=>{const d=v[t];if(!d)return;let l=null;const a=Uo({title:n,onClose:()=>l?.destroy(),anchor:f});dn(a,n,d.wafer.metadata??void 0),l=ht(a.contentWrap,d,o)}}),Oe=me.el,Oe.style.display="none",f.appendChild(Oe),me)),Qt):Promise.resolve(null)}let Te=!1;function Jt(e){H&&(Te=e,Oe&&(Oe.style.display=e?"flex":"none"),q.style.display=e?"none":"flex",O.style.display=e?"none":"inline-flex",W.style.display="inline-flex",se&&(Se(se,e),se.innerHTML=e?We.wafer:We.analysis,se.ariaLabel=e?"Back to gallery view":"Insights"),le(),qe(),e&&uo().then(t=>{!t||!Te||(t.el.style.display="flex",t.render())}))}H&&p.insights?.defaultOpen&&queueMicrotask(()=>Jt(!0));const fo=4,ct=240,en=480,po=720,mo=1.25;let ge=en;function tn(e){const t=A*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const d=o.dies[0].width;if(!(d>0))continue;const l=o.wafer.radius*2*(fo/d),a=Math.ceil(l+t);(n==null||a>n)&&(n=a)}return n}function go(e){const t=tn(e);return t==null?ct:Math.min(ge,Math.max(ct,t))}function ho(e){const t=tn(e);if(t==null)return!1;const n=Math.min(po,Math.max(en,t));return n<=ge?!1:(ge=n,!0)}function ut(){return D!=null?"none":`${ge}px`}function nn(){const e=ut();for(const t of Array.from($.children))t.classList.contains("wmap-gallery-card")&&(t.style.maxWidth=e,t.style.maxHeight=e)}let Ke=ct,on=0;function an(e){if(ho(e)&&nn(),D==null){const n=go(e);n>Ke&&(Ke=n)}pt()}function ln(e){D=Rn(e),nn(),pt()}function ft(e){return`repeat(${e}, minmax(0, ${D!=null?"1fr":`${ge}px`}))`}function sn(e){$.style.gridTemplateColumns!==e&&($.style.gridTemplateColumns=e)}function pt(){if(D!=null){sn(ft(D));return}const e=Math.max(1,on),t=12,n=$.clientWidth||0,o=l=>(n-t*(l-1))/l;let d=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const l=Math.min(ge,Ke*mo),a=r=>{let i=0;for(;i<e&&o(i+1)>=r;)i++;return i};d=a(l)||a(Ke)||1}sn(ft(d))}const $=f.ownerDocument.createElement("div");if(Object.assign($.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:ft(1),gap:w.xl,paddingLeft:oe,paddingRight:oe,justifyContent:"start",alignContent:"start",isolation:"isolate"}),re?.placement){const e=re.placement;b=Mt(e,oe,f.ownerDocument),b.style.maxHeight="calc(100vh - 80px)",b.style.position="sticky",b.style.top="8px",b.style.display="flex",b.style.flexDirection="column"}else if(V||nt()){const e=!!re?.defaultOpen;b=Mt("right",oe,f.ownerDocument),b.style.maxHeight="calc(100vh - 80px)",b.style.position="sticky",b.style.top="8px",b.style.flexDirection="column",b.style.display=e?"flex":"none",N()}le(),b?.style.display!=="none"&&P&&Se(P,!0),(re?.placement??"right")==="left"?(b&&q.appendChild(b),q.appendChild($)):(q.appendChild($),b&&q.appendChild(b));const Le=f.ownerDocument.createElement("div");Object.assign(Le.style,{position:"sticky",top:"0",display:"flex",flexDirection:"column",paddingLeft:oe,paddingRight:oe,paddingTop:oe,zIndex:"1",background:h.menuBg}),Ge.appendChild(pe),Ge.appendChild(W),Le.appendChild(Ge),Le.appendChild(ee),f.appendChild(Le),f.appendChild(q);function qe(){ee.innerHTML="";const e=c.plotMode??"hardBin",t=!Te&&hn.has(e),n=R.filter(g=>g!=null),o=n.find(g=>g.isLotStack),d=ki(n.map(g=>({metadata:g.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),l=e==="metadata",a=c.activeMetadataKey,r=t&&!l?In(n,g=>(e==="softBin"?g.sbin:g.hbin)??void 0,$n):{counts:new Map,total:0,pass:0},i=t&&!l?c.binColors??fe():void 0,s=i?e==="softBin"?i.pass.soft:i.pass.hard:new Set,u=pi(r.counts.entries(),s).map(([g])=>g),m=t&&l&&a?In(n,g=>Bo(g.metadata?.[a])):{counts:new Map,total:0,pass:0},M=l?Nt()?.values:void 0,E=t&&l?(M??[...m.counts.keys()].sort(St)).filter(g=>m.counts.has(g)):[];if(pe.innerHTML="",d&&pe.appendChild(d),pe.style.display=d?"flex":"none",!u.length&&!E.length){ee.style.display="none";return}ee.style.display="flex";const x=f.ownerDocument.createElement("div");Object.assign(x.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:`${w.sm} ${w.xl}`,maxHeight:"86px",overflowY:"auto",overflowX:"hidden"}),ee.appendChild(x);const y=c.highlightBin,B=R.flatMap(g=>g?.metadataFields??[]).find(g=>g.key===a),j=l?B?.label??(a?Ti(a):"Metadata"):Vo[e],U=f.ownerDocument.createElement("span");if(U.textContent=j,Object.assign(U.style,{fontSize:L.body,fontWeight:"700",letterSpacing:Fo,textTransform:"uppercase",color:h.label,flexShrink:"0"}),x.appendChild(U),!l&&r.total>0){const g=r.pass,F=g/r.total*100,te=f.ownerDocument.createElement("span");te.textContent=`Yield ${et(F)}`,Object.assign(te.style,{fontSize:L.body,fontWeight:"700",color:h.value,whiteSpace:"nowrap",flexShrink:"0"});const ne=f.ownerDocument.createElement("span");ne.textContent=`${g.toLocaleString()} / ${r.total.toLocaleString()} dies`,Object.assign(ne.style,{fontSize:L.body,color:h.label,whiteSpace:"nowrap",flexShrink:"0"}),x.appendChild(te),x.appendChild(ne)}if(l){const g=c.highlightMetadataValue;E.forEach((F,te)=>{const ne=g===F,Xe=B?.values?.find(vt=>vt.value===F),So=Xe?.color??Ao(te),mn=m.counts.get(F)??0;Wn(x,{color:So,isActive:ne,label:Xe?.label??F,count:mn,percent:m.total>0?mn/m.total*100:void 0,onClick:()=>{const vt=c.highlightMetadataValue===F?void 0:F;T({highlightMetadataValue:vt})}})});return}const bt=e==="softBin"?R.flatMap(g=>g?.sbinDefs??[]):R.flatMap(g=>g?.hbinDefs??[]),un=new Set,yt=[];for(const g of bt)un.has(g.bin)||(un.add(g.bin),yt.push(g));const wt=yt.length>0?new Map(yt.map(g=>[g.bin,g])):null,fn=i??c.binColors??fe(),Co=e==="softBin"?fn.soft:fn.hard,pn=g=>Co.get(g)??$o;for(const g of u){const F=y===g,te=wt?.get(g),ne=r.counts.get(g)??0;Wn(x,{color:pn(g),isActive:F,label:te?.name?`${g} \xB7 ${te.name}`:`Bin ${g}`,count:ne,percent:r.total>0?ne/r.total*100:void 0,onClick:()=>{const Xe=c.highlightBin===g?void 0:g;T({highlightBin:Xe})}})}r.total>0&&u.length>1&&ee.appendChild(Fi(f.ownerDocument,[...r.counts.entries()].sort(([,g],[,F])=>F-g).map(([g,F])=>({color:pn(g),count:F,label:wt?.get(g)?.name?`${g} \xB7 ${wt.get(g).name}`:`Bin ${g}`})),r.total))}function Re(e){const t=v.filter(r=>r!==null);if(!t.length)return[];const n=t.map(r=>r.dies.filter(Ai)),o=t[0].wafer,d=t.length,l=o.metadata?{...o,metadata:(({wafer:r,waferId:i,...s})=>s)(o.metadata)}:o;function a(r,i){return{...r,stats:{...r.stats,isLotStack:!0,aggregationMethod:i,lotSize:d}}}if(e==="stackedValues"){const r=ve();let i=r?.filter(Ct);if(r!==void 0&&i?.length===0)return[];if(r?.length||(i=Mo(t.flatMap(m=>m.dies)).map(m=>({testNumber:m,name:Li(void 0,m)}))),!i?.length)return[];const s=c.aggregationMethod??"mean";return i.map(u=>{const m=gi(n,s,u.testNumber),M={testNumber:0,name:u.name,unit:u.unit,...Ii(u)};return{wafer:l,dies:m,testDefs:[M],label:`${Ri(u,u.testNumber)} \xB7 ${s}`,isLotStack:!0,aggrMethod:s,lotSize:d,statsSummary:a(Je({wafer:l,dies:m,testDefs:[M]},{testNumbers:[0]}),s)}})}if(e==="stackedBins"){let r=Ye(t.map(i=>i?.hbinDefs));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(s=>s.dies.map(u=>u.hbin).filter(u=>u!=null)))].sort((s,u)=>s-u).map(s=>({bin:s,name:`Bin ${s}`}))),r.map(i=>{const s=Dn(n,i.bin,"hard"),u=[{bin:i.bin,name:i.name}];return{wafer:l,dies:s,hbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:d,statsSummary:a(Je({wafer:l,dies:s,hbinDefs:u}),"countBin")}})}if(e==="stackedSoftBins"){let r=Ye(t.map(i=>i?.sbinDefs));return(!r||r.length===0)&&(r=[...new Set(t.flatMap(s=>s.dies.map(u=>u.sbin).filter(u=>u!=null)))].sort((s,u)=>s-u).map(s=>({bin:s,name:`Bin ${s}`}))),r.map(i=>{const s=Dn(n,i.bin,"soft"),u=[{bin:i.bin,name:i.name}];return{wafer:l,dies:s,sbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:d,statsSummary:a(Je({wafer:l,dies:s,sbinDefs:u}),"countBin")}})}return t}function mt(e){const t=v.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:c.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}function T(e,{fireCallback:t=!0}={}){const n=Object.keys(e),o=c.plotMode,d=we()!==null;c={...c,...e};const l=c.plotMode,a=be.has(l),r=o!==void 0&&be.has(o),i=He>0;if("binColorScheme"in e||"useDefinedBinColors"in e){const u=fe();c={...c,binColors:u},e={...e,binColors:u}}if(e.plotMode!==void 0)if(a){const u=mt(l);if(c={...c,...u},i)for(const m of S)m&&m.setOptions(e);else Z(Re(l))}else if(r){const{valueRange:u,lotSize:m,aggregationMethod:M,...E}=c;if(c=E,i)for(const x of S)x&&x.setOptions(e);else Z(v.filter(x=>x!==null))}else for(const u of S)u&&u.setOptions(e);else if(e.aggregationMethod!==void 0&&l==="stackedValues")if(i)for(const u of S)u&&u.setOptions(e);else Z(Re("stackedValues"));else for(const u of S)u&&u.setOptions(e);we()!==null!==d&&Et(),qe(),qt(),Gt(),jt();const s=e.plotMode!==void 0&&e.plotMode!==o;(vi.some(u=>u in e)||s)&&N(),Be(),Ut(),Xt(),st(),lt(),t&&p.onViewOptionsChange?.(En(c),n,wi(n))}function rn(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0"});const d=e.createElement("span");d.textContent=t,Object.assign(d.style,{fontWeight:"700",fontSize:L.sub,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(d);const l=Ln(n??{});let a=null;if(l.length>0){const r=e.createElement("span");Object.assign(r.style,{fontSize:L.body,lineHeight:Ze.none,color:h.label,flexShrink:"0"}),r.textContent="\u25BE",o.appendChild(r),Object.assign(o.style,{cursor:"pointer",borderRadius:z.control}),o.addEventListener("mouseenter",()=>{o.style.background=h.bgHover}),o.addEventListener("mouseleave",()=>{o.style.background="none"}),a=e.createElement("div"),a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:bn,background:h.menuBg,borderBottom:`1px solid ${h.menuBorder}`,boxShadow:$e.menu,padding:`${w.md} ${w.lg}`,fontSize:L.body,display:"none"});const i=Tn(n??{});i&&a.appendChild(i),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),xn(o,s=>{r.textContent=s?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(s)),a&&(a.style.display=s?"block":"none")})}return{wrap:o,metaPanel:a}}function dn(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),d=Ln(n??{});if(!o||d.length===0)return;const l=o.parentElement,a=f.ownerDocument.createElement("div");Object.assign(a.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0",cursor:"pointer"}),xt(a,"bare"),l?.insertBefore(a,o),a.appendChild(o);const r=f.ownerDocument.createElement("span");Object.assign(r.style,{fontSize:L.body,lineHeight:Ze.none,color:h.label,flexShrink:"0"}),r.textContent="\u25BE",a.appendChild(r);const i=f.ownerDocument.createElement("div");i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:bn,background:h.menuBg,borderBottom:`1px solid ${h.menuBorder}`,boxShadow:$e.menu,padding:`${w.md} ${w.lg}`,fontSize:L.body,display:"none"});const s=Tn(n??{});s&&i.appendChild(s),e.contentWrap.style.position="relative",e.contentWrap.appendChild(i),a.setAttribute("aria-expanded","false"),a.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),xn(a,u=>{r.textContent=u?"\u25B4":"\u25BE",a.setAttribute("aria-expanded",String(u)),i.style.display=u?"block":"none"})}function gt(e,t,n){const o=f.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:h.menuBg,border:`1px solid ${h.menuBorder}`,borderRadius:z.container,boxShadow:$e.panel,overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:ut(),maxHeight:ut()});const d=f.ownerDocument.createElement("div");Object.assign(d.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${h.menuBorder}`,flexShrink:"0",gap:w.sm});const{wrap:l,metaPanel:a}=rn(document,Qe(e,t),e.wafer.metadata??void 0);d.appendChild(l);const r=f.ownerDocument.createElement("button");r.dataset.wmapExpandBtn="1",r.setAttribute("aria-label","Open full view"),Cn(r),r.innerHTML=We.expand,Object.assign(r.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${h.menuBorder}`,borderRadius:z.control,background:h.panelBg,color:h.label,padding:w.xxs,cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),xt(r),d.appendChild(r),o.appendChild(d);const i=f.ownerDocument.createElement("div");Object.assign(i.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(i),a&&i.appendChild(a),$.appendChild(o),o.addEventListener("contextmenu",M=>{if(M.defaultPrevented)return;const E=p.insights?.sweeps;if(!bi(e.testDefs,E))return;M.preventDefault();const x=e.viewOptions?{...c,...e.viewOptions}:c,y=yi(e.dies,{waferLabel:Mn(e),testDefs:e.testDefs,isLotStack:e.isLotStack,activeTest:x.plotMode==="value"?x.activeTest:void 0,waferIndex:t}),B={x:M.clientX,y:M.clientY};import("./drilldown.js").then(({openDrilldownMenu:j})=>{o.isConnected&&j(B,o,y,{sweeps:E,onSaveImage:m.getSaveImageHook()})})});const s=Pe||we()!==null,u=e.viewOptions?{...c,...e.viewOptions}:c,m=kn(i,e,{viewOptions:{...u,showLegend:s,legendPosition:ye},showTooltip:!0,padding:A,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,downloadFilename:p.downloadFilename,onClick:e.onClick,onSelect:e.onSelect,insights:X,onExpand:()=>Ie(t,e),showIdentity:!1,chromeInset:jo});return m.setViewControlsVisible(!1),m.setSummaryVisible(!1),r.onclick=()=>Ie(t,e),{card:o,ctrl:m,canvasWrapper:i,expandBtn:r}}function bo(e){const t=de[e];if(!t)return;const n=[..._.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=We.minimize,t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>wo(n.id)):(t.innerHTML=We.expand,t.setAttribute("aria-label","Open full view"),t.onclick=()=>Ie(e,R[e]))}function Z(e){vo(),Me()?.remove(),De(null),it(),R=[];for(const i of S)i&&i.destroy();S=[],ae=[],de=[],He=0,$.innerHTML="",on=e.length,an(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const s=e[i];if(typeof s=="function"){const u=f.ownerDocument.createElement("div");u.className="wmap-gallery-card",Object.assign(u.style,{background:h.menuBg,border:`1px solid ${h.menuBorder}`,borderRadius:z.container,aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const m=f.ownerDocument.createElement("span");m.textContent="\u2026",Object.assign(m.style,{color:h.label,fontSize:"18px"}),u.appendChild(m),$.appendChild(u),R.push(null),S.push(null),ae.push(null),de.push(null),t.push({index:i,factory:s,placeholder:u}),He++}else{const{ctrl:u,canvasWrapper:m,expandBtn:M}=gt(s,i,e.length);R.push(s),S.push(u),ae.push(m),de.push(M)}}_t(),qe(),st(),lt();const n=++xe,o=()=>{setTimeout(()=>{n===xe&&p.onItemsResolved?.()},0)},d=i=>{setTimeout(()=>{n===xe&&p.onItemResolved?.(i,e.length)},0)};let l=e.length-t.length;l>0&&d(l);let a=0;function r(){if(n!==xe)return;if(a>=t.length){if(be.has(c.plotMode)){const B=c.plotMode;Z(Re(B));return}ke=o,N(),ue||(ke=null,o());return}const{index:i,factory:s,placeholder:u}=t[a++],m=s();R[i]=m,v[i]=m,an([m]);const{card:M,ctrl:E,canvasWrapper:x,expandBtn:y}=gt(m,i,e.length);S[i]=E,ae[i]=x,de[i]=y,He--,u.replaceWith(M),d(++l),to(),eo(),!b&&!re?.placement&&m.statsSummary?.findings.length&&(b=Mt("right",oe,f.ownerDocument),b.style.maxHeight="calc(100vh - 80px)",b.style.position="sticky",b.style.top="8px",b.style.flexDirection="column",b.style.display="none",(re?.placement??"right")==="left"?q.insertBefore(b,$):q.appendChild(b),N(),P||(P=Q("findings","Summary panel",()=>{if(!b)return;const j=b.style.display!=="none";j||N(),b.style.display=j?"none":"flex",Se(P,!j),le()}),W.appendChild(G()),W.appendChild(P)),le()),le(),setTimeout(r,0)}t.length>0?setTimeout(r,0):o()}if(be.has(c.plotMode)&&v.length>0){const e=mt(c.plotMode);c={...c,...e},Z(Re(c.plotMode))}else Z(C);Be();let he=0;const cn=new(f.ownerDocument.defaultView??window).ResizeObserver(()=>{if(he)return;he=(f.ownerDocument.defaultView??window).requestAnimationFrame(()=>{he=0,D==null&&pt()})});cn.observe($),b&&N();function yo(e,t){const n=ae[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=f.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:h.label,fontSize:L.body,textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Ie(e,t){for(const a of _.values())if(a.cardIndex===e)return;const n=Qe(t,e),o=Pn++,d=S[e]?.getOptions(),l=Ko(n);if(l){const a=l.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:L.family}),Yo(f,a.documentElement);const r=Zo(f,a.documentElement,()=>x.setOptions({})),i=a.createElement("div");i.dataset.wmapWindowBanner="1",i.textContent=n,Object.assign(i.style,{display:"none",padding:`${w.sm} ${w.xl}`,fontSize:L.body,fontWeight:"700",background:h.warnBg,color:h.warnText,borderBottom:`1px solid ${h.warnBorder}`,flexShrink:"0"}),a.body.appendChild(i);const s=a.createElement("div");Object.assign(s.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),a.body.appendChild(s);const{wrap:u,metaPanel:m}=rn(a,n,t.wafer.metadata??void 0),M=a.createElement("div");Object.assign(M.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${h.menuBorder}`,flexShrink:"0",gap:w.sm}),M.appendChild(u),s.appendChild(M);const E=a.createElement("div");Object.assign(E.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),m&&E.appendChild(m),s.appendChild(E);const x=ht(E,t,void 0,d),y=setInterval(()=>{l.closed&&Ue(o)},400);l.addEventListener("pagehide",()=>Ue(o)),_.set(o,{id:o,ctrl:x,cardIndex:e,label:n,closePollId:y,stopThemeSync:r,close:()=>{l.closed||l.close()},setTitle:B=>{a.title=B,i.textContent=B,i.style.display="block"}})}else{const a=qo({title:n,onClose:()=>Ue(o),anchor:f});a.contentWrap.style.flexDirection="column",dn(a,n,t.wafer.metadata??void 0);const r=ht(a.contentWrap,t,void 0,d);_.set(o,{id:o,ctrl:r,cardIndex:e,label:n,closePollId:null,close:()=>a.close(),setTitle:i=>{const s=a.box.querySelector("[data-wmap-window-title]");s&&(s.textContent=i,s.title=i)}})}S[e]?.destroy(),S[e]=null,yo(e,l!==null),bo(e)}function ht(e,t,n,o){const d=t.viewOptions?{...c,...t.viewOptions}:c,l=o?{...d,...o}:d,r={...n!==void 0?{...l,plotMode:"value",activeTest:n}:l,showLegend:!0,legendPosition:ye},i=kn(e,t,{viewOptions:r,showTooltip:!0,padding:A,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,downloadFilename:p.downloadFilename,onClick:t.onClick,onSelect:t.onSelect,insights:X,showExpandButton:!1,showIdentity:!1});return i.setViewControlsVisible(!0),i.setSummaryVisible(!0),i.setExpandVisible(!1),i}function Ue(e){const t=_.get(e);if(!t||(_.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.(),t.ctrl.destroy(),t.cardIndex===null))return;const n=t.cardIndex,o=R[n];if(!o)return;const{card:d,ctrl:l,canvasWrapper:a,expandBtn:r}=gt(o,n,R.length);ae[n]?.parentElement?.replaceWith(d),S[n]=l,ae[n]=a,de[n]=r}function wo(e){const t=_.get(e);t&&(t.close(),Ue(e))}function vo(){for(const e of _.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function xo(){const e=[...$.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),d=e[0].width,l=e[0].height,a=8,r=(f.ownerDocument.defaultView??window).devicePixelRatio||1,i=Math.round(26*r),s=Math.round(12*r),u=f.ownerDocument.createElement("canvas");u.width=n*d+(n-1)*a,u.height=o*(l+i)+(o-1)*a;const m=u.getContext("2d"),M=Po($);m.fillStyle=M.background,m.fillRect(0,0,u.width,u.height),e.forEach((E,x)=>{const y=x%n,B=Math.floor(x/n),j=y*(d+a),U=B*(l+i+a),bt=E.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";m.fillStyle=M.surface,m.fillRect(j,U,d,i),m.fillStyle=M.text,m.font=`700 ${s}px system-ui, sans-serif`,m.textAlign="left",m.textBaseline="middle",m.fillText(bt,j+Math.round(10*r),U+i/2,d-Math.round(20*r)),m.drawImage(E,j,U+i)}),u.toBlob(E=>{if(!E)return;const x=S.find(y=>y!=null)?.getExportTitle();ii(E,["gallery",x].filter(Boolean).join(" "),Fe.onSaveImage)})}return{setItems(e){v=e.map(n=>typeof n=="function"?null:n);const t=c.plotMode;if(be.has(t))if(e.some(o=>typeof o=="function"))Z(e);else{const o=mt(t);c={...c,...o},Z(Re(t))}else Z(e)},setOptions(e){T(e,{fireCallback:!1})},getOptions(){return En(c)},setFindingsNotice(e){It=e,N()},setColumns(e){ln(e)},getBinColors(){return c.binColors??fe()},setLotStatsSummary(e){V=e,Be(),b&&N(),le()},openUserGuide:Zt,destroy(){xe++,ue?.cancel(),ue=null,ke=null;for(const e of[..._.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();_.clear();for(const e of S)e&&e.destroy();S=[],Me()?.remove(),cn.disconnect(),he&&((f.ownerDocument.defaultView??window).cancelAnimationFrame(he),he=0),f.ownerDocument.removeEventListener("click",je,!0),window.removeEventListener("blur",Rt),ie(),yn(),Le.remove(),q.remove(),b?.remove(),me?.destroy()}}}
1
+ import{getUniqueTestNumbers as No,resolveTestNumber as zo,findTestDef as _o,collectMetadataValues as Ko}from"../renderer/buildView.js";import{metadataCategoricalValue as Go}from"../core/metadata.js";import{resolveBinColorsForMaps as qo,mergeBinDefs as et,binColorWarning as Xo,mixedPassBinsWarning as Uo,binColorsEqual as Yo}from"../renderer/binColors.js";import{itemPassBins as Zo,INPUT_DEFAULT_PASS_BINS as Qo}from"../core/passBins.js";import{NO_DATA_FILL as Jo}from"../renderer/colorMap.js";import{metadataValueColor as ei}from"../renderer/colorMap.js";import{resolveCanvasTheme as ti}from"./canvasTheme.js";import{ICONS as Fe}from"./icons.js";import{SHADOW as He,LEADING as tt,TRACKING as ni,controlStyle as oi,wireControlHover as Ot,SPACE as w,EDGE_GUTTER as ie,MAP_CHROME_INSET as ii,RADIUS as _,FONT as I,CLR as g,sevColor as kn,MODE_LABELS as si,BIN_LEGEND_MODES as On,STACKED_MODES as be,Z_ABOVE as Tn,applyOverlayZ as ai,getTooltip as li,hideTooltip as Ln,createToolbarHelpers as ri,buildModeMenuEl as di,openDetachWindow as ci,openFloatingWindow as ui,openModal as fi,openReportModal as pi,copyWmapThemeTokens as mi,syncWmapPopupTheme as gi,openUserGuideWindow as hi,makePaletteBtn as yi,makeLogScaleBtn as bi,makeLegendStyleBtn as wi,makeOverlaysBtn as vi,makeOrientationBtn as Ci,menuLayerFor as Rn,saveImageBlob as xi,markMenuTrigger as je,wireMenuA11y as In,wireExpandToggle as Wn,wireTooltip as $n,requestedPassFailDisplay as An,overlayMenuRows as Si,anyOverlayActive as Mi,openCompactDiagnostics as Di,roomForPanel as Pn,logWmapVersionOnce as Ei,buildDataModeEntries as Bi,metadataKeyHasData as ki,metadataModeEntry as Oi}from"./toolbar.js";import{waferDisplayLabel as nt,waferIdentityLabel as Fn}from"../core/waferLabel.js";import{metadataDisplayValue as Ti}from"../core/metadata.js";import{withExportContext as Li}from"./exportName.js";import{sortBinsForDisplay as Ri}from"../stats/binPareto.js";import{diePassStatus as Ii}from"../core/dies.js";import{aggregateValues as Wi,aggregateBinCounts as Hn}from"../core/aggregates.js";import{renderWaferMap as $i,renderWaferMapCard as jn,toPublicViewOptions as Vn}from"./renderWaferMap.js";import{hasDrilldownTargets as Ai,waferPopulation as Pi}from"./chartPopulation.js";import{classifyChanged as Fi,COLOR_KEYS as Hi,findingBin as ji}from"./renderWaferMap.js";import{findingPatternKey as Nn}from"../stats/filterFindings.js";import{buildWaferMap as Vi,getTestPassStatus as zn,isParametricTest as Tt,getDieTestValue as Ni}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as ot}from"../stats/analyzeWaferMap.js";import{collectWarnings as zi,buildWarningsMenuEl as _i,severityOf as Ki}from"./warnings.js";import{asList as _n,compareNatural as Lt,arrayEqual as it,toggleHighlight as Kn}from"../core/utils.js";import{buildCompactMap as Gi,compactLayoutOffered as qi}from"../core/compact.js";import{createSummaryPanelEl as Rt,buildMetadataStripRow as Xi,buildCompactMetadataRows as Gn,metadataEntries as qn,renderLotSummaryContentSteps as Ui,reportMapsFromItems as Yi}from"./summaryPanel.js";import{prettyKey as Zi}from"../stats/facets.js";import{testLabel as Qi,markedTestLabel as Ji,derivedFields as es}from"../renderer/testLabel.js";import{mergeTestDefs as ts}from"../stats/mergeTestDefs.js";import{getDieKey as ns,hasPosition as os}from"../core/dies.js";import{testValue as is}from"../core/dieTable.js";import{runChunked as ss}from"./chunked.js";function Xn(f){if(typeof f!="number"||!Number.isFinite(f))return;const x=Math.round(f);return x>=1?x:void 0}const It=12;function as(f,x,p){let P=x;if(x.length>It){const S=x.slice(0,It-1),W=x.slice(It-1),H=W.reduce((U,se)=>U+se.count,0);P=[...S,{color:g.label,count:H,label:`Other (${W.length} bins)`}]}const E=f.createElement("div");Object.assign(E.style,{display:"flex",columnGap:"1px",width:"100%",height:"8px",borderRadius:_.control,overflow:"hidden",border:`1px solid ${g.menuBorder}`,boxSizing:"border-box",marginTop:w.xs,flexShrink:"0"}),E.setAttribute("role","img"),E.setAttribute("aria-label",`Population split: ${P.map(S=>`${S.label} ${st(S.count/p*100)}`).join(", ")}`);for(const S of P){const W=S.count/p*100,H=f.createElement("div");Object.assign(H.style,{flex:`${W} 1 0`,minWidth:W>0?"2px":"0",background:S.color}),$n(H,`${S.label} \xB7 ${S.count.toLocaleString()} dies \xB7 ${st(W)}`),E.appendChild(H)}return E}function st(f){return f>0&&f<.1?"<0.1%":`${f.toFixed(1)}%`}function Un(f,x,p){const P=new Map;let E=0,S=0;for(const W of f){const H=p?new Set(p(W)):void 0;for(const U of W.dies){if(U.partial||U.edgeExcluded)continue;const se=x(U);se!==void 0&&(P.set(se,(P.get(se)??0)+1),E++,H&&Ii(U,H)&&S++)}}return{counts:P,total:E,pass:S}}function Yn(f,x){const p=f.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:`${w.xxs} ${w.xs}`,borderRadius:_.control});const P=f.ownerDocument.createElement("span");Object.assign(P.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:x.color,border:x.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:_.control,boxSizing:"border-box"});const E=f.ownerDocument.createElement("span");if(E.textContent=x.label,Object.assign(E.style,{fontWeight:x.isActive?"700":"400",color:x.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),p.appendChild(P),p.appendChild(E),x.count!==void 0){const S=f.ownerDocument.createElement("span");if(S.textContent=x.count.toLocaleString(),Object.assign(S.style,{color:x.isActive?g.iconActive:g.text,fontWeight:x.isActive?"700":"400",whiteSpace:"nowrap"}),p.appendChild(S),x.percent!==void 0){const W=f.ownerDocument.createElement("span");W.textContent=st(x.percent),Object.assign(W.style,{color:g.label,whiteSpace:"nowrap"}),p.appendChild(W)}}p.setAttribute("role","button"),p.setAttribute("aria-pressed",x.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",S=>x.onClick(S.ctrlKey||S.metaKey)),p.addEventListener("keydown",S=>{(S.key==="Enter"||S.key===" ")&&(S.preventDefault(),x.onClick(S.ctrlKey||S.metaKey))}),f.appendChild(p)}export function renderWaferGallery(f,x,p={}){Ei();const P=6;let E=Xn(p.columns);const S=p.showHelpButton??!1,W=p.userGuideExtension,H=p.insights?.enabled??!1,U=p.insights?.sweeps?{sweeps:p.insights.sweeps}:void 0,se=ai(p.zIndex),ce=p.summaryPanel,Zn=e=>[...Zo(e)],Wt=()=>v.flatMap(e=>e?[e.ringCount??4]:[]),at=()=>Wt()[0]??4;function Qn(e){const t=[...new Set(e)].sort((n,o)=>n-o);return t.length<2?null:{code:"ring-count-mixed",severity:"warning",message:`These wafers were built with different ring counts (${t.join(", ")}). Each card and each wafer's findings use their own; the lot's ring yield in the Summary panel, report and Insights uses ${e[0]} rings.`}}let z=p.lotStatsSummary,we=p.viewOptions?.legendPosition??"default",Ve=p.perCardLegend??!1;function ve(){const e=l.plotMode??"hardBin";return On.has(e)?null:l.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"These wafers have no shared colour bar for value mode, so each map keeps its own"}function $t(){const e=Ve||ve()!==null;for(const t of M)t&&t.setOptions({showLegend:e})}let l={plotMode:"hardBin",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},M=[],Q=[],ue=[],k=[];const Ce=Li(()=>{const e=k.filter(n=>n!=null),t=[...new Set(e.map(n=>Ti(n.wafer.metadata?.lot)).filter(n=>n!==void 0))].sort(Lt);return{prefix:p.downloadFilename,lots:t,...e.length===1?{wafer:Fn(e[0])}:{waferCount:e.length}}},p.onSaveImage,p.onSaveText);let v=x.map(e=>typeof e=="function"?null:e);function At(){return ts(v)}function xe(){if(v.some(e=>e?.testDefs?.length))return At().defs}let Se=0,Ne=0;const K=new Map;let Jn=0,F=null,ae=null,Pt=new Set,y=null,eo={};function Ft(e){return v[e]?.statsSummary??z?.perWafer.find(t=>t.waferIndex===e)?.summary}function lt(){return!!(v.some(e=>e?.statsSummary?.findings.length)||z?.perWafer.some(e=>e.summary.findings.length))}const to=li(),fe=ri(to),{makeBtn:J,setActive:Me,makeSep:G,makeMenuRow:no,makeMenuSection:oo,makeDropdown:Ht,closeOpenMenu:ze,getOpenMenu:De,setOpenMenu:Ee}=fe;f.ownerDocument.addEventListener("click",ze,!0);const jt=()=>Ln();window.addEventListener("blur",jt);let Vt=p.findingsNotice;function Nt(e){Pt=new Set(e);const t=[...A.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,c)=>{const r=Pt.has(c);o.style.outline=r?`3px solid ${g.findingHighlight}`:"",o.style.outlineOffset=r?"-3px":"",r&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function zt(){Nt([])}let rt=!1;function _t(){rt=!0;for(const e of M)e&&e.clearSelection();rt=!1}function Kt(e){return t=>{!rt&&ae!==null&&(ke(),j()),e.onSelect?.(t)}}function dt(e,t){const n=new Set(e),o=t??M.map((c,r)=>r);for(const c of o){const r=k[c],s=M[c];if(!r||!s)continue;const d=r.dies.filter(i=>n.has(ns(i)));s.setSelection(d)}}function io(){const e=[];for(let t=0;t<v.length;t++){const n=v[t];if(!n)continue;const o=Ft(t)?.findings??[];o.length&&e.push({index:t,item:n,unusualCount:o.filter(c=>c.severity==="unusual").length,notableCount:o.filter(c=>c.severity==="notable").length,totalCount:o.length})}return e}function so(e){const t=k[e]??v[e];t&&Ae(e,t)}function ao(e){const t=Ft(e)?.findings??[];if(t.length)return{total:t.length,unusual:t.filter(n=>n.severity==="unusual").length,notable:t.filter(n=>n.severity==="notable").length}}function lo(){import("../stats/renderSummaryReport.js").then(({renderLotReportHtml:e})=>{pi(e(Yi(v,Qo,at())),{anchor:f})})}function ro(){if(!y)return;y.innerHTML="";const e=io();if(v.length>0){const n=f.ownerDocument.createElement("div"),o=e.length,c=v.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${c} wafers`:`${o} of ${c} wafer${c===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:I.body,color:g.label,marginBottom:w.md}),y.appendChild(n)}if(e.length>0){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent="Summary report",Object.assign(n.style,{...oi("outlined"),marginBottom:w.lg,display:"block",width:"100%",textAlign:"left"}),Ot(n),n.addEventListener("click",lo),y.appendChild(n)}if(e.length===0){const n=f.ownerDocument.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:I.body,padding:"4px 0"}),n.textContent="No findings on any wafer.",y.appendChild(n)}else for(const{index:n,item:o,unusualCount:c,notableCount:r,totalCount:s}of e){const d=c?"unusual":r?"notable":"info",i=c+r||s,a=f.ownerDocument.createElement("button");a.type="button",Object.assign(a.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:w.xs,border:"none",borderLeft:`3px solid ${kn(d)}`,borderRadius:_.control,background:g.bgHover,cursor:"pointer",fontSize:I.body,textAlign:"left",boxSizing:"border-box"}),a.addEventListener("mouseover",()=>{a.style.background=g.bgActive}),a.addEventListener("mouseout",()=>{a.style.background=g.bgHover});const u=f.ownerDocument.createElement("span");u.textContent=nt(o,n),Object.assign(u.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const m=f.ownerDocument.createElement("span");m.textContent=String(i),a.setAttribute("aria-label",`${nt(o,n)} \u2014 ${i} finding${i===1?"":"s"}${c?`, ${c} unusual`:""} \u2014 view wafer`),Object.assign(m.style,{marginLeft:w.sm,flexShrink:"0",background:kn(d),color:"#fff",borderRadius:_.container,padding:"1px 5px",fontSize:I.body,fontWeight:"600"}),a.appendChild(u),a.appendChild(m),a.addEventListener("click",()=>Ae(n,o)),y.appendChild(a)}const t=f.ownerDocument.createElement("div");t.style.height="12px",y.appendChild(t)}let pe=null,Be=null;function j(){if(y)if(pe?.cancel(),pe=null,z){const e=et(v.map(n=>n?.hbinDefs)),t=et(v.map(n=>n?.sbinDefs));pe=ss(Ui(y,{lotSummary:z,items:v,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:xe(),ringCount:at(),binColors:l.binColors,plotMode:l.plotMode??"hardBin",fallbackFormat:l.fallbackFormat,activeFindingId:ae,warnings:p.warnings?.display??!0?ee:[],findingsFilter:eo,findingsNotice:Vt,onFindingsFilterChange:j,onSaveText:Ce.onSaveText,onFindingClick:(n,o)=>{ae===n.id?ke():uo(n,o),j()},onWaferClick:so,findingsFor:ao,dieListOptions:p.dieList}),{onDone:()=>{const n=Be;Be=null,n?.()}})}else ro()}function co(e){const t=e.highlight;return t?.kind==="wafer"&&t.waferIndices?.length?t.waferIndices:null}let _e=[];function Gt(){if(_e.length!==0){for(const e of _e)M[e]?.setOptions({plotMode:l.plotMode,activeTest:l.activeTest});_e=[]}}function ke(){ae=null,zt(),_t(),Gt(),R({highlightBin:void 0},{fireCallback:!1})}function qt(){ae!==null&&(ke(),j())}function uo(e,t){if(ae===e.id){ke();return}ae=e.id,t.style.background=g.bgActive,t.style.fontWeight="600",Gt();const{kind:n,index:o}=e.variable;if(n==="test"){const r=o??0,s=xe();if(s===void 0||s.some(i=>i.testNumber===r))R({plotMode:"value",activeTest:r,highlightBin:void 0},{fireCallback:!1});else{R({highlightBin:void 0},{fireCallback:!1});const a=be.has(l.plotMode??"hardBin")?null:co(e);if(a){for(const u of a)M[u]?.setOptions({plotMode:"value",activeTest:r});_e=[...a]}}}else R({plotMode:n==="softBin"?"softBin":"hardBin",highlightBin:ji(e)},{fireCallback:!1});zt(),_t();const c=e.highlight;if(c.kind==="wafer"){Nt(c.waferIndices);const r=Nn(e);for(const s of c.waferIndices){const d=c.dieKeysByWafer?void 0:k[s]?.statsSummary?.findings.find(a=>Nn(a)===r),i=c.dieKeysByWafer?.[s]??d?.highlight?.dieKeys;i?.length&&dt(i,[s])}}else c.kind==="bin"?c.dieKeys?.length&&dt(c.dieKeys):(c.kind==="region"||c.kind==="dies")&&c.dieKeys?.length&&dt(c.dieKeys)}function le(){if(!F)return;const e=!!y;F.style.display=(z||lt())&&e&&!Re?"flex":"none";const t=y?y.style.display!=="none":!1;(z?.hasNotableFindings||v.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?F.style.color=g.findingIndicator:F.dataset.active||(F.style.color=g.icon)}const $=f.ownerDocument.createElement("div");$.dataset.wmapToolbar="gallery",Object.assign($.style,{flexShrink:"0",marginLeft:"auto",display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:_.control,padding:"0",boxShadow:He.panel,flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const Xt=()=>{const e=De();e&&(e.remove(),Ee(null)),je(Y,!1)},Y=J("mode","Plot mode",()=>{if(De()){Xt();return}const e=v.flatMap(b=>b?.dies??[]),t=xe(),{testEntries:n,binEntries:o,stackedEntries:c}=Bi(e,t,{includeStacked:!0}),r=v.filter(Boolean).length,s=b=>{if(b===void 0)return r;let O=0;for(const T of v)T?.dies?.some(V=>zn(V,b)!==void 0||is(V,b)!==void 0)&&O++;return O},d=r<2?n:n.map(b=>{const O=s(b.activeTest);return O===r?b:{...b,label:`${b.label} \u2014 ${O} of ${r} wafers`}}),i=l.plotMode??"hardBin",a=l.activeTest??0;function u(b){return b.plotMode!==i?!1:b.plotMode==="value"?a===(b.activeTest??0):b.plotMode==="metadata"?l.activeMetadataKey===b.activeMetadataKey:!0}function m(b,O){b.activeTest!==void 0?R({plotMode:"value",activeTest:b.activeTest,activeMetadataKey:void 0,logScale:b.logScale}):b.activeMetadataKey!==void 0?R({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:b.activeMetadataKey,passFailDisplay:"off"}):R({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),O.remove(),Ee(null),je(Y,!1)}const D=new Set,B=v.flatMap(b=>b?.metadataFields??[]).filter(b=>!D.has(b.key)&&D.add(b.key)).filter(b=>ki(e,b.key)).map(Oi),C=di(Y.getBoundingClientRect(),d,o,c,u,m,{makeMenuRow:no,makeMenuSection:oo},i,Y.ownerDocument.defaultView??window,B);Rn(Y).appendChild(C),Ee(C),je(Y,!0),In(C,Y,Xt)});je(Y,!1);const fo=()=>k.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:po,sync:Ut}=yi(fe,()=>({...l,plotMode:l.plotMode??"hardBin"}),fo,e=>R(e));Ut();const mo=x.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Ke(){const e=xe(),{testNumber:t}=zo(l.activeTest??0,e);return{testNumber:t,td:_o(e,t)}}function Yt(){if((l.plotMode??"hardBin")!=="value")return!1;const{td:e}=Ke();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function Oe(){if((l.plotMode??"hardBin")!=="value")return!1;const{td:e}=Ke();return e!==void 0&&!Tt(e)}function go(){if((l.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Ke();return v.some(n=>n?.dies?.some(o=>zn(o,e,t)!==void 0))}function ho(e,t){if(!t||!Tt(t))return;const n=t.limitLow!==void 0||t.limitHigh!==void 0;if((An(l)==="spec"&&n?"spec":l.colorbarRangeMode??"spec")==="spec"&&n)return;let r=1/0,s=-1/0;for(const d of v)if(d)for(const i of d.dies){const a=Ni(i,e);a!==void 0&&(a<r&&(r=a),a>s&&(s=a))}if(isFinite(r))return r===s?[r,r+1]:[r,s]}function Ge(e,t,n){const o=l[e];if(o===t||o!=null&&t!=null&&n(o,t))return!1;l={...l,[e]:t};for(const c of M)c&&c.setOptions({[e]:t});return!0}function Zt(){if((l.plotMode??"hardBin")!=="metadata")return;const e=l.activeMetadataKey;if(!e)return;const t=new Set;for(const n of v)if(n)for(const o of Ko(n.dies,e))t.add(o);return{key:e,values:[...t].sort(Lt)}}function ct(){Ge("metadataValueOrder",Zt(),(e,t)=>e.key===t.key&&it(e.values,t.values))}function ut(){if((l.plotMode??"hardBin")!=="value")return;const{testNumber:e,td:t}=Ke(),n=ho(e,t);Ge("valueRange",n?{test:e,range:n}:void 0,(c,r)=>{const s=a=>Array.isArray(a)?{test:void 0,range:a}:{test:a.test,range:a.range},d=s(c),i=s(r);return d.test===i.test&&it(d.range,i.range)})}let ft=!1;function yo(){if(ft)return;ft=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{ft=!1,ut(),ct(),tn(),en()})}let pt=!1;function bo(){if(pt)return;pt=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{pt=!1,Ze()})}let Qt=[];function me(){const{colors:e,mixedHardBins:t}=qo(v.filter(n=>n!=null),{binColorScheme:l.binColorScheme,useDefinedBinColors:l.useDefinedBinColors});return Qt=t,e}function mt(){return k.filter(e=>e!=null).flatMap(e=>e.dies)}function Jt(){return l.compact?Gi(mt()):void 0}const wo=(e,t)=>it(e.columns,t.columns)&&it(e.rows,t.rows);function en(){Ge("compactMap",Jt(),wo)&&hn()}function vo(){return qi(mt(),k.filter(e=>e!=null).map(e=>e.reticleConfig))}function tn(){Ge("binColors",me(),Yo),Te()}const Co=vi(fe,()=>Si(l,mo,{functionalActive:Oe(),hasLimits:Yt()&&!Oe(),hasRecorded:go()&&!Oe(),binMode:(l.plotMode??"hardBin")==="hardBin"||(l.plotMode??"hardBin")==="softBin"},e=>R(e),{on:!!l.compact,offered:vo(),onChange:e=>R({compact:e}),onDiagnostics:()=>Di(mt(),k.filter(e=>e!=null).map(e=>e.reticleConfig),{anchor:f,onSaveText:Ce.onSaveText})}),()=>Mi(l)),{btn:xo,sync:nn}=wi(fe,()=>({plotMode:l.plotMode,legendPosition:we}),e=>{we=e;for(const t of M)t&&t.setOptions({legendPosition:we})},{get:()=>Ve,set:e=>{Ve=e,$t()},blockedReason:ve});nn();const So=[{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"}],on=Ht("aggr","Aggregation method",()=>So,()=>l.aggregationMethod??"mean",e=>R({aggregationMethod:e}));function sn(){const e=l.plotMode==="stackedValues";on.style.display=e?"":"none"}sn();const{btn:Mo,sync:an}=bi(fe,()=>({...l,functionalActive:Oe()}),e=>R(e));an();const qe=J("specRange","Colorbar range: test limits",()=>{const e=l.colorbarRangeMode==="data"?"spec":"data";R({colorbarRangeMode:e})});function ln(){const e=(l.plotMode??"hardBin")==="value"&&Yt()&&An(l)==="off"&&!Oe();qe.style.display=e?"":"none";const t=(l.colorbarRangeMode??"spec")==="spec";Me(qe,t),qe.ariaLabel=t?"Colorbar range: test limits (click for data range)":"Colorbar range: data range (click for test limits)"}ln();const Do=Ci(fe,()=>l,e=>R(e)),Eo=J("downloadAll","Download gallery PNG",Ho),Bo=Ht("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"}],()=>E!=null?String(E):"auto",e=>bn(e==="auto"?void 0:Number(e))),L=f.ownerDocument.createElement("div");Object.assign(L.style,{display:"inline-flex",alignItems:"center",gap:"0"}),$.appendChild(L),L.appendChild(Y),L.appendChild(po),L.appendChild(on),L.appendChild(Mo),L.appendChild(qe),L.appendChild(G()),L.appendChild(Co),L.appendChild(G()),L.appendChild(xo),L.appendChild(G()),L.appendChild(Do),L.appendChild(G()),L.appendChild(Bo),L.appendChild(G()),L.appendChild(Eo),(z||lt())&&(F=J("findings","Summary panel",()=>{if(!y)return;const e=y.style.display!=="none";e||j(),y.style.display=e?"none":"flex",Me(F,!e),le()}),$.appendChild(G()),$.appendChild(F));let q=null,Xe=null,ee=[],rn=!1;function Te(){const e=zi({lotStatsSummary:z,result:{warnings:[...v.flatMap(n=>n?.warnings??[]),...At().warnings]},extra:[l.binColors&&Xo(l.binColors,l.plotMode),Uo(Qt),Qn(Wt())].filter(n=>!!n)}),t=e.length!==ee.length||e.some((n,o)=>n.code!==ee[o]?.code||n.message!==ee[o]?.message);ee=e,(t||!rn)&&(rn=!0,p.warnings?.onWarning?.(e)),ko()}function ko(){if(!q||!Xe)return;const e=ee.length,t=e>0;if(q.style.display=t?"flex":"none",Xe.style.display=t?"":"none",!t)return;const n=Ki(ee[0]),o=`${e} data ${e===1?"warning":"warnings"}`;q.style.color=n==="error"?g.errText:g.warnText,q.ariaLabel=n==="error"?`${o} \u2014 some wafers may be positionally wrong`:o}(p.warnings?.display??!0)&&(Xe=G(),q=J("warning","Data warnings",()=>{const e=De();if(ze(new MouseEvent("click")),e)return;const t=_i(q.getBoundingClientRect(),ee,q.ownerDocument.defaultView??window);Rn(f).appendChild(t),Ee(t),In(t,q,()=>ze(new MouseEvent("click")))}),je(q,!1),$.appendChild(Xe),$.appendChild(q)),Te();let re=null;H&&(re=J("analysis","Insights",()=>{un(!Re)}),re.dataset.wmapInsightsBtn="1",$.appendChild(G()),$.appendChild(re));function dn(){import("./userGuideHtml.js").then(e=>hi({buildWaferMap:Vi,renderWaferMap:$i,renderWaferGallery,analyzeWaferMap:ot},e.USER_GUIDE_HTML,W,f))}S&&($.appendChild(G()),$.appendChild(J("help","User guide",()=>dn())));const ge=f.ownerDocument.createElement("div");ge.dataset.wmapGalleryMeta="1",Object.assign(ge.style,{flex:"1",minWidth:"0",overflow:"hidden",display:"flex",alignItems:"center",padding:`${w.sm} ${w.lg}`,fontSize:I.sub,lineHeight:tt.none,boxSizing:"border-box"});const Ue=f.ownerDocument.createElement("div");Object.assign(Ue.style,{background:g.canvasBg,display:"flex",alignItems:"stretch",gap:w.lg,paddingBottom:w.lg,minWidth:"0"});const te=f.ownerDocument.createElement("div");te.dataset.wmapGalleryLegend="1",Object.assign(te.style,{display:"flex",flexDirection:"column",gap:w.sm,background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:_.container,padding:`${w.sm} ${w.lg}`,marginBottom:w.lg,boxShadow:He.panel,fontSize:I.body,lineHeight:tt.none,boxSizing:"border-box",width:"100%",minWidth:"0"});const X=f.ownerDocument.createElement("div");Object.assign(X.style,{display:"flex",flexDirection:"row",alignItems:"flex-start"});let he=null,Le=null,cn=null;function Oo(){return H?he?Promise.resolve(he):(cn??=import("./insightsTab.js").then(({createInsightsTab:e})=>(he=e({getItems:()=>v,getLotStats:()=>z,getBinColors:()=>l.binColors??me(),getRingCount:at,defaultView:p.insights?.defaultView,sweeps:p.insights?.sweeps,onRemoveSweeps:p.insights?.onRemoveSweeps,onOpenGuide:void 0,showMetadataStrip:!1,onSaveImage:Ce.onSaveImage,onSaveText:Ce.onSaveText,ownerDocument:f.ownerDocument,openWafer:(t,n,o)=>{const c=v[t];if(!c)return;let r=null;const s=fi({title:n,onClose:()=>r?.destroy(),anchor:f});Cn(s,n,c.wafer.metadata??void 0),r=St(s.contentWrap,c,o,void 0,Pn(s))}}),Le=he.el,Le.style.display="none",f.appendChild(Le),he)),cn):Promise.resolve(null)}let Re=!1;function un(e){H&&(Re=e,Le&&(Le.style.display=e?"flex":"none"),X.style.display=e?"none":"flex",L.style.display=e?"none":"inline-flex",$.style.display="inline-flex",re&&(Me(re,e),re.innerHTML=e?Fe.wafer:Fe.analysis,re.ariaLabel=e?"Back to gallery view":"Insights"),le(),Ze(),e&&Oo().then(t=>{!t||!Re||(t.el.style.display="flex",t.render())}))}H&&p.insights?.defaultOpen&&queueMicrotask(()=>un(!0));const fn=4,Ye=240,gt=480,To=720,Lo=1.25;let de=gt;function pn(e){const t=P*2+110+2,n=mn();if(n)return Math.ceil(n.across*fn+t);let o=null;for(const c of e){if(c==null||!c.dies?.length)continue;const r=c.dies[0].width;if(!(r>0))continue;const s=c.wafer.radius*2*(fn/r),d=Math.ceil(s+t);(o==null||d>o)&&(o=d)}return o}function Ro(e){const t=pn(e);return t==null?Ye:Math.min(de,Math.max(Ye,t))}function Io(e){const t=pn(e);if(t==null)return!1;const n=Math.min(To,Math.max(gt,t));return n<=de?!1:(de=n,!0)}function mn(){const e=l.compact?l.compactMap:void 0,t=k.find(c=>c?.dies?.length)?.dies[0];if(!e||!t||e.columns.length===0||e.rows.length===0||!(t.width>0)||!(t.height>0))return;const n=(l.rotation??0)%180!==0,o=l.showXYIndicator?2.5:0;return{across:(n?e.rows.length:e.columns.length)+o,down:(n?e.columns.length:e.rows.length)+o,cellAspect:n?t.height/t.width:t.width/t.height}}function gn(e,t){const n=mn();if(!n){e.style.aspectRatio="1",t.style.flex="1",t.style.width="",t.style.aspectRatio="";return}e.style.aspectRatio="auto",t.style.flex="none",t.style.width="100%",t.style.aspectRatio=String(n.across*n.cellAspect/n.down)}function Wo(){for(const e of Q)e?.parentElement&&gn(e.parentElement,e)}function hn(){de=gt,Ie=Ye,bt(k.map(e=>e??null)),yt(),Wo()}function ht(){return E!=null?"none":`${de}px`}function yt(){const e=ht();for(const t of Array.from(A.children))t.classList.contains("wmap-gallery-card")&&(t.style.maxWidth=e,t.style.maxHeight=e)}let Ie=Ye,yn=0;function bt(e){if(Io(e)&&yt(),E==null){const n=Ro(e);n>Ie&&(Ie=n)}vt()}function bn(e){E=Xn(e),yt(),vt()}function wt(e){return`repeat(${e}, minmax(0, ${E!=null?"1fr":`${de}px`}))`}function wn(e){A.style.gridTemplateColumns!==e&&(A.style.gridTemplateColumns=e)}function vt(){if(E!=null){wn(wt(E));return}const e=Math.max(1,yn),t=12,n=A.clientWidth||0,o=r=>(n-t*(r-1))/r;let c=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const r=Math.min(de,Ie*Lo),s=d=>{let i=0;for(;i<e&&o(i+1)>=d;)i++;return i};c=s(r)||s(Ie)||1}wn(wt(c))}const A=f.ownerDocument.createElement("div");if(Object.assign(A.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:wt(1),gap:w.xl,paddingLeft:ie,paddingRight:ie,justifyContent:"start",alignContent:"start",isolation:"isolate"}),ce?.placement){const e=ce.placement;y=Rt(e,ie,f.ownerDocument),y.style.maxHeight="calc(100vh - 80px)",y.style.position="sticky",y.style.top="8px",y.style.display="flex",y.style.flexDirection="column"}else if(z||lt()){const e=!!ce?.defaultOpen;y=Rt("right",ie,f.ownerDocument),y.style.maxHeight="calc(100vh - 80px)",y.style.position="sticky",y.style.top="8px",y.style.flexDirection="column",y.style.display=e?"flex":"none",j()}le(),y?.style.display!=="none"&&F&&Me(F,!0),(ce?.placement??"right")==="left"?(y&&X.appendChild(y),X.appendChild(A)):(X.appendChild(A),y&&X.appendChild(y));const We=f.ownerDocument.createElement("div");Object.assign(We.style,{position:"sticky",top:"0",display:"flex",flexDirection:"column",paddingLeft:ie,paddingRight:ie,paddingTop:ie,zIndex:"1",background:g.menuBg}),Ue.appendChild(ge),Ue.appendChild($),We.appendChild(Ue),We.appendChild(te),f.appendChild(We),f.appendChild(X);function Ze(){te.innerHTML="";const e=l.plotMode??"hardBin",t=!Re&&On.has(e),n=k.filter(h=>h!=null),o=n.find(h=>h.isLotStack),c=Xi(n.map(h=>({metadata:h.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),r=e==="metadata",s=l.activeMetadataKey,d=t&&!r?Un(n,h=>(e==="softBin"?h.sbin:h.hbin)??void 0,Zn):{counts:new Map,total:0,pass:0},i=t&&!r?l.binColors??me():void 0,a=i?e==="softBin"?i.pass.soft:i.pass.hard:new Set,u=Ri(d.counts.entries(),a).map(([h])=>h),m=t&&r&&s?Un(n,h=>Go(h.metadata?.[s])):{counts:new Map,total:0,pass:0},D=r?Zt()?.values:void 0,B=t&&r?(D??[...m.counts.keys()].sort(Lt)).filter(h=>m.counts.has(h)):[];if(ge.innerHTML="",c&&ge.appendChild(c),ge.style.display=c?"flex":"none",!u.length&&!B.length){te.style.display="none";return}te.style.display="flex";const C=f.ownerDocument.createElement("div");Object.assign(C.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:`${w.sm} ${w.xl}`,maxHeight:"86px",overflowY:"auto",overflowX:"hidden"}),te.appendChild(C);const b=_n(l.highlightBin),O=k.flatMap(h=>h?.metadataFields??[]).find(h=>h.key===s),T=r?O?.label??(s?Zi(s):"Metadata"):si[e],V=f.ownerDocument.createElement("span");if(V.textContent=T,Object.assign(V.style,{fontSize:I.body,fontWeight:"700",letterSpacing:ni,textTransform:"uppercase",color:g.label,flexShrink:"0"}),C.appendChild(V),!r&&d.total>0){const h=d.pass,N=h/d.total*100,ne=f.ownerDocument.createElement("span");ne.textContent=`Yield ${st(N)}`,Object.assign(ne.style,{fontSize:I.body,fontWeight:"700",color:g.value,whiteSpace:"nowrap",flexShrink:"0"});const oe=f.ownerDocument.createElement("span");oe.textContent=`${h.toLocaleString()} / ${d.total.toLocaleString()} dies`,Object.assign(oe.style,{fontSize:I.body,color:g.label,whiteSpace:"nowrap",flexShrink:"0"}),C.appendChild(ne),C.appendChild(oe)}if(r){const h=_n(l.highlightMetadataValue);B.forEach((N,ne)=>{const oe=h.includes(N),Je=O?.values?.find(kt=>kt.value===N),Bt=Je?.color??ei(ne),Bn=m.counts.get(N)??0;Yn(C,{color:Bt,isActive:oe,label:Je?.label??N,count:Bn,percent:m.total>0?Bn/m.total*100:void 0,onClick:kt=>{const Vo=Kn(l.highlightMetadataValue,N,kt);qt(),R({highlightMetadataValue:Vo})}})});return}const Pe=e==="softBin"?k.flatMap(h=>h?.sbinDefs??[]):k.flatMap(h=>h?.hbinDefs??[]),Mn=new Set,Dt=[];for(const h of Pe)Mn.has(h.bin)||(Mn.add(h.bin),Dt.push(h));const Et=Dt.length>0?new Map(Dt.map(h=>[h.bin,h])):null,Dn=i??l.binColors??me(),jo=e==="softBin"?Dn.soft:Dn.hard,En=h=>jo.get(h)??Jo;for(const h of u){const N=b.includes(h),ne=Et?.get(h),oe=d.counts.get(h)??0;Yn(C,{color:En(h),isActive:N,label:ne?.name?`${h} \xB7 ${ne.name}`:`Bin ${h}`,count:oe,percent:d.total>0?oe/d.total*100:void 0,onClick:Je=>{const Bt=Kn(l.highlightBin,h,Je);qt(),R({highlightBin:Bt})}})}d.total>0&&u.length>1&&te.appendChild(as(f.ownerDocument,[...d.counts.entries()].sort(([,h],[,N])=>N-h).map(([h,N])=>({color:En(h),count:N,label:Et?.get(h)?.name?`${h} \xB7 ${Et.get(h).name}`:`Bin ${h}`})),d.total))}function $e(e){const t=v.filter(d=>d!==null);if(!t.length)return[];const n=t.map(d=>d.dies.filter(os)),o=t[0].wafer,c=t.length,r=o.metadata?{...o,metadata:(({wafer:d,waferId:i,...a})=>a)(o.metadata)}:o;function s(d,i){return{...d,stats:{...d.stats,isLotStack:!0,aggregationMethod:i,lotSize:c}}}if(e==="stackedValues"){const d=xe();let i=d?.filter(Tt);if(d!==void 0&&i?.length===0)return[];if(d?.length||(i=No(t.flatMap(m=>m.dies)).map(m=>({testNumber:m,name:Qi(void 0,m)}))),!i?.length)return[];const a=l.aggregationMethod??"mean";return i.map(u=>{const m=Wi(n,a,u.testNumber),D={testNumber:0,name:u.name,unit:u.unit,...es(u)};return{wafer:r,dies:m,testDefs:[D],label:`${Ji(u,u.testNumber)} \xB7 ${a}`,isLotStack:!0,aggrMethod:a,lotSize:c,statsSummary:s(ot({wafer:r,dies:m,testDefs:[D]},{testNumbers:[0]}),a)}})}if(e==="stackedBins"){let d=et(t.map(i=>i?.hbinDefs));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.hbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(i=>{const a=Hn(n,i.bin,"hard"),u=[{bin:i.bin,name:i.name}];return{wafer:r,dies:a,hbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:c,statsSummary:s(ot({wafer:r,dies:a,hbinDefs:u}),"countBin")}})}if(e==="stackedSoftBins"){let d=et(t.map(i=>i?.sbinDefs));return(!d||d.length===0)&&(d=[...new Set(t.flatMap(a=>a.dies.map(u=>u.sbin).filter(u=>u!=null)))].sort((a,u)=>a-u).map(a=>({bin:a,name:`Bin ${a}`}))),d.map(i=>{const a=Hn(n,i.bin,"soft"),u=[{bin:i.bin,name:i.name}];return{wafer:r,dies:a,sbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:c,statsSummary:s(ot({wafer:r,dies:a,sbinDefs:u}),"countBin")}})}return t}function Ct(e){const t=v.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:l.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}function R(e,{fireCallback:t=!0}={}){const n=Object.keys(e),o=l.plotMode,c=ve()!==null;l={...l,...e};const r=l.plotMode,s=be.has(r),d=o!==void 0&&be.has(o),i=Ne>0;if("binColorScheme"in e||"useDefinedBinColors"in e){const u=me();l={...l,binColors:u},e={...e,binColors:u}}if("compact"in e){const u=Jt();l={...l,compactMap:u},e={...e,compactMap:u}}if(("compact"in e||l.compact&&("rotation"in e||"showXYIndicator"in e))&&hn(),e.plotMode!==void 0)if(s){const u=Ct(r);if(l={...l,...u},i)for(const m of M)m&&m.setOptions(e);else Z($e(r))}else if(d){const{valueRange:u,lotSize:m,aggregationMethod:D,...B}=l;if(l=B,i)for(const C of M)C&&C.setOptions(e);else Z(v.filter(C=>C!==null))}else for(const u of M)u&&u.setOptions(e);else if(e.aggregationMethod!==void 0&&r==="stackedValues")if(i)for(const u of M)u&&u.setOptions(e);else Z($e("stackedValues"));else for(const u of M)u&&u.setOptions(e);ve()!==null!==c&&$t(),Ze(),sn(),nn(),Ut();const a=e.plotMode!==void 0&&e.plotMode!==o;(Hi.some(u=>u in e)||a)&&j(),Te(),an(),ln(),ut(),ct(),t&&p.onViewOptionsChange?.(Vn(l),n,Fi(n))}function vn(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0"});const c=e.createElement("span");c.textContent=t,Object.assign(c.style,{fontWeight:"700",fontSize:I.sub,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(c);const r=qn(n??{});let s=null;if(r.length>0){const d=e.createElement("span");Object.assign(d.style,{fontSize:I.body,lineHeight:tt.none,color:g.label,flexShrink:"0"}),d.textContent="\u25BE",o.appendChild(d),Object.assign(o.style,{cursor:"pointer",borderRadius:_.control}),o.addEventListener("mouseenter",()=>{o.style.background=g.bgHover}),o.addEventListener("mouseleave",()=>{o.style.background="none"}),s=e.createElement("div"),s.dataset.wmapCardMetaPanel="1",Object.assign(s.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Tn,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:He.menu,padding:`${w.md} ${w.lg}`,fontSize:I.body,display:"none"});const i=Gn(n??{});i&&s.appendChild(i),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Wn(o,a=>{d.textContent=a?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(a)),s&&(s.style.display=a?"block":"none")})}return{wrap:o,metaPanel:s}}function Cn(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),c=qn(n??{});if(!o||c.length===0)return;const r=o.parentElement,s=f.ownerDocument.createElement("div");Object.assign(s.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0",cursor:"pointer"}),Ot(s,"bare"),r?.insertBefore(s,o),s.appendChild(o);const d=f.ownerDocument.createElement("span");Object.assign(d.style,{fontSize:I.body,lineHeight:tt.none,color:g.label,flexShrink:"0"}),d.textContent="\u25BE",s.appendChild(d);const i=f.ownerDocument.createElement("div");i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:Tn,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:He.menu,padding:`${w.md} ${w.lg}`,fontSize:I.body,display:"none"});const a=Gn(n??{});a&&i.appendChild(a),e.contentWrap.style.position="relative",e.contentWrap.appendChild(i),s.setAttribute("aria-expanded","false"),s.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),Wn(s,u=>{d.textContent=u?"\u25B4":"\u25BE",s.setAttribute("aria-expanded",String(u)),i.style.display=u?"block":"none"})}function xt(e,t,n){const o=f.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:_.container,boxShadow:He.panel,overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:ht(),maxHeight:ht()});const c=f.ownerDocument.createElement("div");Object.assign(c.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:w.sm});const{wrap:r,metaPanel:s}=vn(document,nt(e,t),e.wafer.metadata??void 0);c.appendChild(r);const d=f.ownerDocument.createElement("button");d.dataset.wmapExpandBtn="1",d.setAttribute("aria-label","Open full view"),$n(d),d.innerHTML=Fe.expand,Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${g.menuBorder}`,borderRadius:_.control,background:g.panelBg,color:g.label,padding:w.xxs,cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),Ot(d),c.appendChild(d),o.appendChild(c);const i=f.ownerDocument.createElement("div");Object.assign(i.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(i),gn(o,i),s&&i.appendChild(s),A.appendChild(o),o.addEventListener("contextmenu",D=>{if(D.defaultPrevented)return;const B=p.insights?.sweeps;if(!Ai(e.testDefs,B))return;D.preventDefault();const C=e.viewOptions?{...l,...e.viewOptions}:l,b=Pi(e.dies,{waferLabel:Fn(e),testDefs:e.testDefs,isLotStack:e.isLotStack,activeTest:C.plotMode==="value"?C.activeTest:void 0,waferIndex:t}),O={x:D.clientX,y:D.clientY};import("./drilldown.js").then(({openDrilldownMenu:T})=>{o.isConnected&&T(O,o,b,{sweeps:B,onSaveImage:m.getSaveImageHook()})})});const a=Ve||ve()!==null,u=e.viewOptions?{...l,...e.viewOptions}:l,m=jn(i,e,{viewOptions:{...u,showLegend:a,legendPosition:we},showTooltip:!0,padding:P,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,downloadFilename:p.downloadFilename,onClick:e.onClick,onSelect:Kt(e),insights:U,onExpand:()=>Ae(t,e),showIdentity:!1,chromeInset:ii,drawWhenVisible:!0});return m.setViewControlsVisible(!1),m.setSummaryVisible(!1),d.onclick=()=>Ae(t,e),{card:o,ctrl:m,canvasWrapper:i,expandBtn:d}}function $o(e){const t=ue[e];if(!t)return;const n=[...K.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=Fe.minimize,t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>Po(n.id)):(t.innerHTML=Fe.expand,t.setAttribute("aria-label","Open full view"),t.onclick=()=>Ae(e,k[e]))}function Z(e){Fo(),De()?.remove(),Ee(null),ke(),k=[];for(const i of M)i&&i.destroy();M=[],Q=[],ue=[],Ne=0,A.innerHTML="",yn=e.length,bt(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const a=e[i];if(typeof a=="function"){const u=f.ownerDocument.createElement("div");u.className="wmap-gallery-card",Object.assign(u.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:_.container,aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const m=f.ownerDocument.createElement("span");m.textContent="\u2026",Object.assign(m.style,{color:g.label,fontSize:"18px"}),u.appendChild(m),A.appendChild(u),k.push(null),M.push(null),Q.push(null),ue.push(null),t.push({index:i,factory:a,placeholder:u}),Ne++}else{const{ctrl:u,canvasWrapper:m,expandBtn:D}=xt(a,i,e.length);k.push(a),M.push(u),Q.push(m),ue.push(D)}}tn(),Ze(),ut(),ct(),en();const n=++Se,o=()=>{setTimeout(()=>{n===Se&&p.onItemsResolved?.()},0)},c=i=>{setTimeout(()=>{n===Se&&p.onItemResolved?.(i,e.length)},0)};let r=e.length-t.length;r>0&&c(r);let s=0;function d(){if(n!==Se)return;if(s>=t.length){if(be.has(l.plotMode)){const O=l.plotMode;Z($e(O));return}Be=o,j(),pe||(Be=null,o());return}const{index:i,factory:a,placeholder:u}=t[s++],m=a();k[i]=m,v[i]=m,bt([m]);const{card:D,ctrl:B,canvasWrapper:C,expandBtn:b}=xt(m,i,e.length);M[i]=B,Q[i]=C,ue[i]=b,Ne--,u.replaceWith(D),c(++r),bo(),yo(),!y&&!ce?.placement&&m.statsSummary?.findings.length&&(y=Rt("right",ie,f.ownerDocument),y.style.maxHeight="calc(100vh - 80px)",y.style.position="sticky",y.style.top="8px",y.style.flexDirection="column",y.style.display="none",(ce?.placement??"right")==="left"?X.insertBefore(y,A):X.appendChild(y),j(),F||(F=J("findings","Summary panel",()=>{if(!y)return;const T=y.style.display!=="none";T||j(),y.style.display=T?"none":"flex",Me(F,!T),le()}),$.appendChild(G()),$.appendChild(F)),le()),le(),setTimeout(d,0)}t.length>0?setTimeout(d,0):o()}if(be.has(l.plotMode)&&v.length>0){const e=Ct(l.plotMode);l={...l,...e},Z($e(l.plotMode))}else Z(x);Te();let ye=0;const xn=new(f.ownerDocument.defaultView??window).ResizeObserver(()=>{if(ye)return;ye=(f.ownerDocument.defaultView??window).requestAnimationFrame(()=>{ye=0,E==null&&vt()})});xn.observe(A),y&&j();function Ao(e,t){const n=Q[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=f.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:g.label,fontSize:I.body,textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Ae(e,t){for(const s of K.values())if(s.cardIndex===e)return;const n=nt(t,e),o=Jn++,c=M[e]?.getOptions(),r=ci(n);if(r){const s=r.document;s.title=n,Object.assign(s.documentElement.style,{height:"100%"}),Object.assign(s.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:I.family}),mi(f,s.documentElement);const d=gi(f,s.documentElement,()=>b.setOptions({})),i=s.createElement("div");i.dataset.wmapWindowBanner="1",i.textContent=n,Object.assign(i.style,{display:"none",padding:`${w.sm} ${w.xl}`,fontSize:I.body,fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),s.body.appendChild(i);const a=s.createElement("div");Object.assign(a.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),s.body.appendChild(a);const{wrap:u,metaPanel:m}=vn(s,n,t.wafer.metadata??void 0),D=s.createElement("div");Object.assign(D.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:w.sm}),D.appendChild(u),a.appendChild(D);const B=s.createElement("div");Object.assign(B.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),m&&B.appendChild(m),a.appendChild(B);let C=0;const b=St(B,t,void 0,c,(T,V)=>{const Pe=T?V:-C;try{r.resizeBy(Pe,0),C=T?V:0}catch{}}),O=setInterval(()=>{r.closed&&Qe(o)},400);r.addEventListener("pagehide",()=>Qe(o)),K.set(o,{id:o,ctrl:b,cardIndex:e,label:n,closePollId:O,stopThemeSync:d,close:()=>{r.closed||r.close()},setTitle:T=>{s.title=T,i.textContent=T,i.style.display="block"}})}else{const s=ui({title:n,onClose:()=>Qe(o),anchor:f});s.contentWrap.style.flexDirection="column",Cn(s,n,t.wafer.metadata??void 0);const d=St(s.contentWrap,t,void 0,c,Pn(s));K.set(o,{id:o,ctrl:d,cardIndex:e,label:n,closePollId:null,close:()=>s.close(),setTitle:i=>{const a=s.box.querySelector("[data-wmap-window-title]");a&&(a.textContent=i,a.title=i)}})}M[e]?.destroy(),M[e]=null,Ao(e,r!==null),$o(e)}function St(e,t,n,o,c){const r=t.viewOptions?{...l,...t.viewOptions}:l,s=o?{...r,...o}:r,i={...n!==void 0?{...s,plotMode:"value",activeTest:n}:s,showLegend:!0,legendPosition:we},a=jn(e,t,{viewOptions:i,showTooltip:!0,padding:P,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,downloadFilename:p.downloadFilename,onClick:t.onClick,onSelect:Kt(t),insights:U,showExpandButton:!1,onSummaryPanelChange:c,showIdentity:!1});return a.setViewControlsVisible(!0),a.setSummaryVisible(!0),a.setExpandVisible(!1),a}function Qe(e){const t=K.get(e);if(!t||(K.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.(),t.ctrl.destroy(),t.cardIndex===null))return;const n=t.cardIndex,o=k[n];if(!o)return;const{card:c,ctrl:r,canvasWrapper:s,expandBtn:d}=xt(o,n,k.length);Q[n]?.parentElement?.replaceWith(c),M[n]=r,Q[n]=s,ue[n]=d}function Po(e){const t=K.get(e);t&&(t.close(),Qe(e))}function Fo(){for(const e of K.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function Mt(){for(const e of M)e?.drawPendingNow()}const Sn=f.ownerDocument.defaultView??window;Sn.addEventListener("beforeprint",Mt);function Ho(){Mt();const e=[...A.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),c=e[0].width,r=e[0].height,s=8,d=(f.ownerDocument.defaultView??window).devicePixelRatio||1,i=Math.round(26*d),a=Math.round(12*d),u=f.ownerDocument.createElement("canvas");u.width=n*c+(n-1)*s,u.height=o*(r+i)+(o-1)*s;const m=u.getContext("2d"),D=ti(A);m.fillStyle=D.background,m.fillRect(0,0,u.width,u.height),e.forEach((B,C)=>{const b=C%n,O=Math.floor(C/n),T=b*(c+s),V=O*(r+i+s),Pe=B.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";m.fillStyle=D.surface,m.fillRect(T,V,c,i),m.fillStyle=D.text,m.font=`700 ${a}px system-ui, sans-serif`,m.textAlign="left",m.textBaseline="middle",m.fillText(Pe,T+Math.round(10*d),V+i/2,c-Math.round(20*d)),m.drawImage(B,T,V+i)}),u.toBlob(B=>{if(!B)return;const C=M.find(b=>b!=null)?.getExportTitle();xi(B,["gallery",C].filter(Boolean).join(" "),Ce.onSaveImage)})}return{setItems(e){v=e.map(n=>typeof n=="function"?null:n);const t=l.plotMode;if(be.has(t))if(e.some(o=>typeof o=="function"))Z(e);else{const o=Ct(t);l={...l,...o},Z($e(t))}else Z(e)},setOptions(e){R(e,{fireCallback:!1})},getOptions(){return Vn(l)},setFindingsNotice(e){Vt=e,j()},setColumns(e){bn(e)},getBinColors(){return l.binColors??me()},setLotStatsSummary(e){z=e,Te(),y&&j(),le()},openUserGuide:dn,destroy(){Se++,Sn.removeEventListener("beforeprint",Mt),pe?.cancel(),pe=null,Be=null;for(const e of[...K.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();K.clear();for(const e of M)e&&e.destroy();M=[],De()?.remove(),xn.disconnect(),ye&&((f.ownerDocument.defaultView??window).cancelAnimationFrame(ye),ye=0),f.ownerDocument.removeEventListener("click",ze,!0),window.removeEventListener("blur",jt),se(),Ln(),We.remove(),X.remove(),y?.remove(),he?.destroy()}}}
@@ -2,13 +2,14 @@ import type { PlotMode } from '../renderer/buildView.js';
2
2
  import type { Die } from '../core/dies.js';
3
3
  import { type ToCanvasOptions } from './toCanvas.js';
4
4
  import type { WaferMapResult } from '../renderer/buildWaferMap.js';
5
- import type { StatsSummary } from '../stats/types.js';
5
+ import type { StatsFinding, StatsSummary } from '../stats/types.js';
6
6
  import { type SaveImageHandler, type SaveTextHandler, type UserGuideExtension } from './toolbar.js';
7
7
  import type { SummaryPanelOptions, FindingsNotice } from './summaryPanel.js';
8
8
  import { type WarningsOptions } from './warnings.js';
9
9
  import type { InsightsOptions } from './insightsTab.js';
10
10
  import { type DieListDisplayOptions } from './dieList.js';
11
11
  import { type BinColors } from '../renderer/binColors.js';
12
+ import { type CompactMap } from '../core/compact.js';
12
13
  /**
13
14
  * Stable display preferences — worth persisting to localStorage or a user profile.
14
15
  * These describe how the user wants to view wafer maps in general.
@@ -46,6 +47,23 @@ export interface WaferPreferences {
46
47
  showQuadrantBoundaries?: boolean;
47
48
  showReticle?: boolean;
48
49
  showXYIndicator?: boolean;
50
+ /**
51
+ * Draw the axis labels (original die coordinates along the bottom and left edges). Unset, they
52
+ * appear while the map is zoomed and not otherwise; `true` shows them always, `false` never.
53
+ * The Overlays menu's **Axis labels** row sets it. Showing them reserves room for the labels,
54
+ * so the map is a little smaller.
55
+ */
56
+ showAxes?: boolean;
57
+ /**
58
+ * Draw the dies on a compact grid with the empty rows and columns removed and each group of
59
+ * dies outlined, instead of at their physical positions. Default false. The toolbar offers
60
+ * the toggle when the occupied rows and columns repeat at a regular pitch (a multi-project
61
+ * wafer), or at the supplied `reticleConfig` width and height; setting it here applies it
62
+ * regardless. Only the layout changes: every die is still drawn and counted, and axis labels
63
+ * stay original die coordinates. The wafer outline, rings, quadrants, reticle grid and XY
64
+ * indicator are not drawn in this layout.
65
+ */
66
+ compact?: boolean;
49
67
  /** Legend position for bin modes. Default 'default'. */
50
68
  legendPosition?: 'default' | 'compact' | 'bottom' | 'top' | 'left' | 'floating';
51
69
  /**
@@ -116,9 +134,9 @@ export interface WaferDisplayState {
116
134
  * when the result has `metadataFields`.
117
135
  */
118
136
  activeMetadataKey?: string;
119
- highlightBin?: number;
120
- /** Dim every die except this metadata value in `'metadata'` mode — the analogue of `highlightBin`. */
121
- highlightMetadataValue?: string;
137
+ highlightBin?: number | number[];
138
+ /** Dim every die except these metadata values in `'metadata'` mode — the analogue of `highlightBin`. */
139
+ highlightMetadataValue?: string | string[];
122
140
  /**
123
141
  * Explicit value colour normalization range.
124
142
  *
@@ -411,6 +429,11 @@ export interface CardSharedState {
411
429
  * `stackedBins`/`stackedSoftBins` hover tooltips.
412
430
  */
413
431
  lotSize?: number;
432
+ /**
433
+ * The compact layout to draw when `compact` is on, built over every die the gallery shows,
434
+ * so all cards share one grid and stay comparable. A lone map builds its own from its dies.
435
+ */
436
+ compactMap?: CompactMap;
414
437
  }
415
438
  /** @internal */
416
439
  export type CardViewOptions = WaferViewOptions & CardSharedState;
@@ -431,6 +454,21 @@ export interface CardRenderOptions extends Omit<RenderOptions, 'viewOptions'> {
431
454
  chromeInset?: string;
432
455
  /** Replaces the expand action for both the expand button and the E key. */
433
456
  onExpand?: () => void;
457
+ /**
458
+ * Draw the canvas only while it is on screen (or near it). An off-screen card
459
+ * keeps its view up to date and is drawn when it scrolls into view, or by
460
+ * `drawPendingNow()` — which anything capturing the canvas (the gallery PNG,
461
+ * printing) must call first. For gallery grid cards: a large lot's gallery
462
+ * spent most of a mode switch drawing cards nobody could see.
463
+ */
464
+ drawWhenVisible?: boolean;
465
+ /**
466
+ * Told when the Summary panel opens or closes beside the map, with the width it took from the
467
+ * map when it opened. For a host that owns the box this map sits in and can widen it by that
468
+ * much, so the map keeps its size (`renderWaferGallery` does this for its detached windows).
469
+ * Without it a map expanded by its own Expand button does the same for its own modal.
470
+ */
471
+ onSummaryPanelChange?: (open: boolean, widthPx: number) => void;
434
472
  }
435
473
  /** @internal */
436
474
  export interface CardController extends WaferMapController {
@@ -446,8 +484,13 @@ export interface CardController extends WaferMapController {
446
484
  getExportTitle(): string;
447
485
  /** This map's save hook, naming files for its own wafer — for a save the gallery starts on a card's behalf. */
448
486
  getSaveImageHook(): SaveImageHandler;
487
+ /** Draw now if a `drawWhenVisible` card skipped drawing while off screen. */
488
+ drawPendingNow(): void;
449
489
  }
450
490
  /** @internal The public view of a card's options: everything but the gallery's shared state. */
491
+ /** The bin a finding is about — what the legend filter shows while the finding
492
+ * is active — or `undefined` for a yield, test or functional finding. */
493
+ export declare function findingBin(finding: StatsFinding): number | undefined;
451
494
  export declare function toPublicViewOptions(opts: CardViewOptions): WaferViewOptions;
452
495
  export type RenderableWaferMap = Pick<WaferMapResult, 'wafer' | 'dies'> & Partial<Omit<WaferMapResult, 'wafer' | 'dies'>>;
453
496
  export declare function renderWaferMap(container: HTMLElement, result: RenderableWaferMap, options?: RenderOptions): WaferMapController;