@wafertools/wafermap 0.30.3 → 0.31.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 (85) hide show
  1. package/AGENTS.md +9 -19
  2. package/CHANGELOG.md +140 -0
  3. package/README.md +2 -2
  4. package/dist/packages/canvas-adapter/charts/boxplot.js +1 -1
  5. package/dist/packages/canvas-adapter/charts/capability.js +1 -1
  6. package/dist/packages/canvas-adapter/charts/chartShell.d.ts +89 -6
  7. package/dist/packages/canvas-adapter/charts/chartShell.js +1 -1
  8. package/dist/packages/canvas-adapter/charts/histogram.js +1 -1
  9. package/dist/packages/canvas-adapter/charts/scatter.d.ts +16 -2
  10. package/dist/packages/canvas-adapter/charts/scatter.js +1 -1
  11. package/dist/packages/canvas-adapter/charts/sweep.js +1 -1
  12. package/dist/packages/canvas-adapter/charts/testPassRate.js +1 -1
  13. package/dist/packages/canvas-adapter/charts/trend.js +1 -1
  14. package/dist/packages/canvas-adapter/dieList.d.ts +1 -1
  15. package/dist/packages/canvas-adapter/exportName.d.ts +1 -12
  16. package/dist/packages/canvas-adapter/exportName.js +1 -1
  17. package/dist/packages/canvas-adapter/index.d.ts +2 -3
  18. package/dist/packages/canvas-adapter/index.js +1 -1
  19. package/dist/packages/canvas-adapter/insightsTab.d.ts +11 -1
  20. package/dist/packages/canvas-adapter/insightsTab.js +1 -1
  21. package/dist/packages/canvas-adapter/maplessSummary.js +1 -1
  22. package/dist/packages/canvas-adapter/renderWaferGallery.d.ts +4 -7
  23. package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
  24. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +15 -30
  25. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
  26. package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
  27. package/dist/packages/canvas-adapter/toCanvas.js +1 -1
  28. package/dist/packages/canvas-adapter/toolbar.js +1 -1
  29. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
  30. package/dist/packages/canvas-adapter/userGuideHtml.js +49 -43
  31. package/dist/packages/canvas-adapter/version.d.ts +2 -2
  32. package/dist/packages/canvas-adapter/version.js +1 -1
  33. package/dist/packages/canvas-adapter/warnings.js +1 -1
  34. package/dist/packages/core/aggregates.d.ts +0 -6
  35. package/dist/packages/core/aggregates.js +1 -1
  36. package/dist/packages/core/dies.d.ts +1 -3
  37. package/dist/packages/core/dies.js +1 -1
  38. package/dist/packages/core/index.d.ts +8 -10
  39. package/dist/packages/core/index.js +1 -1
  40. package/dist/packages/core/stdf.d.ts +9 -0
  41. package/dist/packages/core/stdf.js +1 -0
  42. package/dist/packages/core/transforms.d.ts +0 -23
  43. package/dist/packages/core/transforms.js +1 -1
  44. package/dist/packages/renderer/binColors.js +1 -1
  45. package/dist/packages/renderer/buildView.d.ts +1 -9
  46. package/dist/packages/renderer/buildView.js +1 -1
  47. package/dist/packages/renderer/buildWaferMap.d.ts +54 -34
  48. package/dist/packages/renderer/buildWaferMap.js +1 -1
  49. package/dist/packages/renderer/colorMap.d.ts +0 -2
  50. package/dist/packages/renderer/colorMap.js +1 -1
  51. package/dist/packages/renderer/deprecate.d.ts +1 -1
  52. package/dist/packages/renderer/deprecate.js +1 -1
  53. package/dist/packages/renderer/derivedTests/apply.js +1 -1
  54. package/dist/packages/renderer/derivedTests/parser.js +1 -1
  55. package/dist/packages/renderer/index.d.ts +6 -5
  56. package/dist/packages/renderer/index.js +1 -1
  57. package/dist/packages/renderer/spec.d.ts +17 -0
  58. package/dist/packages/renderer/spec.js +1 -1
  59. package/dist/packages/stats/analyzeWaferMap.js +1 -1
  60. package/dist/packages/stats/capability.d.ts +4 -2
  61. package/dist/packages/stats/capability.js +1 -1
  62. package/dist/packages/stats/clusterDetection.d.ts +2 -1
  63. package/dist/packages/stats/correlation.d.ts +1 -1
  64. package/dist/packages/stats/facets.d.ts +1 -1
  65. package/dist/packages/stats/index.d.ts +6 -16
  66. package/dist/packages/stats/index.js +1 -1
  67. package/dist/packages/stats/mergeTestDefs.d.ts +1 -1
  68. package/dist/packages/stats/mergeTestDefs.js +1 -1
  69. package/dist/packages/stats/patternClassification.d.ts +2 -1
  70. package/dist/packages/stats/regions.d.ts +2 -1
  71. package/dist/packages/stats/renderFindingsReport.d.ts +0 -4
  72. package/dist/packages/stats/renderFindingsReport.js +1 -21
  73. package/dist/packages/stats/renderSummaryReport.js +11 -11
  74. package/dist/packages/stats/sweep.d.ts +8 -0
  75. package/dist/packages/stats/sweep.js +1 -1
  76. package/dist/packages/stats/types.d.ts +9 -3
  77. package/package.json +2 -2
  78. package/dist/packages/canvas-adapter/deprecated.d.ts +0 -7
  79. package/dist/packages/canvas-adapter/deprecated.js +0 -1
  80. package/dist/packages/core/deprecated.d.ts +0 -60
  81. package/dist/packages/core/deprecated.js +0 -1
  82. package/dist/packages/renderer/deprecated.d.ts +0 -45
  83. package/dist/packages/renderer/deprecated.js +0 -1
  84. package/dist/packages/stats/deprecated.d.ts +0 -85
  85. package/dist/packages/stats/deprecated.js +0 -1
