@wafertools/wafermap 0.27.0 → 0.28.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 (61) hide show
  1. package/AGENTS.md +10 -2
  2. package/CHANGELOG.md +310 -0
  3. package/README.md +1 -1
  4. package/dist/packages/canvas-adapter/charts/binCluster.d.ts +0 -1
  5. package/dist/packages/canvas-adapter/charts/boxplot.d.ts +8 -1
  6. package/dist/packages/canvas-adapter/charts/boxplot.js +1 -1
  7. package/dist/packages/canvas-adapter/charts/capability.d.ts +0 -1
  8. package/dist/packages/canvas-adapter/charts/correlation.d.ts +0 -1
  9. package/dist/packages/canvas-adapter/charts/histogram.d.ts +0 -1
  10. package/dist/packages/canvas-adapter/charts/histogram.js +1 -1
  11. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.d.ts +0 -1
  12. package/dist/packages/canvas-adapter/charts/scatter.d.ts +6 -1
  13. package/dist/packages/canvas-adapter/charts/scatter.js +1 -1
  14. package/dist/packages/canvas-adapter/charts/trend.d.ts +7 -0
  15. package/dist/packages/canvas-adapter/charts/trend.js +1 -1
  16. package/dist/packages/canvas-adapter/hitGrid.d.ts +22 -0
  17. package/dist/packages/canvas-adapter/hitGrid.js +1 -0
  18. package/dist/packages/canvas-adapter/index.d.ts +1 -0
  19. package/dist/packages/canvas-adapter/index.js +1 -1
  20. package/dist/packages/canvas-adapter/insightsTab.d.ts +24 -2
  21. package/dist/packages/canvas-adapter/insightsTab.js +1 -1
  22. package/dist/packages/canvas-adapter/maplessSummary.d.ts +5 -1
  23. package/dist/packages/canvas-adapter/maplessSummary.js +1 -1
  24. package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
  25. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +38 -1
  26. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
  27. package/dist/packages/canvas-adapter/summaryPanel.d.ts +15 -5
  28. package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
  29. package/dist/packages/canvas-adapter/toCanvas.js +1 -1
  30. package/dist/packages/canvas-adapter/toolbar.d.ts +42 -9
  31. package/dist/packages/canvas-adapter/toolbar.js +2 -2
  32. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
  33. package/dist/packages/canvas-adapter/userGuideHtml.js +27 -16
  34. package/dist/packages/canvas-adapter/version.d.ts +2 -2
  35. package/dist/packages/canvas-adapter/version.js +1 -1
  36. package/dist/packages/canvas-adapter/warnings.d.ts +25 -0
  37. package/dist/packages/canvas-adapter/warnings.js +1 -1
  38. package/dist/packages/core/dies.d.ts +11 -0
  39. package/dist/packages/core/dies.js +1 -1
  40. package/dist/packages/renderer/binColors.d.ts +80 -0
  41. package/dist/packages/renderer/binColors.js +1 -0
  42. package/dist/packages/renderer/buildView.d.ts +67 -6
  43. package/dist/packages/renderer/buildView.js +1 -1
  44. package/dist/packages/renderer/buildWaferMap.d.ts +8 -2
  45. package/dist/packages/renderer/buildWaferMap.js +1 -1
  46. package/dist/packages/renderer/colorMap.d.ts +16 -15
  47. package/dist/packages/renderer/colorMap.js +1 -1
  48. package/dist/packages/renderer/colorSchemes.d.ts +45 -26
  49. package/dist/packages/renderer/colorSchemes.js +1 -1
  50. package/dist/packages/renderer/index.d.ts +3 -1
  51. package/dist/packages/renderer/index.js +1 -1
  52. package/dist/packages/stats/analyzeWaferLot.js +1 -1
  53. package/dist/packages/stats/analyzeWaferMap.js +1 -1
  54. package/dist/packages/stats/histogram.d.ts +28 -1
  55. package/dist/packages/stats/histogram.js +1 -1
  56. package/dist/packages/stats/population.d.ts +23 -0
  57. package/dist/packages/stats/population.js +1 -0
  58. package/dist/packages/stats/renderFindingsReport.js +10 -10
  59. package/dist/packages/stats/renderSummaryReport.js +22 -22
  60. package/dist/packages/stats/yield.js +1 -1
  61. package/package.json +5 -3