@@ -1 +1 @@
1
- import{buildFacetTable as Re,facetValueOf as We,FACET_NONE_VALUE as Me}from"../stats/facets.js";import{mergeTestDefs as re}from"../stats/mergeTestDefs.js";import{isParametricTest as Ye}from"../renderer/buildWaferMap.js";import{waferDisplayLabel as je,waferIdentityLabel as Ge}from"../core/waferLabel.js";import{hasDrilldownTargets as se,waferPopulation as He}from"./chartPopulation.js";import{openDrilldownMenu as Fe}from"./drilldown.js";import{INPUT_DEFAULT_PASS_BINS as R,itemPassBins as Ne,passBinsLabel as ie}from"../core/passBins.js";import{NO_DATA_FILL as le}from"../renderer/colorMap.js";import{describeWaferPopulation as Ve,populationStat as _e}from"../stats/population.js";import{LEADING as Ue,ALPHA as ze,SPACE as x,EDGE_GUTTER as Z,FONT as Y,CLR as B,RADIUS as qe,SHADOW as Qe,controlStyle as Ke,wireControlHover as de,wireTooltip as Xe}from"./toolbar.js";import{ICONS as Je}from"./icons.js";import{renderCapabilityPanel as Ze}from"./charts/capability.js";import{renderBoxplotPanel as et}from"./charts/boxplot.js";import{renderTrendPanel as tt}from"./charts/trend.js";import{renderSweepPanel as nt}from"./charts/sweep.js";import{renderHistogramPanel as at}from"./charts/histogram.js";import{renderCorrelationPanel as ot}from"./charts/correlation.js";import{renderScatterPanel as rt}from"./charts/scatter.js";import{renderBarPanel as ce}from"./charts/barPanel.js";import{renderBinClusterPanel as st}from"./charts/binCluster.js";import{renderTestPassRatePanel as it}from"./charts/testPassRate.js";import{QUANTITY as lt}from"./charts/palette.js";import{cardFrameStyle as dt,makeChartGridWrap as V,makeLabeledSelect as ct,makeLinkedGroupSelect as pt}from"./charts/chartShell.js";import{buildYieldData as _,buildYieldDataCombined as pe}from"../stats/yield.js";import{buildBinParetoData as ut}from"../stats/binPareto.js";import{buildLotTestSection as ft,buildLotFunctionalSection as mt,buildMetadataStripBox as bt}from"./summaryPanel.js";import{buildRegionYieldData as ue,buildRingRegions as gt,buildQuadrantRegions as yt}from"../stats/regions.js";import{renderRegionYieldDiagram as fe}from"./charts/regionYieldDiagram.js";const me=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}],ht={key:"sweeps",label:"Sweeps"};export function createInsightsTab(T){const{getItems:be,getLotStats:ge,getBinColors:ee,getRingCount:ye,onSaveImage:v,onSaveText:U,openWafer:j,focusTest:te}=T,he=T.showMetadataStrip??!0,W=T.contentInset??Z,p=T.ownerDocument??document,P=p.createElement("div");Object.assign(P.style,{display:"none",flexDirection:"column",width:"100%",paddingTop:"0"});const we=Z,O=p.createElement("div");Object.assign(O.style,{paddingLeft:we});const D=p.createElement("div");Object.assign(D.style,{display:"flex",gap:x.xs,alignItems:"center",background:B.menuBg,border:`1px solid ${B.menuBorder}`,borderRadius:qe.container,boxShadow:Qe.panel,padding:`0 ${x.lg}`,marginBottom:x.lg,marginLeft:W,marginRight:W}),D.setAttribute("role","tablist"),D.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const t=Array.from(D.querySelectorAll('[role="tab"]')),r=t.indexOf(p.activeElement);if(r===-1)return;e.preventDefault();const c=t[(r+(e.key==="ArrowRight"?1:-1)+t.length)%t.length];c.focus(),c.click()});const M=p.createElement("div");Object.assign(M.style,{display:"flex",flexDirection:"column",gap:x.lg,marginTop:"0",paddingLeft:W,paddingRight:W}),P.appendChild(O),P.appendChild(D),P.appendChild(M);const ne=(T.sweeps?.length??0)>0,Ce=ne?[...me,ht]:me;let E=T.defaultView==="sweeps"&&!ne?"overview":T.defaultView??"overview",A,L=null,$=null,G={includeLimits:void 0,clipOutliers:!1};const z=e=>{$!==e&&($=e,F())};let H=new Map;function ae(){for(const e of H.values())e.destroy();H=new Map}function q(e,t,r){j?.(e,t,r)}function Q(e){if(e.some(t=>se(t.testDefs,T.sweeps)))return(t,r,c)=>{const i=e.find(f=>f.waferIndex===t);if(!i||!se(i.testDefs,T.sweeps))return;c.preventDefault();const s=He(i.dies,{waferLabel:i.identity,testDefs:i.testDefs,activeTest:r??L??void 0,waferIndex:t});Fe({x:c.clientX,y:c.clientY},c.target,s,{sweeps:T.sweeps,onSaveImage:v})}}function Se(e){return j?{open:(t,r)=>q(t,`Wafer ${e.find(c=>c.waferIndex===t)?.label??t}`,r)}:te&&e.length===1?{open:(t,r)=>te(r),label:"show this test on the map"}:null}function xe(){return be().map((e,t)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:je(e,t),identity:Ge(e),waferIndex:t,passBins:Ne(e),statsSummary:e.statsSummary,testDefs:e.testDefs}).filter(e=>e!=null)}function oe(e,t){Object.assign(e.style,{background:"none",border:"none",borderBottom:t?`2px solid ${B.iconActive}`:"2px solid transparent",color:t?B.iconActive:B.label,fontWeight:t?"700":"500",fontSize:Y.body,padding:`${x.sm} ${Z} ${x.md}`,cursor:"pointer",marginBottom:"-1px"})}function Te(e,t){const r=p.createElement("button");r.type="button",r.textContent=t;const c=e===E;return oe(r,c),r.dataset.on=c?"true":"false",de(r,"bare"),r.dataset.wmapInsightsTab=e,r.setAttribute("role","tab"),r.setAttribute("aria-selected",c?"true":"false"),r.tabIndex=c?0:-1,r.addEventListener("click",()=>{E!==e&&(E=e,F({keepSections:!0}))}),r}function ve(e){const t=p.createElement("button");return t.type="button",t.textContent=`\u2039 ${e.label}`,oe(t,!1),t.dataset.wmapInsightsBack="1",t.addEventListener("click",e.onBack),t}function ke(e,t,r,c=!0){const i=V(p),s=ee();let f="label";const b=r??"group",u=ie(e.map(d=>d.passBins)),l=ge?.(),g=new Map(l?.lotYieldSeries.map(d=>[d.waferIndex,d.yieldPercent])),C=d=>({...d,label:d.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:g.get(d.waferIndex),key:d.waferIndex}),m=e.map(C),y=t?.map(d=>({key:d.key,items:d.items.map(C)})),S=()=>y?pe(y,R,f):_(m,R,f),w={title:t?`Yield by ${b} (pass: ${u})`:`Yield by wafer (pass: ${u})`,data:S(),selfControl:{current:f,options:[["yield","Sort: yield"],["label",t?`Sort: ${b}`:"Sort: wafer ID"]],onChange:d=>(f=d,{data:S()})},barColor:()=>lt,valueLabel:d=>`${d.percent.toFixed(1)}%`,reference:d=>{if(d.length<3)return null;const k=d.map(J=>J.percent).sort((J,Ae)=>J-Ae),I=k.length%2?k[(k.length-1)/2]:(k[k.length/2-1]+k[k.length/2])/2;return{value:I,label:`median ${I.toFixed(1)}%`}},drill:y?{onOpenGroup:d=>{const k=y.find(I=>I.key===d.label)?.items??[];return{data:_(k,R,f),title:`Yield by wafer \u2014 ${b}: ${d.label} (pass: ${u})`}},onBack:()=>({data:S(),title:`Yield by ${b} (pass: ${u})`}),groupLabelText:b}:void 0,onOpen:j?d=>{typeof d.key=="number"&&q(d.key,`Wafer ${d.label}`)}:void 0,onWaferContextMenu:Q(e),ownerDocument:p};let n=null;if(c&&(n=ce(w,v),n.card.style.minHeight="360px",i.appendChild(n.card)),t){const d=st({title:"Hard bin pareto",groups:t.map(k=>({key:k.key,items:k.items.map(I=>({dies:I.dies,hardBinCounts:I.statsSummary?.stats.hardBinCounts,softBinCounts:I.statsSummary?.stats.softBinCounts}))})),onSaveImage:v,ownerDocument:p});return d.card.style.minHeight="360px",i.appendChild(d.card),{card:i,destroy:()=>{n?.destroy(),d.destroy()}}}let a="hbin";const o=d=>d===void 0?le:(a==="hbin"?s.hard:s.soft).get(d)??le,h=e.map(d=>({dies:d.dies,hardBinCounts:d.statsSummary?.stats.hardBinCounts,softBinCounts:d.statsSummary?.stats.softBinCounts})),N=()=>ut(h,a),Oe={title:"Hard bin pareto",data:N(),selfControl:{current:a,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:d=>(a=d,{data:N(),title:`${a==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:d=>o(d.binCode),ownerDocument:p},X=ce(Oe,v);return X.card.style.minHeight="360px",i.appendChild(X.card),{card:i,destroy:()=>{n?.destroy(),X.destroy()}}}function K(){const e=p.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{...dt(),display:"flex",flexDirection:"column",gap:x.lg,minWidth:"0"}),e}function De(e){if(O.innerHTML="",O.style.marginBottom="0",!he)return;const t=bt(e.map(r=>({metadata:r.metadata})),void 0,{facetableOnly:!1});t&&(t.style.marginBottom="0",O.appendChild(t),O.style.marginBottom=x.xs)}function Be(e,t,r,c){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const i=e.map(o=>o.wafer),s=e.map(o=>o.dies),f=e.flatMap(o=>o.dies),b=e.map(o=>o.statsSummary),u=b.every(o=>o!==void 0)?b:void 0,l=ye?.()??4,g=[],C=[],y=it({groups:(c??[{key:"",items:e}]).map(o=>({key:o.key,items:o.items.map(h=>({dies:h.dies,testSpecYield:h.statsSummary?.stats.testSpecYield,functionalYield:h.statsSummary?.stats.functionalYield}))})),testDefs:r,onSaveImage:v,ownerDocument:p});y.card.style.minHeight="300px",g.push(y.card),C.push(y.destroy);const S=ue(s,i,l,o=>e[o].passBins,gt);if(S.length){const o=fe({title:"Ring yield",mode:"ring",rows:S,onSaveImage:v,ownerDocument:p});g.push(o.card),C.push(o.destroy)}const w=ue(s,i,l,o=>e[o].passBins,yt);if(w.length){const o=fe({title:"Quadrant yield",mode:"quadrant",rows:w,onSaveImage:v,ownerDocument:p});g.push(o.card),C.push(o.destroy)}let n=null;if(t.length){const o=ft(f,t,void 0,u,U,s.map(h=>({dies:h})),void 0,"full");if(o){const h=K();h.appendChild(o),n=h}}let a=null;if(r.length){const o=mt(f,r,u,U);if(o){const h=K();h.appendChild(o),a=h}}return{elements:g,testValuesCard:n,functionalCard:a,destroy:()=>{for(const o of C)o()}}}function Le(e){const t=ie(e.map(l=>l.passBins)),r=e.length===1,c=e[0],i=K();Object.assign(i.style,{flexDirection:"row",flexWrap:"wrap",gap:x.md});const s=l=>{const g=l.lastElementChild;return g&&Object.assign(g.style,{borderRight:"none",paddingRight:"0",marginRight:"0"}),l};function f(l,g,C){const m=p.createElement("div");Object.assign(m.style,{display:"flex",alignItems:"baseline",gap:x.sm,paddingRight:x.xxl,marginRight:x.md,borderRight:`1px solid ${B.menuBorder}`});const y=p.createElement("div");y.textContent=l,Object.assign(y.style,{fontSize:Y.heading,fontWeight:"700",color:B.value,lineHeight:Ue.tight});const S=p.createElement("div");if(S.textContent=g,Object.assign(S.style,{fontSize:Y.body,color:B.label}),m.append(y,S),C){const w=p.createElement("div");w.textContent=C,Object.assign(w.style,{fontSize:Y.meta,color:B.label,opacity:ze.muted}),m.appendChild(w)}return m}if(r){const l=_([{...c,key:c.waferIndex}],R)[0]?.percent;return l!==void 0&&i.appendChild(f(`${l.toFixed(1)}%`,`Yield \xB7 pass: ${t}`)),i.appendChild(f(String(c.dies.length),"Total dies")),s(i)}i.appendChild(f(String(e.length),"Wafers"));const b=_(e.map(l=>({...l,key:l.waferIndex})),R).map(l=>l.percent).filter(l=>Number.isFinite(l));if(b.length){const l=b.reduce((m,y)=>m+y,0)/b.length,g=pe([{key:"all",items:e.map(m=>({...m,key:m.waferIndex}))}],R)[0]?.percent,C=g!==void 0&&g.toFixed(1)!==l.toFixed(1);i.appendChild(f(`${l.toFixed(1)}%`,`Mean per-wafer yield \xB7 pass: ${t}`,C?`${g.toFixed(1)}% by dies`:void 0))}const u=e.map(l=>l.statsSummary);if(u.every(l=>l!==void 0)){const l=u.reduce((C,m)=>C+m.stats.analyzedDies,0),g=u.reduce((C,m)=>C+m.stats.excludedDies,0);i.appendChild(f(l.toLocaleString(),"Dies analysed",g?`${g.toLocaleString()} excluded`:void 0))}else i.appendChild(f(e.reduce((l,g)=>l+g.dies.length,0).toLocaleString(),"Total dies"));return s(i)}function $e(e,t,r,c,i){const s=p.createElement("div");Object.assign(s.style,{display:"flex",flexDirection:"column",gap:x.lg});const f=e.length===1&&!c;e.length&&!c&&s.appendChild(Le(e));const b=ke(e,c,i,!f);s.appendChild(b.card);const u=Be(e,t,r,c);for(const l of u.elements)b.card.appendChild(l);return u.testValuesCard&&s.appendChild(u.testValuesCard),u.functionalCard&&s.appendChild(u.functionalCard),{card:s,destroy:()=>{b.destroy(),u.destroy()}}}function Ee(e,t,r,c){const i=V(p),s=Se(e),f=a=>{G=a;for(const o of[m,y,S])o!==b&&o?.setAxisPrefs(a)};let b=null;const u=a=>o=>{b=a(),f(o),b=null},l=a=>({...a,testStats:a.statsSummary?.stats.perTestStats}),g=e.map(l),C=r?.map(a=>({key:a.key,items:a.items.map(l)})),m=et({title:"Test value distribution",axisPrefs:G,onAxisPrefsChange:u(()=>m),onTestChange:a=>w(a),selectedTestNumber:L??void 0,items:g,testDefs:t,groups:C,groupLabelText:c,onSaveImage:v,onGroupChange:a=>z(a),onOpen:s?.open,openActionLabel:s?.label,onWaferContextMenu:Q(e),ownerDocument:p}),y=at({title:"Value histogram",axisPrefs:G,onAxisPrefsChange:u(()=>y),onTestChange:a=>w(a),selectedTestNumber:L??void 0,items:e,testDefs:t,groups:r,onGroupChange:a=>z(a),onSaveImage:v,ownerDocument:p}),S=tt({title:"Wafer-to-wafer trend",axisPrefs:G,onAxisPrefsChange:u(()=>S),onTestChange:a=>w(a),selectedTestNumber:L??void 0,items:e.map(a=>({label:a.label,key:a.waferIndex,dies:a.dies,testStats:a.statsSummary?.stats.perTestStats})),testDefs:t,onSaveImage:v,centreLabel:_e(Ve(e.map(a=>a.wafer.metadata)),"mean"),onOpen:j?(a,o)=>q(a,`Wafer ${e.find(h=>h.waferIndex===a)?.label??a}`,o):void 0,onWaferContextMenu:Q(e),ownerDocument:p}),w=a=>{L=a,m.setTest(a),y.setTest(a),S.setTest(a),n.setTest(a)},n=Ze({title:"Process capability",items:e,testDefs:t,onSaveImage:v,selectedTestNumber:L??void 0,onSelectTest:a=>w(a),ownerDocument:p});return i.append(n.card,m.card,y.card,S.card),{card:i,destroy:()=>{n.destroy(),m.destroy(),y.destroy(),S.destroy()}}}function Ie(e){const t=V(p),r=re(e).defs,c=e.flatMap(s=>s.dies),i=(T.sweeps??[]).map(s=>nt({spec:s,dies:c,testDefs:r,onSaveImage:v,ownerDocument:p}));for(const s of i)t.appendChild(s.card);return{card:t,destroy:()=>{for(const s of i)s.destroy()}}}function Pe(e,t,r){const c=V(p),i=rt({title:"Test scatter",items:e,testDefs:t,groups:r,binColors:ee().hard,onSaveImage:v,ownerDocument:p}),s=ot({title:"Test correlation matrix",items:e,testDefs:t,onSaveImage:v,onSaveText:U,onSelectPair:(f,b)=>i.setXY(f,b),ownerDocument:p});return c.append(s.card,i.card),{card:c,destroy:()=>{s.destroy(),i.destroy()}}}function F(e){e?.keepSections||ae(),M.innerHTML="",D.innerHTML="",T.backTab&&D.appendChild(ve(T.backTab));for(const n of Ce)D.appendChild(Te(n.key,n.label));const t=xe();De(t);const r=Re(t,{facetableOnly:!0}).filter(n=>n.splittable),c=p.createElement("div");Object.assign(c.style,{display:"flex",gap:x.md,alignItems:"center",marginLeft:x.xxl,paddingBottom:x.xs});let i;r.length>0?(c.appendChild(ct("Group by:",[{value:"",label:"None"},...r.map(n=>({value:n.key,label:`${n.label} (${n.values.length})`}))],A??"",n=>{A=n||void 0,$=null,F()},{hook:"group-by",ownerDocument:p})),i=r.find(n=>n.key===A)?.label):A=void 0;let s;if(A){const n=new Map,a=[];for(const o of t){const h=We(o.metadata,A)??Me;n.has(h)||(n.set(h,[]),a.push(h)),n.get(h).push(o)}s=a.map(o=>({key:o,items:n.get(o)}))}$!==null&&!s?.some(n=>n.key===$)&&($=null),s&&s.length>0&&c.appendChild(pt(s.map(n=>n.key),"Show:",$,n=>z(n),{ownerDocument:p}).el);let f=null;if(T.onOpenGuide){const n=p.createElement("button");n.type="button",n.innerHTML=Je.help,n.setAttribute("aria-label","User guide"),Object.assign(n.style,{...Ke("bare"),display:"inline-flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",flexShrink:"0"}),de(n,"bare"),Xe(n,"User guide"),n.addEventListener("click",()=>T.onOpenGuide()),Object.assign(n.style,{marginLeft:"auto"}),f=n}D.appendChild(c),f&&D.appendChild(f);const b=$!==null?s?.find(n=>n.key===$):void 0,u=b?.items??t,l=b?void 0:s,g=re(u),C=g.defs,m=C.filter(Ye);L!==null&&!m.some(n=>n.testNumber===L)&&(L=null);const y=e?.keepSections?H.get(E):void 0,S=y??(E==="overview"?$e(u,m,C,l,i):E==="distributions"?Ee(u,m,l,i):E==="sweeps"?Ie(u):Pe(u,m,l));y||H.set(E,S);const w=g.conflicts.filter(n=>n.excluded);if(w.length>0){const n=p.createElement("div");Object.assign(n.style,{color:B.label,fontSize:Y.body,padding:`0 ${W} ${x.sm}`});const a=w.slice(0,6).map(N=>N.testNumber).join(", "),o=w.length>6?`, and ${w.length-6} more`:"",h=w.length===1?"it":"them";n.textContent=`${w.length} test ${w.length===1?"number is":"numbers are"} hidden (${a}${o}) \u2014 the wafers in view describe ${h} differently, so their values cannot be pooled. `+(s&&s.length>0?`Pick one ${i??"group"} under "Show:" to analyse ${h}.`:"Load one test program at a time to analyse them."),n.dataset.wmapWithheldTests=String(w.length),M.appendChild(n)}M.appendChild(S.card)}return{el:P,render:F,destroy:()=>{ae(),P.remove()}}}
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 +1 @@
1
- import{getDieTestValue as $}from"../renderer/buildWaferMap.js";import{resolveTestNumber as T,findTestDef as B}from"../renderer/buildView.js";import{buildBinSection as V}from"./summaryPanel.js";import{buildTestHistogramData as z}from"../stats/histogram.js";import{resolveValueColorFn as F}from"../renderer/colorSchemes.js";import{TRACKING as N,SPACE as y,RADIUS as I,FONT as S,CLR as u,wireTooltip as A}from"./toolbar.js";import{fmt as v}from"../renderer/fmt.js";function d(o,n,t){const a=document.createElement(o);return n&&Object.assign(a.style,n),t!==void 0&&(a.textContent=t),a}function W(o,n,t,a,x){let p=1/0,m=-1/0;for(const r of o){const s=$(r,n);s!==void 0&&(s<p&&(p=s),s>m&&(m=s))}const b=a==="spec"&&t&&(t.limitLow!==void 0||t.limitHigh!==void 0);let e,l;b?(e=t.limitLow!==void 0?t.limitLow:isFinite(p)?p:0,l=t.limitHigh!==void 0?t.limitHigh:isFinite(m)?m:1):(e=isFinite(p)?p:0,l=isFinite(m)?m:1),e===l&&(l=e+1);const h=r=>Math.min(1,Math.max(0,r));if(x&&e>0&&l>0){const r=Math.log10(e),s=Math.log10(l)-r;return c=>c<=0?0:h((Math.log10(c)-r)/s)}return r=>h((r-e)/(l-e))}function E(o,n,t,a,x,p,m,b){const e=d("div",{display:"flex",flexDirection:"column",gap:y.xxs,minWidth:"0",flex:"1",minHeight:"0"});e.appendChild(d("div",{fontSize:S.meta,fontWeight:"700",letterSpacing:N,textTransform:"uppercase",color:u.label},n?.name?`${n.name} distribution`:"Value distribution"));const l=o[0].rangeLow,h=o[o.length-1].rangeHigh,r=h-l||1,s=i=>Math.min(1,Math.max(0,(i-l)/r)),c=F(a,x),f=W(p,t,n,m,b),w=Math.max(1,...o.map(i=>i.count)),L=d("div",{position:"relative",display:"flex",alignItems:"flex-end",gap:y.xxs,flex:"1",minHeight:"48px"});for(const i of o){const g=d("div",{flex:"1",minWidth:"2px",background:c(f((i.rangeLow+i.rangeHigh)/2)),height:`${i.count/w*100}%`,borderRadius:"1px 1px 0 0"});g.dataset.wmapBar="1",A(g,`${v(i.rangeLow,n?.unit)} \u2013 ${v(i.rangeHigh,n?.unit)}: ${i.count}`,{asDataPoint:!0}),L.appendChild(g)}const H=[];for(const[i,g]of[[n?.limitLow,"LSL"],[n?.limitHigh,"USL"]]){if(i===void 0||i<l||i>h)continue;const C=s(i)*100,M=d("div",{position:"absolute",top:"0",bottom:"0",left:`${C}%`,width:"2px",marginLeft:"-1px",background:u.value,boxShadow:`0 0 0 1px ${u.panelBg}`,pointerEvents:"none"});M.dataset.wmapLimitMarker="1",L.appendChild(M),H.push({pct:C,text:`${g} ${v(i,n?.unit)}`})}if(e.appendChild(L),H.length){const i=d("div",{position:"relative",height:"14px"});for(const{pct:g,text:C}of H){const M=Math.min(96,Math.max(4,g));i.appendChild(d("span",{position:"absolute",left:`${M}%`,top:"0",transform:"translateX(-50%)",whiteSpace:"nowrap",fontSize:S.body,fontWeight:"600",color:u.text,background:u.panelBg,border:`1px solid ${u.value}`,borderRadius:I.control,padding:"0 3px",lineHeight:"12px"},C))}e.appendChild(i)}const R=d("div",{display:"flex",justifyContent:"space-between",fontSize:S.body,color:u.label});return R.appendChild(d("span",{},v(o[0].rangeLow,n?.unit))),R.appendChild(d("span",{},v(o[o.length-1].rangeHigh,n?.unit))),e.appendChild(R),e}export function buildMaplessSummary(o,n,t){const{plotMode:a,activeTest:x,hbinDefs:p,sbinDefs:m,binColors:b,valueColorScheme:e,reverseValueScheme:l,logScale:h=!1,colorbarRangeMode:r="spec",valueRangeDies:s}=t;if(a==="hardBin"||a==="softBin"){const f=V(o,a==="hardBin"?p:m,a==="hardBin"?"hard":"soft",b);if(f)return f}else if(a==="value"){const{testNumber:c}=T(x??0,n),f=B(n,x??0),w=z([{dies:o}],c,12,f?.limitLow,f?.limitHigh);if(w.length)return E(w,f,c,e,l,s??o,r,h)}return d("div",{padding:y.xl,fontSize:S.body,color:u.label,textAlign:"center"},"No summary available for this view.")}
1
+ import{getDieTestValue as $}from"../renderer/buildWaferMap.js";import{resolveTestNumber as T,findTestDef as B}from"../renderer/buildView.js";import{buildBinSection as V}from"./summaryPanel.js";import{buildTestHistogramData as z}from"../stats/histogram.js";import{resolveValueColorFn as F}from"../renderer/colorSchemes.js";import{TRACKING as N,SPACE as y,RADIUS as I,FONT as H,CLR as u,wireTooltip as A}from"./toolbar.js";import{fmt as v}from"../renderer/fmt.js";function d(o,n,e){const a=document.createElement(o);return n&&Object.assign(a.style,n),e!==void 0&&(a.textContent=e),a}function W(o,n,e,a,x){let p=1/0,m=-1/0;for(const r of o){const s=$(r,n);s!==void 0&&(s<p&&(p=s),s>m&&(m=s))}const b=a==="spec"&&e&&(e.limitLow!==void 0||e.limitHigh!==void 0);let t,l;b?(t=e.limitLow!==void 0?e.limitLow:isFinite(p)?p:0,l=e.limitHigh!==void 0?e.limitHigh:isFinite(m)?m:1):(t=isFinite(p)?p:0,l=isFinite(m)?m:1),t===l&&(l=t+1);const h=r=>Math.min(1,Math.max(0,r));if(x&&t>0&&l>0){const r=Math.log10(t),s=Math.log10(l)-r;return c=>c<=0?0:h((Math.log10(c)-r)/s)}return r=>h((r-t)/(l-t))}function E(o,n,e,a,x,p,m,b){const t=d("div",{display:"flex",flexDirection:"column",gap:y.xxs,minWidth:"0",flex:"1",minHeight:"0"});t.appendChild(d("div",{fontSize:H.meta,fontWeight:"700",letterSpacing:N,textTransform:"uppercase",color:u.label},n?.name?`${n.name} distribution`:"Value distribution"));const l=o[0].rangeLow,h=o[o.length-1].rangeHigh,r=h-l||1,s=i=>Math.min(1,Math.max(0,(i-l)/r)),c=F(a,x),f=W(p,e,n,m,b),w=Math.max(1,...o.map(i=>i.count)),S=d("div",{position:"relative",display:"flex",alignItems:"flex-end",gap:y.xxs,flex:"1",minHeight:"48px"});for(const i of o){const g=d("div",{flex:"1",minWidth:"2px",background:c(f((i.rangeLow+i.rangeHigh)/2)),height:`${i.count/w*100}%`,borderRadius:"1px 1px 0 0"});g.dataset.wmapBar="1",A(g,`${v(i.rangeLow,n?.unit)} \u2013 ${v(i.rangeHigh,n?.unit)}: ${i.count}`,{asDataPoint:!0}),S.appendChild(g)}const L=[];for(const[i,g]of[[n?.limitLow,"Lo limit"],[n?.limitHigh,"Hi limit"]]){if(i===void 0||i<l||i>h)continue;const C=s(i)*100,M=d("div",{position:"absolute",top:"0",bottom:"0",left:`${C}%`,width:"2px",marginLeft:"-1px",background:u.value,boxShadow:`0 0 0 1px ${u.panelBg}`,pointerEvents:"none"});M.dataset.wmapLimitMarker="1",S.appendChild(M),L.push({pct:C,text:`${g} ${v(i,n?.unit)}`})}if(t.appendChild(S),L.length){const i=d("div",{position:"relative",height:"14px"});for(const{pct:g,text:C}of L){const M=Math.min(96,Math.max(4,g));i.appendChild(d("span",{position:"absolute",left:`${M}%`,top:"0",transform:"translateX(-50%)",whiteSpace:"nowrap",fontSize:H.body,fontWeight:"600",color:u.text,background:u.panelBg,border:`1px solid ${u.value}`,borderRadius:I.control,padding:"0 3px",lineHeight:"12px"},C))}t.appendChild(i)}const R=d("div",{display:"flex",justifyContent:"space-between",fontSize:H.body,color:u.label});return R.appendChild(d("span",{},v(o[0].rangeLow,n?.unit))),R.appendChild(d("span",{},v(o[o.length-1].rangeHigh,n?.unit))),t.appendChild(R),t}export function buildMaplessSummary(o,n,e){const{plotMode:a,activeTest:x,hbinDefs:p,sbinDefs:m,binColors:b,valueColorScheme:t,reverseValueScheme:l,logScale:h=!1,colorbarRangeMode:r="spec",valueRangeDies:s}=e;if(a==="hardBin"||a==="softBin"){const f=V(o,a==="hardBin"?p:m,a==="hardBin"?"hard":"soft",b);if(f)return f}else if(a==="value"){const{testNumber:c}=T(x??0,n),f=B(n,x??0),w=z([{dies:o}],c,12,f?.limitLow,f?.limitHigh);if(w.length)return E(w,f,c,t,l,s??o,r,h)}return d("div",{padding:y.xl,fontSize:H.body,color:u.label,textAlign:"center"},"No summary available for this view.")}
@@ -110,13 +110,10 @@ export interface GalleryOptions {
110
110
  */
111
111
  perCardLegend?: boolean;
112
112
  /**
113
- * Name for the composite gallery PNG, without extension. When omitted, it is
114
- * named for its lots, wafer count and plot mode
115
- * (`LOT123_25-wafers_gallery-hard-bin.png`); cards, CSV exports and charts are
116
- * always named that way. See docs/api.md §5.4.5.
117
- *
118
- * **Changes in 0.31.0:** this becomes a prefix for every file the gallery and
119
- * its cards save. Passing it logs a one-time notice.
113
+ * A prefix for every file the gallery, its cards and their detached windows
114
+ * save — PNGs and CSVs alike. The lots, wafer or wafer count, and content
115
+ * follow it (`<prefix>_25-wafers_gallery-hard-bin.png`), except any the prefix
116
+ * already names. See docs/api.md §5.4.5.
120
117
  */
121
118
  downloadFilename?: string;
122
119
  /**
@@ -1 +1 @@
1
- import{getUniqueTestNumbers as Do,resolveTestNumber as ko,findTestDef as Eo,collectMetadataValues as Bo}from"../renderer/buildView.js";import{metadataCategoricalValue as Oo}from"../core/metadata.js";import{resolveBinColorsForMaps as To,mergeBinDefs as Ye,binColorWarning as Lo,mixedPassBinsWarning as Ro,binColorsEqual as Io}from"../renderer/binColors.js";import{itemPassBins as Wo,INPUT_DEFAULT_PASS_BINS as $o}from"../core/passBins.js";import{NO_DATA_FILL as Ao}from"../renderer/colorMap.js";import{metadataValueColor as Po}from"../renderer/colorMap.js";import{resolveCanvasTheme as Fo}from"./canvasTheme.js";import{ICONS as We}from"./icons.js";import{SHADOW as $e,LEADING as Ze,TRACKING as Ho,controlStyle as jo,wireControlHover as xt,SPACE as w,EDGE_GUTTER as oe,MAP_CHROME_INSET as Vo,RADIUS as z,FONT as L,CLR as h,sevColor as gn,MODE_LABELS as No,BIN_LEGEND_MODES as hn,STACKED_MODES as be,Z_ABOVE as bn,applyOverlayZ as zo,getTooltip as _o,hideTooltip as yn,createToolbarHelpers as Go,buildModeMenuEl as Ko,openDetachWindow as qo,openFloatingWindow as Uo,openModal as Xo,openReportModal as Yo,copyWmapThemeTokens as Zo,syncWmapPopupTheme as Qo,openUserGuideWindow as Jo,makePaletteBtn as ei,makeLogScaleBtn as ti,makeLegendStyleBtn as ni,makeOverlaysBtn as oi,makeOrientationBtn as ii,menuLayerFor as wn,saveImageBlob as vn,markMenuTrigger as Ae,wireMenuA11y as xn,wireExpandToggle as Cn,wireTooltip as Sn,requestedPassFailDisplay as Mn,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 Dn}from"../core/waferLabel.js";import{metadataDisplayValue as ui}from"../core/metadata.js";import{withExportContext as fi,noticeDownloadFilenameChange as pi}from"./exportName.js";import{sortBinsForDisplay as mi}from"../stats/binPareto.js";import{diePassStatus as gi}from"../core/dies.js";import{aggregateValues as hi,aggregateBinCounts as kn}from"../core/aggregates.js";import{renderWaferMap as bi,renderWaferMapCard as En,toPublicViewOptions as Bn}from"./renderWaferMap.js";import{hasDrilldownTargets as yi,waferPopulation as wi}from"./chartPopulation.js";import{classifyChanged as vi,COLOR_KEYS as xi}from"./renderWaferMap.js";import{buildWaferMap as Ci,getTestPassStatus as On,isParametricTest as Ct,getDieTestValue as Si}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Je}from"../stats/analyzeWaferMap.js";import{collectWarnings as Mi,buildWarningsMenuEl as Di,severityOf as ki}from"./warnings.js";import{compareNatural as St,arrayEqual as Tn}from"../core/utils.js";import{createSummaryPanelEl as Mt,buildMetadataStripRow as Ei,buildCompactMetadataRows as Ln,metadataEntries as Rn,renderLotSummaryContentSteps as Bi,reportMapsFromItems as Oi}from"./summaryPanel.js";import{renderLotReportHtml as Ti}from"../stats/renderSummaryReport.js";import{prettyKey as Li}from"../stats/facets.js";import{testLabel as Ri,markedTestLabel as Ii,derivedFields as Wi}from"../renderer/testLabel.js";import{mergeTestDefs as $i}from"../stats/mergeTestDefs.js";import{getDieKey as Ai,hasPosition as Pi}from"../core/dies.js";import{runChunked as Fi}from"./chunked.js";function In(f){if(typeof f!="number"||!Number.isFinite(f))return;const C=Math.round(f);return C>=1?C:void 0}const Dt=12;function Hi(f,C,p){let A=C;if(C.length>Dt){const E=C.slice(0,Dt-1),I=C.slice(Dt-1),H=I.reduce((X,ie)=>X+ie.count,0);A=[...E,{color:h.label,count:H,label:`Other (${I.length} bins)`}]}const k=f.createElement("div");Object.assign(k.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"}),k.setAttribute("role","img"),k.setAttribute("aria-label",`Population split: ${A.map(E=>`${E.label} ${et(E.count/p*100)}`).join(", ")}`);for(const E of A){const I=E.count/p*100,H=f.createElement("div");Object.assign(H.style,{flex:`${I} 1 0`,minWidth:I>0?"2px":"0",background:E.color}),Sn(H,`${E.label} \xB7 ${E.count.toLocaleString()} dies \xB7 ${et(I)}`),k.appendChild(H)}return k}function et(f){return f>0&&f<.1?"<0.1%":`${f.toFixed(1)}%`}function Wn(f,C,p){const A=new Map;let k=0,E=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),k++,H&&gi(X,H)&&E++)}}return{counts:A,total:k,pass:E}}function $n(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 k=f.ownerDocument.createElement("span");if(k.textContent=C.label,Object.assign(k.style,{fontWeight:C.isActive?"700":"400",color:C.isActive?h.iconActive:h.text,whiteSpace:"nowrap"}),p.appendChild(A),p.appendChild(k),C.count!==void 0){const E=f.ownerDocument.createElement("span");if(E.textContent=C.count.toLocaleString(),Object.assign(E.style,{color:C.isActive?h.iconActive:h.text,fontWeight:C.isActive?"700":"400",whiteSpace:"nowrap"}),p.appendChild(E),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",E=>{(E.key==="Enter"||E.key===" ")&&(E.preventDefault(),C.onClick())}),f.appendChild(p)}export function renderWaferGallery(f,C,p={}){si();const A=6;let k=In(p.columns);const E=p.showHelpButton??!1,I=p.userGuideExtension,H=p.insights?.enabled??!1,X=p.insights?.sweeps?{sweeps:p.insights.sweeps}:void 0,ie=zo(p.zIndex),re=p.summaryPanel,An=e=>[...Wo(e)],kt=()=>v.flatMap(e=>e?[e.ringCount??4]:[]),tt=()=>kt()[0]??4;function Pn(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);return{lots:[...new Set(e.map(n=>ui(n.wafer.metadata?.lot)).filter(n=>n!==void 0))].sort(St),...e.length===1?{wafer:Dn(e[0])}:{waferCount:e.length}}},p.onSaveImage,p.onSaveText);pi(p.downloadFilename);let v=C.map(e=>typeof e=="function"?null:e);function Bt(){return $i(v)}function ve(){if(v.some(e=>e?.testDefs?.length))return Bt().defs}let xe=0,He=0;const _=new Map;let Fn=0,P=null,Ce=null,Ot=new Set,b=null,Hn={};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 jn=_o(),ce=Go(jn),{makeBtn:Q,setActive:Se,makeSep:G,makeMenuRow:Vn,makeMenuSection:Nn,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(Ai(i)));a.setSelection(r)}}function zn(){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 _n(e){const t=R[e]??v[e];t&&Ie(e,t)}function Gn(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 Kn(){Yo(Ti(Oi(v,$o,tt())),{anchor:f})}function qn(){if(!b)return;b.innerHTML="";const e=zn();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,{...jo("outlined"),marginBottom:w.lg,display:"block",width:"100%",textAlign:"left"}),xt(n),n.addEventListener("click",Kn),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=Fi(Bi(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:Hn,findingsNotice:It,onFindingsFilterChange:N,onSaveText:Fe.onSaveText,onFindingClick:(n,o)=>{Ce===n.id?it():Xn(n,o),N()},onWaferClick:_n,findingsFor:Gn,dieListOptions:p.dieList}),{onDone:()=>{const n=ke;ke=null,n?.()}})}else qn()}function Un(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 Xn(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:Un(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=>On(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,D=v.flatMap(y=>y?.metadataFields??[]).filter(y=>!M.has(y.key)&&M.add(y.key)).filter(y=>di(e,y.key)).map(ci),x=Ko(Y.getBoundingClientRect(),r,o,d,u,m,{makeMenuRow:Vn,makeMenuSection:Nn},i,Y.ownerDocument.defaultView??window,D);wn(Y).appendChild(x),De(x),Ae(Y,!0),xn(x,Y,Ht)});Ae(Y,!1);const Yn=()=>R.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:Zn,sync:jt}=ei(ce,()=>({...c,plotMode:c.plotMode??"hardBin"}),Yn,e=>T(e));jt();const Qn=C.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function Ne(){const e=ve(),{testNumber:t}=ko(c.activeTest??0,e);return{testNumber:t,td:Eo(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 Jn(){if((c.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=Ne();return v.some(n=>n?.dies?.some(o=>On(o,e,t)!==void 0))}function eo(e,t){if(!t||!Ct(t))return;const n=t.limitLow!==void 0||t.limitHigh!==void 0;if((Mn(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=Si(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 Bo(n.dies,e))t.add(o);return{key:e,values:[...t].sort(St)}}function lt(){at("metadataValueOrder",Nt(),(e,t)=>e.key===t.key&&Tn(e.values,t.values))}function st(){if((c.plotMode??"hardBin")!=="value")return;const{testNumber:e,td:t}=Ne(),n=eo(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&&Tn(r.range,i.range)})}let rt=!1;function to(){if(rt)return;rt=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{rt=!1,st(),lt(),_t()})}let dt=!1;function no(){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}=To(v.filter(n=>n!=null),{binColorScheme:c.binColorScheme,useDefinedBinColors:c.useDefinedBinColors});return zt=t,e}function _t(){at("binColors",fe(),Io),Be()}const oo=oi(ce,()=>ai(c,Qn,{functionalActive:Ee(),hasLimits:Vt()&&!Ee(),hasRecorded:Jn()&&!Ee(),binMode:(c.plotMode??"hardBin")==="hardBin"||(c.plotMode??"hardBin")==="softBin"},e=>T(e)),()=>li(c)),{btn:io,sync:Gt}=ni(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 ao=[{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",()=>ao,()=>c.aggregationMethod??"mean",e=>T({aggregationMethod:e}));function qt(){const e=c.plotMode==="stackedValues";Kt.style.display=e?"":"none"}qt();const{btn:lo,sync:Ut}=ti(ce,()=>({...c,functionalActive:Ee()}),e=>T(e));Ut();const ze=Q("specRange","Colorbar range: spec limits",()=>{const e=c.colorbarRangeMode==="data"?"spec":"data";T({colorbarRangeMode:e})});function Xt(){const e=(c.plotMode??"hardBin")==="value"&&Vt()&&Mn(c)==="off"&&!Ee();ze.style.display=e?"":"none";const t=(c.colorbarRangeMode??"spec")==="spec";Se(ze,t),ze.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}Xt();const so=ii(ce,()=>c,e=>T(e)),ro=Q("downloadAll","Download gallery PNG",Co),co=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"}],()=>k!=null?String(k):"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(Zn),O.appendChild(Kt),O.appendChild(lo),O.appendChild(ze),O.appendChild(G()),O.appendChild(oo),O.appendChild(G()),O.appendChild(io),O.appendChild(G()),O.appendChild(so),O.appendChild(G()),O.appendChild(co),O.appendChild(G()),O.appendChild(ro),(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=Mi({lotStatsSummary:V,result:{warnings:[...v.flatMap(n=>n?.warnings??[]),...Bt().warnings]},extra:[c.binColors&&Lo(c.binColors,c.plotMode),Ro(zt),Pn(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)),uo()}function uo(){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=ki(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=Di(K.getBoundingClientRect(),J,K.ownerDocument.defaultView??window);wn(f).appendChild(t),De(t),xn(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=>Jo({buildWaferMap:Ci,renderWaferMap:bi,renderWaferGallery,analyzeWaferMap:Je},e.USER_GUIDE_HTML,I,f))}E&&(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 fo(){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,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=Xo({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&&fo().then(t=>{!t||!Te||(t.el.style.display="flex",t.render())}))}H&&p.insights?.defaultOpen&&queueMicrotask(()=>Jt(!0));const po=4,ct=240,en=480,mo=720,go=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*(po/d),a=Math.ceil(l+t);(n==null||a>n)&&(n=a)}return n}function ho(e){const t=tn(e);return t==null?ct:Math.min(ge,Math.max(ct,t))}function bo(e){const t=tn(e);if(t==null)return!1;const n=Math.min(mo,Math.max(en,t));return n<=ge?!1:(ge=n,!0)}function ut(){return k!=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(bo(e)&&nn(),k==null){const n=ho(e);n>Ke&&(Ke=n)}pt()}function ln(e){k=In(e),nn(),pt()}function ft(e){return`repeat(${e}, minmax(0, ${k!=null?"1fr":`${ge}px`}))`}function sn(e){$.style.gridTemplateColumns!==e&&($.style.gridTemplateColumns=e)}function pt(){if(k!=null){sn(ft(k));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*go),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=Ei(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?Wn(n,g=>(e==="softBin"?g.sbin:g.hbin)??void 0,An):{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=mi(r.counts.entries(),s).map(([g])=>g),m=t&&l&&a?Wn(n,g=>Oo(g.metadata?.[a])):{counts:new Map,total:0,pass:0},M=l?Nt()?.values:void 0,D=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&&!D.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?Li(a):"Metadata"):No[e],U=f.ownerDocument.createElement("span");if(U.textContent=j,Object.assign(U.style,{fontSize:L.body,fontWeight:"700",letterSpacing:Ho,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;D.forEach((F,te)=>{const ne=g===F,Xe=B?.values?.find(vt=>vt.value===F),Mo=Xe?.color??Po(te),mn=m.counts.get(F)??0;$n(x,{color:Mo,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(),So=e==="softBin"?fn.soft:fn.hard,pn=g=>So.get(g)??Ao;for(const g of u){const F=y===g,te=wt?.get(g),ne=r.counts.get(g)??0;$n(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(Hi(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(Pi)),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=Do(t.flatMap(m=>m.dies)).map(m=>({testNumber:m,name:Ri(void 0,m)}))),!i?.length)return[];const s=c.aggregationMethod??"mean";return i.map(u=>{const m=hi(n,s,u.testNumber),M={testNumber:0,name:u.name,unit:u.unit,...Wi(u)};return{wafer:l,dies:m,testDefs:[M],label:`${Ii(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=kn(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=kn(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,...D}=c;if(c=D,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;(xi.some(u=>u in e)||s)&&N(),Be(),Ut(),Xt(),st(),lt(),t&&p.onViewOptionsChange?.(Bn(c),n,vi(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=Rn(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=Ln(n??{});i&&a.appendChild(i),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),Cn(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=Rn(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=Ln(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.`),Cn(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"),Sn(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 D=p.insights?.sweeps;if(!yi(e.testDefs,D))return;M.preventDefault();const x=e.viewOptions?{...c,...e.viewOptions}:c,y=wi(e.dies,{waferLabel:Dn(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:D,onSaveImage:p.onSaveImage})})});const s=Pe||we()!==null,u=e.viewOptions?{...c,...e.viewOptions}:c,m=En(i,e,{viewOptions:{...u,showLegend:s,legendPosition:ye},showTooltip:!0,padding:A,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,insights:X,onExpand:()=>Ie(t,e),showIdentity:!1,chromeInset:Vo});return m.setViewControlsVisible(!1),m.setSummaryVisible(!1),r.onclick=()=>Ie(t,e),{card:o,ctrl:m,canvasWrapper:i,expandBtn:r}}function yo(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=()=>vo(n.id)):(t.innerHTML=We.expand,t.setAttribute("aria-label","Open full view"),t.onclick=()=>Ie(e,R[e]))}function Z(e){xo(),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:D,canvasWrapper:x,expandBtn:y}=gt(m,i,e.length);S[i]=D,ae[i]=x,de[i]=y,He--,u.replaceWith(M),d(++l),no(),to(),!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,k==null&&pt()})});cn.observe($),b&&N();function wo(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=Fn++,d=S[e]?.getOptions(),l=qo(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}),Zo(f,a.documentElement);const r=Qo(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 D=a.createElement("div");Object.assign(D.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),m&&D.appendChild(m),s.appendChild(D);const x=ht(D,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=Uo({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,wo(e,l!==null),yo(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=En(e,t,{viewOptions:r,showTooltip:!0,padding:A,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,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 vo(e){const t=_.get(e);t&&(t.close(),Ue(e))}function xo(){for(const e of _.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function Co(){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=Fo($);m.fillStyle=M.background,m.fillRect(0,0,u.width,u.height),e.forEach((D,x)=>{const y=x%n,B=Math.floor(x/n),j=y*(d+a),U=B*(l+i+a),bt=D.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(D,j,U+i)}),u.toBlob(D=>{if(!D)return;if(p.downloadFilename!=null){vn(D,p.downloadFilename,p.onSaveImage);return}const x=S.find(y=>y!=null)?.getExportTitle();vn(D,["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 Bn(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 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()}}}
@@ -91,12 +91,6 @@ export interface WaferPreferences {
91
91
  * `'data'`: colorbar spans actual data min/max; out-of-spec coloring still applies.
92
92
  */
93
93
  colorbarRangeMode?: 'spec' | 'data';
94
- /**
95
- * When true (default), partial (edge) dies are rendered in muted grey.
96
- * Set to false to hide them entirely, matching real prober behaviour where
97
- * positions outside the wafer circle are never tested.
98
- */
99
- showPartialDies?: boolean;
100
94
  }
101
95
  /**
102
96
  * Transient display state — describes the current view session, not worth persisting.
@@ -158,26 +152,18 @@ export interface WaferDisplayState {
158
152
  */
159
153
  export type WaferViewOptions = WaferPreferences & WaferDisplayState;
160
154
  /**
161
- * The drawing parameters `renderWaferMap` forwards to the canvas. Declared
162
- * explicitly rather than inherited from `ToCanvasOptions`, which is what this
163
- * interface used to do.
155
+ * The drawing parameters `renderWaferMap` forwards to the canvas, listed
156
+ * explicitly rather than inherited from `ToCanvasOptions`.
164
157
  *
165
- * That inheritance leaked 16 low-level fields onto the top-level render API, and
166
- * five of them were **accepted and silently ignored** — `renderWaferMap` computes
167
- * or overrides them on every draw (`topClearance` was always 0, and has since been removed from `toCanvas` too;
168
- * `minRightReserve` is derived from the legend, and `markFailingDies`/`activeBin`/
169
- * `hoverBin` are read from `viewOptions` and internal hover state instead). An
170
- * option that is typed, documented and ignored costs a caller a debugging session
171
- * to discover the API lied, so they are gone rather than merely undocumented.
158
+ * `renderWaferMap` sets the rest of `ToCanvasOptions` itself on every draw
159
+ * (`markFailingDies`, `legendPosition` and `fallbackFormat` from `viewOptions`,
160
+ * `viewport` from zoom and pan, the bin definitions from the result), so
161
+ * exposing them here would type and document options that are ignored. Listing the fields also stops a
162
+ * future `ToCanvasOptions` addition arriving on the render API by accident.
172
163
  *
173
- * Listing the fields also stops future `ToCanvasOptions` additions arriving here
174
- * by accident: `toCanvas` is the low-level surface and is free to grow, and a
175
- * caller who genuinely needs that level of control should call it directly.
176
- *
177
- * These stay at the top level of `RenderOptions` rather than moving under a
178
- * nested `draw` key. Grouping would read better, but it would break every caller
179
- * of the ten options that DO work in exchange for tidiness alone, and the defect
180
- * here was the five that don't.
164
+ * They stay at the top level of `RenderOptions` rather than under a nested
165
+ * `draw` key: grouping would read better, but would break every caller of the
166
+ * options that work, for tidiness alone.
181
167
  */
182
168
  type ForwardedDrawOptions = Pick<ToCanvasOptions, 'padding' | 'background' | 'showColorbar' | 'colorbarWidth' | 'showAxes' | 'showTitle' | 'legendOffset' | 'diePitchMm' | 'metadataFields'>;
183
169
  export interface RenderOptions extends ForwardedDrawOptions {
@@ -218,12 +204,9 @@ export interface RenderOptions extends ForwardedDrawOptions {
218
204
  /** Optional precomputed wafer-level stats summary. Enables the summary panel toggle button in the toolbar. */
219
205
  statsSummary?: StatsSummary;
220
206
  /**
221
- * Name for the map's PNG download, without extension. When omitted, the PNG
222
- * is named for its lot, wafer and map title (`LOT123_W05_hard-bin.png`); CSV
223
- * exports are always named that way. See docs/api.md §5.4.5.
224
- *
225
- * **Changes in 0.31.0:** this becomes a prefix for every file the map saves,
226
- * with the lot, wafer and content appended. Passing it logs a one-time notice.
207
+ * A prefix for every file the map saves — PNGs and CSVs alike. The lot,
208
+ * wafer and content follow it (`<prefix>_W05_hard-bin.png`), except any the
209
+ * prefix already names. See docs/api.md §5.4.5.
227
210
  */
228
211
  downloadFilename?: string;
229
212
  /**
@@ -461,6 +444,8 @@ export interface CardController extends WaferMapController {
461
444
  setExpandVisible(visible: boolean): void;
462
445
  /** The map's title as a file-name content part — the gallery names its composite PNG by it. */
463
446
  getExportTitle(): string;
447
+ /** This map's save hook, naming files for its own wafer — for a save the gallery starts on a card's behalf. */
448
+ getSaveImageHook(): SaveImageHandler;
464
449
  }
465
450
  /** @internal The public view of a card's options: everything but the gallery's shared state. */
466
451
  export declare function toPublicViewOptions(opts: CardViewOptions): WaferViewOptions;