@@ -1 +1 @@
1
- import{buildView as ui,buildHoverText as gi,findTestDef as st,resolveTestNumber as At}from"../renderer/buildView.js";import{toCanvas as hi,BIN_LEGEND_W as Rn,BIN_LEGEND_W_COMPACT as mi,BIN_LEGEND_ADAPT_COMPACT as yi,BIN_LEGEND_ADAPT_FLOATING as bi}from"./toCanvas.js";import{buildWaferMap as vi,getTestPassStatus as xi,isParametricTest as zt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as wi}from"../stats/analyzeWaferMap.js";import{SHADOW as Si,LEADING as In,wireControlHover as Hn,SPACE as H,EDGE_GUTTER as Mi,RADIUS as Wn,FONT as rt,CLR as x,applyOverlayZ as Ci,getTooltip as Fn,hideTooltip as dt,reparentTooltip as Ei,positionTooltip as Yt,createToolbarHelpers as Di,buildModeMenuEl as ki,openReparentedModal as Bi,openUserGuideWindow as Li,makePaletteBtn as Pi,makeLogScaleBtn as Ti,makeLegendStyleBtn as Oi,makeOverlaysBtn as Ri,makeOrientationBtn as Ii,menuLayerFor as An,saveImageBlob as Hi,markMenuTrigger as Ve,wireMenuA11y as zn,wireExpandToggle as Wi,nextFrame as Nt,requestedPassFailDisplay as Fi,overlayMenuRows as Ai,anyOverlayActive as zi,logWmapVersionOnce as Yi,buildDataModeEntries as Ni,metadataKeyHasData as Xi,metadataModeEntry as ji}from"./toolbar.js";import{createSummaryPanelEl as Xt,wrapWithSummaryPanel as jt,renderWaferSummaryContent as Vi}from"./summaryPanel.js";import{collectWarnings as Ki,buildWarningsMenuEl as $i,severityOf as _i}from"./warnings.js";import{ICONS as Yn}from"./icons.js";import{hardBinColor as Gi,softBinColor as Zi,metadataValueColor as Ui}from"../renderer/colorMap.js";import{createIdentityHeader as Qi,collapsedLabel as Vt}from"./identityHeader.js";import{getDieKey as De,hasPosition as Nn,isPositionedDie as qi}from"../core/dies.js";import{buildDieListSection as Ji}from"./dieList.js";import{buildMaplessSummary as eo}from"./maplessSummary.js";const Xn=new Set(["colorScheme","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","ringCount","legendPosition","logScale","colorbarRangeMode","markFailingDies"]);export function classifyChanged(j){const m=j.some(u=>Xn.has(u)),w=j.some(u=>!Xn.has(u));return m&&w?"mixed":m?"preference":"state"}export function renderWaferMap(j,m,w={}){Yi();const u=j.ownerDocument,V=u.defaultView??window;V.getComputedStyle(j).position==="static"&&(j.style.position="relative");const jn=j.clientHeight;w.height!=null&&(j.style.height=typeof w.height=="number"?`${w.height}px`:w.height);const ct=m.dataCoverage?m.dataCoverage.unpositionedDies:m.dies.filter(e=>!Nn(e)).length,Ke=(m.dataCoverage?m.dataCoverage.totalDies:m.dies.length-ct)===0&&ct>0,ke=u.createElement("div");Object.assign(ke.style,{display:"flex",flexDirection:"column",width:"100%",height:"100%"}),j.appendChild(ke);const oe=u.createElement("div");Object.assign(oe.style,{position:"relative",width:"100%",flex:"1 1 auto",minHeight:"0"}),w.maxSize!=null&&(oe.style.maxWidth=`${w.maxSize}px`,oe.style.maxHeight=`${w.maxSize}px`);const ue=w.chromeInset??Mi,J=u.createElement("div");Object.assign(J.style,{display:"flex",alignItems:"stretch",gap:H.sm,background:x.canvasBg,paddingBottom:H.lg,paddingTop:ue,paddingLeft:ue,paddingRight:ue,flexShrink:"0",minWidth:"0"}),ke.appendChild(J),ke.appendChild(oe);const M=u.createElement("div");Object.assign(M.style,{position:"relative",width:"100%",height:"100%"});const a=u.createElement("canvas");Object.assign(a.style,{width:"100%",height:"100%",display:"block"}),M.appendChild(a),oe.appendChild(M);let $e=null;if(ct>0){let n=function(){if(t){const g=Ji(e,m.testDefs,{...w.dieList,onSaveText:w.onSaveText,waferMetadata:K.metadata,metadataFields:de,ownerDocument:u});if(g)return g}const i=st(m.testDefs,d.activeTest??0),s=zt(i)?d.logScale??i?.logScale??!1:!1;return eo(e,m.testDefs,{plotMode:d.plotMode??"hardBin",activeTest:d.activeTest,hbinDefs:G,sbinDefs:Z,colorScheme:d.colorScheme,logScale:s,colorbarRangeMode:d.colorbarRangeMode,valueRangeDies:m.dies})},o=function(i){const s=u.createElement("button");return s.type="button",Hn(s),Object.assign(s.style,{fontSize:rt.body,padding:`${H.xxs} ${H.sm}`,borderRadius:Wn.control,flexShrink:"0",border:`1px solid ${x.menuBorder}`,background:x.menuBg,color:x.text,cursor:"pointer"}),s.textContent=t?"View chart":"View die list",s.addEventListener("click",g=>{g.stopPropagation(),t=!t,s.textContent=t?"View chart":"View die list",i()}),s};const e=m.dies.filter(i=>!Nn(i));let t=!1;if(Ke){const i=u.createElement("div");Object.assign(i.style,{position:"absolute",inset:"0",background:x.panelBg,padding:H.xl,boxSizing:"border-box",overflow:"hidden",display:"flex",flexDirection:"column",gap:H.md,zIndex:"1"});const s=u.createElement("div");Object.assign(s.style,{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:H.md});const g=u.createElement("span");Object.assign(g.style,{fontSize:rt.body,color:x.label,lineHeight:In.base}),g.textContent="No die position data for this wafer.",s.appendChild(g);const l=u.createElement("div");Object.assign(l.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),s.appendChild(o(()=>l.replaceChildren(n()))),i.appendChild(s),i.appendChild(l),M.appendChild(i),$e=()=>{t||l.replaceChildren(n())}}else{const i=u.createElement("div");Object.assign(i.style,{position:"absolute",left:"0",right:"0",bottom:"0",zIndex:"3",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,fontSize:rt.body,color:x.text,cursor:"pointer",padding:`${H.xs} ${H.md}`,display:"flex",alignItems:"center",justifyContent:"space-between",gap:H.md}),Hn(i,"bare");const s=u.createElement("span");s.textContent=`+${e.length} ${e.length===1?"die":"dies"} without position data`,i.appendChild(s);const g=u.createElement("span");g.textContent="\u25BE",Object.assign(g.style,{fontSize:rt.body,lineHeight:In.none,color:x.label,flexShrink:"0"}),i.appendChild(g),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`${e.length} dies without position data. Click to view.`);let l=null,r=null;Wi(i,c=>{if(g.textContent=c?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(c)),c){l=u.createElement("div");const p=i.getBoundingClientRect().height||28;Object.assign(l.style,{position:"absolute",left:"0",right:"0",bottom:`${p}px`,top:"20%",zIndex:"2",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,padding:H.md,boxSizing:"border-box",display:"flex",flexDirection:"column",gap:H.md}),l.addEventListener("click",ie=>ie.stopPropagation());const h=u.createElement("div");Object.assign(h.style,{display:"flex",justifyContent:"flex-end"}),h.appendChild(o(()=>{r&&r.replaceChildren(n())})),l.appendChild(h),r=u.createElement("div"),Object.assign(r.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),r.appendChild(n()),l.appendChild(r),M.appendChild(l)}else l&&(l.remove(),l=null,r=null)}),M.appendChild(i),$e=()=>{r&&!t&&r.replaceChildren(n())}}}const{onHover:_e,onClick:Vn,onSelect:ge,onViewOptionsChange:Kn,showTooltip:$n=!0,showToolbar:Be=!0,showIdentity:Kt=!0,toolbarControls:pt="full",showPlotModeSelector:_n=!0,minZoom:Gn=.4,maxZoom:Zn=20,summaryPanel:Le,renderTooltip:$t,passBins:ft=[1],showHelpButton:_t=!1,userGuideExtension:Un,onExpand:Gt,showExpandButton:Zt=!0,zIndex:Qn,insights:ut,warnings:Ut,viewOptions:qn={},...le}=w,Pe=ut?.enabled??!1,Qt=Ut?.display??!0,Jn=Ci(Qn);let Te=le.fallbackFormat,ae=w.statsSummary,se=[],qt=!1;function Jt(){const e=Ki({result:m,statsSummary:ae}),t=e.length!==se.length||e.some((n,o)=>n.code!==se[o]?.code||n.message!==se[o]?.message);se=e,(t||!qt)&&(qt=!0,Ut?.onWarning?.(e))}Jt();let gt=m,K=m.wafer,re=m.dies,E=new Set,G=m.hbinDefs,Z=m.sbinDefs,ee=m.testDefs,de=m.metadataFields,en=m.reticles?.length?m.reticles:void 0,tn=m.reticleConfig,nn=m.view?.dataAxisFlip,ht=m.isLotStack??!1,mt=m.aggrMethod,yt=m.lotSize;const ei=Be&&pt!=="view-only"&&Pe;let bt=!1,$=null,A=null,U=null;Kt&&($=Qi(Vt(K.metadata??{},Oe())??"",K.metadata,{lotStack:Oe(),ownerDocument:u}),M.appendChild($.metaPanel),$.isEmpty()||(A=on($.wrap),J.insertBefore(A,J.firstChild)));function on(e){const t=u.createElement("div");return Object.assign(t.style,{display:"flex",alignItems:"center",padding:`${H.sm} ${H.lg}`,flex:"1 1 auto",minWidth:"0",overflow:"hidden",gap:H.sm}),Object.assign(e.style,{flex:"1",minWidth:"0"}),t.appendChild(e),t}function Oe(){return ht?{lotSize:yt??1,aggrMethod:mt}:void 0}function ti(){if(!$)return;$.update(Vt(K.metadata??{},Oe())??"",K.metadata,Oe());const e=A?.isConnected??!1,t=!$.isEmpty();!t&&e?(A.remove(),A=null):t&&!e&&(A=on($.wrap),A.style.display=bt?"none":"",J.insertBefore(A,J.firstChild))}const ln=[...G??[],...Z??[]].some(e=>e.color);let d={plotMode:"hardBin",colorScheme:ln?"custom":"default",showDieLabels:!1,showPartialDies:!0,showRingBoundaries:!1,showQuadrantBoundaries:!1,showReticle:!1,showXYIndicator:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,legendPosition:le.legendPosition??"default",...qn},Q=null,he=!1,an=null;function ni(){return Pe?Q?Promise.resolve(Q):(an??=import("./insightsTab.js").then(({createInsightsTab:e})=>(Q=e({getItems:()=>[{wafer:K,dies:re,hbinDefs:G,sbinDefs:Z,testDefs:ee,label:String(K.metadata?.waferId??""),statsSummary:ae}],getColorSchemeName:()=>d.colorScheme??"default",passBins:ft,getRingCount:()=>d.ringCount??4,onSaveImage:w.onSaveImage,onSaveText:w.onSaveText,defaultView:ut?.defaultView,showMetadataStrip:!1,contentInset:ue,backTab:ei?void 0:{label:"Map",onBack:()=>Ge(!1)},onOpenGuide:_t&&!Be?()=>Rt():void 0,ownerDocument:u}),Object.assign(Q.el.style,{position:"absolute",inset:"0",background:x.canvasBg,overflowY:"auto",paddingTop:"0"}),Q.el.style.display="none",oe.appendChild(Q.el),Q)),an):Promise.resolve(null)}function Ge(e){Pe&&(he=e,Q&&(Q.el.style.display=e?"flex":"none"),W&&(W.style.display=e||Ke?"none":"flex"),P&&(P.style.display=e?"none":"flex"),U&&(U.style.display=ye?"none":"flex"),te&&(te.style.display="flex"),A&&(A.style.display=bt?"none":""),$&&e&&$.collapse(),et(),F&&(F.innerHTML=e?Yn.wafer:Yn.analysis,F.ariaLabel=e?"Back to wafer view":"Insights"),e&&ni().then(t=>{!t||!he||(t.el.style.display="flex",t.render())}))}Pe&&ut?.defaultOpen&&queueMicrotask(()=>Ge(!0));let y,sn,z=null,B=null,vt=[],xt;function rn(e){xt!==e&&(xt=e,v())}let Re=null,wt=le.legendOffset??{x:0,y:0},Ie=!1,ve=!1,He={x:0,y:0},St={x:0,y:0},me=!1,xe=!1,Y="pan",we={x:0,y:0},Ze={x:0,y:0},T={x:0,y:0},O={x:0,y:0},We=!1,Se=!1;function Fe(){const e=d;y=ui(K,re.filter(qi),{plotMode:e.plotMode,colorScheme:e.colorScheme,passBins:ft,showDieLabels:e.showDieLabels,showPartialDies:e.showPartialDies,showRingBoundaries:e.showRingBoundaries,showQuadrantBoundaries:e.showQuadrantBoundaries,showReticle:e.showReticle,showXYIndicator:e.showXYIndicator,reticles:en,ringCount:e.ringCount,highlightBin:e.highlightBin,highlightMetadataValue:e.highlightMetadataValue,activeTest:e.activeTest,activeMetadataKey:e.activeMetadataKey,testDefs:ee,valueRange:e.valueRange,logScale:e.logScale,isLotStack:ht,aggregationMethod:mt??e.aggregationMethod,lotSize:yt??e.lotSize,dataAxisFlip:nn,colorbarRangeMode:e.colorbarRangeMode,passFailDisplay:e.passFailDisplay,fallbackFormat:Te,interactiveTransform:{rotation:e.rotation??0,flipX:e.flipX??!1,flipY:e.flipY??!1}},{hbinDefs:G,sbinDefs:Z,metadataFields:de}),sn=new Map(y.dies.map((t,n)=>[De(t),n]))}Fe();let N=null,Me=null,Ue=null,dn=w.findingsNotice,ii={},R=null,ce=null;function oi(e){const{kind:t,index:n}=e.variable;D(t==="test"?{plotMode:"value",activeTest:n??0,highlightBin:void 0}:t==="softBin"?{plotMode:"softBin",highlightBin:void 0}:{plotMode:"hardBin",highlightBin:void 0});const o=e.highlight;o.kind==="bin"?(Bt(o.dieKeys),D({highlightBin:o.bin})):(o.kind==="region"||o.kind==="dies")&&Bt(o.dieKeys)}function cn(e){Vi(e,{wafer:K,dies:re,yieldSummary:gt.yield,dataCoverage:gt.dataCoverage,hbinDefs:G,sbinDefs:Z,testDefs:ee,statsSummary:ae,warnings:Qt?se:[],passBins:ft,ringCount:d.ringCount??4,colorScheme:d.colorScheme,plotMode:d.plotMode??"hardBin",metadataShownElsewhere:Kt,fallbackFormat:Te,activeFindingId:Ue,findingsFilter:ii,findingsNotice:dn,onFindingsFilterChange:pe,onSaveText:w.onSaveText,metadataFields:de,dieListOptions:w.dieList,onFindingClick:(t,n)=>{Ue===t.id?(Ue=null,Bt([]),D({highlightBin:void 0})):(Ue=t.id,oi(t)),pe()}})}function pe(){N&&cn(N)}function Ae(){R&&cn(R)}if(Le?.placement){const e=Le.placement;N=Xt(e,ue,u);const t=M.parentElement,n=M.nextSibling;Me=jt(M,N,e),t?.insertBefore(Me,n),pe()}else if(ae){const e=Le?.defaultOpen??!Be;R=Xt("right",ue,u),R.style.display=e?"block":"none";const t=M.parentElement,n=M.nextSibling;ce=jt(M,R,"right"),t?.insertBefore(ce,n),Ae()}const S=$n?Fn(u):null;let te=null,L=null,W=null,P=null,Qe=null,I=null,qe=null,F=null,ne=null,Je=null;function pn(){if(!ne||!Je)return;const e=se.length,t=e>0;if(ne.style.display=t?"flex":"none",Je.style.display=t?"":"none",!t)return;const n=_i(se[0]),o=`${e} data ${e===1?"warning":"warnings"}`;ne.style.color=n==="error"?x.errText:x.warnText,ne.ariaLabel=n==="error"?`${o} \u2014 the map may be positionally wrong`:o}let Mt=null,fn=null,Ct=null,Et=null,Dt=null,kt=null;function Bt(e){E=new Set(e??[]),ge&&ge(Ot()),v()}function et(){if(!I)return;const e=!!(N??R);I.style.display=ae&&e&&!he?"flex":"none";const t=N??R,n=t?t.style.display!=="none":!1;ae?.hasNotableFindings&&!n?I.style.color=x.findingIndicator:I.dataset.active||(I.style.color=x.icon)}if(Be){let p=function(k){Y=k,o(ie,k==="zoom"),o(C,k==="pan"),Qe&&o(Qe,k==="select"),a.style.cursor=k==="pan"?"grab":"crosshair"};te=u.createElement("div"),te.dataset.wmapToolbar="single",Object.assign(te.style,{marginLeft:"auto",flexShrink:"0",display:"flex",flexDirection:"row",alignItems:"center",flexWrap:"wrap-reverse",justifyContent:"flex-end",maxWidth:"100%",background:x.menuBg,border:`1px solid ${x.menuBorder}`,borderRadius:Wn.control,boxShadow:Si.panel,pointerEvents:"auto"});const e=Fn(u),t=Di(e),{makeBtn:n,setActive:o,makeSep:i,makeMenuRow:s,makeMenuSection:g,closeOpenMenu:l,getOpenMenu:r,setOpenMenu:c}=t;Mt=l,fn=r,u.addEventListener("click",l,!0),W=u.createElement("div"),Object.assign(W.style,{display:Ke?"none":"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),te.appendChild(W);const h=n("download","Download PNG",si);W.appendChild(h),W.appendChild(i());const ie=n("zoomMode","Zoom (drag to zoom region)",()=>p("zoom")),Ee=n("zoomIn","Zoom in",()=>Ce(a.clientWidth/2,a.clientHeight/2,1.2)),q=n("zoomOut","Zoom out",()=>Ce(a.clientWidth/2,a.clientHeight/2,1/1.2)),fe=n("reset","Reset zoom (double-click)",()=>nt());W.appendChild(ie),W.appendChild(Ee),W.appendChild(q),W.appendChild(fe),W.appendChild(i());const C=n("pan","Pan (drag to move)",()=>p("pan"));if(W.appendChild(C),Qe=n("boxSelect","Select (drag to select dies)",()=>p("select")),W.appendChild(Qe),o(C,!0),pt!=="view-only"){let k=function(f){return f.plotMode!==(d.plotMode??"hardBin")?!1:f.plotMode==="value"?(d.activeTest??0)===(f.activeTest??0):f.plotMode==="metadata"?d.activeMetadataKey===f.activeMetadataKey:!0},It=function(f,b){f.activeTest!==void 0?D({plotMode:f.plotMode,activeTest:f.activeTest,activeMetadataKey:void 0,logScale:f.logScale}):f.activeMetadataKey!==void 0?D({plotMode:f.plotMode,activeTest:void 0,activeMetadataKey:f.activeMetadataKey,passFailDisplay:"off"}):D({plotMode:f.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),b.remove(),c(null),Ve(_,!1)};L=u.createElement("div"),Object.assign(L.style,{display:"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),te.appendChild(L),P=u.createElement("div"),Object.assign(P.style,{display:"flex",alignItems:"center",gap:"0"}),L.appendChild(P),P.appendChild(i());const it=()=>{const f=r();f&&(f.remove(),c(null)),Ve(_,!1)},_=n("mode","Plot mode",()=>{if(r()){it();return}const f=re,b=y.testDefs,{testEntries:at,binEntries:be,stackedEntries:Ne}=Ni(f,b,{includeStacked:y.isLotStack}),Ft=(de??[]).filter(je=>Xi(f,je.key)).map(ji),Xe=ki(_.getBoundingClientRect(),at,be,Ne,k,It,{makeMenuRow:s,makeMenuSection:g},d.plotMode??"hardBin",_.ownerDocument.defaultView??window,Ft);An(_).appendChild(Xe),c(Xe),Ve(_,!0),zn(Xe,_,it)});Ve(_,!1);const{btn:ot,sync:Ye}=Pi(t,()=>d.plotMode??"hardBin",()=>d.colorScheme??"default",()=>ln,f=>D({colorScheme:f}),{get:()=>d.markFailingDies??!1,set:f=>D({markFailingDies:f})});Et=Ye,Et();const Ht=Ri(t,()=>{const f=!!y.hasReticle,b=(d.plotMode??"hardBin")==="value",{testNumber:at}=At(d.activeTest??0,y.testDefs),be=st(y.testDefs,at),Ne=b&&be!==void 0&&!zt(be),Ft=b&&!Ne&&(be?.limitLow!==void 0||be?.limitHigh!==void 0),Xe=b&&!Ne&&y.dies.some(je=>xi(je,at,be)!==void 0);return Ai(d,f,{functionalActive:Ne,hasLimits:Ft,hasRecorded:Xe},je=>D(je))},()=>zi(d)),{btn:Wt,sync:ri}=Oi(t,()=>d,f=>D({legendPosition:f}));Ct=ri,Ct();const On=()=>{const{testNumber:f}=At(d.activeTest??0,ee),b=st(ee,f);return b!==void 0&&!zt(b)},{btn:di,sync:ci}=Ti(t,()=>({...d,functionalActive:On()}),f=>D(f));Dt=ci,Dt();const pi=()=>{const{testNumber:f}=At(d.activeTest??0,ee),b=st(ee,f);return b!==void 0&&(b.limitLow!==void 0||b.limitHigh!==void 0)},lt=n("specRange","Colorbar range: spec limits",()=>{const f=d.colorbarRangeMode==="data"?"spec":"data";D({colorbarRangeMode:f})});kt=()=>{const f=d.plotMode==="value"&&pi()&&Fi(d)==="off"&&!On();lt.style.display=f?"":"none";const b=(d.colorbarRangeMode??"spec")==="spec";o(lt,b),lt.ariaLabel=b?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"},kt();const fi=Ii(t,()=>d,f=>D(f));_n&&P.appendChild(_),P.appendChild(ot),P.appendChild(di),P.appendChild(lt),Ke||(P.appendChild(i()),P.appendChild(Ht),P.appendChild(i()),P.appendChild(Wt),P.appendChild(i()),P.appendChild(fi)),ae&&(I=n("findings","Summary panel",()=>{const f=N??R;if(!f)return;const b=f.style.display!=="none";f.style.display=b?"none":"block",o(I,!b),et()}),L.appendChild(i()),L.appendChild(I),R?.style.display!=="none"&&o(I,!0),et()),Qt&&(Je=i(),ne=n("warning","Data warnings",()=>{const f=r();if(l(new MouseEvent("click")),f)return;const b=$i(ne.getBoundingClientRect(),se,V);An(oe).appendChild(b),c(b),zn(b,ne,()=>l(new MouseEvent("click")))}),Ve(ne,!1),L.appendChild(Je),L.appendChild(ne),pn()),Pe&&(L.appendChild(i()),F=n("analysis","Insights",()=>{Ge(!he),o(F,he)}),F.dataset.wmapInsightsBtn="1",L.appendChild(F)),Zt&&(L.appendChild(i()),U=n("expand","Expand (E)",Gt??un),L.appendChild(U)),_t&&(L.appendChild(i()),qe=n("help","User guide",()=>Rt()),L.appendChild(qe))}J.appendChild(te)}let ye=null;function un(){ye&&(ye.close(),ye=null);const e=oe;e.style.flex="1",e.style.minWidth="0",e.style.minHeight="0";const t=e.style.maxWidth,n=e.style.maxHeight;e.style.maxWidth="none",e.style.maxHeight="none";const o=Vt(K.metadata??{},Oe()),i=J.childElementCount>0?[J,e]:[e],s=Bi(i,{ownerDocument:u,boxSize:he?{width:"min(96vw, 1600px)",height:"min(92vh, 1000px)"}:void 0,onClosed:()=>{ye=null,e.style.maxWidth=t,e.style.maxHeight=n,U&&(U.style.display="flex"),he||a.focus({preventScroll:!0})}});s&&(s.box.setAttribute("aria-label",o??"Expanded wafer map"),i.length>1&&(s.contentWrap.style.flexDirection="column"),ye=s,U&&(U.style.display="none"))}function gn(e){const t=d.plotMode;if(d={...d,...e},e.plotMode!==void 0&&e.plotMode!==t){const i=d.plotMode;(i==="hardBin"||i==="softBin")&&!new Set(["default","accessible","custom"]).has(d.colorScheme??"")&&(d={...d,colorScheme:"default"})}Object.keys(e).every(i=>i==="legendPosition"||i==="showLegend"||i==="markFailingDies")||Fe(),Ct?.(),Et?.(),Dt?.(),kt?.(),v();const o=e.plotMode!==void 0&&e.plotMode!==t;(e.colorScheme!==void 0||o)&&(pe(),Ae()),(e.colorScheme!==void 0||o||e.activeTest!==void 0||e.logScale!==void 0||e.colorbarRangeMode!==void 0)&&$e?.()}function D(e){gn(e);const t=Object.keys(e);Kn?.(d,t,classifyChanged(t))}let Lt=!1;function Pt(){Lt||(Lt=!0,Nt(()=>{Lt=!1,v()},V))}function v(){const e=B??void 0,t=y.dies[0],n=t?{x:t.width,y:t.height}:le.diePitchMm,o=Math.floor(a.clientWidth||a.width),i=!!(G?.length||Z?.length||y.dies.some(h=>h.hbin!=null||h.sbin!=null)),s=d.legendPosition??"default",g=d.showLegend??!0,l=s==="default"||s==="compact",r=(le.colorbarWidth??16)+28,c=i&&l?s!=="default"?Math.max(Rn,r):o<bi?0:o<yi?Math.max(mi,r):Math.max(Rn,r):void 0,p=hi(a,y,{...le,topClearance:0,minRightReserve:g?c:0,showColorbar:g&&(le.showColorbar??!0),markFailingDies:d.markFailingDies??!1,legendPosition:s,legendOffset:wt,diePitchMm:n,fallbackFormat:Te,showAxes:le.showAxes??B!==null,viewport:e,activeBin:d.plotMode==="metadata"?d.highlightMetadataValue:d.highlightBin,hoverBin:xt,hbinDefs:G,sbinDefs:Z,metadataFields:de});vt=p.binLegendRows,Re=p.legendBox??null,B===null&&(z=p.viewport),E.size>0&&li(),xe&&ai()}function li(){const e=X();if(!e)return;const t=a.getContext("2d"),n=y.hoverPoints,o=y.rectangles[0],i=o?o.width/2*e.ppm:e.ppm*.5,s=o?o.height/2*e.ppm:e.ppm*.5,g=Math.max(1,Math.min(3,i*.08)),l=i-g,r=s-g,c=[];for(const p of E){const h=sn.get(p);h!==void 0&&c.push({sx:e.originX+n[h].x*e.ppm,sy:e.originY-n[h].y*e.ppm})}if(c.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:p,sy:h}of c)t.rect(p-l,h-r,l*2,r*2);t.fill(),t.strokeStyle="rgba(255,255,255,0.9)",t.lineWidth=3,t.beginPath();for(const{sx:p,sy:h}of c)t.rect(p-l,h-r,l*2,r*2);t.stroke(),t.strokeStyle="rgba(0,0,0,0.9)",t.lineWidth=1.5,t.beginPath();for(const{sx:p,sy:h}of c)t.rect(p-l,h-r,l*2,r*2);t.stroke(),t.restore()}}function ai(){const e=a.getContext("2d"),t=Math.min(T.x,O.x),n=Math.min(T.y,O.y),o=Math.abs(O.x-T.x),i=Math.abs(O.y-T.y);e.save(),e.fillStyle="rgba(0,0,0,0.08)",e.fillRect(t,n,o,i),e.setLineDash([5,3]),e.strokeStyle="rgba(255,255,255,0.9)",e.lineWidth=3,e.strokeRect(t,n,o,i),e.strokeStyle="rgba(0,0,0,0.9)",e.lineWidth=1.5,e.strokeRect(t,n,o,i),e.restore()}function si(){a.toBlob(e=>{e&&Hi(e,w.downloadFilename??"wafermap",w.onSaveImage)})}function hn(e){return z?Math.max(z.ppm*Gn,Math.min(z.ppm*Zn,e)):e}function Ce(e,t,n){const o=B??z;if(!o)return;const i=hn(o.ppm*n),s=i/o.ppm,g=e-(e-o.originX)*s,l=t-(t-o.originY)*s,r=(z?.snapDist??1)/(i/(z?.ppm??i));B={originX:g,originY:l,ppm:i,snapDist:r},v()}function X(){return B??z}function mn(e){if(e.ctrlKey||e.metaKey){e.preventDefault();const t=a.getBoundingClientRect(),n=e.deltaY<0?1.12:1/1.12;Ce(e.clientX-t.left,e.clientY-t.top,n)}else if(B!==null){e.preventDefault();const t=X(),n=B.snapDist;B={originX:t.originX-e.deltaX,originY:t.originY-e.deltaY,ppm:t.ppm,snapDist:n},v()}}function yn(e,t,n){return e>=n.x&&e<n.x+n.w&&t>=n.y&&t<n.y+n.h}function bn(e){if(e.button!==0||!X())return;a.focus({preventScroll:!0}),a.setPointerCapture(e.pointerId);const t=a.getBoundingClientRect(),n=e.clientX-t.left,o=e.clientY-t.top;if(Re&&d.legendPosition==="floating"&&yn(n,o,Re)){ve=!0,He={x:n,y:o},St={...wt};return}if(We&&Y!=="pan"){Se=!0,me=!0,we={x:n,y:o},Ze={x:X().originX,y:X().originY},a.style.cursor="grabbing";return}if(Y==="zoom"||Y==="select"){xe=!0,T=O={x:n,y:o};return}me=!0,we={x:n,y:o},Ze={x:X().originX,y:X().originY},a.style.cursor="grabbing"}function vn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,o=e.clientY-t.top;if(xe){O={x:n,y:o},Pt();return}if(ve){const p=n-He.x,h=o-He.y;p*p+h*h>16&&(ve=!1,Ie=!0,a.style.cursor="grabbing")}if(Ie){wt={x:St.x+(n-He.x),y:St.y+(o-He.y)},Pt();return}if(me){const p=X(),h=B?.snapDist??z?.snapDist??1;B={originX:Ze.x+(n-we.x),originY:Ze.y+(o-we.y),ppm:p.ppm,snapDist:h},Pt();return}const i=X();if(!i)return;const s=(n-i.originX)/i.ppm,g=(i.originY-o)/i.ppm,r=Mn(s,g,i.snapDist)?.die??null,c=vt.find(p=>n>=p.x&&n<p.x+p.w&&o>=p.y&&o<p.y+p.h);if(rn(c?c.bin:void 0),c){a.style.cursor="pointer",S&&(S.innerHTML=c.label??`Bin ${c.bin}`,S.style.display="block",Yt(S,a,e.clientX,e.clientY)),_e?.(null,e);return}if(Y==="pan"&&(a.style.cursor=r?"crosshair":"grab"),S)if(r)if($t){const p=$t(r);p===null?S.style.display="none":(typeof p=="string"?S.innerHTML=p:(S.innerHTML="",S.appendChild(p)),S.style.display="block",Yt(S,a,e.clientX,e.clientY))}else S.innerHTML=gi(r,y.plotMode,{testDefs:ee,hbinDefs:G,sbinDefs:Z,fallbackFormat:Te,aggrMethod:y.aggrMethod,lotSize:y.lotSize,metadataFields:de,activeTest:y.activeTest,reticleConfig:tn}),S.style.display="block",Yt(S,a,e.clientX,e.clientY);else S.style.display="none";_e?.(r,e)}function xn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,o=e.clientY-t.top,i=e.ctrlKey||e.metaKey;if(S&&(n<0||o<0||n>t.width||o>t.height)&&(S.style.display="none"),xe){xe=!1,O={x:n,y:o};const l=n-T.x,r=o-T.y,c=X();if(Y==="zoom"){if(l*l+r*r<25)Ce(n,o,2);else if(c){const p=Math.min(T.x,O.x),h=Math.max(T.x,O.x),ie=Math.min(T.y,O.y),Ee=Math.max(T.y,O.y),q=h-p,fe=Ee-ie;if(q>4&&fe>4){const C=a.clientWidth,k=a.clientHeight,It=C/q,it=k/fe,_=Math.min(It,it),ot=hn(c.ppm*_),Ye=ot/c.ppm,Ht=(p+h)/2,Wt=(ie+Ee)/2;B={originX:C/2-(Ht-c.originX)*Ye,originY:k/2-(Wt-c.originY)*Ye,ppm:ot,snapDist:c.snapDist/Ye}}}v(),a.style.cursor="crosshair";return}if(l*l+r*r<25)Tt(n,o,i,e);else if(c){const p=(Math.min(T.x,O.x)-c.originX)/c.ppm,h=(Math.max(T.x,O.x)-c.originX)/c.ppm,ie=(c.originY-Math.max(T.y,O.y))/c.ppm,Ee=(c.originY-Math.min(T.y,O.y))/c.ppm,q=y.hoverPoints,fe=[];for(let C=0;C<q.length;C++)if(q[C].x>=p&&q[C].x<=h&&q[C].y>=ie&&q[C].y<=Ee){const k=y.dies[C];k&&fe.push(k)}if(i)for(const C of fe){const k=De(C);E.has(k)?E.delete(k):E.add(k)}else E=new Set(fe.map(C=>De(C)));ge?.(Ot())}v(),a.style.cursor="crosshair";return}if(ve){ve=!1,Tt(n,o,i,e);return}if(Ie){Ie=!1,a.style.cursor="grab";return}if(!me)return;if(me=!1,Se){Se=!1,a.style.cursor=We||Y==="pan"?"grab":"crosshair";return}a.style.cursor=Y==="pan"?"grab":"crosshair";const s=n-we.x,g=o-we.y;s*s+g*g<25&&Tt(n,o,i,e)}function Tt(e,t,n,o){for(const l of vt)if(e>=l.x&&e<l.x+l.w&&t>=l.y&&t<l.y+l.h){if(typeof l.bin=="number"){const r=d.highlightBin===l.bin?void 0:l.bin;D({highlightBin:r})}else{const r=d.highlightMetadataValue===l.bin?void 0:l.bin;D({highlightMetadataValue:r})}return}if(Re&&yn(e,t,Re))return;const i=X();if(!i)return;const g=Mn((e-i.originX)/i.ppm,(i.originY-t)/i.ppm,i.snapDist)?.die??null;if(g){Vn?.(g,o);const l=De(g);n?E.has(l)?E.delete(l):E.add(l):E=new Set([l]),ge?.(Ot()),v()}else n||(E=new Set,ge?.([]),v())}function Ot(){const e=[],t=y.hoverPoints;for(let n=0;n<t.length;n++){const o=y.dies[n];o&&E.has(De(o))&&e.push(o)}return e}function wn(){rn(void 0),S&&dt(u),_e?.(null,new MouseEvent("mouseleave")),a.style.cursor=Y==="pan"?"grab":"crosshair"}function Sn(){me=!1,Se=!1,xe=!1,ve=!1,Ie=!1,S&&dt(u),_e?.(null,new MouseEvent("mouseleave")),a.style.cursor=Y==="pan"?"grab":"crosshair",v()}function Mn(e,t,n){const o=y.hoverPoints,i=y.rectangles;for(let r=0;r<i.length;r++){const c=i[r];if(Math.abs(e-c.x)<=c.width/2&&Math.abs(t-c.y)<=c.height/2){const p=y.dies[r];return p?{die:p,index:r}:null}}let s=null,g=-1,l=n*n;for(let r=0;r<o.length;r++){const c=o[r].x-e,p=o[r].y-t,h=c*c+p*p;h<l&&(l=h,s=y.dies[r]??null,g=r)}return s?{die:s,index:g}:null}const Cn=new V.ResizeObserver(()=>{z=null,B=null,v()});Cn.observe(a),w.height==null&&jn<=0&&Nt(()=>Nt(()=>{j.clientHeight>0||console.warn("[wafermap] The map container has zero height, so the map cannot render. renderWaferMap fills its container \u2014 give the container a resolved height: an explicit CSS `height` (e.g. 600px), a height-resolved flex/grid parent, or `position:absolute; inset:0`. Alternatively pass `{ height: 600 }` in the render options and the library will size it for you.")}));let ze=V.matchMedia(`(resolution: ${V.devicePixelRatio}dppx)`);const tt=()=>{ze.removeEventListener("change",tt),ze=V.matchMedia(`(resolution: ${V.devicePixelRatio}dppx)`),ze.addEventListener("change",tt),v()};ze.addEventListener("change",tt);const En=V.matchMedia("(prefers-color-scheme: dark)"),Dn=()=>v();En.addEventListener("change",Dn);const kn=()=>{S&&dt(u)};V.addEventListener("blur",kn);function Bn(e){if(e.key==="Escape"&&E.size>0&&(E=new Set,ge?.([]),v()),(e.key==="e"||e.key==="E")&&pt!=="view-only"&&Zt&&(e.stopPropagation(),(Gt??un)()),(e.ctrlKey||e.metaKey)&&(e.key==="="||e.key==="+"?(e.preventDefault(),Ce(a.clientWidth/2,a.clientHeight/2,1.2)):e.key==="-"?(e.preventDefault(),Ce(a.clientWidth/2,a.clientHeight/2,1/1.2)):e.key==="0"&&(e.preventDefault(),nt())),!e.ctrlKey&&!e.metaKey&&!e.shiftKey){const n=X();if(n){const o=B?.snapDist??z?.snapDist??1;let i=0,s=0;e.key==="ArrowLeft"&&(i=20,e.preventDefault()),e.key==="ArrowRight"&&(i=-20,e.preventDefault()),e.key==="ArrowUp"&&(s=20,e.preventDefault()),e.key==="ArrowDown"&&(s=-20,e.preventDefault()),(i||s)&&(B={originX:n.originX+i,originY:n.originY+s,ppm:n.ppm,snapDist:o},v())}e.key===" "&&!We&&(e.preventDefault(),We=!0,Y!=="pan"&&(a.style.cursor="grab"))}}function Ln(e){e.key===" "&&(We=!1,Se&&(me=!1,Se=!1),a.style.cursor=Y==="pan"?"grab":"crosshair")}a.style.cursor="grab",a.setAttribute("tabindex","0"),a.addEventListener("wheel",mn,{passive:!1}),a.addEventListener("pointerdown",bn),a.addEventListener("pointermove",vn),a.addEventListener("pointerup",xn),a.addEventListener("pointerleave",wn),a.addEventListener("pointercancel",Sn);const Pn=()=>nt();a.addEventListener("dblclick",Pn),a.addEventListener("keydown",Bn),a.addEventListener("keyup",Ln);const Tn=e=>{e.stopPropagation()};a.addEventListener("click",Tn),a.clientWidth,v(),$e?.();function nt(){z=null,B=null,v()}function Rt(){import("./userGuideHtml.js").then(e=>Li({buildWaferMap:vi,renderWaferMap,renderWaferGallery:void 0,analyzeWaferMap:wi},e.USER_GUIDE_HTML,Un,j))}return{setDies(e){re=e,Fe(),v(),N&&pe()},setResult(e){gt=e,K=e.wafer,re=e.dies,G=e.hbinDefs,Z=e.sbinDefs,ee=e.testDefs,de=e.metadataFields,en=e.reticles?.length?e.reticles:void 0,tn=e.reticleConfig,nn=e.view?.dataAxisFlip,ht=e.isLotStack,mt=e.aggrMethod,yt=e.lotSize,ti(),Fe(),v(),N&&pe()},setOptions(e){gn(e)},getOptions(){return{...d}},resetZoom:nt,setSelection(e){E=new Set(e.map(t=>De(t))),v()},clearSelection(){E=new Set,ge?.([]),v()},setFallbackFormat(e){Te=e,Fe(),v()},setFindingsNotice(e){dn=e,N?pe():R&&Ae()},setStatsSummary(e){if(ae=e,Jt(),pn(),N)pe();else if(R)Ae();else if(e&&!Le?.placement){const t=Le?.defaultOpen??!Be;R=Xt("right",ue,u),R.style.display=t?"block":"none";const n=M.parentElement,o=M.nextSibling;ce=jt(M,R,"right"),n?.insertBefore(ce,o),Ae()}et()},setSummaryVisible(e){I&&(I.style.display=e?"flex":"none")},setViewControlsVisible(e){L&&(L.style.display=e?"flex":"none")},setExpandVisible(e){U&&(U.style.display=e?"flex":"none")},setHelpButtonVisible(e){qe&&(qe.style.display=e?"flex":"none")},setIdentityVisible(e){bt=!e,A&&(A.style.display=e?"":"none")},openUserGuide:Rt,setInsightsOpen(e){Ge(e),F&&(e?(F.dataset.active="1",F.style.background=x.bgActive,F.style.color=x.iconActive):(delete F.dataset.active,F.style.background="transparent",F.style.color=x.icon))},closeSummaryPanel(){const e=N??R;!e||e.style.display==="none"||(e.style.display="none",I&&(delete I.dataset.active,I.style.background="transparent",I.style.color=x.icon))},setTooltipParent(e){S&&Ei(e)},getActiveLegend(){const e=d.plotMode;if(e==="metadata"){const i=d.activeMetadataKey;if(!i)return null;const s=de?.find(l=>l.key===i),g=[...new Set(re.map(l=>l.metadata?.[i]).filter(l=>l!=null&&(typeof l=="string"||typeof l=="number"||typeof l=="boolean")).map(String))].sort();return g.length?g.map((l,r)=>{const c=s?.values?.find(h=>h.value===l),p=c?.color??Ui(r);return{bin:l,name:c?.label??l,color:p}}):null}if(e!=="hardBin"&&e!=="softBin")return null;const t=e==="hardBin",n=t?G:Z,o=[...new Set(re.map(i=>t?i.hbin:i.sbin).filter(i=>i!==void 0))].sort((i,s)=>i-s);return o.length?o.map(i=>{const s=n?.find(l=>l.bin===i),g=s?.color??(t?Gi(i):Zi(i));return{bin:i,name:s?.name??`Bin ${i}`,color:g}}):null},destroy(){ye?.close(),fn?.()?.remove(),Mt&&u.removeEventListener("click",Mt,!0),a.removeEventListener("wheel",mn),a.removeEventListener("pointerdown",bn),a.removeEventListener("pointermove",vn),a.removeEventListener("pointerup",xn),a.removeEventListener("pointerleave",wn),a.removeEventListener("pointercancel",Sn),a.removeEventListener("dblclick",Pn),a.removeEventListener("keydown",Bn),a.removeEventListener("keyup",Ln),a.removeEventListener("click",Tn),Cn.disconnect(),ze.removeEventListener("change",tt),En.removeEventListener("change",Dn),V.removeEventListener("blur",kn),Jn(),S&&dt(u),te?.remove(),Me&&(Me.parentElement?.insertBefore(M,Me),Me.remove()),ce&&(ce.parentElement?.insertBefore(M,ce),ce.remove()),M.remove(),a.style.cursor="",Q?.destroy(),$?.destroy(),ke.remove()}}}
1
+ import{buildView as vi,buildHoverText as xi,findTestDef as ct,resolveTestNumber as Nt}from"../renderer/buildView.js";import{toCanvas as Ci,BIN_LEGEND_W as Fn,BIN_LEGEND_W_COMPACT as wi,BIN_LEGEND_ADAPT_COMPACT as Si,BIN_LEGEND_ADAPT_FLOATING as Mi}from"./toCanvas.js";import{buildWaferMap as Ei,getTestPassStatus as Di,isParametricTest as jt}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Bi}from"../stats/analyzeWaferMap.js";import{SHADOW as ki,LEADING as An,wireControlHover as zn,SPACE as W,EDGE_GUTTER as Li,RADIUS as Yn,FONT as ft,CLR as x,applyOverlayZ as Ti,getTooltip as Vn,hideTooltip as pt,reparentTooltip as Oi,positionTooltip as Kt,createToolbarHelpers as Pi,buildModeMenuEl as Ri,openReparentedModal as Ii,openUserGuideWindow as Wi,makePaletteBtn as Hi,makeLogScaleBtn as Fi,makeLegendStyleBtn as Ai,makeOverlaysBtn as zi,makeOrientationBtn as Yi,menuLayerFor as Xn,saveImageBlob as Vi,markMenuTrigger as _e,wireMenuA11y as Nn,wireExpandToggle as Xi,nextFrame as _t,requestedPassFailDisplay as Ni,overlayMenuRows as ji,anyOverlayActive as Ki,logWmapVersionOnce as _i,buildDataModeEntries as $i,metadataKeyHasData as Gi,metadataModeEntry as Ui}from"./toolbar.js";import{createSummaryPanelEl as $t,wrapWithSummaryPanel as Gt,renderWaferSummaryContent as Zi}from"./summaryPanel.js";import{collectWarnings as Qi,buildWarningsMenuEl as qi,severityOf as Ji}from"./warnings.js";import{ICONS as jn}from"./icons.js";import{metadataValueColor as eo,NO_DATA_FILL as to}from"../renderer/colorMap.js";import{createIdentityHeader as no,collapsedLabel as Ut}from"./identityHeader.js";import{getDieKey as Be,hasPosition as Kn,isPositionedDie as io}from"../core/dies.js";import{buildDieListSection as oo}from"./dieList.js";import{buildMaplessSummary as so}from"./maplessSummary.js";import{resolveBinColors as lo,binColorWarning as ao}from"../renderer/binColors.js";const _n=new Set(["binColorScheme","valueColorScheme","useDefinedBinColors","rotation","flipX","flipY","showDieLabels","showPartialDies","showRingBoundaries","showQuadrantBoundaries","showReticle","showXYIndicator","ringCount","legendPosition","logScale","colorbarRangeMode","markFailingDies"]);export const COLOR_KEYS=["binColorScheme","valueColorScheme","useDefinedBinColors","binColors"];export function classifyChanged(K){const y=K.some(g=>_n.has(g)),C=K.some(g=>!_n.has(g));return y&&C?"mixed":y?"preference":"state"}export function renderWaferMap(K,y,C={}){_i();const g=K.ownerDocument,H=g.defaultView??window;H.getComputedStyle(K).position==="static"&&(K.style.position="relative");const $n=K.clientHeight;C.height!=null&&(K.style.height=typeof C.height=="number"?`${C.height}px`:C.height);const ut=y.dataCoverage?y.dataCoverage.unpositionedDies:y.dies.filter(e=>!Kn(e)).length,$e=(y.dataCoverage?y.dataCoverage.totalDies:y.dies.length-ut)===0&&ut>0,ke=g.createElement("div");Object.assign(ke.style,{display:"flex",flexDirection:"column",width:"100%",height:"100%"}),K.appendChild(ke);const le=g.createElement("div");Object.assign(le.style,{position:"relative",width:"100%",flex:"1 1 auto",minHeight:"0"}),C.maxSize!=null&&(le.style.maxWidth=`${C.maxSize}px`,le.style.maxHeight=`${C.maxSize}px`);const ge=C.chromeInset??Li,_=g.createElement("div");Object.assign(_.style,{display:"flex",alignItems:"stretch",gap:W.sm,background:x.canvasBg,paddingBottom:W.lg,paddingTop:ge,paddingLeft:ge,paddingRight:ge,flexShrink:"0",minWidth:"0"}),ke.appendChild(_),ke.appendChild(le);function ve(){const e=[..._.children].some(t=>t.style.display!=="none");_.style.display=e?"flex":"none"}const S=g.createElement("div");Object.assign(S.style,{position:"relative",width:"100%",height:"100%"});const a=g.createElement("canvas");Object.assign(a.style,{width:"100%",height:"100%",display:"block"}),S.appendChild(a),le.appendChild(S);let Ge=null;if(ut>0){let n=function(){if(t){const d=oo(e,y.testDefs,{...C.dieList,onSaveText:C.onSaveText,waferMetadata:$.metadata,metadataFields:ce,ownerDocument:g});if(d)return d}const o=ct(y.testDefs,p.activeTest??0),s=jt(o)?p.logScale??o?.logScale??!1:!1;return so(e,y.testDefs,{plotMode:p.plotMode??"hardBin",activeTest:p.activeTest,hbinDefs:G,sbinDefs:U,binColors:m.binColors,valueColorScheme:p.valueColorScheme,logScale:s,colorbarRangeMode:p.colorbarRangeMode,valueRangeDies:y.dies})},i=function(o){const s=g.createElement("button");return s.type="button",zn(s),Object.assign(s.style,{fontSize:ft.body,padding:`${W.xxs} ${W.sm}`,borderRadius:Yn.control,flexShrink:"0",border:`1px solid ${x.menuBorder}`,background:x.menuBg,color:x.text,cursor:"pointer"}),s.textContent=t?"View chart":"View die list",s.addEventListener("click",d=>{d.stopPropagation(),t=!t,s.textContent=t?"View chart":"View die list",o()}),s};const e=y.dies.filter(o=>!Kn(o));let t=!1;if($e){const o=g.createElement("div");Object.assign(o.style,{position:"absolute",inset:"0",background:x.panelBg,padding:W.xl,boxSizing:"border-box",overflow:"hidden",display:"flex",flexDirection:"column",gap:W.md,zIndex:"1"});const s=g.createElement("div");Object.assign(s.style,{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:W.md});const d=g.createElement("span");Object.assign(d.style,{fontSize:ft.body,color:x.label,lineHeight:An.base}),d.textContent="No die position data for this wafer.",s.appendChild(d);const r=g.createElement("div");Object.assign(r.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),s.appendChild(i(()=>r.replaceChildren(n()))),o.appendChild(s),o.appendChild(r),S.appendChild(o),Ge=()=>{t||r.replaceChildren(n())}}else{const o=g.createElement("div");Object.assign(o.style,{position:"absolute",left:"0",right:"0",bottom:"0",zIndex:"3",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,fontSize:ft.body,color:x.text,cursor:"pointer",padding:`${W.xs} ${W.md}`,display:"flex",alignItems:"center",justifyContent:"space-between",gap:W.md}),zn(o,"bare");const s=g.createElement("span");s.textContent=`+${e.length} ${e.length===1?"die":"dies"} without position data`,o.appendChild(s);const d=g.createElement("span");d.textContent="\u25BE",Object.assign(d.style,{fontSize:ft.body,lineHeight:An.none,color:x.label,flexShrink:"0"}),o.appendChild(d),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`${e.length} dies without position data. Click to view.`);let r=null,l=null;Xi(o,c=>{if(d.textContent=c?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(c)),c){r=g.createElement("div");const f=o.getBoundingClientRect().height||28;Object.assign(r.style,{position:"absolute",left:"0",right:"0",bottom:`${f}px`,top:"20%",zIndex:"2",background:x.panelBg,borderTop:`1px solid ${x.menuBorder}`,padding:W.md,boxSizing:"border-box",display:"flex",flexDirection:"column",gap:W.md}),r.addEventListener("click",Q=>Q.stopPropagation());const h=g.createElement("div");Object.assign(h.style,{display:"flex",justifyContent:"flex-end"}),h.appendChild(i(()=>{l&&l.replaceChildren(n())})),r.appendChild(h),l=g.createElement("div"),Object.assign(l.style,{flex:"1",minHeight:"0",overflow:"auto",display:"flex",flexDirection:"column"}),l.appendChild(n()),r.appendChild(l),S.appendChild(r)}else r&&(r.remove(),r=null,l=null)}),S.appendChild(o),Ge=()=>{l&&!t&&l.replaceChildren(n())}}}const{onHover:Ue,onClick:Gn,onSelect:he,onViewOptionsChange:Un,showTooltip:Zn=!0,showToolbar:Le=!0,showIdentity:Zt=!0,toolbarControls:gt="full",showPlotModeSelector:Qn=!0,minZoom:qn=.4,maxZoom:Jn=20,summaryPanel:Te,renderTooltip:Qt,passBins:Ze=[1],showHelpButton:qt=!1,userGuideExtension:ei,onExpand:Jt,showExpandButton:en=!0,zIndex:ti,insights:ht,warnings:tn,viewOptions:ni={},...ae}=C,Oe=ht?.enabled??!1,nn=tn?.display??!0,ii=Ti(ti);let Pe=ae.fallbackFormat,re=C.statsSummary,de=[],on=!1,Qe=null,sn=!1;function mt(){const e=Qi({result:y,statsSummary:re,extra:Qe?[Qe]:[]}),t=e.length!==de.length||e.some((n,i)=>n.code!==de[i]?.code||n.message!==de[i]?.message);de=e,(t||!on)&&(on=!0,tn?.onWarning?.(e))}mt();let yt=y,$=y.wafer,te=y.dies,E=new Set,G=y.hbinDefs,U=y.sbinDefs,ne=y.testDefs,ce=y.metadataFields,ln=y.reticles?.length?y.reticles:void 0,an=y.reticleConfig,rn=y.view?.dataAxisFlip,bt=y.isLotStack??!1,vt=y.aggrMethod,xt=y.lotSize;const oi=Le&&gt!=="view-only"&&Oe;let Ct=!1,Z=null,z=null,J=null;Zt&&(Z=no(Ut($.metadata??{},Re())??"",$.metadata,{lotStack:Re(),ownerDocument:g}),S.appendChild(Z.metaPanel),Z.isEmpty()||(z=dn(Z.wrap),_.insertBefore(z,_.firstChild),ve()));function dn(e){const t=g.createElement("div");return Object.assign(t.style,{display:"flex",alignItems:"center",padding:`${W.sm} ${W.lg}`,flex:"1 1 auto",minWidth:"0",overflow:"hidden",gap:W.sm}),Object.assign(e.style,{flex:"1",minWidth:"0"}),t.appendChild(e),t}function Re(){return bt?{lotSize:xt??1,aggrMethod:vt}:void 0}function si(){if(!Z)return;Z.update(Ut($.metadata??{},Re())??"",$.metadata,Re());const e=z?.isConnected??!1,t=!Z.isEmpty();!t&&e?(z.remove(),z=null):t&&!e&&(z=dn(Z.wrap),z.style.display=Ct?"none":"",_.insertBefore(z,_.firstChild),ve())}const li=[...G??[],...U??[]].some(e=>e.color);let p={plotMode:"hardBin",showDieLabels:!1,showPartialDies:!0,showRingBoundaries:!1,showQuadrantBoundaries:!1,showReticle:!1,showXYIndicator:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,legendPosition:ae.legendPosition??"default",...ni},Y=null,ie=!1,cn=null;function ai(){return Oe?Y?Promise.resolve(Y):(cn??=import("./insightsTab.js").then(({createInsightsTab:e})=>(Y=e({getItems:()=>[{wafer:$,dies:te,hbinDefs:G,sbinDefs:U,testDefs:ne,label:String($.metadata?.waferId??""),statsSummary:re}],getBinColors:()=>m.binColors,passBins:Ze,getRingCount:()=>p.ringCount??4,onSaveImage:C.onSaveImage,onSaveText:C.onSaveText,defaultView:ht?.defaultView,showMetadataStrip:!1,contentInset:ge,backTab:oi?void 0:{label:"Map",onBack:()=>Ie(!1)},onOpenGuide:qt&&!Le?()=>At():void 0,focusTest:t=>{D({plotMode:"value",activeTest:t,highlightBin:void 0}),Ie(!1)},ownerDocument:g}),Object.assign(Y.el.style,{position:"absolute",inset:"0",background:x.canvasBg,overflowY:"auto",paddingTop:"0"}),Y.el.style.display="none",le.appendChild(Y.el),Y)),cn):Promise.resolve(null)}let fn=0;const wt=["wheel","touchstart","pointerdown","keydown"];function ri(e,t){if(t<=0)return;let n=!1;const i=[],o=()=>{n=!0;for(const d of i)H.clearTimeout(d);i.length=0;for(const d of wt)e.removeEventListener(d,o)},s=()=>n||!ie?!0:(e.scrollTop=t,e.scrollTop>=t);if(!s()){for(const d of wt)e.addEventListener(d,o,{passive:!0,once:!0});for(const d of[0,50,150,300,600])i.push(H.setTimeout(()=>{s()},d));i.push(H.setTimeout(()=>{for(const d of wt)e.removeEventListener(d,o)},700))}}function Ie(e){if(!Oe)return;const t=ie;ie=e,Y&&!e&&t&&(fn=Y.el.scrollTop),Y&&(Y.el.style.display=e?"flex":"none"),F&&(F.style.display=e||$e?"none":"flex"),T&&(T.style.display=e?"none":"flex"),J&&(J.style.display=ye?"none":"flex"),oe&&(oe.style.display="flex"),z&&(z.style.display=Ct?"none":""),ve(),Z&&e&&Z.collapse(),it(),A&&(A.innerHTML=e?jn.wafer:jn.analysis,A.ariaLabel=e?"Back to wafer view":"Insights"),e&&ai().then(n=>{!n||!ie||(n.el.style.display="flex",n.render(),ri(n.el,fn))})}Oe&&ht?.defaultOpen&&queueMicrotask(()=>Ie(!0));let m,pn,V=null,k=null,St=[],Mt;function un(e){Mt!==e&&(Mt=e,v())}let We=null,Et=ae.legendOffset??{x:0,y:0},He=!1,xe=!1,Fe={x:0,y:0},Dt={x:0,y:0},me=!1,Ce=!1,X="pan",we={x:0,y:0},qe={x:0,y:0},O={x:0,y:0},P={x:0,y:0},Ae=!1,Se=!1;function ze(){const e=p;m=vi($,te.filter(io),{plotMode:e.plotMode,binColorScheme:e.binColorScheme,valueColorScheme:e.valueColorScheme,useDefinedBinColors:e.useDefinedBinColors,binColors:e.binColors??lo(te,{passBins:Ze,binColorScheme:e.binColorScheme,hbinDefs:G,sbinDefs:U,useDefinedBinColors:e.useDefinedBinColors}),passBins:Ze,showDieLabels:e.showDieLabels,showPartialDies:e.showPartialDies,showRingBoundaries:e.showRingBoundaries,showQuadrantBoundaries:e.showQuadrantBoundaries,showReticle:e.showReticle,showXYIndicator:e.showXYIndicator,reticles:ln,ringCount:e.ringCount,highlightBin:e.highlightBin,highlightMetadataValue:e.highlightMetadataValue,activeTest:e.activeTest,activeMetadataKey:e.activeMetadataKey,testDefs:ne,valueRange:e.valueRange,metadataValueOrder:e.metadataValueOrder,logScale:e.logScale,isLotStack:bt,aggregationMethod:vt??e.aggregationMethod,lotSize:xt??e.lotSize,dataAxisFlip:rn,colorbarRangeMode:e.colorbarRangeMode,passFailDisplay:e.passFailDisplay,fallbackFormat:Pe,interactiveTransform:{rotation:e.rotation??0,flipX:e.flipX??!1,flipY:e.flipY??!1}},{hbinDefs:G,sbinDefs:U,metadataFields:ce}),pn=new Map(m.dies.map((n,i)=>[Be(n),i]));const t=e.binColors?null:ao(m.binColors,m.plotMode);t?.message!==Qe?.message&&(Qe=t,mt(),sn&&Bt())}ze();let N=null,Me=null,Je=null,gn=C.findingsNotice,di={},R=null,fe=null;function ci(e){const{kind:t,index:n}=e.variable;D(t==="test"?{plotMode:"value",activeTest:n??0,highlightBin:void 0}:t==="softBin"?{plotMode:"softBin",highlightBin:void 0}:{plotMode:"hardBin",highlightBin:void 0});const i=e.highlight;i.kind==="bin"?(Rt(i.dieKeys),D({highlightBin:i.bin})):(i.kind==="region"||i.kind==="dies")&&Rt(i.dieKeys)}function hn(e){Zi(e,{wafer:$,dies:te,yieldSummary:yt.yield,dataCoverage:yt.dataCoverage,hbinDefs:G,sbinDefs:U,testDefs:ne,statsSummary:re,warnings:nn?de:[],passBins:Ze,ringCount:p.ringCount??4,binColors:m.binColors,plotMode:p.plotMode??"hardBin",metadataShownElsewhere:Zt,fallbackFormat:Pe,activeFindingId:Je,findingsFilter:di,findingsNotice:gn,onFindingsFilterChange:pe,onSaveText:C.onSaveText,metadataFields:ce,dieListOptions:C.dieList,onFindingClick:(t,n)=>{Je===t.id?(Je=null,Rt([]),D({highlightBin:void 0})):(Je=t.id,ci(t)),pe()}})}function pe(){N&&hn(N)}function Ye(){R&&hn(R)}if(Te?.placement){const e=Te.placement;N=$t(e,ge,g);const t=S.parentElement,n=S.nextSibling;Me=Gt(S,N,e),t?.insertBefore(Me,n),pe()}else if(re){const e=Te?.defaultOpen??!Le;R=$t("right",ge,g),R.style.display=e?"block":"none";const t=S.parentElement,n=S.nextSibling;fe=Gt(S,R,"right"),t?.insertBefore(fe,n),Ye()}const w=Zn?Vn(g):null;let oe=null,L=null,F=null,T=null,et=null,I=null,tt=null,A=null,se=null,nt=null;sn=!0;function Bt(){if(!se||!nt)return;const e=de.length,t=e>0;if(se.style.display=t?"flex":"none",nt.style.display=t?"":"none",!t)return;const n=Ji(de[0]),i=`${e} data ${e===1?"warning":"warnings"}`;se.style.color=n==="error"?x.errText:x.warnText,se.ariaLabel=n==="error"?`${i} \u2014 the map may be positionally wrong`:i}let kt=null,mn=null,Lt=null,Tt=null,Ot=null,Pt=null;function Rt(e){E=new Set(e??[]),he&&he(Ft()),v()}function it(){if(!I)return;const e=!!(N??R);I.style.display=re&&e&&!ie?"flex":"none";const t=N??R,n=t?t.style.display!=="none":!1;re?.hasNotableFindings&&!n?I.style.color=x.findingIndicator:I.dataset.active||(I.style.color=x.icon)}if(Le){let f=function(B){X=B,i(Q,B==="zoom"),i(M,B==="pan"),et&&i(et,B==="select"),a.style.cursor=B==="pan"?"grab":"crosshair"};oe=g.createElement("div"),oe.dataset.wmapToolbar="single",Object.assign(oe.style,{marginLeft:"auto",flexShrink:"0",display:"flex",flexDirection:"row",alignItems:"center",flexWrap:"wrap-reverse",justifyContent:"flex-end",maxWidth:"100%",background:x.menuBg,border:`1px solid ${x.menuBorder}`,borderRadius:Yn.control,boxShadow:ki.panel,pointerEvents:"auto"});const e=Vn(g),t=Pi(e),{makeBtn:n,setActive:i,makeSep:o,makeMenuRow:s,makeMenuSection:d,closeOpenMenu:r,getOpenMenu:l,setOpenMenu:c}=t;kt=r,mn=l,g.addEventListener("click",r,!0),F=g.createElement("div"),Object.assign(F.style,{display:$e?"none":"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),oe.appendChild(F);const h=n("download","Download PNG",ui);F.appendChild(h),F.appendChild(o());const Q=n("zoomMode","Zoom (drag to zoom region)",()=>f("zoom")),De=n("zoomIn","Zoom in",()=>Ee(a.clientWidth/2,a.clientHeight/2,1.2)),ee=n("zoomOut","Zoom out",()=>Ee(a.clientWidth/2,a.clientHeight/2,1/1.2)),ue=n("reset","Reset zoom (double-click)",()=>st());F.appendChild(Q),F.appendChild(De),F.appendChild(ee),F.appendChild(ue),F.appendChild(o());const M=n("pan","Pan (drag to move)",()=>f("pan"));if(F.appendChild(M),et=n("boxSelect","Select (drag to select dies)",()=>f("select")),F.appendChild(et),i(M,!0),gt!=="view-only"){let B=function(u){return u.plotMode!==(p.plotMode??"hardBin")?!1:u.plotMode==="value"?(p.activeTest??0)===(u.activeTest??0):u.plotMode==="metadata"?p.activeMetadataKey===u.activeMetadataKey:!0},zt=function(u,b){u.activeTest!==void 0?D({plotMode:u.plotMode,activeTest:u.activeTest,activeMetadataKey:void 0,logScale:u.logScale}):u.activeMetadataKey!==void 0?D({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:u.activeMetadataKey,passFailDisplay:"off"}):D({plotMode:u.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),b.remove(),c(null),_e(q,!1)};L=g.createElement("div"),Object.assign(L.style,{display:"flex",alignItems:"center",gap:"0",flexWrap:"wrap",justifyContent:"flex-end"}),oe.appendChild(L),T=g.createElement("div"),Object.assign(T.style,{display:"flex",alignItems:"center",gap:"0"}),L.appendChild(T),T.appendChild(o());const lt=()=>{const u=l();u&&(u.remove(),c(null)),_e(q,!1)},q=n("mode","Plot mode",()=>{if(l()){lt();return}const u=te,b=m.testDefs,{testEntries:dt,binEntries:be,stackedEntries:Ne}=$i(u,b,{includeStacked:m.isLotStack}),Xt=(ce??[]).filter(Ke=>Gi(u,Ke.key)).map(Ui),je=Ri(q.getBoundingClientRect(),dt,be,Ne,B,zt,{makeMenuRow:s,makeMenuSection:d},p.plotMode??"hardBin",q.ownerDocument.defaultView??window,Xt);Xn(q).appendChild(je),c(je),_e(q,!0),Nn(je,q,lt)});_e(q,!1);const{btn:at,sync:Xe}=Hi(t,()=>({...p,plotMode:p.plotMode??"hardBin"}),()=>li,D);Tt=Xe,Tt();const Yt=zi(t,()=>{const u=!!m.hasReticle,b=(p.plotMode??"hardBin")==="value",{testNumber:dt}=Nt(p.activeTest??0,m.testDefs),be=ct(m.testDefs,dt),Ne=b&&be!==void 0&&!jt(be),Xt=b&&!Ne&&(be?.limitLow!==void 0||be?.limitHigh!==void 0),je=b&&!Ne&&m.dies.some(Ke=>Di(Ke,dt,be)!==void 0);return ji(p,u,{functionalActive:Ne,hasLimits:Xt,hasRecorded:je,binMode:(p.plotMode??"hardBin")==="hardBin"||(p.plotMode??"hardBin")==="softBin"},Ke=>D(Ke))},()=>Ki(p)),{btn:Vt,sync:gi}=Ai(t,()=>p,u=>D({legendPosition:u}));Lt=gi,Lt();const Hn=()=>{const{testNumber:u}=Nt(p.activeTest??0,ne),b=ct(ne,u);return b!==void 0&&!jt(b)},{btn:hi,sync:mi}=Fi(t,()=>({...p,functionalActive:Hn()}),u=>D(u));Ot=mi,Ot();const yi=()=>{const{testNumber:u}=Nt(p.activeTest??0,ne),b=ct(ne,u);return b!==void 0&&(b.limitLow!==void 0||b.limitHigh!==void 0)},rt=n("specRange","Colorbar range: spec limits",()=>{const u=p.colorbarRangeMode==="data"?"spec":"data";D({colorbarRangeMode:u})});Pt=()=>{const u=p.plotMode==="value"&&yi()&&Ni(p)==="off"&&!Hn();rt.style.display=u?"":"none";const b=(p.colorbarRangeMode??"spec")==="spec";i(rt,b),rt.ariaLabel=b?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"},Pt();const bi=Yi(t,()=>p,u=>D(u));Qn&&T.appendChild(q),T.appendChild(at),T.appendChild(hi),T.appendChild(rt),$e||(T.appendChild(o()),T.appendChild(Yt),T.appendChild(o()),T.appendChild(Vt),T.appendChild(o()),T.appendChild(bi)),re&&(I=n("findings","Summary panel",()=>{const u=N??R;if(!u)return;const b=u.style.display!=="none";u.style.display=b?"none":"block",i(I,!b),it()}),L.appendChild(o()),L.appendChild(I),R?.style.display!=="none"&&i(I,!0),it()),nn&&(nt=o(),se=n("warning","Data warnings",()=>{const u=l();if(r(new MouseEvent("click")),u)return;const b=qi(se.getBoundingClientRect(),de,H);Xn(le).appendChild(b),c(b),Nn(b,se,()=>r(new MouseEvent("click")))}),_e(se,!1),L.appendChild(nt),L.appendChild(se),Bt()),Oe&&(L.appendChild(o()),A=n("analysis","Insights",()=>{Ie(!ie),i(A,ie)}),A.dataset.wmapInsightsBtn="1",L.appendChild(A)),en&&(L.appendChild(o()),J=n("expand","Expand (E)",Jt??yn),L.appendChild(J)),qt&&(L.appendChild(o()),tt=n("help","User guide",()=>At()),L.appendChild(tt))}_.appendChild(oe),ve()}let ye=null;function yn(){ye&&(ye.close(),ye=null);const e=le;e.style.flex="1",e.style.minWidth="0",e.style.minHeight="0";const t=e.style.maxWidth,n=e.style.maxHeight;e.style.maxWidth="none",e.style.maxHeight="none";const i=Ut($.metadata??{},Re()),o=_.childElementCount>0?[_,e]:[e],s=Ii(o,{ownerDocument:g,boxSize:ie?{width:"min(96vw, 1600px)",height:"min(92vh, 1000px)"}:void 0,onClosed:()=>{ye=null,e.style.maxWidth=t,e.style.maxHeight=n,J&&(J.style.display="flex"),ie||a.focus({preventScroll:!0})}});s&&(s.box.setAttribute("aria-label",i??"Expanded wafer map"),o.length>1&&(s.contentWrap.style.flexDirection="column"),ye=s,J&&(J.style.display="none"))}function bn(e){const t=p.plotMode;p={...p,...e},e.plotMode!==void 0&&e.plotMode,Object.keys(e).every(s=>s==="legendPosition"||s==="showLegend"||s==="markFailingDies")||ze(),Lt?.(),Tt?.(),Ot?.(),Pt?.(),v();const i=e.plotMode!==void 0&&e.plotMode!==t,o=COLOR_KEYS.some(s=>s in e);(o||i)&&(pe(),Ye()),(o||i||e.activeTest!==void 0||e.logScale!==void 0||e.colorbarRangeMode!==void 0)&&Ge?.()}function D(e){bn(e);const t=Object.keys(e);Un?.(p,t,classifyChanged(t))}let It=!1;function Wt(){It||(It=!0,_t(()=>{It=!1,v()},H))}function v(){const e=k??void 0,t=m.dies[0],n=t?{x:t.width,y:t.height}:ae.diePitchMm,i=Math.floor(a.clientWidth||a.width),o=!!(G?.length||U?.length||m.dies.some(h=>h.hbin!=null||h.sbin!=null)),s=p.legendPosition??"default",d=p.showLegend??!0,r=s==="default"||s==="compact",l=(ae.colorbarWidth??16)+28,c=o&&r?s!=="default"?Math.max(Fn,l):i<Mi?0:i<Si?Math.max(wi,l):Math.max(Fn,l):void 0,f=Ci(a,m,{...ae,topClearance:0,minRightReserve:d?c:0,showColorbar:d&&(ae.showColorbar??!0),markFailingDies:p.markFailingDies??!1,legendPosition:s,legendOffset:Et,diePitchMm:n,fallbackFormat:Pe,showAxes:ae.showAxes??k!==null,viewport:e,activeBin:p.plotMode==="metadata"?p.highlightMetadataValue:p.highlightBin,hoverBin:Mt,hbinDefs:G,sbinDefs:U,metadataFields:ce});St=f.binLegendRows,We=f.legendBox??null,k===null&&(V=f.viewport),E.size>0&&fi(),Ce&&pi()}function fi(){const e=j();if(!e)return;const t=a.getContext("2d"),n=m.hoverPoints,i=m.rectangles[0],o=i?i.width/2*e.ppm:e.ppm*.5,s=i?i.height/2*e.ppm:e.ppm*.5,d=Math.max(1,Math.min(3,o*.08)),r=o-d,l=s-d,c=[];for(const f of E){const h=pn.get(f);h!==void 0&&c.push({sx:e.originX+n[h].x*e.ppm,sy:e.originY-n[h].y*e.ppm})}if(c.length){t.save(),t.setLineDash([]),t.fillStyle="rgba(0,0,0,0.12)",t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.fill(),t.strokeStyle="rgba(255,255,255,0.9)",t.lineWidth=3,t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.stroke(),t.strokeStyle="rgba(0,0,0,0.9)",t.lineWidth=1.5,t.beginPath();for(const{sx:f,sy:h}of c)t.rect(f-r,h-l,r*2,l*2);t.stroke(),t.restore()}}function pi(){const e=a.getContext("2d"),t=Math.min(O.x,P.x),n=Math.min(O.y,P.y),i=Math.abs(P.x-O.x),o=Math.abs(P.y-O.y);e.save(),e.fillStyle="rgba(0,0,0,0.08)",e.fillRect(t,n,i,o),e.setLineDash([5,3]),e.strokeStyle="rgba(255,255,255,0.9)",e.lineWidth=3,e.strokeRect(t,n,i,o),e.strokeStyle="rgba(0,0,0,0.9)",e.lineWidth=1.5,e.strokeRect(t,n,i,o),e.restore()}function ui(){a.toBlob(e=>{e&&Vi(e,C.downloadFilename??"wafermap",C.onSaveImage)})}function vn(e){return V?Math.max(V.ppm*qn,Math.min(V.ppm*Jn,e)):e}function Ee(e,t,n){const i=k??V;if(!i)return;const o=vn(i.ppm*n),s=o/i.ppm,d=e-(e-i.originX)*s,r=t-(t-i.originY)*s,l=(V?.snapDist??1)/(o/(V?.ppm??o));k={originX:d,originY:r,ppm:o,snapDist:l},v()}function j(){return k??V}function xn(e){if(e.ctrlKey||e.metaKey){e.preventDefault();const t=a.getBoundingClientRect(),n=e.deltaY<0?1.12:1/1.12;Ee(e.clientX-t.left,e.clientY-t.top,n)}else if(k!==null){e.preventDefault();const t=j(),n=k.snapDist;k={originX:t.originX-e.deltaX,originY:t.originY-e.deltaY,ppm:t.ppm,snapDist:n},v()}}function Cn(e,t,n){return e>=n.x&&e<n.x+n.w&&t>=n.y&&t<n.y+n.h}function wn(e){if(e.button!==0||!j())return;a.focus({preventScroll:!0}),a.setPointerCapture(e.pointerId);const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(We&&p.legendPosition==="floating"&&Cn(n,i,We)){xe=!0,Fe={x:n,y:i},Dt={...Et};return}if(Ae&&X!=="pan"){Se=!0,me=!0,we={x:n,y:i},qe={x:j().originX,y:j().originY},a.style.cursor="grabbing";return}if(X==="zoom"||X==="select"){Ce=!0,O=P={x:n,y:i};return}me=!0,we={x:n,y:i},qe={x:j().originX,y:j().originY},a.style.cursor="grabbing"}function Sn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;if(Ce){P={x:n,y:i},Wt();return}if(xe){const f=n-Fe.x,h=i-Fe.y;f*f+h*h>16&&(xe=!1,He=!0,a.style.cursor="grabbing")}if(He){Et={x:Dt.x+(n-Fe.x),y:Dt.y+(i-Fe.y)},Wt();return}if(me){const f=j(),h=k?.snapDist??V?.snapDist??1;k={originX:qe.x+(n-we.x),originY:qe.y+(i-we.y),ppm:f.ppm,snapDist:h},Wt();return}const o=j();if(!o)return;const s=(n-o.originX)/o.ppm,d=(o.originY-i)/o.ppm,l=Bn(s,d,o.snapDist)?.die??null,c=St.find(f=>n>=f.x&&n<f.x+f.w&&i>=f.y&&i<f.y+f.h);if(un(c?c.bin:void 0),c){a.style.cursor="pointer",w&&(w.innerHTML=c.label??`Bin ${c.bin}`,w.style.display="block",Kt(w,a,e.clientX,e.clientY)),Ue?.(null,e);return}if(X==="pan"&&(a.style.cursor=l?"crosshair":"grab"),w)if(l)if(Qt){const f=Qt(l);f===null?w.style.display="none":(typeof f=="string"?w.innerHTML=f:(w.innerHTML="",w.appendChild(f)),w.style.display="block",Kt(w,a,e.clientX,e.clientY))}else w.innerHTML=xi(l,m.plotMode,{testDefs:ne,hbinDefs:G,sbinDefs:U,fallbackFormat:Pe,aggrMethod:m.aggrMethod,lotSize:m.lotSize,metadataFields:ce,activeTest:m.activeTest,reticleConfig:an}),w.style.display="block",Kt(w,a,e.clientX,e.clientY);else w.style.display="none";Ue?.(l,e)}function Mn(e){const t=a.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top,o=e.ctrlKey||e.metaKey;if(w&&(n<0||i<0||n>t.width||i>t.height)&&(w.style.display="none"),Ce){Ce=!1,P={x:n,y:i};const r=n-O.x,l=i-O.y,c=j();if(X==="zoom"){if(r*r+l*l<25)Ee(n,i,2);else if(c){const f=Math.min(O.x,P.x),h=Math.max(O.x,P.x),Q=Math.min(O.y,P.y),De=Math.max(O.y,P.y),ee=h-f,ue=De-Q;if(ee>4&&ue>4){const M=a.clientWidth,B=a.clientHeight,zt=M/ee,lt=B/ue,q=Math.min(zt,lt),at=vn(c.ppm*q),Xe=at/c.ppm,Yt=(f+h)/2,Vt=(Q+De)/2;k={originX:M/2-(Yt-c.originX)*Xe,originY:B/2-(Vt-c.originY)*Xe,ppm:at,snapDist:c.snapDist/Xe}}}v(),a.style.cursor="crosshair";return}if(r*r+l*l<25)Ht(n,i,o,e);else if(c){const f=(Math.min(O.x,P.x)-c.originX)/c.ppm,h=(Math.max(O.x,P.x)-c.originX)/c.ppm,Q=(c.originY-Math.max(O.y,P.y))/c.ppm,De=(c.originY-Math.min(O.y,P.y))/c.ppm,ee=m.hoverPoints,ue=[];for(let M=0;M<ee.length;M++)if(ee[M].x>=f&&ee[M].x<=h&&ee[M].y>=Q&&ee[M].y<=De){const B=m.dies[M];B&&ue.push(B)}if(o)for(const M of ue){const B=Be(M);E.has(B)?E.delete(B):E.add(B)}else E=new Set(ue.map(M=>Be(M)));he?.(Ft())}v(),a.style.cursor="crosshair";return}if(xe){xe=!1,Ht(n,i,o,e);return}if(He){He=!1,a.style.cursor="grab";return}if(!me)return;if(me=!1,Se){Se=!1,a.style.cursor=Ae||X==="pan"?"grab":"crosshair";return}a.style.cursor=X==="pan"?"grab":"crosshair";const s=n-we.x,d=i-we.y;s*s+d*d<25&&Ht(n,i,o,e)}function Ht(e,t,n,i){for(const r of St)if(e>=r.x&&e<r.x+r.w&&t>=r.y&&t<r.y+r.h){if(typeof r.bin=="number"){const l=p.highlightBin===r.bin?void 0:r.bin;D({highlightBin:l})}else{const l=p.highlightMetadataValue===r.bin?void 0:r.bin;D({highlightMetadataValue:l})}return}if(We&&Cn(e,t,We))return;const o=j();if(!o)return;const d=Bn((e-o.originX)/o.ppm,(o.originY-t)/o.ppm,o.snapDist)?.die??null;if(d){Gn?.(d,i);const r=Be(d);n?E.has(r)?E.delete(r):E.add(r):E=new Set([r]),he?.(Ft()),v()}else n||(E=new Set,he?.([]),v())}function Ft(){const e=[],t=m.hoverPoints;for(let n=0;n<t.length;n++){const i=m.dies[n];i&&E.has(Be(i))&&e.push(i)}return e}function En(){un(void 0),w&&pt(g),Ue?.(null,new MouseEvent("mouseleave")),a.style.cursor=X==="pan"?"grab":"crosshair"}function Dn(){me=!1,Se=!1,Ce=!1,xe=!1,He=!1,w&&pt(g),Ue?.(null,new MouseEvent("mouseleave")),a.style.cursor=X==="pan"?"grab":"crosshair",v()}function Bn(e,t,n){const i=m.hoverPoints,o=m.rectangles;for(let l=0;l<o.length;l++){const c=o[l];if(Math.abs(e-c.x)<=c.width/2&&Math.abs(t-c.y)<=c.height/2){const f=m.dies[l];return f?{die:f,index:l}:null}}let s=null,d=-1,r=n*n;for(let l=0;l<i.length;l++){const c=i[l].x-e,f=i[l].y-t,h=c*c+f*f;h<r&&(r=h,s=m.dies[l]??null,d=l)}return s?{die:s,index:d}:null}const kn=new H.ResizeObserver(()=>{V=null,k=null,v()});kn.observe(a),C.height==null&&$n<=0&&_t(()=>_t(()=>{K.clientHeight>0||console.warn("[wafermap] The map container has zero height, so the map cannot render. renderWaferMap fills its container \u2014 give the container a resolved height: an explicit CSS `height` (e.g. 600px), a height-resolved flex/grid parent, or `position:absolute; inset:0`. Alternatively pass `{ height: 600 }` in the render options and the library will size it for you.")}));let Ve=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`);const ot=()=>{Ve.removeEventListener("change",ot),Ve=H.matchMedia(`(resolution: ${H.devicePixelRatio}dppx)`),Ve.addEventListener("change",ot),v()};Ve.addEventListener("change",ot);const Ln=H.matchMedia("(prefers-color-scheme: dark)"),Tn=()=>v();Ln.addEventListener("change",Tn);const On=()=>{w&&pt(g)};H.addEventListener("blur",On);function Pn(e){if(e.key==="Escape"&&E.size>0&&(E=new Set,he?.([]),v()),(e.key==="e"||e.key==="E")&&gt!=="view-only"&&en&&(e.stopPropagation(),(Jt??yn)()),(e.ctrlKey||e.metaKey)&&(e.key==="="||e.key==="+"?(e.preventDefault(),Ee(a.clientWidth/2,a.clientHeight/2,1.2)):e.key==="-"?(e.preventDefault(),Ee(a.clientWidth/2,a.clientHeight/2,1/1.2)):e.key==="0"&&(e.preventDefault(),st())),!e.ctrlKey&&!e.metaKey&&!e.shiftKey){const n=j();if(n){const i=k?.snapDist??V?.snapDist??1;let o=0,s=0;e.key==="ArrowLeft"&&(o=20,e.preventDefault()),e.key==="ArrowRight"&&(o=-20,e.preventDefault()),e.key==="ArrowUp"&&(s=20,e.preventDefault()),e.key==="ArrowDown"&&(s=-20,e.preventDefault()),(o||s)&&(k={originX:n.originX+o,originY:n.originY+s,ppm:n.ppm,snapDist:i},v())}e.key===" "&&!Ae&&(e.preventDefault(),Ae=!0,X!=="pan"&&(a.style.cursor="grab"))}}function Rn(e){e.key===" "&&(Ae=!1,Se&&(me=!1,Se=!1),a.style.cursor=X==="pan"?"grab":"crosshair")}a.style.cursor="grab",a.setAttribute("tabindex","0"),a.addEventListener("wheel",xn,{passive:!1}),a.addEventListener("pointerdown",wn),a.addEventListener("pointermove",Sn),a.addEventListener("pointerup",Mn),a.addEventListener("pointerleave",En),a.addEventListener("pointercancel",Dn);const In=()=>st();a.addEventListener("dblclick",In),a.addEventListener("keydown",Pn),a.addEventListener("keyup",Rn);const Wn=e=>{e.stopPropagation()};a.addEventListener("click",Wn),a.clientWidth,v(),Ge?.();function st(){V=null,k=null,v()}function At(){import("./userGuideHtml.js").then(e=>Wi({buildWaferMap:Ei,renderWaferMap,renderWaferGallery:void 0,analyzeWaferMap:Bi},e.USER_GUIDE_HTML,ei,K))}return ve(),{setDies(e){te=e,ze(),v(),N&&pe()},setResult(e){yt=e,$=e.wafer,te=e.dies,G=e.hbinDefs,U=e.sbinDefs,ne=e.testDefs,ce=e.metadataFields,ln=e.reticles?.length?e.reticles:void 0,an=e.reticleConfig,rn=e.view?.dataAxisFlip,bt=e.isLotStack,vt=e.aggrMethod,xt=e.lotSize,si(),ze(),v(),N&&pe()},setOptions(e){bn(e)},getOptions(){return{...p}},resetZoom:st,setSelection(e){E=new Set(e.map(t=>Be(t))),v()},clearSelection(){E=new Set,he?.([]),v()},setFallbackFormat(e){Pe=e,ze(),v()},setFindingsNotice(e){gn=e,N?pe():R&&Ye()},setStatsSummary(e){if(re=e,mt(),Bt(),N)pe();else if(R)Ye();else if(e&&!Te?.placement){const t=Te?.defaultOpen??!Le;R=$t("right",ge,g),R.style.display=t?"block":"none";const n=S.parentElement,i=S.nextSibling;fe=Gt(S,R,"right"),n?.insertBefore(fe,i),Ye()}it()},setSummaryVisible(e){I&&(I.style.display=e?"flex":"none")},setViewControlsVisible(e){L&&(L.style.display=e?"flex":"none")},setExpandVisible(e){J&&(J.style.display=e?"flex":"none")},setHelpButtonVisible(e){tt&&(tt.style.display=e?"flex":"none")},setIdentityVisible(e){Ct=!e,z&&(z.style.display=e?"":"none"),ve()},openUserGuide:At,setInsightsOpen(e){Ie(e),A&&(e?(A.dataset.active="1",A.style.background=x.bgActive,A.style.color=x.iconActive):(delete A.dataset.active,A.style.background="transparent",A.style.color=x.icon))},closeSummaryPanel(){const e=N??R;!e||e.style.display==="none"||(e.style.display="none",I&&(delete I.dataset.active,I.style.background="transparent",I.style.color=x.icon))},setTooltipParent(e){w&&Oi(e)},getActiveLegend(){const e=p.plotMode;if(e==="metadata"){const s=p.activeMetadataKey;if(!s)return null;const d=ce?.find(l=>l.key===s),r=[...new Set(te.map(l=>l.metadata?.[s]).filter(l=>l!=null&&(typeof l=="string"||typeof l=="number"||typeof l=="boolean")).map(String))].sort();return r.length?r.map((l,c)=>{const f=d?.values?.find(Q=>Q.value===l),h=f?.color??eo(c);return{bin:l,name:f?.label??l,color:h}}):null}if(e!=="hardBin"&&e!=="softBin")return null;const t=e==="hardBin",n=t?G:U,i=[...new Set(te.map(s=>t?s.hbin:s.sbin).filter(s=>s!==void 0))].sort((s,d)=>s-d);if(!i.length)return null;const o=t?m.binColors.hard:m.binColors.soft;return i.map(s=>{const d=n?.find(r=>r.bin===s);return{bin:s,name:d?.name??`Bin ${s}`,color:o.get(s)??to}})},destroy(){ye?.close(),mn?.()?.remove(),kt&&g.removeEventListener("click",kt,!0),a.removeEventListener("wheel",xn),a.removeEventListener("pointerdown",wn),a.removeEventListener("pointermove",Sn),a.removeEventListener("pointerup",Mn),a.removeEventListener("pointerleave",En),a.removeEventListener("pointercancel",Dn),a.removeEventListener("dblclick",In),a.removeEventListener("keydown",Pn),a.removeEventListener("keyup",Rn),a.removeEventListener("click",Wn),kn.disconnect(),Ve.removeEventListener("change",ot),Ln.removeEventListener("change",Tn),H.removeEventListener("blur",On),ii(),w&&pt(g),oe?.remove(),Me&&(Me.parentElement?.insertBefore(S,Me),Me.remove()),fe&&(fe.parentElement?.insertBefore(S,fe),fe.remove()),S.remove(),a.style.cursor="",Y?.destroy(),Z?.destroy(),ke.remove()}}}
@@ -3,6 +3,7 @@ import type { Die } from '../core/dies.js';
3
3
  import { type BinDef, type TestDef, type YieldSummary, type MetadataFieldDef } from '../renderer/buildWaferMap.js';
4
4
  import type { StatsFinding, StatsSummary, LotStatsSummary } from '../stats/types.js';
5
5
  import { type FindingsFilter } from '../stats/filterFindings.js';
6
+ import { type BinColors } from '../renderer/binColors.js';
6
7
  import { buildWarningsBanner, type WaferWarning } from './warnings.js';
7
8
  export { buildWarningsBanner };
8
9
  import type { PlotMode } from '../renderer/buildView.js';
@@ -87,7 +88,13 @@ export declare function buildYieldSection(yieldSummary: YieldSummary, dataCovera
87
88
  edgeExcludedDies: number;
88
89
  ratio: number;
89
90
  }, passBins?: number[]): HTMLDivElement;
90
- export declare function buildBinSection(dies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft', colorScheme?: string,
91
+ export declare function buildBinSection(dies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft',
92
+ /**
93
+ * The map's resolved colours for this bin type (`View.binColors.hard`/`.soft`),
94
+ * so bars match die fills. Omitted ⇒ resolved here from `dies` with the
95
+ * default palette — never a second colour rule.
96
+ */
97
+ binColors?: ReadonlyMap<number, string>,
91
98
  /**
92
99
  * Precomputed counts (e.g. `StatsSummary.stats.hardBinCounts`/`.softBinCounts`,
93
100
  * already scoped to the yield-eligible population) — used directly instead
@@ -114,7 +121,8 @@ export declare function buildBinBreakdownSection(params: {
114
121
  dies: Die[];
115
122
  hbinDefs?: BinDef[];
116
123
  sbinDefs?: BinDef[];
117
- colorScheme?: string;
124
+ /** The map's resolved bin colours (`View.binColors`). Omitted ⇒ resolved from `dies`. */
125
+ binColors?: BinColors;
118
126
  hardCounts?: Record<number, number>;
119
127
  softCounts?: Record<number, number>;
120
128
  /** The map's active plot mode. `hardBin`/`softBin` pick the matching bin type. */
@@ -126,7 +134,7 @@ export declare function buildBinBreakdownSection(params: {
126
134
  * precomputed bin counts exist (`hardBinCounts`/`softBinCounts` are
127
135
  * per-wafer only), so this scans the pooled `Die[]` directly, same as
128
136
  * `buildBinSection` does when it has no `precomputedCounts`. */
129
- export declare function buildLotBinSection(allDies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft', colorScheme?: string): HTMLDivElement | null;
137
+ export declare function buildLotBinSection(allDies: Die[], binDefs: BinDef[] | undefined, mode: 'hard' | 'soft', binColors?: ReadonlyMap<number, string>): HTMLDivElement | null;
130
138
  /**
131
139
  * Region yield as ONE section with a Ring/Quadrant selector, replacing the two
132
140
  * always-on stacked sections (`Ring Yield` + `Quadrant Yield`) this used to render.
@@ -417,7 +425,8 @@ export declare function renderWaferSummaryContent(panel: HTMLDivElement, params:
417
425
  warnings?: WaferWarning[];
418
426
  passBins?: number[];
419
427
  ringCount?: number;
420
- colorScheme?: string;
428
+ /** The map's resolved bin colours (`View.binColors`), so bars match die fills. */
429
+ binColors?: BinColors;
421
430
  /**
422
431
  * The map's active plot mode. Selects which bin type the bin breakdown opens
423
432
  * on, so the panel describes the population actually on screen — see
@@ -466,7 +475,8 @@ export declare function renderLotSummaryContent(panel: HTMLDivElement, params: {
466
475
  testDefs?: TestDef[];
467
476
  passBins?: number[];
468
477
  ringCount?: number;
469
- colorScheme?: string;
478
+ /** The gallery-wide bin colours, so bars match every card. */
479
+ binColors?: BinColors;
470
480
  /** The gallery's active plot mode — see the wafer panel's `plotMode`. */
471
481
  plotMode?: PlotMode;
472
482
  fallbackFormat?: 'si' | 'engineering';
@@ -1,3 +1,3 @@
1
- import{isParametricTest as _t}from"../renderer/buildWaferMap.js";import{buildRingRegions as jt,buildQuadrantRegions as qt,buildRegionYieldData as Vt}from"../stats/regions.js";import{computeFunctionalYield as Kt}from"../stats/analyzeWaferMap.js";import{renderSummaryReportHtml as Gt,renderLotSummaryReportHtml as Ut}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as Qt}from"../stats/findingsNarrative.js";import{filterFindings as Xt}from"../stats/filterFindings.js";import{buildFacetTable as Zt,prettyKey as xt}from"../stats/facets.js";import{commonMetadata as yt}from"../stats/facets.js";import{resolveMetadataColumns as Jt}from"../stats/metadataColumns.js";import{getColorScheme as te}from"../renderer/colorSchemes.js";import{buildWarningsBanner as mt,collectWarnings as Ct}from"./warnings.js";export{mt as buildWarningsBanner};import{fmt as St,fmtAggregationMethod as ee,plainBinTerms as nt}from"../renderer/fmt.js";import{getUniqueTestNumbers as ne}from"../renderer/buildView.js";import{quantile as it}from"../stats/math.js";import{buildCapabilityData as ie}from"../stats/capability.js";import{sortBinsForDisplay as oe}from"../stats/binPareto.js";import{poolFunctionalYield as ae}from"../stats/testPassRate.js";import{makeLabeledSelect as wt,makeSegmented as ht}from"./charts/chartShell.js";import{SHADOW as vt,MOTION as $t,LEADING as Q,TRACKING as rt,wireControlHover as O,controlStyle as lt,SPACE as y,RADIUS as _,FONT as E,CLR as B,sevColor as dt,openModal as kt,openReportModal as Lt,saveTextFile as Bt,wireTooltip as ot}from"./toolbar.js";import{buildDieListSection as se}from"./dieList.js";export{csvField}from"../core/utils.js";import{medianOfSorted as re,csvField as ct}from"../core/utils.js";import{metadataDisplayValue as le}from"../core/metadata.js";const de=B.panelBg,Nt=`1px solid ${B.menuBorder}`,ce="12px",Y=B.label,U=B.value,Et="10px";function s(t,n,i,e=document){const o=e.createElement(t);return n&&Object.assign(o.style,n),i!==void 0&&(o.textContent=i),o}function J(t){return s("div",{fontSize:Et,fontWeight:"700",letterSpacing:rt,textTransform:"uppercase",color:Y,marginBottom:y.sm},t)}const Ft=new WeakMap,Rt=["regionYield","testValues","functionalTests"];function pt(t){if(!t)return{collapsed:new Set(Rt),regionMode:"ring",waferSort:"slot"};let n=Ft.get(t);return n||(n={collapsed:new Set(Rt),regionMode:"ring",waferSort:"slot"},Ft.set(t,n)),n}function X(t,n=!0,i,e){const o=s("div"),a=pt(e?.panel);e?.stateKey&&e.panel&&(n=!a.collapsed.has(e.stateKey));const r=document.createElement("button");r.type="button",Object.assign(r.style,{display:"flex",alignItems:"center",gap:y.xs,width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const f=s("span",{fontSize:E.meta,color:Y,transition:`transform ${$t.base}`,transform:n?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:Q.none,marginRight:"1px"},"\u25B6"),c=s("span",{fontSize:Et,fontWeight:"700",letterSpacing:rt,textTransform:"uppercase",color:Y,flex:"1"},t);if(O(r,"bare"),r.setAttribute("aria-expanded",n?"true":"false"),r.appendChild(f),r.appendChild(c),i){const b=s("span",{fontSize:E.meta,fontWeight:"700",background:B.warnBg,color:B.warnText,borderRadius:_.pill,padding:"1px 5px"},i);r.appendChild(b)}const l=s("div");l.style.display=n?"block":"none";let d=n;if(r.addEventListener("click",()=>{d=!d,l.style.display=d?"block":"none",f.style.transform=d?"rotate(90deg)":"rotate(0deg)",r.setAttribute("aria-expanded",d?"true":"false"),e?.stateKey&&e.panel&&(d?a.collapsed.delete(e.stateKey):a.collapsed.add(e.stateKey))}),e?.control){const b=s("div",{display:"flex",alignItems:"center",gap:y.sm});r.style.width="auto",r.style.flex="1",b.appendChild(r);const p=()=>{l.innerHTML="",e.render?.(l)},v=e.control(p);v&&(v.style.marginBottom="6px",v.addEventListener("click",N=>N.stopPropagation()),b.appendChild(v)),o.appendChild(b)}else o.appendChild(r);return o.appendChild(l),e?.render?.(l),{outer:o,content:l}}function Tt(){return s("div",{height:"1px",background:B.separator,margin:`${ce} 0`,flexShrink:"0"})}function gt(t,n,i=B.barFill,e,o){const a=s("div",{marginBottom:"5px"}),r=s("div",{display:"flex",justifyContent:"space-between",fontSize:E.body,color:U,marginBottom:y.xxs}),f=s("span",{color:Y},t),c=s("span",{fontWeight:"600"},`${n.toFixed(1)}%`);r.appendChild(f),r.appendChild(c);const l=e!==void 0?e:Math.min(100,Math.max(0,n)),d=i,b=s("div",{position:"relative",height:"9px",background:B.bgActive,borderRadius:_.control,overflow:"hidden"}),p=s("div",{height:"100%",width:`${l}%`,background:d,borderRadius:_.control,transition:`width ${$t.base}`});if(b.appendChild(p),o!==void 0){const v=s("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"2px",marginLeft:"-1px",background:B.value,opacity:"0.8"});b.appendChild(v)}return a.appendChild(r),a.appendChild(b),a}function Dt(){const t=s("div",{display:"flex",gap:y.sm,marginBottom:y.md});return t.finish=()=>{const n=t.lastElementChild;n&&Object.assign(n.style,{borderRight:"none",paddingRight:"0"})},t}function at(t,n,i){const e=s("div",{padding:`${y.xxs} ${y.md} ${y.xxs} 0`,borderRight:Nt,textAlign:"center",flex:"1"}),o=s("div",{fontSize:E.heading,fontWeight:"700",color:U,lineHeight:Q.tight},t),a=s("div",{fontSize:E.body,color:Y,marginTop:y.xxs},n);return e.appendChild(o),e.appendChild(a),i&&e.appendChild(s("div",{fontSize:E.body,color:Y,opacity:"0.85"},i)),e}function Mt(t,n){const i=s("div",{display:"flex",justifyContent:"space-between",fontSize:E.body,gap:y.md,marginBottom:"3px"}),e=s("span",{color:Y,flexShrink:"0"},t),o=s("span",{color:U,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},n);return i.appendChild(e),i.appendChild(o),i}function pe(t,n){const i=s("div",{display:"flex",fontSize:E.body,gap:y.sm,marginBottom:"3px"}),e=s("span",{color:Y,flexShrink:"0"},`${t}:`),o=s("span",{color:U,fontWeight:"500",wordBreak:"break-all"},n);return i.appendChild(e),i.appendChild(o),i}export function metadataEntries(t){const n=[];for(const[i,e]of Object.entries(t)){const o=le(e);o!==void 0&&n.push([i,o])}return n}const ue=["lot","product","testprogram","split"],ut=t=>{const n=ue.indexOf(t.toLowerCase().replace(/[^a-z]/g,""));return n===-1?Number.MAX_SAFE_INTEGER:n};export function buildFacetSummaryChips(t,n=3){if(!t.length)return null;const i=s("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:`${y.xs} ${y.lg}`}),e=[...t].sort((f,c)=>ut(f.key)-ut(c.key)),o=e.filter(f=>ut(f.key)!==Number.MAX_SAFE_INTEGER),a=e.filter(f=>ut(f.key)===Number.MAX_SAFE_INTEGER),r=f=>{const c=s("span",{whiteSpace:"nowrap"}),l=s("span",{color:Y},`${xt(f.key)}: `);c.appendChild(l);const d=f.values.slice(0,n),b=f.values.length-d.length;let p=d.map(v=>v.value).join(", ");return b>0&&(p+=` +${b} more`),c.appendChild(document.createTextNode(p)),c};for(const f of o)i.appendChild(r(f));if(a.length){const f=s("span",{display:"none",flexWrap:"wrap",alignItems:"baseline",gap:`${y.xs} ${y.lg}`});for(const d of a)f.appendChild(r(d));const c=s("button",{background:"none",border:"none",padding:"0",cursor:"pointer",color:B.iconActive,fontSize:E.body,whiteSpace:"nowrap"});c.type="button",O(c,"bare");const l=d=>{f.style.display=d?"contents":"none",c.textContent=d?"less":`+${a.length} more`,c.setAttribute("aria-expanded",String(d))};l(!1),c.addEventListener("click",()=>l(c.getAttribute("aria-expanded")!=="true")),i.appendChild(f),i.appendChild(c)}return i}export function buildMetadataStripRow(t,n,i){const e=Zt(t,i),o=buildFacetSummaryChips(e);if(!o&&!n)return null;const a=s("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(n){const r=s("span",{fontWeight:"500",whiteSpace:"nowrap"},n.aggrMethod?`${n.lotSize} wafers stacked \xB7 ${n.aggrMethod}`:`${n.lotSize} wafers stacked`);a.appendChild(r)}return o&&a.appendChild(o),a}const fe={display:"flex",flexDirection:"column",gap:y.sm,background:B.menuBg,border:`1px solid ${B.menuBorder}`,borderRadius:_.container,padding:`${y.sm} ${y.lg}`,boxShadow:vt.panel,fontSize:E.body,lineHeight:Q.none,boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,n,i){const e=buildMetadataStripRow(t,n,i);if(!e)return null;const o=s("div",fe);return o.appendChild(e),o}export function buildCompactMetadataRows(t){const n=metadataEntries(t);if(!n.length)return null;const i=s("div");for(const[e,o]of n)i.appendChild(pe(xt(e),o));return i}export function buildMetadataInfoSection(t,n){const i=buildMetadataStripRow(t,n,{facetableOnly:t.length>1});if(!i)return null;const e=s("div");return e.appendChild(J("Wafer Info")),e.appendChild(i),e}export function buildYieldSection(t,n,i=[1]){const e=s("div");e.appendChild(J("Summary"));const o=Dt();if(o.appendChild(at(String(t.totalDies),"Total dies")),t.partialDies>0&&o.appendChild(at(String(t.partialDies),"Partial")),t.yieldPercent!==null){const a=i.length===1?`bin ${i[0]}`:`bins ${i.join(", ")}`;o.appendChild(at(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${a}`))}return o.finish(),e.appendChild(o),t.edgeExcludedDies>0&&e.appendChild(Mt("Edge excluded (outer zone)",String(t.edgeExcludedDies))),e}export function buildBinSection(t,n,i,e,o,a){const r=new Map;if(o)for(const[c,l]of Object.entries(o))r.set(Number(c),l);else for(const c of t){if(c.partial||c.edgeExcluded)continue;const l=i==="hard"?c.hbin:c.sbin;l!=null&&r.set(l,(r.get(l)??0)+1)}if(!r.size)return null;const f=s("div");f.appendChild(J(At(i,[...r.values()].reduce((c,l)=>c+l,0))));for(const c of It(r,n,e,a))f.appendChild(c);return f}function At(t,n){return`${t==="hard"?"Hard":"Soft"} Bin Breakdown \u2014 % of dies (N=${n})`}function It(t,n,i,e=[1]){const o=[...t.values()].reduce((c,l)=>c+l,0),a=n?new Map(n.map(c=>[c.bin,c])):null,r=oe(t.entries(),e),f=te(i);return r.map(([c,l])=>{const d=a?.get(c),b=d?.name?`Bin ${c} \xB7 ${d.name}`:`Bin ${c}`,p=l/o*100,v=(i==="custom"?d?.color:void 0)??f.forBin(c);return gt(`${b} (${l})`,p,v)})}export function buildBinBreakdownSection(t){const{dies:n,hbinDefs:i,sbinDefs:e,colorScheme:o,hardCounts:a,softCounts:r,plotMode:f,passBins:c=[1],panel:l}=t,d=m=>{const x=m==="hard"?a:r,S=new Map;if(x){for(const[$,L]of Object.entries(x))S.set(Number($),L);return S}for(const $ of n){if($.partial||$.edgeExcluded)continue;const L=m==="hard"?$.hbin:$.sbin;L!=null&&S.set(L,(S.get(L)??0)+1)}return S},b=d("hard"),p=d("soft"),v=b.size>0,N=p.size>0;if(!v&&!N)return null;const M=pt(l),W=f==="softBin"||f==="stackedSoftBins"?"soft":f==="hardBin"||f==="stackedBins"?"hard":void 0;let R=M.binMode??W??(v?"hard":"soft");R==="hard"&&!v&&(R="soft"),R==="soft"&&!N&&(R="hard");const H=R==="hard"?b:p,h=R==="hard"?i:e,u=[...H.values()].reduce((m,x)=>m+x,0),{outer:w}=X(At(R,u),!0,void 0,{stateKey:"bins",panel:l,render:m=>{for(const x of It(H,h,o,c))m.appendChild(x)},control:v&&N&&l?()=>ht([["hard","Hard"],["soft","Soft"]],R,m=>{M.binMode=m;const x=buildBinBreakdownSection(t);x&&w.replaceWith(x)},l.ownerDocument,!0):void 0});return w}export function buildLotBinSection(t,n,i,e){return buildBinSection(t,n,i,e)}export function buildRegionYieldPanelSection(t){const{diesByWafer:n,allWafers:i,ringCount:e,passBins:o,panel:a}=t,r=pt(a),f=d=>Vt(n,i,e,o,d==="ring"?jt:qt);if(!f("ring").length&&!f("quadrant").length)return null;const c=r.regionMode,{outer:l}=X(c==="ring"?"Ring Yield":"Quadrant Yield",!0,void 0,{stateKey:"regionYield",panel:a,render:d=>{const b=f(c);if(!b.length){d.appendChild(s("div",{fontSize:E.body,color:Y},"No positioned dies for this breakdown."));return}for(const{label:p,n:v,yieldPercent:N}of b)d.appendChild(gt(`${p} (N=${v})`,N))},control:a?()=>ht([["ring","Ring"],["quadrant","Quadrant"]],c,d=>{r.regionMode=d;const b=buildRegionYieldPanelSection(t);b&&l.replaceWith(b)},a.ownerDocument,!0):void 0});return l}export function buildLotOverviewSection(t,n=[]){const i=s("div");i.appendChild(J("Lot Summary"));const e=Dt();e.appendChild(at(String(t.stats.waferCount),"Wafers"));const o=t.perWafer.map(a=>a.summary.stats.yieldPercent).filter(a=>a!==null);if(o.length){const a=o.reduce((r,f)=>r+f,0)/o.length;e.appendChild(at(`${a.toFixed(1)}%`,"Mean per-wafer yield"))}if(e.finish(),i.appendChild(e),n.length){const a=n.reduce((f,c)=>f+c.stats.analyzedDies,0),r=n.reduce((f,c)=>f+c.stats.excludedDies,0);(a||r)&&i.appendChild(Mt("Dies analysed",r?`${a.toLocaleString()} (${r.toLocaleString()} excluded)`:a.toLocaleString()))}return i}export function buildPerWaferYieldSection(t,n,i,e,o){const a=t.perWafer.map(u=>({waferIndex:u.waferIndex,label:(n[u.waferIndex]?.label??`W${u.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:u.summary.stats.yieldPercent})).filter(u=>u.yieldPct!==null);if(!a.length)return null;const r=Math.min(...a.map(u=>u.yieldPct)),f=Math.max(...a.map(u=>u.yieldPct)),c=r===f?"":` (${r.toFixed(1)}\u2013${f.toFixed(1)}%)`,l=[...a.map(u=>u.yieldPct)].sort((u,w)=>u-w),d=re(l),b=it(l,.25),p=it(l,.75),v=a.length>=5?b-1.5*(p-b):-1/0,N=pt(e),M=u=>{const w=N.waferSort==="yield"?[...a].sort((m,x)=>m.yieldPct-x.yieldPct):a;for(const{waferIndex:m,label:x,yieldPct:S}of w){const L=S<v?`${x} \xB7 low outlier`:x,F=gt(L,S,void 0,void 0,d),T=o?.(m);T?.total&&H(F,T),h(F,m,x,S,T),u.appendChild(F)}},W=` \xB7 median ${d.toFixed(1)}%`,{outer:R}=X("Wafer Yield"+c+W,!0,void 0,{stateKey:"waferYield",panel:e,render:M,control:e?u=>ht([["slot","Slot"],["yield","Yield"]],N.waferSort,w=>{N.waferSort=w,u()},e.ownerDocument,!0):void 0});return R;function H(u,w){const m=w.unusual?"unusual":w.notable?"notable":"info",x=s("span",{marginLeft:y.sm,flexShrink:"0",background:dt(m),color:"#fff",borderRadius:_.container,padding:"0 5px",fontSize:E.body,fontWeight:"600"},`${w.total}`);x.setAttribute("aria-hidden","true"),ot(x,`${w.total} finding${w.total===1?"":"s"}`+(w.unusual?`, ${w.unusual} unusual`:"")+(w.notable?`, ${w.notable} notable`:"")),u.firstElementChild?.firstElementChild?.appendChild(x)}function h(u,w,m,x,S){i&&(u.style.cursor="pointer",u.style.borderRadius="4px",u.style.padding="2px 3px",u.style.marginLeft="-3px",u.style.marginRight="-3px",u.setAttribute("role","button"),u.setAttribute("aria-label",`${m}, ${x.toFixed(1)}% yield`+(S?.total?`, ${S.total} finding${S.total===1?"":"s"}${S.unusual?`, ${S.unusual} unusual`:""}`:"")+" \u2014 open wafer"),u.tabIndex=0,u.addEventListener("mouseenter",()=>{u.style.background=B.bgHover}),u.addEventListener("mouseleave",()=>{u.style.background=""}),u.addEventListener("focus",()=>{u.style.background=B.bgHover}),u.addEventListener("blur",()=>{u.style.background=""}),u.addEventListener("click",()=>i(w)),u.addEventListener("keydown",$=>{($.key==="Enter"||$.key===" ")&&($.preventDefault(),i(w))}))}}function me(t){const n=[...t].sort((o,a)=>o-a),i=t.reduce((o,a)=>o+a,0)/t.length,e=t.reduce((o,a)=>o+(a-i)**2,0)/t.length;return{min:n[0],max:n[n.length-1],mean:i,count:t.length,stddev:Math.sqrt(e),median:it(n,.5),q1:it(n,.25),q3:it(n,.75)}}function Wt(t,n){if(!t)return[];const i=t.waferMetadata??(t.perWaferMetadata?yt(t.perWaferMetadata.map(e=>({metadata:e}))):void 0);return!i||!Object.keys(i).length?[]:Jt({waferMetadata:i,waferKeys:"identity",waferPlacement:"csv",reservedLabels:n}).columns}function Pt(t){return t?.populationLabel?[{key:"population",label:"Population",scope:"wafer",constant:t.populationLabel,get:()=>t.populationLabel,csvOnly:!0}]:[]}export function buildTestSection(t,n,i,e,o,a,r,f,c="full"){const l=t.filter(g=>!g.partial&&!g.edgeExcluded),d=new Map((e?.perTestStats??[]).map(g=>[g.testNumber,g])),b=new Map((e?.testSpecYield??[]).map(g=>[g.testNumber,g]));let p;if(n?.length?p=n.filter(_t).map(g=>({testNumber:g.testNumber,name:g.name,unit:g.unit,limitLow:g.limitLow,limitHigh:g.limitHigh})):p=ne(l).map(C=>({testNumber:C,name:`Test ${C}`})),!p.length)return null;const v=p.filter(g=>l.some(C=>{const I=C.testValues?.[g.testNumber];return I!==void 0&&isFinite(I)}));if(!v.length)return null;const N=v.some(g=>g.limitLow!==void 0||g.limitHigh!==void 0),M=[];for(const g of v){const C=d.get(g.testNumber),I=C&&C.stddev!==void 0&&C.median!==void 0&&C.q1!==void 0&&C.q3!==void 0;let j;if(I){const k=C;j={testNumber:g.testNumber,min:k.min,max:k.max,mean:k.mean,count:k.count,stddev:k.stddev,median:k.median,q1:k.q1,q3:k.q3}}else{const k=l.map(D=>D.testValues?.[g.testNumber]).filter(D=>D!==void 0&&isFinite(D));if(!k.length)continue;j={testNumber:g.testNumber,...me(k)}}let z=null,P=0;if(g.limitLow!==void 0||g.limitHigh!==void 0){const k=b.get(g.testNumber);if(k)({yieldPercent:z,totalDies:P}=k);else{const D=l.map(q=>q.testValues?.[g.testNumber]).filter(q=>q!==void 0&&isFinite(q)),Z=D.filter(q=>g.limitLow!==void 0&&q<g.limitLow||g.limitHigh!==void 0&&q>g.limitHigh).length;P=D.length,z=D.length>0?(D.length-Z)/D.length*100:null}}M.push({entry:g,stats:j,specYieldPct:z,specN:P})}if(!M.length)return null;const W=new Map;if(r?.length&&n?.length)for(const g of ie(r,n))g.hasSpec&&W.set(g.testNumber,g.ppk);const R=W.size>0,h=new Set(M.map(g=>g.stats.count)).size===1?M[0].stats.count:null,u=s("div"),w=s("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:y.sm}),m=h!==null?` \xB7 N=${h.toLocaleString()}`:"",x=a?.populationLabel?`Test Values (${M.length}) \u2014 ${a.populationLabel}${m}`:`Test Values (${M.length})${m}`,S=J(x);S.style.marginBottom="0",w.appendChild(S);const $=document.createElement("button");$.type="button",$.textContent="Test values CSV",Object.assign($.style,{...lt("outlined")}),O($),$.addEventListener("click",()=>{const g=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];R&&g.push("Ppk");const C=M.some(k=>k.specYieldPct!==null&&k.specN!==k.stats.count);N&&(g.push("LSL","USL","Spec Yield %"),C&&g.push("Spec Yield N"));const I=[...Wt(a,g),...Pt(a)],z=[[...I.map(k=>k.label),...g].map(ct).join(",")],P=k=>St(k,void 0,"engineering");for(const{entry:k,stats:D,specYieldPct:Z,specN:q}of M){const st=[...I.map(et=>et.constant??""),k.name,k.unit??"",String(D.count),P(D.min),P(D.q1),P(D.median),P(D.mean),P(D.q3),P(D.max),P(D.stddev)];if(R){const et=W.get(k.testNumber);st.push(et==null?"":et.toFixed(3))}N&&(st.push(k.limitLow!==void 0?P(k.limitLow):"",k.limitHigh!==void 0?P(k.limitHigh):"",Z!==null?Z.toFixed(1):""),C&&st.push(k.limitLow!==void 0||k.limitHigh!==void 0?String(q):"")),z.push(st.map(ct).join(","))}Bt(z.join(`
2
- `),"test-values.csv","text/csv",o)}),w.appendChild($),u.appendChild(w);const L=s("table",{width:"100%",borderCollapse:"collapse",fontSize:E.body}),F=document.createElement("thead"),T=document.createElement("tr"),A=["Test"];h===null&&A.push("N"),c==="full"&&A.push("Min","Q1","Median"),A.push("Mean"),c==="full"&&A.push("Q3","Max","StdDev"),R&&A.push("Ppk"),c==="full"&&N&&A.push("LSL","USL"),N&&A.push("Spec yield");for(const g of A){const C=s("th",{textAlign:g==="Test"?"left":"right",fontWeight:"600",fontSize:E.meta,letterSpacing:rt,textTransform:"uppercase",color:Y,padding:"3px 8px 5px",borderBottom:`1px solid ${B.menuBorder}`,whiteSpace:"nowrap"},g);T.appendChild(C)}F.appendChild(T),L.appendChild(F);const V=document.createElement("tbody");for(const{entry:g,stats:C,specYieldPct:I,specN:j}of M){const z=D=>St(D,g.unit,i),P=document.createElement("tr"),k=(D,Z="right")=>{const q=s("td",{textAlign:Z,padding:`${y.xs} ${y.md}`,borderBottom:`1px solid ${B.menuBorder}`,color:B.text,whiteSpace:"nowrap"},D);P.appendChild(q)};if(k(g.name,"left"),h===null&&k(`${C.count}`),c==="full"&&(k(z(C.min)),k(z(C.q1)),k(z(C.median))),k(z(C.mean)),c==="full"&&(k(z(C.q3)),k(z(C.max)),k(z(C.stddev))),R){const D=W.get(g.testNumber);k(D==null?"\u2014":D.toFixed(2))}c==="full"&&N&&(k(g.limitLow!==void 0?z(g.limitLow):"\u2014"),k(g.limitHigh!==void 0?z(g.limitHigh):"\u2014")),N&&k(I!==null?h!==null&&j===h?`${I.toFixed(1)}%`:`${I.toFixed(1)}% (N=${j})`:"\u2014"),V.appendChild(P)}L.appendChild(V);const K=s("div",{overflowX:"auto"});if(K.appendChild(L),!f)return u.appendChild(K),u;w.remove();const{outer:G}=X(x,!0,void 0,{stateKey:"testValues",panel:f,render:g=>g.appendChild(K),control:()=>$});return G}export function buildFunctionalTestSection(t,n,i,e,o,a){const r=i??Kt(t,n);if(!r?.length)return null;const c=new Set(r.map(m=>m.totalDies)).size===1?r[0].totalDies:null,l=c!==null?` \xB7 N=${c.toLocaleString()}`:"",d=s("div"),b=s("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:y.sm}),p=o?.populationLabel?`Functional Tests (${r.length}) \u2014 ${o.populationLabel}${l}`:`Functional Tests (${r.length})${l}`,v=J(p);v.style.marginBottom="0",b.appendChild(v);const N=document.createElement("button");N.type="button",N.textContent="Functional CSV",Object.assign(N.style,{...lt("outlined")}),O(N),N.addEventListener("click",()=>{const m=["Test","N","Pass","Fail","Pass Rate %"],x=[...Wt(o,m),...Pt(o)],S=[[...x.map($=>$.label),...m].map(ct).join(",")];for(const $ of r)S.push([...x.map(L=>L.constant??""),$.label,String($.totalDies),String($.passDies),String($.failDies),$.passRatePercent!==null?$.passRatePercent.toFixed(1):""].map(ct).join(","));Bt(S.join(`
3
- `),"functional-tests.csv","text/csv",e)}),b.appendChild(N),d.appendChild(b);const M=s("table",{width:"100%",borderCollapse:"collapse",fontSize:E.body}),W=document.createElement("thead"),R=document.createElement("tr"),H=c===null?["Test","N","Pass","Fail","Pass rate"]:["Test","Pass","Fail","Pass rate"];for(const m of H)R.appendChild(s("th",{textAlign:m==="Test"?"left":"right",fontWeight:"700",fontSize:E.body,letterSpacing:rt,textTransform:"uppercase",color:Y,padding:"3px 8px 5px",borderBottom:`1px solid ${B.menuBorder}`,whiteSpace:"nowrap"},m));W.appendChild(R),M.appendChild(W);const h=document.createElement("tbody");for(const m of r){const x=document.createElement("tr"),S=($,L="right")=>{x.appendChild(s("td",{textAlign:L,padding:`${y.xs} ${y.md}`,borderBottom:`1px solid ${B.menuBorder}`,color:U,whiteSpace:"nowrap"},$))};S(m.label,"left"),c===null&&S(String(m.totalDies)),S(String(m.passDies)),S(String(m.failDies)),S(m.passRatePercent!==null?`${m.passRatePercent.toFixed(1)}%`:"\u2014"),h.appendChild(x)}M.appendChild(h);const u=s("div",{overflowX:"auto"});if(u.appendChild(M),!a)return d.appendChild(u),d;b.remove();const{outer:w}=X(p,!0,void 0,{stateKey:"functionalTests",panel:a,render:m=>m.appendChild(u),control:()=>N});return w}export function buildLotFunctionalSection(t,n,i,e,o){const a=i?.length?{perWaferMetadata:i.map(f=>f.wafer??{}),populationLabel:`${i.length} wafer${i.length===1?"":"s"} pooled`}:void 0,r=ae(i);return r?buildFunctionalTestSection(t,n,r,e,a,o):buildFunctionalTestSection(t,n,void 0,e,a,o)}const tt={unusual:0,notable:1,info:2};function bt(t){return s("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:_.pill,background:dt(t),flexShrink:"0"})}function zt(t,n){let i=t.summary;return n&&(i.startsWith(`${n} has `)?i=i.slice(n.length+5):i.startsWith(`${n} `)&&(i=i.slice(n.length+1))),i=nt(i),i.length?i[0].toUpperCase()+i.slice(1):i}export function buildFindingsSection(t,n,i,e,o=!1){if(!t.length)return null;const a=t.some(h=>h.severity==="unusual"||h.severity==="notable"),r=a?t.filter(h=>h.severity!=="info").length.toString():void 0,{outer:f,content:c}=o?(()=>{const h=s("div");return{outer:h,content:h}})():X(`Findings (${t.length})`,a,r);function l(h){return h.reduce((u,w)=>tt[w.severity]<tt[u]?w.severity:u,"info")}function d(h){const u=new Map;for(const m of h){const x=`${m.comparison.family}\0${m.comparison.left}`,S=u.get(x)??[];S.push(m),u.set(x,S)}const w=[...u.entries()].map(([m,x])=>{const S=[...x].sort(($,L)=>tt[$.severity]-tt[L.severity]);return{key:m,findings:S,worst:l(S)}});return w.sort((m,x)=>tt[m.worst]-tt[x.worst]),w}function b(h,u){const m={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[h]??h;return u.toLowerCase().startsWith(m.toLowerCase())?u:`${m}: ${u}`}const p=t.filter(h=>h.comparison.family==="spatial-pattern"),v=new Set([...p.flatMap(h=>h.relatedIds??[]),...t.flatMap(h=>h.absorbedIds??[])]),N=t.filter(h=>h.comparison.family!=="spatial-pattern"&&!v.has(h.id)),M=d(N);function W(h,u=!1,w){const m=e===h.id,x=document.createElement("button");return x.type="button",x.dataset.wmapFinding=h.id,x.textContent=zt(h,w),ot(x,h.summary),x.setAttribute("aria-current",m?"true":"false"),Object.assign(x.style,{border:`1px solid ${B.menuBorder}`,borderLeft:`3px solid ${dt(h.severity)}`,background:m?B.bgActive:B.menuBg,borderRadius:_.container,padding:u?"6px 10px":"8px 10px",textAlign:"left",fontSize:u?"10px":"11px",fontWeight:m?"600":"400",color:B.text,cursor:"pointer",width:"100%",marginBottom:y.xs}),O(x,"bare"),x.addEventListener("click",()=>i(h,x)),x}const R=nt(Qt(t)??"");if(R){const h=s("div",{background:B.bgActive,borderRadius:_.container,padding:`${y.md} ${y.lg}`,marginBottom:y.md,display:"flex",gap:y.md,alignItems:"flex-start"}),u=s("span",{flex:"1",fontSize:E.body,lineHeight:Q.base,color:B.text},R);h.appendChild(u);const w=s("button",{flexShrink:"0",border:"none",background:"none",fontSize:E.body,color:B.icon,cursor:"pointer",padding:"0",lineHeight:Q.base,whiteSpace:"nowrap"},"Detail \u25B8");w.type="button",O(w,"bare"),w.addEventListener("click",()=>{const m=kt({title:"Findings Summary",onClose:()=>{},anchor:w}),x=s("p",{fontSize:"16px",lineHeight:Q.base,color:B.text,padding:`${y.xxl} ${y.xxxl} ${y.xxl}`,margin:"0",borderBottom:`1px solid ${B.menuBorder}`,flexShrink:"0"},R);m.contentWrap.appendChild(x);const S=s("div",{overflowY:"auto",padding:`${y.xxl} ${y.xxxl}`,flex:"1"}),$=(L,F)=>{const T=s("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:E.sub,fontWeight:"600",color:U,marginTop:y.lg,marginBottom:y.xs});return T.appendChild(bt(L)),T.appendChild(s("span",{},F)),T};for(const L of p){S.appendChild($(L.severity,L.comparison.left)),S.appendChild(s("div",{fontSize:E.body,color:B.text,padding:"4px 0 4px 15px",marginBottom:y.xxs},nt(L.summary)));const F=t.filter(T=>L.relatedIds?.includes(T.id));for(const T of F)S.appendChild(s("div",{fontSize:E.body,color:Y,padding:"2px 0 2px 23px",marginBottom:y.xxs},nt(T.summary)))}for(const L of M){const[F,T]=L.key.split("\0");S.appendChild($(L.worst,b(F,T)));for(const A of L.findings)S.appendChild(s("div",{fontSize:E.body,color:B.text,padding:"4px 0 4px 15px",marginBottom:y.xxs},zt(A,T)))}m.contentWrap.appendChild(S),Object.assign(m.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),h.appendChild(w),c.appendChild(h)}let H=!0;for(const h of p){H||c.appendChild(s("div",{height:"1px",background:B.separator,margin:"4px 0"})),H=!1;const u=t.filter($=>h.relatedIds?.includes($.id)),w=u.length>0,m=s("div",{position:"relative",marginBottom:w?"2px":"4px"}),x=e===h.id,S=document.createElement("button");if(S.type="button",S.dataset.wmapFinding=h.id,Object.assign(S.style,{border:`1px solid ${B.menuBorder}`,borderLeft:`3px solid ${dt(h.severity)}`,background:x?B.bgActive:B.menuBg,borderRadius:_.container,padding:"8px 32px 8px 10px",textAlign:"left",fontSize:E.body,fontWeight:x?"600":"500",color:B.text,cursor:"pointer",width:"100%"}),S.textContent=nt(h.summary),ot(S,h.summary),S.setAttribute("aria-current",x?"true":"false"),O(S,"bare"),S.addEventListener("click",()=>i(h,S)),m.appendChild(S),w){const $=s("div",{display:"none",paddingLeft:"12px",marginBottom:y.xs});for(const T of u)$.appendChild(W(T,!0));m.appendChild($);let L=!1;const F=s("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:E.body,color:B.icon,cursor:"pointer",padding:`${y.xxs} ${y.xs}`,lineHeight:Q.none},"\u25B8");O(F,"bare"),F.type="button",ot(F),O(F,"bare"),F.setAttribute("aria-label","Show supporting findings"),F.setAttribute("aria-expanded","false"),F.addEventListener("click",T=>{T.stopPropagation(),L=!L,$.style.display=L?"block":"none",F.textContent=L?"\u25BE":"\u25B8";const A=L?"Hide supporting findings":"Show supporting findings";F.setAttribute("aria-label",A),F.setAttribute("aria-expanded",String(L))}),m.appendChild(F)}c.appendChild(m)}for(const h of M){H||c.appendChild(s("div",{height:"1px",background:B.separator,margin:"4px 0"})),H=!1;const[u,w]=h.key.split("\0"),m=s("div",{display:"flex",alignItems:"center",gap:y.sm,fontSize:E.body,fontWeight:"600",color:U,margin:"2px 0 4px"});m.appendChild(bt(h.worst)),m.appendChild(s("span",{},b(u,w))),c.appendChild(m);for(const x of h.findings)c.appendChild(W(x,!1,w))}return f}const he=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],ge=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],be=["unusual","notable","info"],xe={unusual:"Unusual",notable:"Notable",info:"Info"};function ye(t,n,i){const e=s("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:y.lg,marginBottom:y.lg,paddingBottom:"10px",borderBottom:`1px solid ${B.separator}`}),o={unusual:0,notable:0,info:0};for(const l of t)o[l.severity]++;const a=be.filter(l=>o[l]>0),r=new Set(n.severity===void 0?a:Array.isArray(n.severity)?n.severity:[n.severity]),f=s("div",{display:"flex",gap:y.xs,flexWrap:"wrap"});for(const l of a){const d=document.createElement("button");d.type="button";const b=()=>{const p=r.has(l);d.setAttribute("aria-pressed",p?"true":"false"),Object.assign(d.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${B.menuBorder}`,borderRadius:_.pill,background:p?B.bgActive:"none",opacity:p?"1":"0.5",color:B.text,fontSize:E.body,padding:`${y.xxs} ${y.md}`,cursor:"pointer"}),d.dataset.on=p?"true":"false"};d.appendChild(bt(l)),d.appendChild(s("span",{},`${xe[l]} ${o[l]}`)),ot(d,()=>r.has(l)?"Click to hide these findings":"Click to show these findings"),b(),O(d,"bare"),d.addEventListener("click",()=>{r.has(l)?r.delete(l):r.add(l),n.severity=r.size===a.length?void 0:[...r],i()}),f.appendChild(d)}e.appendChild(f);const c=n.kind!==void 0||n.family!==void 0;return(t.length>=Ce||c)&&(e.appendChild(wt("Kind:",he,n.kind??"",l=>{n.kind=l||void 0,i()},{maxWidth:"130px"})),e.appendChild(wt("Region:",ge,n.family??"",l=>{n.family=l||void 0,i()},{maxWidth:"150px"}))),e}const Ce=8;function Se(t,n){const i=s("div",{display:"flex",flexDirection:"column",gap:y.xs,padding:y.md,marginBottom:y.md,background:B.bgHover,borderRadius:_.control},void 0,n);if(i.appendChild(s("div",{fontSize:E.body,color:B.value},t.message,n)),t.detail&&i.appendChild(s("div",{fontSize:E.meta,color:Y},t.detail,n)),t.actionLabel&&t.onAction){const e=s("button",lt("outlined"),t.actionLabel,n);e.type="button",e.style.alignSelf="flex-start",e.style.marginTop=y.xs,O(e),e.addEventListener("click",t.onAction),i.appendChild(e)}return i}export function buildFindingsSectionWithFilter(t,n,i,e,o,a,r){if(!t.findings.length&&!r)return null;const f=t.findings.some(N=>N.severity==="unusual"||N.severity==="notable"),c=f?t.findings.filter(N=>N.severity!=="info").length.toString():void 0,l=a?.ownerDocument??document,{outer:d,content:b}=X(`Findings (${t.findings.length})`,f||!!r,c,{stateKey:"findings",panel:a});if(r&&b.appendChild(Se(r,l)),!t.findings.length)return d;b.appendChild(ye(t.findings,e,o));const p=Xt(t,e);if(!p.length)return b.appendChild(s("div",{color:Y,fontSize:E.body,textAlign:"center",padding:`${y.xxl} ${y.md}`},"No findings match the current filter.")),d;const v=buildFindingsSection(p,t,n,i,!0);return v&&b.appendChild(v),d}export function buildLotTestSection(t,n,i,e,o,a,r,f="full"){const c=e?.length?{perWaferMetadata:e.map(d=>d.wafer??{}),populationLabel:`${e.length} wafer${e.length===1?"":"s"} pooled`}:void 0;let l;if(e?.length&&e.every(d=>d.stats.perTestStats!==void 0)){const d=new Map;for(const b of e)for(const p of b.stats.perTestStats??[]){const v=d.get(p.testNumber);v?(v.n+=p.count,v.sum+=p.mean*p.count,v.min=Math.min(v.min,p.min),v.max=Math.max(v.max,p.max)):d.set(p.testNumber,{n:p.count,sum:p.mean*p.count,min:p.min,max:p.max})}l={perTestStats:[...d.entries()].map(([b,p])=>({testNumber:b,count:p.n,min:p.min,max:p.max,mean:p.sum/p.n}))}}if(e?.length&&e.every(d=>d.stats.testSpecYield!==void 0)){const d=new Map;for(const b of e)for(const p of b.stats.testSpecYield??[]){const v=d.get(p.testNumber);v?(v.passDies+=p.passDies,v.totalDies+=p.totalDies):d.set(p.testNumber,{passDies:p.passDies,totalDies:p.totalDies})}l={...l,testSpecYield:[...d.entries()].map(([b,p])=>({testNumber:b,totalDies:p.totalDies,yieldPercent:p.totalDies>0?p.passDies/p.totalDies*100:null}))}}return buildTestSection(t,n,i,l,o,c,a,r,f)}export function createSummaryPanelEl(t,n,i=document){const e=t==="top"||t==="bottom",o=s("div",{background:de,color:B.text,fontVariantNumeric:"tabular-nums",border:Nt,borderRadius:_.container,padding:y.xl,overflowY:e?"hidden":"auto",overflowX:e?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:E.family,fontSize:E.sub,boxShadow:vt.panel},void 0,i);return t==="right"&&(o.style.marginRight=n),t==="left"&&(o.style.marginLeft=n),t==="bottom"&&(o.style.marginBottom=n),e?(o.style.height="180px",o.style.width="100%"):(o.style.width="300px",o.style.maxHeight="100%"),o}export function wrapWithSummaryPanel(t,n,i){const e=i==="top"||i==="bottom",o=s("div",{display:"flex",flexDirection:e?"column":"row",gap:y.md,width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:e?"flex-start":"stretch"});return t.style.flex="1 1 0",t.style.minWidth="0",t.style.minHeight="0",i==="right"||i==="bottom"?(o.appendChild(t),o.appendChild(n)):(o.appendChild(n),o.appendChild(t)),o}function Ht(t){return s("div",{fontSize:E.heading,fontWeight:"600",color:U,marginBottom:y.lg},t)}function ft(t,n){const i=s("button",lt("outlined"),t);return i.type="button",O(i),i.addEventListener("click",n),i}function Yt(...t){const n=t.filter(e=>!!e);if(!n.length)return null;const i=s("div",{display:"flex",flexWrap:"wrap",gap:y.sm,marginBottom:y.lg});for(const e of n)i.appendChild(e);return i}function Ot(t,n,i,e,o,a,r,f,c,l,d){const b=t.ownerDocument,p=kt({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:b});p.contentWrap.style.padding="14px 16px";const v=se(n,i,{...r,title:e,onSaveText:f,waferMetadata:o,metadataFields:a,extraColumn:c,getWafer:l,ringCount:d,ownerDocument:b});v&&p.contentWrap.appendChild(v)}export function renderWaferSummaryContent(t,n){const i=t.scrollTop;t.innerHTML="";const{wafer:e,dies:o,yieldSummary:a,dataCoverage:r,hbinDefs:f,sbinDefs:c,testDefs:l,statsSummary:d,passBins:b=[1],ringCount:p=4,colorScheme:v,plotMode:N,fallbackFormat:M,onFindingClick:W,activeFindingId:R=null,findingsFilter:H,onFindingsFilterChange:h,findingsNotice:u,onSaveText:w,metadataFields:m,dieListOptions:x,metadataShownElsewhere:S}=n;t.appendChild(Ht("Wafer Summary"));const $=n.warnings??Ct({statsSummary:d});$.length&&t.appendChild(mt($,t.ownerDocument));const L=a&&r?ft("Summary report",()=>{Lt(Gt({wafer:e,dies:o,yieldSummary:a,dataCoverage:r,hbinDefs:f,sbinDefs:c,testDefs:l,statsSummary:d,passBins:b,ringCount:p}),{anchor:t})}):null,F=(x?.enabled??!0)&&o.length?ft("View die list",()=>{Ot(t,o,l,`Die list \u2014 ${o.length} dies`,e.metadata,m,x,w,void 0,()=>e,p)}):null,T=Yt(L,F);T&&t.appendChild(T);const A=[],V=d?.stats.isLotStack?d.stats:void 0,K=V?.lotSize!==void 0?{lotSize:V.lotSize,aggrMethod:ee(V.aggregationMethod)}:void 0;S||A.push(buildMetadataInfoSection([{metadata:e.metadata??void 0}],K)),a&&r&&A.push(buildYieldSection(a,r,b)),d&&W&&H&&h&&A.push(buildFindingsSectionWithFilter(d,W,R,H,h,t,u)),A.push(buildBinBreakdownSection({dies:o,hbinDefs:f,sbinDefs:c,colorScheme:v,hardCounts:d?.stats.hardBinCounts,softCounts:d?.stats.softBinCounts,plotMode:N,passBins:b,panel:t})),A.push(buildRegionYieldPanelSection({diesByWafer:[o],allWafers:[e],ringCount:p,passBins:b,panel:t}));const G=e.metadata?{waferMetadata:e.metadata}:void 0;A.push(buildTestSection(o,l,M,d?.stats,w,G,[{dies:o}],t,"compact")),A.push(buildFunctionalTestSection(o,l,d?.stats.functionalYield,w,G,t));let g=!0;for(const C of A)C&&(g||t.appendChild(Tt()),g=!1,t.appendChild(C));t.appendChild(s("div",{height:"12px",flexShrink:"0"})),t.scrollTop=i}export function renderLotSummaryContent(t,n){const i=t.scrollTop;t.innerHTML="";const{lotSummary:e,items:o,hbinDefs:a,sbinDefs:r,testDefs:f,passBins:c=[1],ringCount:l=4,colorScheme:d,plotMode:b,fallbackFormat:p,onFindingClick:v,activeFindingId:N=null,onWaferClick:M,findingsFilter:W,onFindingsFilterChange:R,findingsNotice:H,onSaveText:h,dieListOptions:u,findingsFor:w}=n;t.appendChild(Ht(`Lot Summary \u2014 ${e.stats.waferCount} wafer${e.stats.waferCount===1?"":"s"}`));const m=n.warnings??Ct({lotStatsSummary:e});m.length&&t.appendChild(mt(m,t.ownerDocument));const x=ft("Summary report",()=>{Lt(Ut({items:o.map((C,I)=>({label:C?.label??`W${I+1}`,wafer:C?.wafer,dies:C?.dies,statsSummary:C?.statsSummary})),hbinDefs:a,sbinDefs:r,testDefs:f,passBins:c,ringCount:l}),{anchor:t})}),S=[],$=[],L=[],F=new WeakMap,T=new WeakMap;for(let C=0;C<o.length;C++){const I=o[C];if(!I){$.push([]);continue}I.wafer&&S.push(I.wafer);const j=I.dies??[],z=I.label??`W${C+1}`;for(const P of j)F.set(P,z),I.wafer&&T.set(P,I.wafer);$.push(j),L.push(...j)}const A=u?.enabled??!0?ft("View die list",()=>{L.length&&Ot(t,L,f,`Die list \u2014 ${L.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,yt(o.filter(C=>!!C).map(C=>({metadata:C.wafer?.metadata}))),o.find(C=>C?.metadataFields?.length)?.metadataFields,u,h,{label:"Wafer",get:C=>F.get(C)},C=>T.get(C),l)}):null,V=Yt(x,A);V&&t.appendChild(V);const K=o.map(C=>C?.statsSummary).filter(C=>!!C),G=[buildLotOverviewSection(e,K)];v&&W&&R&&G.push(buildFindingsSectionWithFilter(e,v,N,W,R,t,H)),G.push(buildPerWaferYieldSection(e,o,M,t,w),buildBinBreakdownSection({dies:L,hbinDefs:a,sbinDefs:r,colorScheme:d,plotMode:b,passBins:c,panel:t}),buildRegionYieldPanelSection({diesByWafer:$,allWafers:S,ringCount:l,passBins:c,panel:t}),f?.length?buildLotTestSection(L,f,p,K,h,$.map(C=>({dies:C})),t,"compact"):null,f?.length?buildLotFunctionalSection(L,f,K,h,t):null);let g=!0;for(const C of G)C&&(g||t.appendChild(Tt()),g=!1,t.appendChild(C));t.appendChild(s("div",{height:"12px",flexShrink:"0"})),t.scrollTop=i}
1
+ import{isParametricTest as qt}from"../renderer/buildWaferMap.js";import{buildRingRegions as Vt,buildQuadrantRegions as Kt,buildRegionYieldData as Gt}from"../stats/regions.js";import{computeFunctionalYield as Ut}from"../stats/analyzeWaferMap.js";import{renderSummaryReportHtml as Qt,renderLotSummaryReportHtml as Xt}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as Zt}from"../stats/findingsNarrative.js";import{filterFindings as Jt}from"../stats/filterFindings.js";import{buildFacetTable as te,prettyKey as xt}from"../stats/facets.js";import{commonMetadata as yt}from"../stats/facets.js";import{resolveMetadataColumns as ee}from"../stats/metadataColumns.js";import{resolveBinColors as Ct}from"../renderer/binColors.js";import{NO_DATA_FILL as ne}from"../renderer/colorMap.js";import{describeWaferPopulation as wt,populationLabel as oe}from"../stats/population.js";import{buildWarningsBanner as mt,collectWarnings as St}from"./warnings.js";export{mt as buildWarningsBanner};import{fmt as vt,fmtAggregationMethod as ie,plainBinTerms as nt}from"../renderer/fmt.js";import{getUniqueTestNumbers as ae}from"../renderer/buildView.js";import{quantile as ot}from"../stats/math.js";import{buildCapabilityData as se}from"../stats/capability.js";import{sortBinsForDisplay as re}from"../stats/binPareto.js";import{poolFunctionalYield as le}from"../stats/testPassRate.js";import{makeLabeledSelect as $t,makeSegmented as ht}from"./charts/chartShell.js";import{SHADOW as kt,MOTION as Lt,LEADING as Q,TRACKING as rt,wireControlHover as q,controlStyle as lt,SPACE as y,RADIUS as O,FONT as F,CLR as B,sevColor as dt,openModal as Bt,openReportModal as Nt,saveTextFile as Ft,wireTooltip as it}from"./toolbar.js";import{buildDieListSection as de}from"./dieList.js";export{csvField}from"../core/utils.js";import{medianOfSorted as ce,csvField as ct}from"../core/utils.js";import{metadataDisplayValue as pe}from"../core/metadata.js";const ue=B.panelBg,Et=`1px solid ${B.menuBorder}`,fe="12px",Y=B.label,U=B.value,Rt="10px";function l(t,e,o,n=document){const i=n.createElement(t);return e&&Object.assign(i.style,e),o!==void 0&&(i.textContent=o),i}function J(t){return l("div",{fontSize:Rt,fontWeight:"700",letterSpacing:rt,textTransform:"uppercase",color:Y,marginBottom:y.sm},t)}const Tt=new WeakMap,Dt=["regionYield","testValues","functionalTests"];function pt(t){if(!t)return{collapsed:new Set(Dt),regionMode:"ring",waferSort:"slot"};let e=Tt.get(t);return e||(e={collapsed:new Set(Dt),regionMode:"ring",waferSort:"slot"},Tt.set(t,e)),e}function X(t,e=!0,o,n){const i=l("div"),d=pt(n?.panel);n?.stateKey&&n.panel&&(e=!d.collapsed.has(n.stateKey));const a=document.createElement("button");a.type="button",Object.assign(a.style,{display:"flex",alignItems:"center",gap:y.xs,width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const p=l("span",{fontSize:F.meta,color:Y,transition:`transform ${Lt.base}`,transform:e?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:Q.none,marginRight:"1px"},"\u25B6"),c=l("span",{fontSize:Rt,fontWeight:"700",letterSpacing:rt,textTransform:"uppercase",color:Y,flex:"1"},t);if(q(a,"bare"),a.setAttribute("aria-expanded",e?"true":"false"),a.appendChild(p),a.appendChild(c),o){const b=l("span",{fontSize:F.meta,fontWeight:"700",background:B.warnBg,color:B.warnText,borderRadius:O.pill,padding:"1px 5px"},o);a.appendChild(b)}const r=l("div");r.style.display=e?"block":"none";let s=e;if(a.addEventListener("click",()=>{s=!s,r.style.display=s?"block":"none",p.style.transform=s?"rotate(90deg)":"rotate(0deg)",a.setAttribute("aria-expanded",s?"true":"false"),n?.stateKey&&n.panel&&(s?d.collapsed.delete(n.stateKey):d.collapsed.add(n.stateKey))}),n?.control){const b=l("div",{display:"flex",alignItems:"center",gap:y.sm});a.style.width="auto",a.style.flex="1",b.appendChild(a);const u=()=>{r.innerHTML="",n.render?.(r)},v=n.control(u);v&&(v.style.marginBottom="6px",v.addEventListener("click",N=>N.stopPropagation()),b.appendChild(v)),i.appendChild(b)}else i.appendChild(a);return i.appendChild(r),n?.render?.(r),{outer:i,content:r}}function Mt(){return l("div",{height:"1px",background:B.separator,margin:`${fe} 0`,flexShrink:"0"})}function gt(t,e,o=B.barFill,n,i){const d=l("div",{marginBottom:"5px"}),a=l("div",{display:"flex",justifyContent:"space-between",fontSize:F.body,color:U,marginBottom:y.xxs}),p=l("span",{color:Y},t),c=l("span",{fontWeight:"600"},`${e.toFixed(1)}%`);a.appendChild(p),a.appendChild(c);const r=n!==void 0?n:Math.min(100,Math.max(0,e)),s=o,b=l("div",{position:"relative",height:"9px",background:B.bgActive,borderRadius:O.control,overflow:"hidden"}),u=l("div",{height:"100%",width:`${r}%`,background:s,borderRadius:O.control,transition:`width ${Lt.base}`});if(b.appendChild(u),i!==void 0){const v=l("div",{position:"absolute",top:"0",bottom:"0",left:`${i}%`,width:"2px",marginLeft:"-1px",background:B.value,opacity:"0.8"});b.appendChild(v)}return d.appendChild(a),d.appendChild(b),d}function At(){const t=l("div",{display:"flex",gap:y.sm,marginBottom:y.md});return t.finish=()=>{const e=t.lastElementChild;e&&Object.assign(e.style,{borderRight:"none",paddingRight:"0"})},t}function at(t,e,o){const n=l("div",{padding:`${y.xxs} ${y.md} ${y.xxs} 0`,borderRight:Et,textAlign:"center",flex:"1"}),i=l("div",{fontSize:F.heading,fontWeight:"700",color:U,lineHeight:Q.tight},t),d=l("div",{fontSize:F.body,color:Y,marginTop:y.xxs},e);return n.appendChild(i),n.appendChild(d),o&&n.appendChild(l("div",{fontSize:F.body,color:Y,opacity:"0.85"},o)),n}function It(t,e){const o=l("div",{display:"flex",justifyContent:"space-between",fontSize:F.body,gap:y.md,marginBottom:"3px"}),n=l("span",{color:Y,flexShrink:"0"},t),i=l("span",{color:U,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},e);return o.appendChild(n),o.appendChild(i),o}function me(t,e){const o=l("div",{display:"flex",fontSize:F.body,gap:y.sm,marginBottom:"3px"}),n=l("span",{color:Y,flexShrink:"0"},`${t}:`),i=l("span",{color:U,fontWeight:"500",wordBreak:"break-all"},e);return o.appendChild(n),o.appendChild(i),o}export function metadataEntries(t){const e=[];for(const[o,n]of Object.entries(t)){const i=pe(n);i!==void 0&&e.push([o,i])}return e}const he=["lot","product","testprogram","split"],ut=t=>{const e=he.indexOf(t.toLowerCase().replace(/[^a-z]/g,""));return e===-1?Number.MAX_SAFE_INTEGER:e};export function buildFacetSummaryChips(t,e=3){if(!t.length)return null;const o=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:`${y.xs} ${y.lg}`}),n=[...t].sort((p,c)=>ut(p.key)-ut(c.key)),i=n.filter(p=>ut(p.key)!==Number.MAX_SAFE_INTEGER),d=n.filter(p=>ut(p.key)===Number.MAX_SAFE_INTEGER),a=p=>{const c=l("span",{whiteSpace:"nowrap"}),r=l("span",{color:Y},`${xt(p.key)}: `);c.appendChild(r);const s=p.values.slice(0,e),b=p.values.length-s.length;let u=s.map(v=>v.value).join(", ");return b>0&&(u+=` +${b} more`),c.appendChild(document.createTextNode(u)),c};for(const p of i)o.appendChild(a(p));if(d.length){const p=l("span",{display:"none",flexWrap:"wrap",alignItems:"baseline",gap:`${y.xs} ${y.lg}`});for(const s of d)p.appendChild(a(s));const c=l("button",{background:"none",border:"none",padding:"0",cursor:"pointer",color:B.iconActive,fontSize:F.body,whiteSpace:"nowrap"});c.type="button",q(c,"bare");const r=s=>{p.style.display=s?"contents":"none",c.textContent=s?"less":`+${d.length} more`,c.setAttribute("aria-expanded",String(s))};r(!1),c.addEventListener("click",()=>r(c.getAttribute("aria-expanded")!=="true")),o.appendChild(p),o.appendChild(c)}return o}export function buildMetadataStripRow(t,e,o){const n=te(t,o),i=buildFacetSummaryChips(n);if(!i&&!e)return null;const d=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(e){const a=l("span",{fontWeight:"500",whiteSpace:"nowrap"},e.aggrMethod?`${e.lotSize} wafers stacked \xB7 ${e.aggrMethod}`:`${e.lotSize} wafers stacked`);d.appendChild(a)}return i&&d.appendChild(i),d}const ge={display:"flex",flexDirection:"column",gap:y.sm,background:B.menuBg,border:`1px solid ${B.menuBorder}`,borderRadius:O.container,padding:`${y.sm} ${y.lg}`,boxShadow:kt.panel,fontSize:F.body,lineHeight:Q.none,boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,e,o){const n=buildMetadataStripRow(t,e,o);if(!n)return null;const i=l("div",ge);return i.appendChild(n),i}export function buildCompactMetadataRows(t){const e=metadataEntries(t);if(!e.length)return null;const o=l("div");for(const[n,i]of e)o.appendChild(me(xt(n),i));return o}export function buildMetadataInfoSection(t,e){const o=buildMetadataStripRow(t,e,{facetableOnly:t.length>1});if(!o)return null;const n=l("div");return n.appendChild(J("Wafer Info")),n.appendChild(o),n}export function buildYieldSection(t,e,o=[1]){const n=l("div");n.appendChild(J("Summary"));const i=At();if(i.appendChild(at(String(t.totalDies),"Total dies")),t.partialDies>0&&i.appendChild(at(String(t.partialDies),"Partial")),t.yieldPercent!==null){const d=o.length===1?`bin ${o[0]}`:`bins ${o.join(", ")}`;i.appendChild(at(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${d}`))}return i.finish(),n.appendChild(i),t.edgeExcludedDies>0&&n.appendChild(It("Edge excluded (outer zone)",String(t.edgeExcludedDies))),n}export function buildBinSection(t,e,o,n,i,d){const a=new Map;if(i)for(const[r,s]of Object.entries(i))a.set(Number(r),s);else for(const r of t){if(r.partial||r.edgeExcluded)continue;const s=o==="hard"?r.hbin:r.sbin;s!=null&&a.set(s,(a.get(s)??0)+1)}if(!a.size)return null;const p=n??be(t,o,e,d),c=l("div");c.appendChild(J(Wt(o,[...a.values()].reduce((r,s)=>r+s,0))));for(const r of Pt(a,e,p,d))c.appendChild(r);return c}function be(t,e,o,n){const i=Ct(t,{passBins:n,...e==="hard"?{hbinDefs:o}:{sbinDefs:o}});return e==="hard"?i.hard:i.soft}function Wt(t,e){return`${t==="hard"?"Hard":"Soft"} Bin Breakdown \u2014 % of dies (N=${e})`}function Pt(t,e,o,n=[1]){const i=[...t.values()].reduce((p,c)=>p+c,0),d=e?new Map(e.map(p=>[p.bin,p])):null;return re(t.entries(),n).map(([p,c])=>{const r=d?.get(p),s=r?.name?`Bin ${p} \xB7 ${r.name}`:`Bin ${p}`,b=c/i*100,u=o.get(p)??ne;return gt(`${s} (${c})`,b,u)})}export function buildBinBreakdownSection(t){const{dies:e,hbinDefs:o,sbinDefs:n,hardCounts:i,softCounts:d,plotMode:a,passBins:p=[1],panel:c}=t,r=t.binColors??Ct(e,{passBins:p,hbinDefs:o,sbinDefs:n}),s=m=>{const x=m==="hard"?i:d,w=new Map;if(x){for(const[$,L]of Object.entries(x))w.set(Number($),L);return w}for(const $ of e){if($.partial||$.edgeExcluded)continue;const L=m==="hard"?$.hbin:$.sbin;L!=null&&w.set(L,(w.get(L)??0)+1)}return w},b=s("hard"),u=s("soft"),v=b.size>0,N=u.size>0;if(!v&&!N)return null;const M=pt(c),W=a==="softBin"||a==="stackedSoftBins"?"soft":a==="hardBin"||a==="stackedBins"?"hard":void 0;let E=M.binMode??W??(v?"hard":"soft");E==="hard"&&!v&&(E="soft"),E==="soft"&&!N&&(E="hard");const H=E==="hard"?b:u,h=E==="hard"?o:n,f=[...H.values()].reduce((m,x)=>m+x,0),{outer:S}=X(Wt(E,f),!0,void 0,{stateKey:"bins",panel:c,render:m=>{const x=E==="hard"?r.hard:r.soft;for(const w of Pt(H,h,x,p))m.appendChild(w)},control:v&&N&&c?()=>ht([["hard","Hard"],["soft","Soft"]],E,m=>{M.binMode=m;const x=buildBinBreakdownSection(t);x&&S.replaceWith(x)},c.ownerDocument,!0):void 0});return S}export function buildLotBinSection(t,e,o,n){return buildBinSection(t,e,o,n)}export function buildRegionYieldPanelSection(t){const{diesByWafer:e,allWafers:o,ringCount:n,passBins:i,panel:d}=t,a=pt(d),p=s=>Gt(e,o,n,i,s==="ring"?Vt:Kt);if(!p("ring").length&&!p("quadrant").length)return null;const c=a.regionMode,{outer:r}=X(c==="ring"?"Ring Yield":"Quadrant Yield",!0,void 0,{stateKey:"regionYield",panel:d,render:s=>{const b=p(c);if(!b.length){s.appendChild(l("div",{fontSize:F.body,color:Y},"No positioned dies for this breakdown."));return}for(const{label:u,n:v,yieldPercent:N}of b)s.appendChild(gt(`${u} (N=${v})`,N))},control:d?()=>ht([["ring","Ring"],["quadrant","Quadrant"]],c,s=>{a.regionMode=s;const b=buildRegionYieldPanelSection(t);b&&r.replaceWith(b)},d.ownerDocument,!0):void 0});return r}export function buildLotOverviewSection(t,e=[]){const o=l("div"),n=wt(t.perWafer.map(a=>a.summary.wafer));o.appendChild(J(n.lotId!==void 0?"Lot Summary":"Summary"));const i=At();i.appendChild(at(String(t.stats.waferCount),"Wafers"));const d=t.perWafer.map(a=>a.summary.stats.yieldPercent).filter(a=>a!==null);if(d.length){const a=d.reduce((p,c)=>p+c,0)/d.length;i.appendChild(at(`${a.toFixed(1)}%`,"Mean per-wafer yield"))}if(i.finish(),o.appendChild(i),e.length){const a=e.reduce((c,r)=>c+r.stats.analyzedDies,0),p=e.reduce((c,r)=>c+r.stats.excludedDies,0);(a||p)&&o.appendChild(It("Dies analysed",p?`${a.toLocaleString()} (${p.toLocaleString()} excluded)`:a.toLocaleString()))}return o}export function buildPerWaferYieldSection(t,e,o,n,i){const d=t.perWafer.map(f=>({waferIndex:f.waferIndex,label:(e[f.waferIndex]?.label??`W${f.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:f.summary.stats.yieldPercent})).filter(f=>f.yieldPct!==null);if(!d.length)return null;const a=Math.min(...d.map(f=>f.yieldPct)),p=Math.max(...d.map(f=>f.yieldPct)),c=a===p?"":` (${a.toFixed(1)}\u2013${p.toFixed(1)}%)`,r=[...d.map(f=>f.yieldPct)].sort((f,S)=>f-S),s=ce(r),b=ot(r,.25),u=ot(r,.75),v=d.length>=5?b-1.5*(u-b):-1/0,N=pt(n),M=f=>{const S=N.waferSort==="yield"?[...d].sort((m,x)=>m.yieldPct-x.yieldPct):d;for(const{waferIndex:m,label:x,yieldPct:w}of S){const L=w<v?`${x} \xB7 low outlier`:x,R=gt(L,w,void 0,void 0,s),T=i?.(m);T?.total&&H(R,T),h(R,m,x,w,T),f.appendChild(R)}},W=` \xB7 median ${s.toFixed(1)}%`,{outer:E}=X("Wafer Yield"+c+W,!0,void 0,{stateKey:"waferYield",panel:n,render:M,control:n?f=>ht([["slot","Slot"],["yield","Yield"]],N.waferSort,S=>{N.waferSort=S,f()},n.ownerDocument,!0):void 0});return E;function H(f,S){const m=S.unusual?"unusual":S.notable?"notable":"info",x=l("span",{marginLeft:y.sm,flexShrink:"0",background:dt(m),color:"#fff",borderRadius:O.container,padding:"0 5px",fontSize:F.body,fontWeight:"600"},`${S.total}`);x.setAttribute("aria-hidden","true"),it(x,`${S.total} finding${S.total===1?"":"s"}`+(S.unusual?`, ${S.unusual} unusual`:"")+(S.notable?`, ${S.notable} notable`:"")),f.firstElementChild?.firstElementChild?.appendChild(x)}function h(f,S,m,x,w){o&&(f.style.cursor="pointer",f.style.borderRadius="4px",f.style.padding="2px 3px",f.style.marginLeft="-3px",f.style.marginRight="-3px",f.setAttribute("role","button"),f.setAttribute("aria-label",`${m}, ${x.toFixed(1)}% yield`+(w?.total?`, ${w.total} finding${w.total===1?"":"s"}${w.unusual?`, ${w.unusual} unusual`:""}`:"")+" \u2014 open wafer"),f.tabIndex=0,f.addEventListener("mouseenter",()=>{f.style.background=B.bgHover}),f.addEventListener("mouseleave",()=>{f.style.background=""}),f.addEventListener("focus",()=>{f.style.background=B.bgHover}),f.addEventListener("blur",()=>{f.style.background=""}),f.addEventListener("click",()=>o(S)),f.addEventListener("keydown",$=>{($.key==="Enter"||$.key===" ")&&($.preventDefault(),o(S))}))}}function xe(t){const e=[...t].sort((i,d)=>i-d),o=t.reduce((i,d)=>i+d,0)/t.length,n=t.reduce((i,d)=>i+(d-o)**2,0)/t.length;return{min:e[0],max:e[e.length-1],mean:o,count:t.length,stddev:Math.sqrt(n),median:ot(e,.5),q1:ot(e,.25),q3:ot(e,.75)}}function zt(t,e){if(!t)return[];const o=t.waferMetadata??(t.perWaferMetadata?yt(t.perWaferMetadata.map(n=>({metadata:n}))):void 0);return!o||!Object.keys(o).length?[]:ee({waferMetadata:o,waferKeys:"identity",waferPlacement:"csv",reservedLabels:e}).columns}function Ht(t){return t?.populationLabel?[{key:"population",label:"Population",scope:"wafer",constant:t.populationLabel,get:()=>t.populationLabel,csvOnly:!0}]:[]}export function buildTestSection(t,e,o,n,i,d,a,p,c="full"){const r=t.filter(g=>!g.partial&&!g.edgeExcluded),s=new Map((n?.perTestStats??[]).map(g=>[g.testNumber,g])),b=new Map((n?.testSpecYield??[]).map(g=>[g.testNumber,g]));let u;if(e?.length?u=e.filter(qt).map(g=>({testNumber:g.testNumber,name:g.name,unit:g.unit,limitLow:g.limitLow,limitHigh:g.limitHigh})):u=ae(r).map(C=>({testNumber:C,name:`Test ${C}`})),!u.length)return null;const v=u.filter(g=>r.some(C=>{const I=C.testValues?.[g.testNumber];return I!==void 0&&isFinite(I)}));if(!v.length)return null;const N=v.some(g=>g.limitLow!==void 0||g.limitHigh!==void 0),M=[];for(const g of v){const C=s.get(g.testNumber),I=C&&C.stddev!==void 0&&C.median!==void 0&&C.q1!==void 0&&C.q3!==void 0;let _;if(I){const k=C;_={testNumber:g.testNumber,min:k.min,max:k.max,mean:k.mean,count:k.count,stddev:k.stddev,median:k.median,q1:k.q1,q3:k.q3}}else{const k=r.map(D=>D.testValues?.[g.testNumber]).filter(D=>D!==void 0&&isFinite(D));if(!k.length)continue;_={testNumber:g.testNumber,...xe(k)}}let z=null,P=0;if(g.limitLow!==void 0||g.limitHigh!==void 0){const k=b.get(g.testNumber);if(k)({yieldPercent:z,totalDies:P}=k);else{const D=r.map(j=>j.testValues?.[g.testNumber]).filter(j=>j!==void 0&&isFinite(j)),Z=D.filter(j=>g.limitLow!==void 0&&j<g.limitLow||g.limitHigh!==void 0&&j>g.limitHigh).length;P=D.length,z=D.length>0?(D.length-Z)/D.length*100:null}}M.push({entry:g,stats:_,specYieldPct:z,specN:P})}if(!M.length)return null;const W=new Map;if(a?.length&&e?.length)for(const g of se(a,e))g.hasSpec&&W.set(g.testNumber,g.ppk);const E=W.size>0,h=new Set(M.map(g=>g.stats.count)).size===1?M[0].stats.count:null,f=l("div"),S=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:y.sm}),m=h!==null?` \xB7 N=${h.toLocaleString()}`:"",x=d?.populationLabel?`Test Values (${M.length}) \u2014 ${d.populationLabel}${m}`:`Test Values (${M.length})${m}`,w=J(x);w.style.marginBottom="0",S.appendChild(w);const $=document.createElement("button");$.type="button",$.textContent="Test values CSV",Object.assign($.style,{...lt("outlined")}),q($),$.addEventListener("click",()=>{const g=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];E&&g.push("Ppk");const C=M.some(k=>k.specYieldPct!==null&&k.specN!==k.stats.count);N&&(g.push("LSL","USL","Spec Yield %"),C&&g.push("Spec Yield N"));const I=[...zt(d,g),...Ht(d)],z=[[...I.map(k=>k.label),...g].map(ct).join(",")],P=k=>vt(k,void 0,"engineering");for(const{entry:k,stats:D,specYieldPct:Z,specN:j}of M){const st=[...I.map(et=>et.constant??""),k.name,k.unit??"",String(D.count),P(D.min),P(D.q1),P(D.median),P(D.mean),P(D.q3),P(D.max),P(D.stddev)];if(E){const et=W.get(k.testNumber);st.push(et==null?"":et.toFixed(3))}N&&(st.push(k.limitLow!==void 0?P(k.limitLow):"",k.limitHigh!==void 0?P(k.limitHigh):"",Z!==null?Z.toFixed(1):""),C&&st.push(k.limitLow!==void 0||k.limitHigh!==void 0?String(j):"")),z.push(st.map(ct).join(","))}Ft(z.join(`
2
+ `),"test-values.csv","text/csv",i)}),S.appendChild($),f.appendChild(S);const L=l("table",{width:"100%",borderCollapse:"collapse",fontSize:F.body}),R=document.createElement("thead"),T=document.createElement("tr"),A=["Test"];h===null&&A.push("N"),c==="full"&&A.push("Min","Q1","Median"),A.push("Mean"),c==="full"&&A.push("Q3","Max","StdDev"),E&&A.push("Ppk"),c==="full"&&N&&A.push("LSL","USL"),N&&A.push("Spec yield");for(const g of A){const C=l("th",{textAlign:g==="Test"?"left":"right",fontWeight:"600",fontSize:F.meta,letterSpacing:rt,textTransform:"uppercase",color:Y,padding:"3px 8px 5px",borderBottom:`1px solid ${B.menuBorder}`,whiteSpace:"nowrap"},g);T.appendChild(C)}R.appendChild(T),L.appendChild(R);const V=document.createElement("tbody");for(const{entry:g,stats:C,specYieldPct:I,specN:_}of M){const z=D=>vt(D,g.unit,o),P=document.createElement("tr"),k=(D,Z="right")=>{const j=l("td",{textAlign:Z,padding:`${y.xs} ${y.md}`,borderBottom:`1px solid ${B.menuBorder}`,color:B.text,whiteSpace:"nowrap"},D);P.appendChild(j)};if(k(g.name,"left"),h===null&&k(`${C.count}`),c==="full"&&(k(z(C.min)),k(z(C.q1)),k(z(C.median))),k(z(C.mean)),c==="full"&&(k(z(C.q3)),k(z(C.max)),k(z(C.stddev))),E){const D=W.get(g.testNumber);k(D==null?"\u2014":D.toFixed(2))}c==="full"&&N&&(k(g.limitLow!==void 0?z(g.limitLow):"\u2014"),k(g.limitHigh!==void 0?z(g.limitHigh):"\u2014")),N&&k(I!==null?h!==null&&_===h?`${I.toFixed(1)}%`:`${I.toFixed(1)}% (N=${_})`:"\u2014"),V.appendChild(P)}L.appendChild(V);const K=l("div",{overflowX:"auto"});if(K.appendChild(L),!p)return f.appendChild(K),f;S.remove();const{outer:G}=X(x,!0,void 0,{stateKey:"testValues",panel:p,render:g=>g.appendChild(K),control:()=>$});return G}export function buildFunctionalTestSection(t,e,o,n,i,d){const a=o??Ut(t,e);if(!a?.length)return null;const c=new Set(a.map(m=>m.totalDies)).size===1?a[0].totalDies:null,r=c!==null?` \xB7 N=${c.toLocaleString()}`:"",s=l("div"),b=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:y.sm}),u=i?.populationLabel?`Functional Tests (${a.length}) \u2014 ${i.populationLabel}${r}`:`Functional Tests (${a.length})${r}`,v=J(u);v.style.marginBottom="0",b.appendChild(v);const N=document.createElement("button");N.type="button",N.textContent="Functional CSV",Object.assign(N.style,{...lt("outlined")}),q(N),N.addEventListener("click",()=>{const m=["Test","N","Pass","Fail","Pass Rate %"],x=[...zt(i,m),...Ht(i)],w=[[...x.map($=>$.label),...m].map(ct).join(",")];for(const $ of a)w.push([...x.map(L=>L.constant??""),$.label,String($.totalDies),String($.passDies),String($.failDies),$.passRatePercent!==null?$.passRatePercent.toFixed(1):""].map(ct).join(","));Ft(w.join(`
3
+ `),"functional-tests.csv","text/csv",n)}),b.appendChild(N),s.appendChild(b);const M=l("table",{width:"100%",borderCollapse:"collapse",fontSize:F.body}),W=document.createElement("thead"),E=document.createElement("tr"),H=c===null?["Test","N","Pass","Fail","Pass rate"]:["Test","Pass","Fail","Pass rate"];for(const m of H)E.appendChild(l("th",{textAlign:m==="Test"?"left":"right",fontWeight:"700",fontSize:F.body,letterSpacing:rt,textTransform:"uppercase",color:Y,padding:"3px 8px 5px",borderBottom:`1px solid ${B.menuBorder}`,whiteSpace:"nowrap"},m));W.appendChild(E),M.appendChild(W);const h=document.createElement("tbody");for(const m of a){const x=document.createElement("tr"),w=($,L="right")=>{x.appendChild(l("td",{textAlign:L,padding:`${y.xs} ${y.md}`,borderBottom:`1px solid ${B.menuBorder}`,color:U,whiteSpace:"nowrap"},$))};w(m.label,"left"),c===null&&w(String(m.totalDies)),w(String(m.passDies)),w(String(m.failDies)),w(m.passRatePercent!==null?`${m.passRatePercent.toFixed(1)}%`:"\u2014"),h.appendChild(x)}M.appendChild(h);const f=l("div",{overflowX:"auto"});if(f.appendChild(M),!d)return s.appendChild(f),s;b.remove();const{outer:S}=X(u,!0,void 0,{stateKey:"functionalTests",panel:d,render:m=>m.appendChild(f),control:()=>N});return S}export function buildLotFunctionalSection(t,e,o,n,i){const d=o?.length?{perWaferMetadata:o.map(p=>p.wafer??{}),populationLabel:`${o.length} wafer${o.length===1?"":"s"} pooled`}:void 0,a=le(o);return a?buildFunctionalTestSection(t,e,a,n,d,i):buildFunctionalTestSection(t,e,void 0,n,d,i)}const tt={unusual:0,notable:1,info:2};function bt(t){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:O.pill,background:dt(t),flexShrink:"0"})}function Yt(t,e){let o=t.summary;return e&&(o.startsWith(`${e} has `)?o=o.slice(e.length+5):o.startsWith(`${e} `)&&(o=o.slice(e.length+1))),o=nt(o),o.length?o[0].toUpperCase()+o.slice(1):o}export function buildFindingsSection(t,e,o,n,i=!1){if(!t.length)return null;const d=t.some(h=>h.severity==="unusual"||h.severity==="notable"),a=d?t.filter(h=>h.severity!=="info").length.toString():void 0,{outer:p,content:c}=i?(()=>{const h=l("div");return{outer:h,content:h}})():X(`Findings (${t.length})`,d,a);function r(h){return h.reduce((f,S)=>tt[S.severity]<tt[f]?S.severity:f,"info")}function s(h){const f=new Map;for(const m of h){const x=`${m.comparison.family}\0${m.comparison.left}`,w=f.get(x)??[];w.push(m),f.set(x,w)}const S=[...f.entries()].map(([m,x])=>{const w=[...x].sort(($,L)=>tt[$.severity]-tt[L.severity]);return{key:m,findings:w,worst:r(w)}});return S.sort((m,x)=>tt[m.worst]-tt[x.worst]),S}function b(h,f){const m={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[h]??h;return f.toLowerCase().startsWith(m.toLowerCase())?f:`${m}: ${f}`}const u=t.filter(h=>h.comparison.family==="spatial-pattern"),v=new Set([...u.flatMap(h=>h.relatedIds??[]),...t.flatMap(h=>h.absorbedIds??[])]),N=t.filter(h=>h.comparison.family!=="spatial-pattern"&&!v.has(h.id)),M=s(N);function W(h,f=!1,S){const m=n===h.id,x=document.createElement("button");return x.type="button",x.dataset.wmapFinding=h.id,x.textContent=Yt(h,S),it(x,h.summary),x.setAttribute("aria-current",m?"true":"false"),Object.assign(x.style,{border:`1px solid ${B.menuBorder}`,borderLeft:`3px solid ${dt(h.severity)}`,background:m?B.bgActive:B.menuBg,borderRadius:O.container,padding:f?"6px 10px":"8px 10px",textAlign:"left",fontSize:f?"10px":"11px",fontWeight:m?"600":"400",color:B.text,cursor:"pointer",width:"100%",marginBottom:y.xs}),q(x,"bare"),x.addEventListener("click",()=>o(h,x)),x}const E=nt(Zt(t)??"");if(E){const h=l("div",{background:B.bgActive,borderRadius:O.container,padding:`${y.md} ${y.lg}`,marginBottom:y.md,display:"flex",gap:y.md,alignItems:"flex-start"}),f=l("span",{flex:"1",fontSize:F.body,lineHeight:Q.base,color:B.text},E);h.appendChild(f);const S=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:F.body,color:B.icon,cursor:"pointer",padding:"0",lineHeight:Q.base,whiteSpace:"nowrap"},"Detail \u25B8");S.type="button",q(S,"bare"),S.addEventListener("click",()=>{const m=Bt({title:"Findings Summary",onClose:()=>{},anchor:S}),x=l("p",{fontSize:"16px",lineHeight:Q.base,color:B.text,padding:`${y.xxl} ${y.xxxl} ${y.xxl}`,margin:"0",borderBottom:`1px solid ${B.menuBorder}`,flexShrink:"0"},E);m.contentWrap.appendChild(x);const w=l("div",{overflowY:"auto",padding:`${y.xxl} ${y.xxxl}`,flex:"1"}),$=(L,R)=>{const T=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:F.sub,fontWeight:"600",color:U,marginTop:y.lg,marginBottom:y.xs});return T.appendChild(bt(L)),T.appendChild(l("span",{},R)),T};for(const L of u){w.appendChild($(L.severity,L.comparison.left)),w.appendChild(l("div",{fontSize:F.body,color:B.text,padding:"4px 0 4px 15px",marginBottom:y.xxs},nt(L.summary)));const R=t.filter(T=>L.relatedIds?.includes(T.id));for(const T of R)w.appendChild(l("div",{fontSize:F.body,color:Y,padding:"2px 0 2px 23px",marginBottom:y.xxs},nt(T.summary)))}for(const L of M){const[R,T]=L.key.split("\0");w.appendChild($(L.worst,b(R,T)));for(const A of L.findings)w.appendChild(l("div",{fontSize:F.body,color:B.text,padding:"4px 0 4px 15px",marginBottom:y.xxs},Yt(A,T)))}m.contentWrap.appendChild(w),Object.assign(m.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),h.appendChild(S),c.appendChild(h)}let H=!0;for(const h of u){H||c.appendChild(l("div",{height:"1px",background:B.separator,margin:"4px 0"})),H=!1;const f=t.filter($=>h.relatedIds?.includes($.id)),S=f.length>0,m=l("div",{position:"relative",marginBottom:S?"2px":"4px"}),x=n===h.id,w=document.createElement("button");if(w.type="button",w.dataset.wmapFinding=h.id,Object.assign(w.style,{border:`1px solid ${B.menuBorder}`,borderLeft:`3px solid ${dt(h.severity)}`,background:x?B.bgActive:B.menuBg,borderRadius:O.container,padding:"8px 32px 8px 10px",textAlign:"left",fontSize:F.body,fontWeight:x?"600":"500",color:B.text,cursor:"pointer",width:"100%"}),w.textContent=nt(h.summary),it(w,h.summary),w.setAttribute("aria-current",x?"true":"false"),q(w,"bare"),w.addEventListener("click",()=>o(h,w)),m.appendChild(w),S){const $=l("div",{display:"none",paddingLeft:"12px",marginBottom:y.xs});for(const T of f)$.appendChild(W(T,!0));m.appendChild($);let L=!1;const R=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:F.body,color:B.icon,cursor:"pointer",padding:`${y.xxs} ${y.xs}`,lineHeight:Q.none},"\u25B8");q(R,"bare"),R.type="button",it(R),R.setAttribute("aria-label","Show supporting findings"),R.setAttribute("aria-expanded","false"),R.addEventListener("click",T=>{T.stopPropagation(),L=!L,$.style.display=L?"block":"none",R.textContent=L?"\u25BE":"\u25B8";const A=L?"Hide supporting findings":"Show supporting findings";R.setAttribute("aria-label",A),R.setAttribute("aria-expanded",String(L))}),m.appendChild(R)}c.appendChild(m)}for(const h of M){H||c.appendChild(l("div",{height:"1px",background:B.separator,margin:"4px 0"})),H=!1;const[f,S]=h.key.split("\0"),m=l("div",{display:"flex",alignItems:"center",gap:y.sm,fontSize:F.body,fontWeight:"600",color:U,margin:"2px 0 4px"});m.appendChild(bt(h.worst)),m.appendChild(l("span",{},b(f,S))),c.appendChild(m);for(const x of h.findings)c.appendChild(W(x,!1,S))}return p}const ye=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],Ce=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],we=["unusual","notable","info"],Se={unusual:"Unusual",notable:"Notable",info:"Info"};function ve(t,e,o){const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:y.lg,marginBottom:y.lg,paddingBottom:"10px",borderBottom:`1px solid ${B.separator}`}),i={unusual:0,notable:0,info:0};for(const r of t)i[r.severity]++;const d=we.filter(r=>i[r]>0),a=new Set(e.severity===void 0?d:Array.isArray(e.severity)?e.severity:[e.severity]),p=l("div",{display:"flex",gap:y.xs,flexWrap:"wrap"});for(const r of d){const s=document.createElement("button");s.type="button";const b=()=>{const u=a.has(r);s.setAttribute("aria-pressed",u?"true":"false"),Object.assign(s.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${B.menuBorder}`,borderRadius:O.pill,background:u?B.bgActive:"none",opacity:u?"1":"0.5",color:B.text,fontSize:F.body,padding:`${y.xxs} ${y.md}`,cursor:"pointer"}),s.dataset.on=u?"true":"false"};s.appendChild(bt(r)),s.appendChild(l("span",{},`${Se[r]} ${i[r]}`)),it(s,()=>a.has(r)?"Click to hide these findings":"Click to show these findings"),b(),q(s,"bare"),s.addEventListener("click",()=>{a.has(r)?a.delete(r):a.add(r),e.severity=a.size===d.length?void 0:[...a],o()}),p.appendChild(s)}n.appendChild(p);const c=e.kind!==void 0||e.family!==void 0;return(t.length>=$e||c)&&(n.appendChild($t("Kind:",ye,e.kind??"",r=>{e.kind=r||void 0,o()},{maxWidth:"130px"})),n.appendChild($t("Region:",Ce,e.family??"",r=>{e.family=r||void 0,o()},{maxWidth:"150px"}))),n}const $e=8;function ke(t,e){const o=l("div",{display:"flex",flexDirection:"column",gap:y.xs,padding:y.md,marginBottom:y.md,background:B.bgHover,borderRadius:O.control},void 0,e);if(o.appendChild(l("div",{fontSize:F.body,color:B.value},t.message,e)),t.detail&&o.appendChild(l("div",{fontSize:F.meta,color:Y},t.detail,e)),t.actionLabel&&t.onAction){const n=l("button",lt("outlined"),t.actionLabel,e);n.type="button",n.style.alignSelf="flex-start",n.style.marginTop=y.xs,q(n),n.addEventListener("click",t.onAction),o.appendChild(n)}return o}export function buildFindingsSectionWithFilter(t,e,o,n,i,d,a){if(!t.findings.length&&!a)return null;const p=t.findings.some(N=>N.severity==="unusual"||N.severity==="notable"),c=p?t.findings.filter(N=>N.severity!=="info").length.toString():void 0,r=d?.ownerDocument??document,{outer:s,content:b}=X(`Findings (${t.findings.length})`,p||!!a,c,{stateKey:"findings",panel:d});if(a&&b.appendChild(ke(a,r)),!t.findings.length)return s;b.appendChild(ve(t.findings,n,i));const u=Jt(t,n);if(!u.length)return b.appendChild(l("div",{color:Y,fontSize:F.body,textAlign:"center",padding:`${y.xxl} ${y.md}`},"No findings match the current filter.")),s;const v=buildFindingsSection(u,t,e,o,!0);return v&&b.appendChild(v),s}export function buildLotTestSection(t,e,o,n,i,d,a,p="full"){const c=n?.length?{perWaferMetadata:n.map(s=>s.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;let r;if(n?.length&&n.every(s=>s.stats.perTestStats!==void 0)){const s=new Map;for(const b of n)for(const u of b.stats.perTestStats??[]){const v=s.get(u.testNumber);v?(v.n+=u.count,v.sum+=u.mean*u.count,v.min=Math.min(v.min,u.min),v.max=Math.max(v.max,u.max)):s.set(u.testNumber,{n:u.count,sum:u.mean*u.count,min:u.min,max:u.max})}r={perTestStats:[...s.entries()].map(([b,u])=>({testNumber:b,count:u.n,min:u.min,max:u.max,mean:u.sum/u.n}))}}if(n?.length&&n.every(s=>s.stats.testSpecYield!==void 0)){const s=new Map;for(const b of n)for(const u of b.stats.testSpecYield??[]){const v=s.get(u.testNumber);v?(v.passDies+=u.passDies,v.totalDies+=u.totalDies):s.set(u.testNumber,{passDies:u.passDies,totalDies:u.totalDies})}r={...r,testSpecYield:[...s.entries()].map(([b,u])=>({testNumber:b,totalDies:u.totalDies,yieldPercent:u.totalDies>0?u.passDies/u.totalDies*100:null}))}}return buildTestSection(t,e,o,r,i,c,d,a,p)}export function createSummaryPanelEl(t,e,o=document){const n=t==="top"||t==="bottom",i=l("div",{background:ue,color:B.text,fontVariantNumeric:"tabular-nums",border:Et,borderRadius:O.container,padding:y.xl,overflowY:"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:F.family,fontSize:F.sub,boxShadow:kt.panel},void 0,o);return t==="right"&&(i.style.marginRight=e),t==="left"&&(i.style.marginLeft=e),t==="bottom"&&(i.style.marginBottom=e),n?(i.style.height="180px",i.style.width="100%"):(i.style.width="300px",i.style.maxHeight="100%"),i}export function wrapWithSummaryPanel(t,e,o){const n=o==="top"||o==="bottom",i=l("div",{display:"flex",flexDirection:n?"column":"row",gap:y.md,width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:n?"flex-start":"stretch"});return t.style.flex="1 1 0",t.style.minWidth="0",t.style.minHeight="0",o==="right"||o==="bottom"?(i.appendChild(t),i.appendChild(e)):(i.appendChild(e),i.appendChild(t)),i}function Ot(t){return l("div",{fontSize:F.heading,fontWeight:"600",color:U,marginBottom:y.lg},t)}function ft(t,e){const o=l("button",lt("outlined"),t);return o.type="button",q(o),o.addEventListener("click",e),o}function _t(...t){const e=t.filter(n=>!!n);if(!e.length)return null;const o=l("div",{display:"flex",flexWrap:"wrap",gap:y.sm,marginBottom:y.lg});for(const n of e)o.appendChild(n);return o}function jt(t,e,o,n,i,d,a,p,c,r,s){const b=t.ownerDocument,u=Bt({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:b});u.contentWrap.style.padding="14px 16px";const v=de(e,o,{...a,title:n,onSaveText:p,waferMetadata:i,metadataFields:d,extraColumn:c,getWafer:r,ringCount:s,ownerDocument:b});v&&u.contentWrap.appendChild(v)}export function renderWaferSummaryContent(t,e){const o=t.scrollTop;t.innerHTML="";const{wafer:n,dies:i,yieldSummary:d,dataCoverage:a,hbinDefs:p,sbinDefs:c,testDefs:r,statsSummary:s,passBins:b=[1],ringCount:u=4,binColors:v,plotMode:N,fallbackFormat:M,onFindingClick:W,activeFindingId:E=null,findingsFilter:H,onFindingsFilterChange:h,findingsNotice:f,onSaveText:S,metadataFields:m,dieListOptions:x,metadataShownElsewhere:w}=e;t.appendChild(Ot("Wafer Summary"));const $=e.warnings??St({statsSummary:s});$.length&&t.appendChild(mt($,t.ownerDocument));const L=d&&a?ft("Summary report",()=>{Nt(Qt({wafer:n,dies:i,yieldSummary:d,dataCoverage:a,hbinDefs:p,sbinDefs:c,testDefs:r,statsSummary:s,passBins:b,ringCount:u}),{anchor:t})}):null,R=(x?.enabled??!0)&&i.length?ft("View die list",()=>{jt(t,i,r,`Die list \u2014 ${i.length} dies`,n.metadata,m,x,S,void 0,()=>n,u)}):null,T=_t(L,R);T&&t.appendChild(T);const A=[],V=s?.stats.isLotStack?s.stats:void 0,K=V?.lotSize!==void 0?{lotSize:V.lotSize,aggrMethod:ie(V.aggregationMethod)}:void 0;w||A.push(buildMetadataInfoSection([{metadata:n.metadata??void 0}],K)),d&&a&&A.push(buildYieldSection(d,a,b)),s&&W&&H&&h&&A.push(buildFindingsSectionWithFilter(s,W,E,H,h,t,f)),A.push(buildBinBreakdownSection({dies:i,hbinDefs:p,sbinDefs:c,binColors:v,hardCounts:s?.stats.hardBinCounts,softCounts:s?.stats.softBinCounts,plotMode:N,passBins:b,panel:t})),A.push(buildRegionYieldPanelSection({diesByWafer:[i],allWafers:[n],ringCount:u,passBins:b,panel:t}));const G=n.metadata?{waferMetadata:n.metadata}:void 0;A.push(buildTestSection(i,r,M,s?.stats,S,G,[{dies:i}],t,"compact")),A.push(buildFunctionalTestSection(i,r,s?.stats.functionalYield,S,G,t));let g=!0;for(const C of A)C&&(g||t.appendChild(Mt()),g=!1,t.appendChild(C));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=o}export function renderLotSummaryContent(t,e){const o=t.scrollTop;t.innerHTML="";const{lotSummary:n,items:i,hbinDefs:d,sbinDefs:a,testDefs:p,passBins:c=[1],ringCount:r=4,binColors:s,plotMode:b,fallbackFormat:u,onFindingClick:v,activeFindingId:N=null,onWaferClick:M,findingsFilter:W,onFindingsFilterChange:E,findingsNotice:H,onSaveText:h,dieListOptions:f,findingsFor:S}=e;t.appendChild(Ot(`Summary \u2014 ${oe(wt(n.perWafer.map(C=>C.summary.wafer)))}`));const m=e.warnings??St({lotStatsSummary:n});m.length&&t.appendChild(mt(m,t.ownerDocument));const x=ft("Summary report",()=>{Nt(Xt({items:i.map((C,I)=>({label:C?.label??`W${I+1}`,wafer:C?.wafer,dies:C?.dies,statsSummary:C?.statsSummary})),hbinDefs:d,sbinDefs:a,testDefs:p,passBins:c,ringCount:r}),{anchor:t})}),w=[],$=[],L=[],R=new WeakMap,T=new WeakMap;for(let C=0;C<i.length;C++){const I=i[C];if(!I){$.push([]);continue}I.wafer&&w.push(I.wafer);const _=I.dies??[],z=I.label??`W${C+1}`;for(const P of _)R.set(P,z),I.wafer&&T.set(P,I.wafer);$.push(_),L.push(..._)}const A=f?.enabled??!0?ft("View die list",()=>{L.length&&jt(t,L,p,`Die list \u2014 ${L.length} dies across ${i.length} wafer${i.length===1?"":"s"}`,yt(i.filter(C=>!!C).map(C=>({metadata:C.wafer?.metadata}))),i.find(C=>C?.metadataFields?.length)?.metadataFields,f,h,{label:"Wafer",get:C=>R.get(C)},C=>T.get(C),r)}):null,V=_t(x,A);V&&t.appendChild(V);const K=i.map(C=>C?.statsSummary).filter(C=>!!C),G=[buildLotOverviewSection(n,K)];v&&W&&E&&G.push(buildFindingsSectionWithFilter(n,v,N,W,E,t,H)),G.push(buildPerWaferYieldSection(n,i,M,t,S),buildBinBreakdownSection({dies:L,hbinDefs:d,sbinDefs:a,binColors:s,plotMode:b,passBins:c,panel:t}),buildRegionYieldPanelSection({diesByWafer:$,allWafers:w,ringCount:r,passBins:c,panel:t}),p?.length?buildLotTestSection(L,p,u,K,h,$.map(C=>({dies:C})),t,"compact"):null,p?.length?buildLotFunctionalSection(L,p,K,h,t):null);let g=!0;for(const C of G)C&&(g||t.appendChild(Mt()),g=!1,t.appendChild(C));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=o}
@@ -1 +1 @@
1
- import{fontPx as _t}from"./toolbar.js";import{findTestDef as Re,buildMapTitle as _e}from"../renderer/buildView.js";import{affineInvert as Je,affineVector as Ce}from"../core/transforms.js";import{compareNatural as Ze}from"../core/utils.js";import{getColorScheme as Be}from"../renderer/colorSchemes.js";import{SPEC_PASS_FILL as Pe,SPEC_FAIL_LOW as je,SPEC_FAIL_HIGH as We,contrastTextColor as De}from"../renderer/colorMap.js";import{fmt as Oe,fmtColorbarAxis as Qe}from"../renderer/fmt.js";import{resolveCanvasTheme as ve}from"./canvasTheme.js";function Ie(m,e,F,M,h){m.moveTo(e,F+h*M),m.lineTo(e-M*.9,F-h*M*.6),m.lineTo(e+M*.9,F-h*M*.6),m.closePath()}const to=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),eo=new Set(["hardBin","softBin","metadata"]),Z=()=>`${_t(-2)}px system-ui, sans-serif`,Fe=3,Ut=2,oo=6,no=20,so=()=>`600 ${_t()}px system-ui, sans-serif`,Kt=()=>`${_t(-1)}px system-ui, sans-serif`,lo=()=>`600 ${_t(-1)}px system-ui, sans-serif`,qt=128,io=()=>`${_t(-2)}px system-ui, sans-serif`,Ne=4,D=17,Y=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const zt=28,mt=5,ut=8,ao=15;export function toCanvas(m,e,F={}){const M=ve(m.parentElement??m),{padding:h=16,showColorbar:H=!0,markFailingDies:X=!1,colorbarWidth:P=16,background:pt=M.background,legendPosition:j="default",legendOffset:xt,showAxes:Mt=!1,diePitchMm:G,viewport:q,activeBin:N,hoverBin:z,fallbackFormat:St,topClearance:Q=0,minRightReserve:ct,hbinDefs:yt,sbinDefs:st,metadataFields:bt,showTitle:rt=!0}=F,O=Math.floor(m.clientWidth||m.width),E=Math.floor(m.clientHeight||m.height),Lt=O>=BIN_LEGEND_MIN_CANVAS_W&&E>=BIN_LEGEND_MIN_CANVAS_H,kt=H&&Lt&&to.has(e.plotMode)&&e.passFailDisplay==="off",ft=H&&Lt&&eo.has(e.plotMode),tt=H&&Lt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),ht=ft||tt,Ct=ft&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[c])=>o-c):[],Bt=ft&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Ze)].map(o=>[o,e.metadataCounts.get(o)??0]):[],et=[];if(tt&&e.passFailDisplay==="test"){const o=e.passFailCounts;et.push({key:-1,color:Pe,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),et.push({key:-2,color:We,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(tt){const o=e.specCounts,c=Re(e.testDefs,e.activeTest);et.push({key:-1,color:Pe,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),c?.limitHigh!==void 0&&et.push({key:-2,color:We,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),c?.limitLow!==void 0&&et.push({key:-3,color:je,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const S=tt?et.length:e.plotMode==="metadata"?Bt.length:Ct.length,L=(m.ownerDocument.defaultView??window).devicePixelRatio??1;if(O<=0||E<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const $=j!=="default"?j:O<BIN_LEGEND_ADAPT_FLOATING?"floating":O<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",re=$==="default"||$==="compact",fe=$==="left",Zt=$==="bottom",Pt=$==="top",Wt=$==="floating",Dt=$==="compact"||$==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,he=Math.floor((E-2*h)/D),de=S>he?he-1:S,ge=ht&&Zt?de*D:0,jt=ht&&Pt?de*D:0,Qt=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",vt=Re(e.testDefs,e.activeTest),Ee=Qt?"Count":vt?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),we=Qt?void 0:vt?.unit,[Ot,It]=e.valueRange,{tickFmt:Ye}=Qe(It,Ee,we,St),Ft=e.allIntegerValues?o=>String(Math.round(o)):Ye;let te=0;if(kt){const o=m.getContext("2d");o.font=Z();const c=[Ft(Ot),Ft(It)];Ot<0&&c.push(Ft(-Math.max(Math.abs(Ot),Math.abs(It))));for(const s of c)te=Math.max(te,o.measureText(s).width)}const me=Math.max(no,Math.ceil(te)+Fe+Ut+oo-h),ee=kt?P+me+8:ht&&re?Dt:0,oe=ht&&fe?Dt:0,ne=Mt?32:0,Nt=Mt?36:0,He=ct!=null?Math.max(ee,ct):ee,Xe=O-2*h-He-Nt-oe,ue=E-2*h-ne-ge-jt;m.width=Math.round(O*L),m.height=Math.round(E*L);const t=m.getContext("2d");t.scale(L,L),t.fillStyle=pt,t.fillRect(0,0,O,E);const V=e.hoverPoints;if(!V.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Et=e.rectangles[0],se=Et?Et.width/2:0,le=Et?Et.height/2:0,wt=e.dieBounds,pe=(wt?.minX??0)-se,$e=(wt?.maxX??0)+se,Ge=(wt?.minY??0)-le,xe=(wt?.maxY??0)+le,Me=$e-pe,ye=xe-Ge;let ot,nt,k;if(q)({originX:ot,originY:nt,ppm:k}=q);else{const c=e.notchDir,s=c&&c.y>.1?13:0,a=c&&c.y<-.1?13:0,r=c&&c.x<-.1?13:0,f=c&&c.x>.1?13:0,d=Xe-r-f,i=ue-Q-s-a;k=Math.min(d/Me,i/ye),ot=h+Nt+oe+r+(d-Me*k)/2-pe*k,nt=h+Q+jt+s+(i-ye*k)/2+xe*k}const Yt=q?.snapDist??Math.max(se,le,1)*1.5,Ht=ot+e.waferCenter.x*k,Ve=nt-e.waferCenter.y*k,ie=e.waferRadius*k,lt=o=>{const c=Math.abs(o-Ve);return c>=ie?0:Math.sqrt(ie*ie-c*c)},it=(o,c,s,a,r,f,d=so(),i=M.text)=>{if(!o)return;t.save(),t.fillStyle=i,t.font=d,t.textAlign=a,t.textBaseline=r;const p=a==="right"?c-f:f-c;let l=o;if(p>8&&t.measureText(l).width>p){for(;l.length>1&&t.measureText(l+"\u2026").width>p;)l=l.slice(0,-1);l=l+"\u2026"}p>8&&t.fillText(l,c,s),t.restore()};if(t.save(),t.setTransform(k*L,0,0,-k*L,ot*L,nt*L),e.rectangles.length>0){const o=new Map;for(const s of e.rectangles){const a=String(s.fill);let r=o.get(a);r||(r=[],o.set(a,r)),r.push(s)}for(const[s,a]of o){t.beginPath();for(const r of a)t.rect(r.x-r.width/2,r.y-r.height/2,r.width,r.height);t.fillStyle=s,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(k*L),t.beginPath();for(const s of e.rectangles)t.rect(s.x-s.width/2,s.y-s.height/2,s.width,s.height);if(t.stroke(),X){const s=e.rectangles.filter(a=>a.binFail);if(s.length>0){const a=new Map;for(const r of s){const f=De(String(r.fill));let d=a.get(f);d||(d=[],a.set(f,d)),d.push(r)}t.save(),t.lineCap="butt";for(const[r,f]of a){t.strokeStyle=r,t.globalAlpha=.55,t.lineWidth=Math.max(.6/(k*L),Math.min(f[0].width,f[0].height)*.1);for(const d of f){const i=d.width/2,p=d.height/2,l=Math.max(1.6/(k*L),Math.min(d.width,d.height)/3);t.save(),t.beginPath(),t.rect(d.x-i,d.y-p,d.width,d.height),t.clip(),t.beginPath();for(let y=-(i+p);y<=i+p;y+=l)t.moveTo(d.x-i+y,d.y-p),t.lineTo(d.x-i+y+d.height,d.y+p);t.stroke(),t.restore()}}t.restore()}}const c=e.rectangles.filter(s=>s.specMark);if(c.length>0){const s=new Map;for(const r of c){const f=De(String(r.fill)),d=`${r.specMark}|${f}`;let i=s.get(d);i||(i=[],s.set(d,i)),i.push(r)}const a=2.5/(k*L);t.lineJoin="round";for(const[r,f]of s){const[d,i]=r.split("|"),p=i==="#000000"?"#ffffff":"#000000",l=d==="failHigh"?1:-1,y=Math.min(f[0].width,f[0].height),w=Math.max(2.5/(k*L),y*.3);t.beginPath();for(const A of f)Ie(t,A.x,A.y,w,l);t.strokeStyle=p,t.lineWidth=a,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const c of o.points){for(let s=0;s<c.length;s++)s===0?t.moveTo(c[s].x,c[s].y):t.lineTo(c[s].x,c[s].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3/(k*L),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(k*L),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(k*L),t.stroke())}if(t.restore(),e.notchDir){const o=ot+e.waferCenter.x*k,c=nt-e.waferCenter.y*k,s=e.notchDir.x,a=-e.notchDir.y,r=e.waferRadius*k,f=4,d=9,i=5,p=o+s*(r+f),l=c+a*(r+f),y=p+s*d,w=l+a*d,A={x:-a,y:s},W=h+Nt+oe,U=O-h-ee,K=h+Q+jt,_=E-h-ge-ne;t.save(),t.beginPath(),t.rect(W,K,U-W,_-K),t.clip(),t.beginPath(),t.moveTo(p,l),t.lineTo(y+A.x*i,w+A.y*i),t.lineTo(y-A.x*i,w-A.y*i),t.closePath(),t.fillStyle=M.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let be=0;if(e.rectangles.length>0){let o=1;for(const f of e.texts)f.role!=="indicator"&&f.text.length>o&&(o=f.text.length);const c=e.rectangles[0].width*k,s=e.rectangles[0].height*k,a=Math.min(c,s),r=c/o;be=Math.max(8,Math.min(64,Math.round(Math.min(a*.55,r*1.8))))}for(const o of e.texts){const c=ot+o.x*k,s=nt-o.y*k;t.font=`${o.role==="indicator"?o.fontSize:be}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,c,s)}if(t.restore(),Mt&&co(t,O,E,ot,nt,k,h,ne,Nt,G,e.gridToScreen,e.rotation,M),kt){const o=Be(e.colorScheme),c=me,s=ue-Q,a=Math.round(s*.75),r=h+Q+Math.round((s-a)/2),f=O-h-P-c,d=Ot,i=It,p=i-d,l=e.plotMode==="stackedSoftBins"?st:yt,{primary:y,secondary:w}=rt?_e(e,St,l):{primary:"",secondary:""};if(rt){const n=Math.max(r-6,h+Q+11),b=Ht+Math.max(lt(n),lt(n-12))+8;it(y,O-h,n,"right","bottom",b)}let A=r+a+4;const W=n=>Ht+Math.max(lt(n),lt(n+12))+8,U=e.logScale&&d>0?Math.log10(d):0,K=e.logScale&&i>0?Math.log10(i)-U:1,_=n=>e.logScale?(1-(Math.log10(n)-U)/K)*a:(1-(n-d)/p)*a;for(let n=0;n<qt;n++){const b=1-n/(qt-1),u=r+n/qt*a,g=a/qt+1;t.fillStyle=o.forValue(b),t.fillRect(f,u,P,g)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(f,r,P,a),t.fillStyle=M.text,t.font=Z(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const C=Fe,Rt=36,v=14,I=e.logScale&&K>0?ro(d,i,a,Rt,v,U,K):e.allIntegerValues?(()=>{const n=Math.max(1,Jt(p*Rt/a)),b=[],u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&b.push(Math.round(g))}return b})():(()=>{const n=p>0?Jt(p*Rt/a):0,b=[];if(n>0){const u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&b.push(g)}}return b})(),R=vt,x=Qt,T=Ft;t.textBaseline="middle";for(const n of I){const b=r+_(n);t.beginPath(),t.moveTo(f+P,b),t.lineTo(f+P+C,b),t.stroke(),t.fillText(T(n),f+P+C+Ut,b)}if(t.beginPath(),t.moveTo(f+P,r),t.lineTo(f+P+C,r),t.stroke(),t.textBaseline="top",t.fillText(T(i),f+P+C+Ut,r),t.beginPath(),t.moveTo(f+P,r+a),t.lineTo(f+P+C,r+a),t.stroke(),t.textBaseline="bottom",t.fillText(T(d),f+P+C+Ut,r+a),!x&&R&&(R.limitLow!==void 0||R.limitHigh!==void 0)){const n=[],b=e.colorbarRangeMode==="spec";for(const[u,g]of[[R.limitLow,"LSL"],[R.limitHigh,"USL"]]){if(u===void 0||e.logScale&&u<=0)continue;const B=_(u);!b&&(B<-v||B>a+v)||n.push({value:u,label:g,py:Math.max(0,Math.min(a,B))})}if(n.length>0){t.save(),t.font=Z(),t.textAlign="right",t.textBaseline="middle";for(const{py:u,label:g}of n){const B=r+u;b||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke()),t.fillStyle=M.text,t.fillText(g,f-3,B);const dt=g==="USL"?-1:1,gt=4,Tt=f-3-t.measureText(g).width-gt-4;t.beginPath(),Ie(t,Tt,B,gt,dt),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=M.text,t.fill()}t.restore()}}if(!x){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=M.text,t.font=lo(),t.textAlign="right",t.textBaseline="top",t.fillText(n,O-h,A),t.restore(),A+=15)}rt&&w&&it(w,O-h,A,"right","top",W(A),Kt(),M.text)}const ae=[];let J;if(ht){const o=Be(e.colorScheme),c=$==="compact",s=e.plotMode==="softBin"?st:yt,a=s?new Map(s.map(l=>[l.bin,l])):null,r=l=>{const y=a?.get(l);return(e.colorScheme==="custom"?y?.color:void 0)??o.forBin(l)},f=(l,y)=>{const w=t.measureText(l).width,A=c?0:t.measureText(String(y)).width,W=Y+mt+w+(A?zt:0);return{labelWidth:w,countWidth:A,totalWidth:W}},d=bt?.find(l=>l.key===e.activeMetadataKey),i=tt?et.map(l=>{const y=c?l.compactLabel:l.label;return{key:l.key,color:l.color,count:l.count,label:y,tooltipLabel:l.tooltip,...f(y,l.count)}}):e.plotMode==="metadata"?Bt.map(([l,y])=>{const A=d?.values?.find(K=>K.value===l)?.label??l,W=c?l:A,U=e.metadataColorMap?.get(l)??"#d6d9dd";return{key:l,color:U,count:y,label:W,tooltipLabel:`${A} \xB7 ${y} dies`,...f(W,y)}}):Ct.map(([l,y])=>{const w=a?.get(l),A=w?.name?`${l} \xB7 ${w.name}`:`Bin ${l}`,W=c?String(l):A;return{key:l,color:r(l),count:y,label:W,tooltipLabel:`${A} \xB7 ${y} dies`,...f(W,y)}}),p=O-h*2;if(i.length>0){const l=Math.max(1,Math.floor((E-2*h)/D));let y=i.length,w=1,A=y*D,W=[],U=0;const K=Zt||Pt;if(K){const I=Math.max(...i.map(x=>x.totalWidth)),R=Math.max(1,Math.min(i.length,Math.floor((p+8)/(I+8))));for(let x=R;x>=1;x--){const T=Math.ceil(i.length/x);if(T>l)continue;const n=new Array(x).fill(0);for(let u=0;u<i.length;u++){const g=u%x;n[g]=Math.max(n[g],i[u].totalWidth)}if(n.reduce((u,g)=>u+g,0)+(x-1)*8<=p||x===1){w=x,W=n,y=T,A=T*D;break}}}else y=Math.min(i.length,l),A=y*D,i.length>l&&(U=i.length-(l-1)),W=[Dt];let _,C;if(Wt){const I=Math.max(...i.map(g=>Y+mt+t.measureText(g.label).width+zt)),R=Math.ceil(I);W=[R];const x=rt?ao:0,T=R+ut*2,n=A+x+ut*2,b=xt?.x??0,u=xt?.y??0;_=Math.min(Math.max(O-h-T+b,h),O-h-T),C=Math.min(Math.max(E-h-n+u,h),E-h-n),J={x:_,y:C,w:T,h:n},t.save(),t.globalAlpha=.92,t.fillStyle=M.surface,t.fillRect(_,C,T,n),t.globalAlpha=1,t.strokeStyle=M.axisLine,t.lineWidth=1,t.strokeRect(_,C,T,n),t.restore(),_+=ut,C+=ut+x}else Zt?(_=h,C=E-h-A):Pt?(_=h,C=h+Q):fe?(_=h+4,C=h+Math.round((E-2*h-A)/2)):(_=O-h-Dt+4,C=h+Math.round((E-2*h-A)/2));if(rt){const I=e.plotMode==="softBin"?st:yt,{primary:R,secondary:x}=_e(e,St,I),T=6,n=g=>Ht-Math.max(lt(g),lt(g-12))-8,b=g=>re?O-h:n(g),u=Wt?J.y+J.h:C+A;if(Pt){const g=u+T;it(R,_,g,"left","top",Ht-Math.max(lt(g),lt(g+12))-8),x&&it(x,_,g+16,"left","top",n(g+16),Kt(),M.text)}else if(Wt)it(R,J.x+ut,J.y+ut,"left","top",J.x+J.w-ut),x&&it(x,J.x,u+T,"left","top",J.x+J.w,Kt(),M.text);else{const g=Math.max(C-T,h+Q+12);if(it(R,_,g,"left","bottom",b(g)),x){const B=u+T;it(x,_,B,"left","top",b(B),Kt(),M.text)}}}t.save(),t.font=Z();const Rt=K?8:0,v=(I,R)=>{if(t.measureText(I).width<=R)return I;let x=0,T=I.length;const n="\u2026",b=t.measureText(n).width;for(;x<T;){const u=x+T+1>>1;t.measureText(I.slice(0,u)).width+b<=R?x=u:T=u-1}return x===0?n:I.slice(0,x)+n};if(K){let I=0;for(let R=0;R<y;R++){let x=_;for(let T=0;T<w;T++){const n=i[I++];if(!n)break;const b=n.key===N,u=!b&&n.key===z,g=x,B=x+Y+mt,dt=C+R*D+D/2,gt=C+R*D+Math.round((D-Y)/2),Tt=W[T]-Y-mt-zt;u&&(t.fillStyle=M.hoverRow,t.fillRect(x,C+R*D,W[T],D)),t.fillStyle=n.color,t.fillRect(g,gt,Y,Y),t.strokeStyle=b?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=b?2:.75,t.strokeRect(g,gt,Y,Y),t.fillStyle=b?M.accent:M.text,t.font=b?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(n.label,Tt),B,dt),t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(n.count),x+W[T]-2,dt),ae.push({bin:n.key,x,y:C+R*D,w:W[T],h:D,label:n.tooltipLabel}),x+=W[T]+Rt}}}else{const I=W[0],R=$!=="compact",x=I-Y-mt-(R?zt:0),T=_+I-2;let n=i;U>0&&(n=i.slice(0,l-1));let b=C;for(const u of n){const g=u.key===N,B=!g&&u.key===z,dt=_,gt=_+Y+mt,Tt=b+D/2,Ae=b+Math.round((D-Y)/2),ze=u.label;B&&(t.fillStyle=M.hoverRow,t.fillRect(_-3,b,I+3,D)),t.fillStyle=u.color,t.fillRect(dt,Ae,Y,Y),t.strokeStyle=g?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=g?2:.75,t.strokeRect(dt,Ae,Y,Y),t.fillStyle=g?M.accent:M.text,t.font=g?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(ze,x),gt,Tt),(R||Wt)&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(u.count),T,Tt)),ae.push({bin:u.key,x:_,y:b,w:I,h:D,label:u.tooltipLabel}),b+=D}U>0&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${U} more`,_+Y+mt,b+D/2))}}i.length>0&&t.restore()}const Ue={originX:ot,originY:nt,ppm:k,snapDist:Yt},Te=e.rectangles[0]?.width??1,Se=e.rectangles[0]?.height??1,Xt=Te*1.5,$t=Se*1.5,at=e.dieBounds,Gt=at?at.minX:V.length?Math.min(...V.map(o=>o.x)):0,Vt=at?at.minY:V.length?Math.min(...V.map(o=>o.y)):0,Ke=at?at.maxX:V.length?Math.max(...V.map(o=>o.x)):1,qe=at?at.maxY:V.length?Math.max(...V.map(o=>o.y)):1,At=Math.max(1,Math.ceil((Ke-Gt)/Xt)+1),ce=Math.max(1,Math.ceil((qe-Vt)/$t)+1),Le=Array.from({length:At*ce},()=>[]);for(let o=0;o<V.length;o++){const c=Math.floor((V[o].x-Gt)/Xt),s=Math.floor((V[o].y-Vt)/$t),a=Math.max(0,Math.min(At-1,c)),r=Math.max(0,Math.min(ce-1,s));Le[r*At+a].push(o)}function ke(o,c,s){const a=Math.max(0,Math.floor((o-s-Gt)/Xt)),r=Math.min(At-1,Math.floor((o+s-Gt)/Xt)),f=Math.max(0,Math.floor((c-s-Vt)/$t)),d=Math.min(ce-1,Math.floor((c+s-Vt)/$t)),i=[];for(let p=f;p<=d;p++)for(let l=a;l<=r;l++)for(const y of Le[p*At+l])i.push(y);return i}return{hitTarget:{getDieAtPoint(o,c){const s=(o-ot)/k,a=(nt-c)/k,r=Math.max(Te,Se);for(const i of ke(s,a,r)){const p=e.rectangles[i];if(p&&Math.abs(s-p.x)<=p.width/2&&Math.abs(a-p.y)<=p.height/2)return e.dies[i]??null}let f=null,d=Yt*Yt;for(const i of ke(s,a,Yt)){const p=V[i].x-s,l=V[i].y-a,y=p*p+l*l;y<d&&(d=y,f=e.dies[i]??null)}return f}},viewport:Ue,binLegendRows:ae,legendBox:J}}function co(m,e,F,M,h,H,X,P,pt,j,xt,Mt,G){m.save(),m.font=io(),m.fillStyle=G.text,m.strokeStyle=G.axisLine,m.lineWidth=.5;const q=F-P+4,N=X+pt-4,z=Je(xt),St=Ce(z,1,0),Q=Ce(z,0,1),ct=1e-9;function yt(S){return j?Math.abs(S.y)<ct&&Math.abs(S.x)>ct?{pitch:j.x,sign:Math.sign(S.x)}:Math.abs(S.x)<ct&&Math.abs(S.y)>ct?{pitch:j.y,sign:Math.sign(S.y)}:null:null}const st=yt(St),bt=yt(Q);function rt(S){return st?Math.round(S*st.sign/st.pitch):S}function O(S){return bt?Math.round(S*bt.sign/bt.pitch):S}function E(S){if(!S)return Jt(50/H);const L=50/(S*H);return Math.max(1,Math.round(L))*S}const Lt=st?.pitch,kt=bt?.pitch,ft=E(Lt),tt=E(kt);m.textAlign="center",m.textBaseline="top";const ht=Math.ceil((X-M)/H/ft)*ft,Ct=(e-X-M)/H;for(let S=ht;S<=Ct;S+=ft){const L=M+S*H;if(L<X||L>e-X)continue;m.beginPath(),m.moveTo(L,q-Ne),m.lineTo(L,q),m.stroke();const $=j?String(rt(S)):Oe(S);m.fillText($,L,q+2)}m.textAlign="right",m.textBaseline="middle";const Bt=Math.ceil((h-(F-X))/H/tt)*tt,et=(h-X)/H;for(let S=Bt;S<=et;S+=tt){const L=h-S*H;if(L<X||L>F-X)continue;m.beginPath(),m.moveTo(N,L),m.lineTo(N+Ne,L),m.stroke();const $=j?String(O(S)):Oe(S);m.fillText($,N-2,L)}m.restore()}function Jt(m){const e=Math.pow(10,Math.floor(Math.log10(m))),F=m/e;return(F<1.5?1:F<3.5?2:F<7.5?5:10)*e}function ro(m,e,F,M,h,H,X){const P=[],pt=X;if(pt<1){const G=Jt((e-m)*M/F);if(G>0){const q=Math.ceil(m/G)*G;for(let N=q;N<=e+G*1e-6;N+=G){if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}}return P}const j=pt<3?[1,2,5]:[1],xt=Math.floor(Math.log10(m)),Mt=Math.ceil(Math.log10(e));for(let G=xt;G<=Mt;G++)for(const q of j){const N=q*Math.pow(10,G);if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}return P}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";
1
+ import{fontPx as Ct}from"./toolbar.js";import{findTestDef as Re,buildMapTitle as Ce}from"../renderer/buildView.js";import{affineInvert as ze,affineVector as _e}from"../core/transforms.js";import{compareNatural as Je}from"../core/utils.js";import{getValueColorScheme as Ze}from"../renderer/colorSchemes.js";import{NO_DATA_FILL as je}from"../renderer/colorMap.js";import{SPEC_PASS_FILL as Be,SPEC_FAIL_LOW as Qe,SPEC_FAIL_HIGH as Pe,contrastTextColor as We}from"../renderer/colorMap.js";import{fmt as De,fmtColorbarAxis as ve}from"../renderer/fmt.js";import{resolveCanvasTheme as to}from"./canvasTheme.js";import{hitGridDims as eo}from"./hitGrid.js";function Oe(m,e,F,M,h){m.moveTo(e,F+h*M),m.lineTo(e-M*.9,F-h*M*.6),m.lineTo(e+M*.9,F-h*M*.6),m.closePath()}const oo=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),no=new Set(["hardBin","softBin","metadata"]),Z=()=>`${Ct(-2)}px system-ui, sans-serif`,Ie=3,Gt=2,so=6,lo=20,io=()=>`600 ${Ct()}px system-ui, sans-serif`,Vt=()=>`${Ct(-1)}px system-ui, sans-serif`,ao=()=>`600 ${Ct(-1)}px system-ui, sans-serif`,Ut=128,co=()=>`${Ct(-2)}px system-ui, sans-serif`,Fe=4,D=17,Y=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const Kt=28,mt=5,ut=8,ro=15;export function toCanvas(m,e,F={}){const M=to(m.parentElement??m),{padding:h=16,showColorbar:H=!0,markFailingDies:X=!1,colorbarWidth:P=16,background:pt=M.background,legendPosition:j="default",legendOffset:xt,showAxes:Mt=!1,diePitchMm:V,viewport:q,activeBin:N,hoverBin:z,fallbackFormat:St,topClearance:Q=0,minRightReserve:ct,hbinDefs:yt,sbinDefs:st,metadataFields:bt,showTitle:rt=!0}=F,O=Math.floor(m.clientWidth||m.width),E=Math.floor(m.clientHeight||m.height),Lt=O>=BIN_LEGEND_MIN_CANVAS_W&&E>=BIN_LEGEND_MIN_CANVAS_H,kt=H&&Lt&&oo.has(e.plotMode)&&e.passFailDisplay==="off",ft=H&&Lt&&no.has(e.plotMode),tt=H&&Lt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),ht=ft||tt,_t=ft&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[c])=>o-c):[],Bt=ft&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Je)].map(o=>[o,e.metadataCounts.get(o)??0]):[],et=[];if(tt&&e.passFailDisplay==="test"){const o=e.passFailCounts;et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),et.push({key:-2,color:Pe,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(tt){const o=e.specCounts,c=Re(e.testDefs,e.activeTest);et.push({key:-1,color:Be,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),c?.limitHigh!==void 0&&et.push({key:-2,color:Pe,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),c?.limitLow!==void 0&&et.push({key:-3,color:Qe,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const S=tt?et.length:e.plotMode==="metadata"?Bt.length:_t.length,L=(m.ownerDocument.defaultView??window).devicePixelRatio??1;if(O<=0||E<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const $=j!=="default"?j:O<BIN_LEGEND_ADAPT_FLOATING?"floating":O<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",re=$==="default"||$==="compact",fe=$==="left",zt=$==="bottom",Pt=$==="top",Wt=$==="floating",Dt=$==="compact"||$==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,he=Math.floor((E-2*h)/D),de=S>he?he-1:S,ge=ht&&zt?de*D:0,Jt=ht&&Pt?de*D:0,Zt=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",jt=Re(e.testDefs,e.activeTest),Ne=Zt?"Count":jt?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),Ee=Zt?void 0:jt?.unit,[Ot,It]=e.valueRange,{tickFmt:we}=ve(It,Ne,Ee,St),Ft=e.allIntegerValues?o=>String(Math.round(o)):we;let Qt=0;if(kt){const o=m.getContext("2d");o.font=Z();const c=[Ft(Ot),Ft(It)];Ot<0&&c.push(Ft(-Math.max(Math.abs(Ot),Math.abs(It))));for(const s of c)Qt=Math.max(Qt,o.measureText(s).width)}const me=Math.max(lo,Math.ceil(Qt)+Ie+Gt+so-h),vt=kt?P+me+8:ht&&re?Dt:0,te=ht&&fe?Dt:0,ee=Mt?32:0,Nt=Mt?36:0,Ye=ct!=null?Math.max(vt,ct):vt,He=O-2*h-Ye-Nt-te,ue=E-2*h-ee-ge-Jt;m.width=Math.round(O*L),m.height=Math.round(E*L);const t=m.getContext("2d");t.scale(L,L),t.fillStyle=pt,t.fillRect(0,0,O,E);const G=e.hoverPoints;if(!G.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Et=e.rectangles[0],oe=Et?Et.width/2:0,ne=Et?Et.height/2:0,wt=e.dieBounds,pe=(wt?.minX??0)-oe,Xe=(wt?.maxX??0)+oe,$e=(wt?.minY??0)-ne,xe=(wt?.maxY??0)+ne,Me=Xe-pe,ye=xe-$e;let ot,nt,k;if(q)({originX:ot,originY:nt,ppm:k}=q);else{const c=e.notchDir,s=c&&c.y>.1?13:0,a=c&&c.y<-.1?13:0,r=c&&c.x<-.1?13:0,f=c&&c.x>.1?13:0,d=He-r-f,i=ue-Q-s-a;k=Math.min(d/Me,i/ye),ot=h+Nt+te+r+(d-Me*k)/2-pe*k,nt=h+Q+Jt+s+(i-ye*k)/2+xe*k}const Yt=q?.snapDist??Math.max(oe,ne,1)*1.5,Ht=ot+e.waferCenter.x*k,Ge=nt-e.waferCenter.y*k,se=e.waferRadius*k,lt=o=>{const c=Math.abs(o-Ge);return c>=se?0:Math.sqrt(se*se-c*c)},it=(o,c,s,a,r,f,d=io(),i=M.text)=>{if(!o)return;t.save(),t.fillStyle=i,t.font=d,t.textAlign=a,t.textBaseline=r;const p=a==="right"?c-f:f-c;let l=o;if(p>8&&t.measureText(l).width>p){for(;l.length>1&&t.measureText(l+"\u2026").width>p;)l=l.slice(0,-1);l=l+"\u2026"}p>8&&t.fillText(l,c,s),t.restore()};if(t.save(),t.setTransform(k*L,0,0,-k*L,ot*L,nt*L),e.rectangles.length>0){const o=new Map;for(const s of e.rectangles){const a=String(s.fill);let r=o.get(a);r||(r=[],o.set(a,r)),r.push(s)}for(const[s,a]of o){t.beginPath();for(const r of a)t.rect(r.x-r.width/2,r.y-r.height/2,r.width,r.height);t.fillStyle=s,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(k*L),t.beginPath();for(const s of e.rectangles)t.rect(s.x-s.width/2,s.y-s.height/2,s.width,s.height);if(t.stroke(),X){const s=e.rectangles.filter(a=>a.binFail);if(s.length>0){const a=new Map;for(const r of s){const f=We(String(r.fill));let d=a.get(f);d||(d=[],a.set(f,d)),d.push(r)}t.save(),t.lineCap="butt";for(const[r,f]of a){t.strokeStyle=r,t.globalAlpha=.55,t.lineWidth=Math.max(.6/(k*L),Math.min(f[0].width,f[0].height)*.1);for(const d of f){const i=d.width/2,p=d.height/2,l=Math.max(1.6/(k*L),Math.min(d.width,d.height)/3);t.save(),t.beginPath(),t.rect(d.x-i,d.y-p,d.width,d.height),t.clip(),t.beginPath();for(let b=-(i+p);b<=i+p;b+=l)t.moveTo(d.x-i+b,d.y-p),t.lineTo(d.x-i+b+d.height,d.y+p);t.stroke(),t.restore()}}t.restore()}}const c=e.rectangles.filter(s=>s.specMark);if(c.length>0){const s=new Map;for(const r of c){const f=We(String(r.fill)),d=`${r.specMark}|${f}`;let i=s.get(d);i||(i=[],s.set(d,i)),i.push(r)}const a=2.5/(k*L);t.lineJoin="round";for(const[r,f]of s){const[d,i]=r.split("|"),p=i==="#000000"?"#ffffff":"#000000",l=d==="failHigh"?1:-1,b=Math.min(f[0].width,f[0].height),w=Math.max(2.5/(k*L),b*.3);t.beginPath();for(const A of f)Oe(t,A.x,A.y,w,l);t.strokeStyle=p,t.lineWidth=a,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const c of o.points){for(let s=0;s<c.length;s++)s===0?t.moveTo(c[s].x,c[s].y):t.lineTo(c[s].x,c[s].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3/(k*L),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(k*L),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(k*L),t.stroke())}if(t.restore(),e.notchDir){const o=ot+e.waferCenter.x*k,c=nt-e.waferCenter.y*k,s=e.notchDir.x,a=-e.notchDir.y,r=e.waferRadius*k,f=4,d=9,i=5,p=o+s*(r+f),l=c+a*(r+f),b=p+s*d,w=l+a*d,A={x:-a,y:s},W=h+Nt+te,U=O-h-vt,K=h+Q+Jt,C=E-h-ge-ee;t.save(),t.beginPath(),t.rect(W,K,U-W,C-K),t.clip(),t.beginPath(),t.moveTo(p,l),t.lineTo(b+A.x*i,w+A.y*i),t.lineTo(b-A.x*i,w-A.y*i),t.closePath(),t.fillStyle=M.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let be=0;if(e.rectangles.length>0){let o=1;for(const f of e.texts)f.role!=="indicator"&&f.text.length>o&&(o=f.text.length);const c=e.rectangles[0].width*k,s=e.rectangles[0].height*k,a=Math.min(c,s),r=c/o;be=Math.max(8,Math.min(64,Math.round(Math.min(a*.55,r*1.8))))}for(const o of e.texts){const c=ot+o.x*k,s=nt-o.y*k;t.font=`${o.role==="indicator"?o.fontSize:be}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,c,s)}if(t.restore(),Mt&&fo(t,O,E,ot,nt,k,h,ee,Nt,V,e.gridToScreen,e.rotation,M),kt){const o=Ze(e.valueColorScheme),c=me,s=ue-Q,a=Math.round(s*.75),r=h+Q+Math.round((s-a)/2),f=O-h-P-c,d=Ot,i=It,p=i-d,l=e.plotMode==="stackedSoftBins"?st:yt,{primary:b,secondary:w}=rt?Ce(e,St,l):{primary:"",secondary:""};if(rt){const n=Math.max(r-6,h+Q+11),y=Ht+Math.max(lt(n),lt(n-12))+8;it(b,O-h,n,"right","bottom",y)}let A=r+a+4;const W=n=>Ht+Math.max(lt(n),lt(n+12))+8,U=e.logScale&&d>0?Math.log10(d):0,K=e.logScale&&i>0?Math.log10(i)-U:1,C=n=>e.logScale?(1-(Math.log10(n)-U)/K)*a:(1-(n-d)/p)*a;for(let n=0;n<Ut;n++){const y=1-n/(Ut-1),u=r+n/Ut*a,g=a/Ut+1;t.fillStyle=o.forValue(y),t.fillRect(f,u,P,g)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(f,r,P,a),t.fillStyle=M.text,t.font=Z(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const _=Ie,Rt=36,v=14,I=e.logScale&&K>0?ho(d,i,a,Rt,v,U,K):e.allIntegerValues?(()=>{const n=Math.max(1,qt(p*Rt/a)),y=[],u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(Math.round(g))}return y})():(()=>{const n=p>0?qt(p*Rt/a):0,y=[];if(n>0){const u=Math.ceil(d/n)*n;for(let g=u;g<=i+n*1e-6;g+=n){const B=(1-(g-d)/p)*a;B>v&&B<a-v&&y.push(g)}}return y})(),R=jt,x=Zt,T=Ft;t.textBaseline="middle";for(const n of I){const y=r+C(n);t.beginPath(),t.moveTo(f+P,y),t.lineTo(f+P+_,y),t.stroke(),t.fillText(T(n),f+P+_+Gt,y)}if(t.beginPath(),t.moveTo(f+P,r),t.lineTo(f+P+_,r),t.stroke(),t.textBaseline="top",t.fillText(T(i),f+P+_+Gt,r),t.beginPath(),t.moveTo(f+P,r+a),t.lineTo(f+P+_,r+a),t.stroke(),t.textBaseline="bottom",t.fillText(T(d),f+P+_+Gt,r+a),!x&&R&&(R.limitLow!==void 0||R.limitHigh!==void 0)){const n=[],y=e.colorbarRangeMode==="spec";for(const[u,g]of[[R.limitLow,"LSL"],[R.limitHigh,"USL"]]){if(u===void 0||e.logScale&&u<=0)continue;const B=C(u);!y&&(B<-v||B>a+v)||n.push({value:u,label:g,py:Math.max(0,Math.min(a,B))})}if(n.length>0){t.save(),t.font=Z(),t.textAlign="right",t.textBaseline="middle";for(const{py:u,label:g}of n){const B=r+u;y||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(f,B),t.lineTo(f+P,B),t.stroke()),t.fillStyle=M.text,t.fillText(g,f-3,B);const dt=g==="USL"?-1:1,gt=4,Tt=f-3-t.measureText(g).width-gt-4;t.beginPath(),Oe(t,Tt,B,gt,dt),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=M.text,t.fill()}t.restore()}}if(!x){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=M.text,t.font=ao(),t.textAlign="right",t.textBaseline="top",t.fillText(n,O-h,A),t.restore(),A+=15)}rt&&w&&it(w,O-h,A,"right","top",W(A),Vt(),M.text)}const le=[];let J;if(ht){const o=$==="compact",c=e.plotMode==="softBin"?st:yt,s=c?new Map(c.map(l=>[l.bin,l])):null,a=e.plotMode==="softBin"?e.binColors.soft:e.binColors.hard,r=l=>a.get(l)??je,f=(l,b)=>{const w=t.measureText(l).width,A=o?0:t.measureText(String(b)).width,W=Y+mt+w+(A?Kt:0);return{labelWidth:w,countWidth:A,totalWidth:W}},d=bt?.find(l=>l.key===e.activeMetadataKey),i=tt?et.map(l=>{const b=o?l.compactLabel:l.label;return{key:l.key,color:l.color,count:l.count,label:b,tooltipLabel:l.tooltip,...f(b,l.count)}}):e.plotMode==="metadata"?Bt.map(([l,b])=>{const A=d?.values?.find(K=>K.value===l)?.label??l,W=o?l:A,U=e.metadataColorMap?.get(l)??"#d6d9dd";return{key:l,color:U,count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}):_t.map(([l,b])=>{const w=s?.get(l),A=w?.name?`${l} \xB7 ${w.name}`:`Bin ${l}`,W=o?String(l):A;return{key:l,color:r(l),count:b,label:W,tooltipLabel:`${A} \xB7 ${b} dies`,...f(W,b)}}),p=O-h*2;if(i.length>0){const l=Math.max(1,Math.floor((E-2*h)/D));let b=i.length,w=1,A=b*D,W=[],U=0;const K=zt||Pt;if(K){const I=Math.max(...i.map(x=>x.totalWidth)),R=Math.max(1,Math.min(i.length,Math.floor((p+8)/(I+8))));for(let x=R;x>=1;x--){const T=Math.ceil(i.length/x);if(T>l)continue;const n=new Array(x).fill(0);for(let u=0;u<i.length;u++){const g=u%x;n[g]=Math.max(n[g],i[u].totalWidth)}if(n.reduce((u,g)=>u+g,0)+(x-1)*8<=p||x===1){w=x,W=n,b=T,A=T*D;break}}}else b=Math.min(i.length,l),A=b*D,i.length>l&&(U=i.length-(l-1)),W=[Dt];let C,_;if(Wt){const I=Math.max(...i.map(g=>Y+mt+t.measureText(g.label).width+Kt)),R=Math.ceil(I);W=[R];const x=rt?ro:0,T=R+ut*2,n=A+x+ut*2,y=xt?.x??0,u=xt?.y??0;C=Math.min(Math.max(O-h-T+y,h),O-h-T),_=Math.min(Math.max(E-h-n+u,h),E-h-n),J={x:C,y:_,w:T,h:n},t.save(),t.globalAlpha=.92,t.fillStyle=M.surface,t.fillRect(C,_,T,n),t.globalAlpha=1,t.strokeStyle=M.axisLine,t.lineWidth=1,t.strokeRect(C,_,T,n),t.restore(),C+=ut,_+=ut+x}else zt?(C=h,_=E-h-A):Pt?(C=h,_=h+Q):fe?(C=h+4,_=h+Math.round((E-2*h-A)/2)):(C=O-h-Dt+4,_=h+Math.round((E-2*h-A)/2));if(rt){const I=e.plotMode==="softBin"?st:yt,{primary:R,secondary:x}=Ce(e,St,I),T=6,n=g=>Ht-Math.max(lt(g),lt(g-12))-8,y=g=>re?O-h:n(g),u=Wt?J.y+J.h:_+A;if(Pt){const g=u+T;it(R,C,g,"left","top",Ht-Math.max(lt(g),lt(g+12))-8),x&&it(x,C,g+16,"left","top",n(g+16),Vt(),M.text)}else if(Wt)it(R,J.x+ut,J.y+ut,"left","top",J.x+J.w-ut),x&&it(x,J.x,u+T,"left","top",J.x+J.w,Vt(),M.text);else{const g=Math.max(_-T,h+Q+12);if(it(R,C,g,"left","bottom",y(g)),x){const B=u+T;it(x,C,B,"left","top",y(B),Vt(),M.text)}}}t.save(),t.font=Z();const Rt=K?8:0,v=(I,R)=>{if(t.measureText(I).width<=R)return I;let x=0,T=I.length;const n="\u2026",y=t.measureText(n).width;for(;x<T;){const u=x+T+1>>1;t.measureText(I.slice(0,u)).width+y<=R?x=u:T=u-1}return x===0?n:I.slice(0,x)+n};if(K){let I=0;for(let R=0;R<b;R++){let x=C;for(let T=0;T<w;T++){const n=i[I++];if(!n)break;const y=n.key===N,u=!y&&n.key===z,g=x,B=x+Y+mt,dt=_+R*D+D/2,gt=_+R*D+Math.round((D-Y)/2),Tt=W[T]-Y-mt-Kt;u&&(t.fillStyle=M.hoverRow,t.fillRect(x,_+R*D,W[T],D)),t.fillStyle=n.color,t.fillRect(g,gt,Y,Y),t.strokeStyle=y?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=y?2:.75,t.strokeRect(g,gt,Y,Y),t.fillStyle=y?M.accent:M.text,t.font=y?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(n.label,Tt),B,dt),t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(n.count),x+W[T]-2,dt),le.push({bin:n.key,x,y:_+R*D,w:W[T],h:D,label:n.tooltipLabel}),x+=W[T]+Rt}}}else{const I=W[0],R=$!=="compact",x=I-Y-mt-(R?Kt:0),T=C+I-2;let n=i;U>0&&(n=i.slice(0,l-1));let y=_;for(const u of n){const g=u.key===N,B=!g&&u.key===z,dt=C,gt=C+Y+mt,Tt=y+D/2,Ae=y+Math.round((D-Y)/2),qe=u.label;B&&(t.fillStyle=M.hoverRow,t.fillRect(C-3,y,I+3,D)),t.fillStyle=u.color,t.fillRect(dt,Ae,Y,Y),t.strokeStyle=g?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=g?2:.75,t.strokeRect(dt,Ae,Y,Y),t.fillStyle=g?M.accent:M.text,t.font=g?`bold ${Z()}`:Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(v(qe,x),gt,Tt),(R||Wt)&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="right",t.fillText(String(u.count),T,Tt)),le.push({bin:u.key,x:C,y,w:I,h:D,label:u.tooltipLabel}),y+=D}U>0&&(t.fillStyle=M.textMuted,t.font=Z(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${U} more`,C+Y+mt,y+D/2))}}i.length>0&&t.restore()}const Ve={originX:ot,originY:nt,ppm:k,snapDist:Yt},Te=e.rectangles[0]?.width??1,Se=e.rectangles[0]?.height??1,at=e.dieBounds,Xt=at?at.minX:G.length?Math.min(...G.map(o=>o.x)):0,$t=at?at.minY:G.length?Math.min(...G.map(o=>o.y)):0,Ue=at?at.maxX:G.length?Math.max(...G.map(o=>o.x)):1,Ke=at?at.maxY:G.length?Math.max(...G.map(o=>o.y)):1,{cellW:ie,cellH:ae,nCols:At,nRows:ce}=eo(Ue-Xt,Ke-$t,Te*1.5,Se*1.5,G.length),Le=Array.from({length:At*ce},()=>[]);for(let o=0;o<G.length;o++){const c=Math.floor((G[o].x-Xt)/ie),s=Math.floor((G[o].y-$t)/ae),a=Number.isFinite(c)?Math.max(0,Math.min(At-1,c)):0,r=Number.isFinite(s)?Math.max(0,Math.min(ce-1,s)):0;Le[r*At+a].push(o)}function ke(o,c,s){const a=Math.max(0,Math.floor((o-s-Xt)/ie)),r=Math.min(At-1,Math.floor((o+s-Xt)/ie)),f=Math.max(0,Math.floor((c-s-$t)/ae)),d=Math.min(ce-1,Math.floor((c+s-$t)/ae)),i=[];for(let p=f;p<=d;p++)for(let l=a;l<=r;l++)for(const b of Le[p*At+l])i.push(b);return i}return{hitTarget:{getDieAtPoint(o,c){const s=(o-ot)/k,a=(nt-c)/k,r=Math.max(Te,Se);for(const i of ke(s,a,r)){const p=e.rectangles[i];if(p&&Math.abs(s-p.x)<=p.width/2&&Math.abs(a-p.y)<=p.height/2)return e.dies[i]??null}let f=null,d=Yt*Yt;for(const i of ke(s,a,Yt)){const p=G[i].x-s,l=G[i].y-a,b=p*p+l*l;b<d&&(d=b,f=e.dies[i]??null)}return f}},viewport:Ve,binLegendRows:le,legendBox:J}}function fo(m,e,F,M,h,H,X,P,pt,j,xt,Mt,V){m.save(),m.font=co(),m.fillStyle=V.text,m.strokeStyle=V.axisLine,m.lineWidth=.5;const q=F-P+4,N=X+pt-4,z=ze(xt),St=_e(z,1,0),Q=_e(z,0,1),ct=1e-9;function yt(S){return j?Math.abs(S.y)<ct&&Math.abs(S.x)>ct?{pitch:j.x,sign:Math.sign(S.x)}:Math.abs(S.x)<ct&&Math.abs(S.y)>ct?{pitch:j.y,sign:Math.sign(S.y)}:null:null}const st=yt(St),bt=yt(Q);function rt(S){return st?Math.round(S*st.sign/st.pitch):S}function O(S){return bt?Math.round(S*bt.sign/bt.pitch):S}function E(S){if(!S)return qt(50/H);const L=50/(S*H);return Math.max(1,Math.round(L))*S}const Lt=st?.pitch,kt=bt?.pitch,ft=E(Lt),tt=E(kt);m.textAlign="center",m.textBaseline="top";const ht=Math.ceil((X-M)/H/ft)*ft,_t=(e-X-M)/H;for(let S=ht;S<=_t;S+=ft){const L=M+S*H;if(L<X||L>e-X)continue;m.beginPath(),m.moveTo(L,q-Fe),m.lineTo(L,q),m.stroke();const $=j?String(rt(S)):De(S);m.fillText($,L,q+2)}m.textAlign="right",m.textBaseline="middle";const Bt=Math.ceil((h-(F-X))/H/tt)*tt,et=(h-X)/H;for(let S=Bt;S<=et;S+=tt){const L=h-S*H;if(L<X||L>F-X)continue;m.beginPath(),m.moveTo(N,L),m.lineTo(N+Fe,L),m.stroke();const $=j?String(O(S)):De(S);m.fillText($,N-2,L)}m.restore()}function qt(m){const e=Math.pow(10,Math.floor(Math.log10(m))),F=m/e;return(F<1.5?1:F<3.5?2:F<7.5?5:10)*e}function ho(m,e,F,M,h,H,X){const P=[],pt=X;if(pt<1){const V=qt((e-m)*M/F);if(V>0){const q=Math.ceil(m/V)*V;for(let N=q;N<=e+V*1e-6;N+=V){if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}}return P}const j=pt<3?[1,2,5]:[1],xt=Math.floor(Math.log10(m)),Mt=Math.ceil(Math.log10(e));for(let V=xt;V<=Mt;V++)for(const q of j){const N=q*Math.pow(10,V);if(N<=m||N>=e)continue;const z=(1-(Math.log10(N)-H)/X)*F;z>h&&z<F-h&&P.push(N)}return P}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";