@wafertools/wafermap 0.24.3 → 0.25.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.
@@ -1,3 +1,3 @@
1
- import{isParametricTest as xt}from"../renderer/buildWaferMap.js";import{buildRingRegions as K,buildQuadrantRegions as Z,buildRegionYieldData as bt}from"../stats/regions.js";import{computeFunctionalYield as vt}from"../stats/analyzeWaferMap.js";import{openHtmlReport as J}from"../stats/renderFindingsReport.js";import{renderSummaryReportHtml as wt,renderLotSummaryReportHtml as yt}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as Ct}from"../stats/findingsNarrative.js";import{filterFindings as St}from"../stats/filterFindings.js";import{buildFacetTable as kt,prettyKey as tt}from"../stats/facets.js";import{commonMetadata as et}from"../stats/facets.js";import{resolveMetadataColumns as Bt}from"../stats/metadataColumns.js";import{getColorScheme as $t}from"../renderer/colorSchemes.js";import{buildWarningsBanner as _,collectWarnings as nt}from"./warnings.js";export{_ as buildWarningsBanner};import{fmt as it,fmtAggregationMethod as Lt,plainBinTerms as P}from"../renderer/fmt.js";import{getUniqueTestNumbers as Dt}from"../renderer/buildView.js";import{quantile as Q}from"../stats/math.js";import{makeLabeledSelect as ot}from"./charts/chartShell.js";import{CLR as w,sevColor as G,openModal as at,saveTextFile as rt}from"./toolbar.js";import{buildDieListSection as Rt}from"./dieList.js";import{medianOfSorted as Ft}from"../core/utils.js";import{metadataDisplayValue as Tt}from"../core/metadata.js";const Et=w.panelBg,Y=`1px solid ${w.menuBorder}`,Nt="12px",I=w.label,z=w.value,st="10px";function l(t,i,n,e=document){const o=e.createElement(t);return i&&Object.assign(o.style,i),n!==void 0&&(o.textContent=n),o}function H(t){return l("div",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,marginBottom:"6px"},t)}function lt(t,i=!0,n){const e=l("div"),o=document.createElement("button");o.type="button",Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const d=l("span",{fontSize:"9px",color:I,transition:"transform 0.15s",transform:i?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:"1",marginRight:"1px"},"\u25B6"),f=l("span",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,flex:"1"},t);if(o.setAttribute("aria-expanded",i?"true":"false"),o.appendChild(d),o.appendChild(f),n){const a=l("span",{fontSize:"9px",fontWeight:"700",background:w.warnBg,color:w.warnText,borderRadius:"10px",padding:"1px 5px"},n);o.appendChild(a)}const c=l("div");c.style.display=i?"block":"none";let s=i;return o.addEventListener("click",()=>{s=!s,c.style.display=s?"block":"none",d.style.transform=s?"rotate(90deg)":"rotate(0deg)",o.setAttribute("aria-expanded",s?"true":"false")}),e.appendChild(o),e.appendChild(c),{outer:e,content:c}}function dt(){return l("div",{height:"1px",background:w.separator,margin:`${Nt} 0`,flexShrink:"0"})}function U(t,i,n=w.barFill,e,o,d){const f=l("div",{marginBottom:"5px"}),c=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",color:z,marginBottom:"2px"}),s=l("span",{},t),a=l("span",{fontWeight:"600"},`${i.toFixed(1)}%`);c.appendChild(s),c.appendChild(a);const p=e!==void 0?e:Math.min(100,Math.max(0,i)),h=d?w.barFillMuted:n,g=l("div",{position:"relative",height:"9px",background:w.bgActive,borderRadius:"4px",overflow:"hidden"}),T=l("div",{height:"100%",width:`${p}%`,background:h,borderRadius:"4px",transition:"width 0.3s ease"});if(g.appendChild(T),o!==void 0){const N=l("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"1px",background:w.infoText,opacity:"0.5"});g.appendChild(N)}return f.appendChild(c),f.appendChild(g),f}function O(t,i,n){const e=l("div",{background:w.menuBg,border:Y,borderRadius:"6px",padding:"8px 10px",textAlign:"center",flex:"1"}),o=l("div",{fontSize:"20px",fontWeight:"700",color:z,lineHeight:"1.2"},t),d=l("div",{fontSize:"10px",color:I,marginTop:"2px"},i);return e.appendChild(o),e.appendChild(d),n&&e.appendChild(l("div",{fontSize:"9px",color:I,opacity:"0.85"},n)),e}function Mt(t,i){const n=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",gap:"8px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},t),o=l("span",{color:z,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}function Wt(t,i){const n=l("div",{display:"flex",fontSize:"11px",gap:"6px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},`${t}:`),o=l("span",{color:z,fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}export function metadataEntries(t){const i=[];for(const[n,e]of Object.entries(t)){const o=Tt(e);o!==void 0&&i.push([n,o])}return i}export function buildFacetSummaryChips(t,i=3){if(!t.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 10px",fontSize:"11px"});for(const e of t){const o=l("span",{whiteSpace:"nowrap"}),d=l("span",{color:I},`${tt(e.key)}: `);o.appendChild(d);const f=e.values.slice(0,i),c=e.values.length-f.length;let s=f.map(a=>a.value).join(", ");c>0&&(s+=` +${c} more`),o.appendChild(document.createTextNode(s)),n.appendChild(o)}return n}export function buildMetadataStripRow(t,i,n){const e=kt(t,n),o=buildFacetSummaryChips(e);if(!o&&!i)return null;const d=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(i){const f=l("span",{fontWeight:"500",whiteSpace:"nowrap"},i.aggrMethod?`${i.lotSize} wafers stacked \xB7 ${i.aggrMethod}`:`${i.lotSize} wafers stacked`);d.appendChild(f)}return o&&d.appendChild(o),d}const It={display:"flex",flexDirection:"column",gap:"6px",background:w.menuBg,border:`1px solid ${w.menuBorder}`,borderRadius:"6px",padding:"6px 10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,i,n){const e=buildMetadataStripRow(t,i,n);if(!e)return null;const o=l("div",It);return o.appendChild(e),o}export function buildCompactMetadataRows(t){const i=metadataEntries(t);if(!i.length)return null;const n=l("div");for(const[e,o]of i)n.appendChild(Wt(tt(e),o));return n}export function buildMetadataInfoSection(t,i){const n=buildMetadataStripRow(t,i,{facetableOnly:t.length>1});if(!n)return null;const e=l("div");return e.appendChild(H("Wafer Info")),e.appendChild(n),e}export function buildYieldSection(t,i,n=[1]){const e=l("div");e.appendChild(H("Summary"));const o=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});if(o.appendChild(O(String(t.totalDies),"Total dies")),t.partialDies>0&&o.appendChild(O(String(t.partialDies),"Partial")),t.yieldPercent!==null){const d=n.length===1?`bin ${n[0]}`:`bins ${n.join(", ")}`;o.appendChild(O(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${d}`))}return e.appendChild(o),t.edgeExcludedDies>0&&e.appendChild(Mt("Edge excluded (outer zone)",String(t.edgeExcludedDies))),e}export function buildBinSection(t,i,n,e,o){const d=new Map;if(o)for(const[p,h]of Object.entries(o))d.set(Number(p),h);else for(const p of t){if(p.partial||p.edgeExcluded)continue;const h=n==="hard"?p.hbin:p.sbin;h!=null&&d.set(h,(d.get(h)??0)+1)}if(!d.size)return null;const f=[...d.values()].reduce((p,h)=>p+h,0),c=i?new Map(i.map(p=>[p.bin,p])):null,s=[...d.entries()].sort((p,h)=>p[0]-h[0]),a=l("div");a.appendChild(H(n==="hard"?"Hard Bin Breakdown":"Soft Bin Breakdown"));for(const[p,h]of s){const g=c?.get(p),T=g?.name?`Bin ${p} \xB7 ${g.name}`:`Bin ${p}`,N=h/f*100,B=$t(e),E=(e==="custom"?g?.color:void 0)??B.forBin(p);a.appendChild(U(`${T} (${h})`,N,E))}return a}export function buildLotBinSection(t,i,n,e){return buildBinSection(t,i,n,e)}function j(t,i,n,e,o,d){const f=bt(t,i,n,e,o);if(!f.length)return null;const c=l("div");c.appendChild(H(d));for(const{label:s,n:a,yieldPercent:p}of f)c.appendChild(U(`${s} (N=${a})`,p));return c}export function buildRingSection(t,i,n,e){return j([t],[i],n,e,K,"Ring Yield")}export function buildQuadrantSection(t,i,n,e){return j([t],[i],n,e,Z,"Quadrant Yield")}export function buildLotRingSection(t,i,n,e){return j(t,i,n,e,K,"Ring Yield")}export function buildLotQuadrantSection(t,i,n,e){return j(t,i,n,e,Z,"Quadrant Yield")}export function buildLotOverviewSection(t){const i=l("div");i.appendChild(H("Lot Summary"));const n=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});n.appendChild(O(String(t.stats.waferCount),"Wafers"));const e=t.perWafer.map(o=>o.summary.stats.yieldPercent).filter(o=>o!==null);if(e.length){const o=e.reduce((d,f)=>d+f,0)/e.length;n.appendChild(O(`${o.toFixed(1)}%`,"Mean wafer yield"))}return i.appendChild(n),i}export function buildPerWaferYieldSection(t,i,n){const e=t.perWafer.map(a=>({waferIndex:a.waferIndex,label:(i[a.waferIndex]?.label??`W${a.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:a.summary.stats.yieldPercent})).filter(a=>a.yieldPct!==null);if(!e.length)return null;const o=Math.min(...e.map(a=>a.yieldPct)),d=Math.max(...e.map(a=>a.yieldPct)),f=o===d?"":` (${o.toFixed(1)}\u2013${d.toFixed(1)}%)`,c=Ft([...e.map(a=>a.yieldPct)].sort((a,p)=>a-p)),s=l("div");s.appendChild(H("Wafer Yield"+f));for(const{waferIndex:a,label:p,yieldPct:h}of e){const g=U(p,h,void 0,void 0,c,h<c);n&&(g.style.cursor="pointer",g.style.borderRadius="4px",g.style.padding="2px 3px",g.style.marginLeft="-3px",g.style.marginRight="-3px",g.setAttribute("role","button"),g.setAttribute("aria-label",`${p}, ${h.toFixed(1)}% yield \u2014 view wafer`),g.tabIndex=0,g.addEventListener("mouseenter",()=>{g.style.background=w.bgHover}),g.addEventListener("mouseleave",()=>{g.style.background=""}),g.addEventListener("focus",()=>{g.style.background=w.bgHover}),g.addEventListener("blur",()=>{g.style.background=""}),g.addEventListener("click",()=>n(a)),g.addEventListener("keydown",T=>{(T.key==="Enter"||T.key===" ")&&(T.preventDefault(),n(a))})),s.appendChild(g)}return s}function zt(t){const i=[...t].sort((o,d)=>o-d),n=t.reduce((o,d)=>o+d,0)/t.length,e=t.reduce((o,d)=>o+(d-n)**2,0)/t.length;return{min:i[0],max:i[i.length-1],mean:n,count:t.length,stddev:Math.sqrt(e),median:Q(i,.5),q1:Q(i,.25),q3:Q(i,.75)}}function pt(t,i){if(!t)return[];const n=t.waferMetadata??(t.perWaferMetadata?et(t.perWaferMetadata.map(e=>({metadata:e}))):void 0);return!n||!Object.keys(n).length?[]:Bt({waferMetadata:n,waferPlacement:"csv",reservedLabels:i}).columns}export function csvField(t){return/[",\n]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}export function buildTestSection(t,i,n,e,o,d){const f=t.filter(r=>!r.partial&&!r.edgeExcluded),c=new Map((e?.perTestStats??[]).map(r=>[r.testNumber,r])),s=new Map((e?.testSpecYield??[]).map(r=>[r.testNumber,r]));let a;if(i?.length?a=i.filter(xt).map(r=>({testNumber:r.testNumber,name:r.name,unit:r.unit,limitLow:r.limitLow,limitHigh:r.limitHigh})):a=Dt(f).map(m=>({testNumber:m,name:`Test ${m}`})),!a.length)return null;const p=a.filter(r=>f.some(m=>{const D=m.testValues?.[r.testNumber];return D!==void 0&&isFinite(D)}));if(!p.length)return null;const h=p.some(r=>r.limitLow!==void 0||r.limitHigh!==void 0),g=[];for(const r of p){const m=c.get(r.testNumber),D=m&&m.stddev!==void 0&&m.median!==void 0&&m.q1!==void 0&&m.q3!==void 0;let y;if(D){const v=m;y={testNumber:r.testNumber,min:v.min,max:v.max,mean:v.mean,count:v.count,stddev:v.stddev,median:v.median,q1:v.q1,q3:v.q3}}else{const v=f.map(F=>F.testValues?.[r.testNumber]).filter(F=>F!==void 0&&isFinite(F));if(!v.length)continue;y={testNumber:r.testNumber,...zt(v)}}let b=null,S=0;if(r.limitLow!==void 0||r.limitHigh!==void 0){const v=s.get(r.testNumber);if(v)({yieldPercent:b,totalDies:S}=v);else{const F=f.map(x=>x.testValues?.[r.testNumber]).filter(x=>x!==void 0&&isFinite(x)),W=F.filter(x=>r.limitLow!==void 0&&x<r.limitLow||r.limitHigh!==void 0&&x>r.limitHigh).length;S=F.length,b=F.length>0?(F.length-W)/F.length*100:null}}g.push({entry:r,stats:y,specYieldPct:b,specN:S})}if(!g.length)return null;const T=l("div"),N=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),B=H(d?.populationLabel?`Test Values (${g.length}) \u2014 ${d.populationLabel}`:`Test Values (${g.length})`);B.style.marginBottom="0",N.appendChild(B);const E=document.createElement("button");E.type="button",E.textContent="Export CSV",Object.assign(E.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:w.iconHover,padding:"2px 7px"}),E.addEventListener("click",()=>{const r=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&r.push("LSL","USL","Spec Yield %","Spec Yield N");const m=pt(d,r),y=[[...m.map(S=>S.label),...r].map(csvField).join(",")],b=S=>it(S,void 0,"engineering");for(const{entry:S,stats:v,specYieldPct:F,specN:W}of g){const x=[...m.map(M=>M.constant??""),S.name,S.unit??"",String(v.count),b(v.min),b(v.q1),b(v.median),b(v.mean),b(v.q3),b(v.max),b(v.stddev)];h&&x.push(S.limitLow!==void 0?b(S.limitLow):"",S.limitHigh!==void 0?b(S.limitHigh):"",F!==null?F.toFixed(1):"",S.limitLow!==void 0||S.limitHigh!==void 0?String(W):""),y.push(x.map(csvField).join(","))}rt(y.join(`
2
- `),"test-values.csv","text/csv",o)}),N.appendChild(E),T.appendChild(N);const R=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),L=document.createElement("thead"),u=document.createElement("tr"),$=["Test","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&$.push("LSL","USL","Spec yield");for(const r of $){const m=l("th",{textAlign:r==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${w.menuBorder}`,whiteSpace:"nowrap"},r);u.appendChild(m)}L.appendChild(u),R.appendChild(L);const k=document.createElement("tbody");for(const{entry:r,stats:m,specYieldPct:D,specN:y}of g){const b=F=>it(F,r.unit,n),S=document.createElement("tr"),v=(F,W="right")=>{const x=l("td",{textAlign:W,padding:"4px 8px",borderBottom:`1px solid ${w.menuBorder}`,color:z,whiteSpace:"nowrap"},F);S.appendChild(x)};v(r.name,"left"),v(`${m.count}`),v(b(m.min)),v(b(m.q1)),v(b(m.median)),v(b(m.mean)),v(b(m.q3)),v(b(m.max)),v(b(m.stddev)),h&&(v(r.limitLow!==void 0?b(r.limitLow):"\u2014"),v(r.limitHigh!==void 0?b(r.limitHigh):"\u2014"),v(D!==null?`${D.toFixed(1)}% (N=${y})`:"\u2014")),k.appendChild(S)}R.appendChild(k);const C=l("div",{overflowX:"auto"});return C.appendChild(R),T.appendChild(C),T}export function buildFunctionalTestSection(t,i,n,e,o){const d=n??vt(t,i);if(!d?.length)return null;const f=l("div"),c=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),s=H(o?.populationLabel?`Functional Tests (${d.length}) \u2014 ${o.populationLabel}`:`Functional Tests (${d.length})`);s.style.marginBottom="0",c.appendChild(s);const a=document.createElement("button");a.type="button",a.textContent="Export CSV",Object.assign(a.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:w.iconHover,padding:"2px 7px"}),a.addEventListener("click",()=>{const B=["Test","N","Pass","Fail","Pass Rate %"],E=pt(o,B),R=[[...E.map(L=>L.label),...B].map(csvField).join(",")];for(const L of d)R.push([...E.map(u=>u.constant??""),L.label,String(L.totalDies),String(L.passDies),String(L.failDies),L.passRatePercent!==null?L.passRatePercent.toFixed(1):""].map(csvField).join(","));rt(R.join(`
3
- `),"functional-tests.csv","text/csv",e)}),c.appendChild(a),f.appendChild(c);const p=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),h=document.createElement("thead"),g=document.createElement("tr");for(const B of["Test","N","Pass","Fail","Pass rate"])g.appendChild(l("th",{textAlign:B==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${w.menuBorder}`,whiteSpace:"nowrap"},B));h.appendChild(g),p.appendChild(h);const T=document.createElement("tbody");for(const B of d){const E=document.createElement("tr"),R=(L,u="right")=>{E.appendChild(l("td",{textAlign:u,padding:"4px 8px",borderBottom:`1px solid ${w.menuBorder}`,color:z,whiteSpace:"nowrap"},L))};R(B.label,"left"),R(String(B.totalDies)),R(String(B.passDies)),R(String(B.failDies)),R(B.passRatePercent!==null?`${B.passRatePercent.toFixed(1)}% (N=${B.totalDies})`:"\u2014"),T.appendChild(E)}p.appendChild(T);const N=l("div",{overflowX:"auto"});return N.appendChild(p),f.appendChild(N),f}export function buildLotFunctionalSection(t,i,n,e){const o=n?.length?{perWaferMetadata:n.map(d=>d.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;if(n?.length&&n.every(d=>d.stats.functionalYield!==void 0)){const d=new Map;for(const c of n)for(const s of c.stats.functionalYield??[]){const a=d.get(s.testNumber)??{label:s.label,passDies:0,failDies:0,totalDies:0};a.passDies+=s.passDies,a.failDies+=s.failDies,a.totalDies+=s.totalDies,d.set(s.testNumber,a)}const f=[...d.entries()].map(([c,s])=>({testNumber:c,...s,passRatePercent:s.totalDies>0?s.passDies/s.totalDies*100:null}));if(f.length)return buildFunctionalTestSection(t,i,f,e,o)}return buildFunctionalTestSection(t,i,void 0,e,o)}const A={unusual:0,notable:1,info:2};function X(t){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:G(t),flexShrink:"0"})}function ct(t,i){let n=t.summary;return i&&(n.startsWith(`${i} has `)?n=n.slice(i.length+5):n.startsWith(`${i} `)&&(n=n.slice(i.length+1))),n=P(n),n.length?n[0].toUpperCase()+n.slice(1):n}export function buildFindingsSection(t,i,n,e,o=!1){if(!t.length)return null;const d=t.some(u=>u.severity==="unusual"||u.severity==="notable"),f=d?t.filter(u=>u.severity!=="info").length.toString():void 0,{outer:c,content:s}=o?(()=>{const u=l("div");return{outer:u,content:u}})():lt(`Findings (${t.length})`,d,f);function a(u){return u.reduce(($,k)=>A[k.severity]<A[$]?k.severity:$,"info")}function p(u){const $=new Map;for(const C of u){const r=`${C.comparison.family}\0${C.comparison.left}`,m=$.get(r)??[];m.push(C),$.set(r,m)}const k=[...$.entries()].map(([C,r])=>{const m=[...r].sort((D,y)=>A[D.severity]-A[y.severity]);return{key:C,findings:m,worst:a(m)}});return k.sort((C,r)=>A[C.worst]-A[r.worst]),k}function h(u,$){const C={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[u]??u;return $.toLowerCase().startsWith(C.toLowerCase())?$:`${C}: ${$}`}const g=t.filter(u=>u.comparison.family==="spatial-pattern"),T=new Set([...g.flatMap(u=>u.relatedIds??[]),...t.flatMap(u=>u.absorbedIds??[])]),N=t.filter(u=>u.comparison.family!=="spatial-pattern"&&!T.has(u.id)),B=p(N);function E(u,$=!1,k){const C=e===u.id,r=document.createElement("button");return r.type="button",r.dataset.wmapFinding=u.id,r.textContent=ct(u,k),r.title=u.summary,r.setAttribute("aria-current",C?"true":"false"),Object.assign(r.style,{border:`1px solid ${w.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:C?w.bgActive:w.menuBg,borderRadius:"6px",padding:$?"6px 10px":"8px 10px",textAlign:"left",fontSize:$?"10px":"11px",fontWeight:C?"600":"400",color:w.iconHover,cursor:"pointer",width:"100%",marginBottom:"4px"}),r.addEventListener("click",()=>n(u,r)),r}const R=P(Ct(t)??"");if(R){const u=l("div",{background:w.bgActive,borderRadius:"6px",padding:"8px 10px",marginBottom:"8px",display:"flex",gap:"8px",alignItems:"flex-start"}),$=l("span",{flex:"1",fontSize:"12px",lineHeight:"1.5",color:w.iconHover},R);u.appendChild($);const k=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:"10px",color:w.icon,cursor:"pointer",padding:"0",lineHeight:"1.5",whiteSpace:"nowrap"},"Detail \u25B8");k.type="button",k.addEventListener("click",()=>{const C=at({title:"Findings Summary",onClose:()=>{},anchor:k}),r=l("p",{fontSize:"16px",lineHeight:"1.6",color:w.iconHover,padding:"20px 24px 16px",margin:"0",borderBottom:`1px solid ${w.menuBorder}`,flexShrink:"0"},R);C.contentWrap.appendChild(r);const m=l("div",{overflowY:"auto",padding:"16px 24px",flex:"1"}),D=(y,b)=>{const S=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:"13px",fontWeight:"600",color:z,marginTop:"10px",marginBottom:"4px"});return S.appendChild(X(y)),S.appendChild(l("span",{},b)),S};for(const y of g){m.appendChild(D(y.severity,y.comparison.left)),m.appendChild(l("div",{fontSize:"13px",color:w.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},P(y.summary)));const b=t.filter(S=>y.relatedIds?.includes(S.id));for(const S of b)m.appendChild(l("div",{fontSize:"12px",color:w.icon,padding:"2px 0 2px 23px",marginBottom:"2px"},P(S.summary)))}for(const y of B){const[b,S]=y.key.split("\0");m.appendChild(D(y.worst,h(b,S)));for(const v of y.findings)m.appendChild(l("div",{fontSize:"13px",color:w.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},ct(v,S)))}C.contentWrap.appendChild(m),Object.assign(C.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),u.appendChild(k),s.appendChild(u)}let L=!0;for(const u of g){L||s.appendChild(l("div",{height:"1px",background:w.separator,margin:"4px 0"})),L=!1;const $=t.filter(D=>u.relatedIds?.includes(D.id)),k=$.length>0,C=l("div",{position:"relative",marginBottom:k?"2px":"4px"}),r=e===u.id,m=document.createElement("button");if(m.type="button",m.dataset.wmapFinding=u.id,Object.assign(m.style,{border:`1px solid ${w.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:r?w.bgActive:w.menuBg,borderRadius:"6px",padding:"8px 32px 8px 10px",textAlign:"left",fontSize:"11px",fontWeight:r?"600":"500",color:w.iconHover,cursor:"pointer",width:"100%"}),m.textContent=P(u.summary),m.title=u.summary,m.setAttribute("aria-current",r?"true":"false"),m.addEventListener("click",()=>n(u,m)),C.appendChild(m),k){const D=l("div",{display:"none",paddingLeft:"12px",marginBottom:"4px"});for(const S of $)D.appendChild(E(S,!0));C.appendChild(D);let y=!1;const b=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:"10px",color:w.icon,cursor:"pointer",padding:"2px 4px",lineHeight:"1"},"\u25B8");b.type="button",b.title="Show supporting findings",b.setAttribute("aria-label","Show supporting findings"),b.setAttribute("aria-expanded","false"),b.addEventListener("click",S=>{S.stopPropagation(),y=!y,D.style.display=y?"block":"none",b.textContent=y?"\u25BE":"\u25B8";const v=y?"Hide supporting findings":"Show supporting findings";b.title=v,b.setAttribute("aria-label",v),b.setAttribute("aria-expanded",String(y))}),C.appendChild(b)}s.appendChild(C)}for(const u of B){L||s.appendChild(l("div",{height:"1px",background:w.separator,margin:"4px 0"})),L=!1;const[$,k]=u.key.split("\0"),C=l("div",{display:"flex",alignItems:"center",gap:"6px",fontSize:"11px",fontWeight:"600",color:z,margin:"2px 0 4px"});C.appendChild(X(u.worst)),C.appendChild(l("span",{},h($,k))),s.appendChild(C);for(const r of u.findings)s.appendChild(E(r,!1,k))}return c}const Ht=[{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"}],At=[{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"}],Pt=["unusual","notable","info"],Yt={unusual:"Unusual",notable:"Notable",info:"Info"};function Ot(t,i,n){const e=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"10px",marginBottom:"10px",paddingBottom:"10px",borderBottom:`1px solid ${w.separator}`}),o={unusual:0,notable:0,info:0};for(const s of t)o[s.severity]++;const d=Pt.filter(s=>o[s]>0),f=new Set(i.severity===void 0?d:Array.isArray(i.severity)?i.severity:[i.severity]),c=l("div",{display:"flex",gap:"4px",flexWrap:"wrap"});for(const s of d){const a=document.createElement("button");a.type="button";const p=()=>{const h=f.has(s);a.setAttribute("aria-pressed",h?"true":"false"),Object.assign(a.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${w.menuBorder}`,borderRadius:"10px",background:h?w.bgActive:"none",opacity:h?"1":"0.5",color:w.text,fontSize:"11px",padding:"2px 8px",cursor:"pointer"})};a.appendChild(X(s)),a.appendChild(l("span",{},`${Yt[s]} ${o[s]}`)),a.title=f.has(s)?"Click to hide these findings":"Click to show these findings",p(),a.addEventListener("click",()=>{f.has(s)?f.delete(s):f.add(s),i.severity=f.size===d.length?void 0:[...f],n()}),c.appendChild(a)}return e.appendChild(c),e.appendChild(ot("Kind:",Ht,i.kind??"",s=>{i.kind=s||void 0,n()},{maxWidth:"130px"})),e.appendChild(ot("Region:",At,i.family??"",s=>{i.family=s||void 0,n()},{maxWidth:"150px"})),e}export function buildFindingsSectionWithFilter(t,i,n,e,o){if(!t.findings.length)return null;const d=t.findings.some(h=>h.severity==="unusual"||h.severity==="notable"),f=d?t.findings.filter(h=>h.severity!=="info").length.toString():void 0,{outer:c,content:s}=lt(`Findings (${t.findings.length})`,d,f);s.appendChild(Ot(t.findings,e,o));const a=St(t,e);if(!a.length)return s.appendChild(l("div",{color:I,fontSize:"11px",textAlign:"center",padding:"16px 8px"},"No findings match the current filter.")),c;const p=buildFindingsSection(a,t,i,n,!0);return p&&s.appendChild(p),c}export function buildLotTestSection(t,i,n,e,o){const d=e?.length?{perWaferMetadata:e.map(c=>c.wafer??{}),populationLabel:`${e.length} wafer${e.length===1?"":"s"} pooled`}:void 0;let f;if(e?.length&&e.every(c=>c.stats.perTestStats!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.perTestStats??[]){const p=c.get(a.testNumber);p?(p.n+=a.count,p.sum+=a.mean*a.count,p.min=Math.min(p.min,a.min),p.max=Math.max(p.max,a.max)):c.set(a.testNumber,{n:a.count,sum:a.mean*a.count,min:a.min,max:a.max})}f={perTestStats:[...c.entries()].map(([s,a])=>({testNumber:s,count:a.n,min:a.min,max:a.max,mean:a.sum/a.n}))}}if(e?.length&&e.every(c=>c.stats.testSpecYield!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.testSpecYield??[]){const p=c.get(a.testNumber);p?(p.passDies+=a.passDies,p.totalDies+=a.totalDies):c.set(a.testNumber,{passDies:a.passDies,totalDies:a.totalDies})}f={...f,testSpecYield:[...c.entries()].map(([s,a])=>({testNumber:s,totalDies:a.totalDies,yieldPercent:a.totalDies>0?a.passDies/a.totalDies*100:null}))}}return buildTestSection(t,i,n,f,o,d)}export function createSummaryPanelEl(t,i=document){const n=t==="top"||t==="bottom",e=l("div",{background:Et,border:Y,borderRadius:"6px",padding:"12px",overflowY:n?"hidden":"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:"system-ui, sans-serif",fontSize:"12px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)"},void 0,i);return n?(e.style.height="180px",e.style.width="100%"):(e.style.width="260px",e.style.maxHeight="100%"),e}export function wrapWithSummaryPanel(t,i,n){const e=n==="top"||n==="bottom",o=l("div",{display:"flex",flexDirection:e?"column":"row",gap:"8px",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",n==="right"||n==="bottom"?(o.appendChild(t),o.appendChild(i)):(o.appendChild(i),o.appendChild(t)),o}function ut(t){return l("div",{fontSize:"13px",fontWeight:"700",color:z,marginBottom:"10px"},t)}function q(t,i){const n=l("button",{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:w.iconHover,padding:"2px 7px"},t);return n.type="button",n.addEventListener("click",i),n}function ft(...t){const i=t.filter(e=>!!e);if(!i.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",gap:"6px",marginBottom:"10px"});for(const e of i)n.appendChild(e);return n}function mt(t,i,n,e,o,d,f,c,s){const a=t.ownerDocument,p=at({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:a});p.contentWrap.style.padding="14px 16px";const h=Rt(i,n,{...f,title:e,onSaveText:c,waferMetadata:o,metadataFields:d,extraColumn:s,ownerDocument:a});h&&p.contentWrap.appendChild(h)}export function renderWaferSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h=[1],ringCount:g=4,colorScheme:T,fallbackFormat:N,onFindingClick:B,activeFindingId:E=null,findingsFilter:R,onFindingsFilterChange:L,onSaveText:u,metadataFields:$,dieListOptions:k}=i;t.appendChild(ut("Wafer Summary"));const C=i.warnings??nt({statsSummary:p});C.length&&t.appendChild(_(C,t.ownerDocument));const r=d&&f?q("Summary report",()=>{J(wt({wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h,ringCount:g}))}):null,m=(k?.enabled??!0)&&o.length?q("View die list",()=>{mt(t,o,a,`Die list \u2014 ${o.length} dies`,e.metadata,$,k,u)}):null,D=ft(r,m);D&&t.appendChild(D);const y=[],b=p?.stats.isLotStack?p.stats:void 0,S=b?.lotSize!==void 0?{lotSize:b.lotSize,aggrMethod:Lt(b.aggregationMethod)}:void 0;y.push(buildMetadataInfoSection([{metadata:e.metadata??void 0}],S)),d&&f&&y.push(buildYieldSection(d,f,h));const v=o.some(M=>M.hbin!=null),F=o.some(M=>M.sbin!=null);v?y.push(buildBinSection(o,c,"hard",T,p?.stats.hardBinCounts)):F&&y.push(buildBinSection(o,s,"soft",T,p?.stats.softBinCounts)),y.push(buildRingSection(o,e,g,h)),y.push(buildQuadrantSection(o,e,g,h));const W=e.metadata?{waferMetadata:e.metadata}:void 0;y.push(buildTestSection(o,a,N,p?.stats,u,W)),y.push(buildFunctionalTestSection(o,a,p?.stats.functionalYield,u,W)),p&&B&&R&&L&&y.push(buildFindingsSectionWithFilter(p,B,E,R,L));let x=!0;for(const M of y)M&&(x||t.appendChild(dt()),x=!1,t.appendChild(M));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}export function renderLotSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{lotSummary:e,items:o,hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s=[1],ringCount:a=4,colorScheme:p,fallbackFormat:h,onFindingClick:g,activeFindingId:T=null,onWaferClick:N,findingsFilter:B,onFindingsFilterChange:E,onSaveText:R,dieListOptions:L}=i;t.appendChild(ut(`Lot Summary \u2014 ${e.stats.waferCount} wafer${e.stats.waferCount===1?"":"s"}`));const u=i.warnings??nt({lotStatsSummary:e});u.length&&t.appendChild(_(u,t.ownerDocument));const $=q("Summary report",()=>{J(yt({items:o.map((x,M)=>({label:x?.label??`W${M+1}`,wafer:x?.wafer,dies:x?.dies,statsSummary:x?.statsSummary})),hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s,ringCount:a}))}),k=[],C=[],r=[],m=new WeakMap;for(let x=0;x<o.length;x++){const M=o[x];if(!M){C.push([]);continue}M.wafer&&k.push(M.wafer);const V=M.dies??[],ht=M.label??`W${x+1}`;for(const gt of V)m.set(gt,ht);C.push(V),r.push(...V)}const D=L?.enabled??!0?q("View die list",()=>{r.length&&mt(t,r,c,`Die list \u2014 ${r.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,et(o.filter(x=>!!x).map(x=>({metadata:x.wafer?.metadata}))),o.find(x=>x?.metadataFields?.length)?.metadataFields,L,R,{label:"Wafer",get:x=>m.get(x)})}):null,y=ft($,D);y&&t.appendChild(y);const b=r.some(x=>x.hbin!=null),S=r.some(x=>x.sbin!=null),v=o.map(x=>x?.statsSummary).filter(x=>!!x),F=[buildLotOverviewSection(e),buildMetadataInfoSection(o.filter(x=>x!==null).map(x=>({metadata:x.wafer?.metadata}))),buildPerWaferYieldSection(e,o,N),b?buildLotBinSection(r,d,"hard",p):S?buildLotBinSection(r,f,"soft",p):null,buildLotRingSection(C,k,a,s),buildLotQuadrantSection(C,k,a,s),c?.length?buildLotTestSection(r,c,h,v,R):null,c?.length?buildLotFunctionalSection(r,c,v,R):null];g&&B&&E&&F.push(buildFindingsSectionWithFilter(e,g,T,B,E));let W=!0;for(const x of F)x&&(W||t.appendChild(dt()),W=!1,t.appendChild(x));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}
1
+ import{isParametricTest as xt}from"../renderer/buildWaferMap.js";import{buildRingRegions as K,buildQuadrantRegions as Z,buildRegionYieldData as bt}from"../stats/regions.js";import{computeFunctionalYield as vt}from"../stats/analyzeWaferMap.js";import{openHtmlReport as J}from"../stats/renderFindingsReport.js";import{renderSummaryReportHtml as wt,renderLotSummaryReportHtml as yt}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as Ct}from"../stats/findingsNarrative.js";import{filterFindings as St}from"../stats/filterFindings.js";import{buildFacetTable as kt,prettyKey as tt}from"../stats/facets.js";import{commonMetadata as et}from"../stats/facets.js";import{resolveMetadataColumns as Bt}from"../stats/metadataColumns.js";import{getColorScheme as $t}from"../renderer/colorSchemes.js";import{buildWarningsBanner as _,collectWarnings as nt}from"./warnings.js";export{_ as buildWarningsBanner};import{fmt as it,fmtAggregationMethod as Lt,plainBinTerms as P}from"../renderer/fmt.js";import{getUniqueTestNumbers as Dt}from"../renderer/buildView.js";import{quantile as Q}from"../stats/math.js";import{makeLabeledSelect as ot}from"./charts/chartShell.js";import{CLR as v,sevColor as G,openModal as at,saveTextFile as rt}from"./toolbar.js";import{buildDieListSection as Rt}from"./dieList.js";import{medianOfSorted as Ft}from"../core/utils.js";import{metadataDisplayValue as Tt}from"../core/metadata.js";const Et=v.panelBg,Y=`1px solid ${v.menuBorder}`,Nt="12px",I=v.label,z=v.value,st="10px";function l(t,i,n,e=document){const o=e.createElement(t);return i&&Object.assign(o.style,i),n!==void 0&&(o.textContent=n),o}function H(t){return l("div",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,marginBottom:"6px"},t)}function lt(t,i=!0,n){const e=l("div"),o=document.createElement("button");o.type="button",Object.assign(o.style,{display:"flex",alignItems:"center",gap:"4px",width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const d=l("span",{fontSize:"9px",color:I,transition:"transform 0.15s",transform:i?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:"1",marginRight:"1px"},"\u25B6"),f=l("span",{fontSize:st,fontWeight:"700",letterSpacing:"0.06em",textTransform:"uppercase",color:I,flex:"1"},t);if(o.setAttribute("aria-expanded",i?"true":"false"),o.appendChild(d),o.appendChild(f),n){const a=l("span",{fontSize:"9px",fontWeight:"700",background:v.warnBg,color:v.warnText,borderRadius:"10px",padding:"1px 5px"},n);o.appendChild(a)}const c=l("div");c.style.display=i?"block":"none";let s=i;return o.addEventListener("click",()=>{s=!s,c.style.display=s?"block":"none",d.style.transform=s?"rotate(90deg)":"rotate(0deg)",o.setAttribute("aria-expanded",s?"true":"false")}),e.appendChild(o),e.appendChild(c),{outer:e,content:c}}function dt(){return l("div",{height:"1px",background:v.separator,margin:`${Nt} 0`,flexShrink:"0"})}function U(t,i,n=v.barFill,e,o,d){const f=l("div",{marginBottom:"5px"}),c=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",color:z,marginBottom:"2px"}),s=l("span",{},t),a=l("span",{fontWeight:"600"},`${i.toFixed(1)}%`);c.appendChild(s),c.appendChild(a);const p=e!==void 0?e:Math.min(100,Math.max(0,i)),h=d?v.barFillMuted:n,g=l("div",{position:"relative",height:"9px",background:v.bgActive,borderRadius:"4px",overflow:"hidden"}),T=l("div",{height:"100%",width:`${p}%`,background:h,borderRadius:"4px",transition:"width 0.3s ease"});if(g.appendChild(T),o!==void 0){const N=l("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"1px",background:v.infoText,opacity:"0.5"});g.appendChild(N)}return f.appendChild(c),f.appendChild(g),f}function O(t,i,n){const e=l("div",{background:v.menuBg,border:Y,borderRadius:"6px",padding:"8px 10px",textAlign:"center",flex:"1"}),o=l("div",{fontSize:"20px",fontWeight:"700",color:z,lineHeight:"1.2"},t),d=l("div",{fontSize:"10px",color:I,marginTop:"2px"},i);return e.appendChild(o),e.appendChild(d),n&&e.appendChild(l("div",{fontSize:"9px",color:I,opacity:"0.85"},n)),e}function Mt(t,i){const n=l("div",{display:"flex",justifyContent:"space-between",fontSize:"11px",gap:"8px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},t),o=l("span",{color:z,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}function Wt(t,i){const n=l("div",{display:"flex",fontSize:"11px",gap:"6px",marginBottom:"3px"}),e=l("span",{color:I,flexShrink:"0"},`${t}:`),o=l("span",{color:z,fontWeight:"500",wordBreak:"break-all"},i);return n.appendChild(e),n.appendChild(o),n}export function metadataEntries(t){const i=[];for(const[n,e]of Object.entries(t)){const o=Tt(e);o!==void 0&&i.push([n,o])}return i}export function buildFacetSummaryChips(t,i=3){if(!t.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 10px",fontSize:"11px"});for(const e of t){const o=l("span",{whiteSpace:"nowrap"}),d=l("span",{color:I},`${tt(e.key)}: `);o.appendChild(d);const f=e.values.slice(0,i),c=e.values.length-f.length;let s=f.map(a=>a.value).join(", ");c>0&&(s+=` +${c} more`),o.appendChild(document.createTextNode(s)),n.appendChild(o)}return n}export function buildMetadataStripRow(t,i,n){const e=kt(t,n),o=buildFacetSummaryChips(e);if(!o&&!i)return null;const d=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(i){const f=l("span",{fontWeight:"500",whiteSpace:"nowrap"},i.aggrMethod?`${i.lotSize} wafers stacked \xB7 ${i.aggrMethod}`:`${i.lotSize} wafers stacked`);d.appendChild(f)}return o&&d.appendChild(o),d}const It={display:"flex",flexDirection:"column",gap:"6px",background:v.menuBg,border:`1px solid ${v.menuBorder}`,borderRadius:"6px",padding:"6px 10px",boxShadow:"0 1px 4px rgba(0,0,0,0.10)",fontSize:"12px",lineHeight:"1",boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(t,i,n){const e=buildMetadataStripRow(t,i,n);if(!e)return null;const o=l("div",It);return o.appendChild(e),o}export function buildCompactMetadataRows(t){const i=metadataEntries(t);if(!i.length)return null;const n=l("div");for(const[e,o]of i)n.appendChild(Wt(tt(e),o));return n}export function buildMetadataInfoSection(t,i){const n=buildMetadataStripRow(t,i,{facetableOnly:t.length>1});if(!n)return null;const e=l("div");return e.appendChild(H("Wafer Info")),e.appendChild(n),e}export function buildYieldSection(t,i,n=[1]){const e=l("div");e.appendChild(H("Summary"));const o=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});if(o.appendChild(O(String(t.totalDies),"Total dies")),t.partialDies>0&&o.appendChild(O(String(t.partialDies),"Partial")),t.yieldPercent!==null){const d=n.length===1?`bin ${n[0]}`:`bins ${n.join(", ")}`;o.appendChild(O(`${t.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${d}`))}return e.appendChild(o),t.edgeExcludedDies>0&&e.appendChild(Mt("Edge excluded (outer zone)",String(t.edgeExcludedDies))),e}export function buildBinSection(t,i,n,e,o){const d=new Map;if(o)for(const[p,h]of Object.entries(o))d.set(Number(p),h);else for(const p of t){if(p.partial||p.edgeExcluded)continue;const h=n==="hard"?p.hbin:p.sbin;h!=null&&d.set(h,(d.get(h)??0)+1)}if(!d.size)return null;const f=[...d.values()].reduce((p,h)=>p+h,0),c=i?new Map(i.map(p=>[p.bin,p])):null,s=[...d.entries()].sort((p,h)=>p[0]-h[0]),a=l("div");a.appendChild(H(n==="hard"?"Hard Bin Breakdown":"Soft Bin Breakdown"));for(const[p,h]of s){const g=c?.get(p),T=g?.name?`Bin ${p} \xB7 ${g.name}`:`Bin ${p}`,N=h/f*100,B=$t(e),E=(e==="custom"?g?.color:void 0)??B.forBin(p);a.appendChild(U(`${T} (${h})`,N,E))}return a}export function buildLotBinSection(t,i,n,e){return buildBinSection(t,i,n,e)}function j(t,i,n,e,o,d){const f=bt(t,i,n,e,o);if(!f.length)return null;const c=l("div");c.appendChild(H(d));for(const{label:s,n:a,yieldPercent:p}of f)c.appendChild(U(`${s} (N=${a})`,p));return c}export function buildRingSection(t,i,n,e){return j([t],[i],n,e,K,"Ring Yield")}export function buildQuadrantSection(t,i,n,e){return j([t],[i],n,e,Z,"Quadrant Yield")}export function buildLotRingSection(t,i,n,e){return j(t,i,n,e,K,"Ring Yield")}export function buildLotQuadrantSection(t,i,n,e){return j(t,i,n,e,Z,"Quadrant Yield")}export function buildLotOverviewSection(t){const i=l("div");i.appendChild(H("Lot Summary"));const n=l("div",{display:"flex",gap:"6px",marginBottom:"8px"});n.appendChild(O(String(t.stats.waferCount),"Wafers"));const e=t.perWafer.map(o=>o.summary.stats.yieldPercent).filter(o=>o!==null);if(e.length){const o=e.reduce((d,f)=>d+f,0)/e.length;n.appendChild(O(`${o.toFixed(1)}%`,"Mean wafer yield"))}return i.appendChild(n),i}export function buildPerWaferYieldSection(t,i,n){const e=t.perWafer.map(a=>({waferIndex:a.waferIndex,label:(i[a.waferIndex]?.label??`W${a.waferIndex+1}`).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:a.summary.stats.yieldPercent})).filter(a=>a.yieldPct!==null);if(!e.length)return null;const o=Math.min(...e.map(a=>a.yieldPct)),d=Math.max(...e.map(a=>a.yieldPct)),f=o===d?"":` (${o.toFixed(1)}\u2013${d.toFixed(1)}%)`,c=Ft([...e.map(a=>a.yieldPct)].sort((a,p)=>a-p)),s=l("div");s.appendChild(H("Wafer Yield"+f));for(const{waferIndex:a,label:p,yieldPct:h}of e){const g=U(p,h,void 0,void 0,c,h<c);n&&(g.style.cursor="pointer",g.style.borderRadius="4px",g.style.padding="2px 3px",g.style.marginLeft="-3px",g.style.marginRight="-3px",g.setAttribute("role","button"),g.setAttribute("aria-label",`${p}, ${h.toFixed(1)}% yield \u2014 view wafer`),g.tabIndex=0,g.addEventListener("mouseenter",()=>{g.style.background=v.bgHover}),g.addEventListener("mouseleave",()=>{g.style.background=""}),g.addEventListener("focus",()=>{g.style.background=v.bgHover}),g.addEventListener("blur",()=>{g.style.background=""}),g.addEventListener("click",()=>n(a)),g.addEventListener("keydown",T=>{(T.key==="Enter"||T.key===" ")&&(T.preventDefault(),n(a))})),s.appendChild(g)}return s}function zt(t){const i=[...t].sort((o,d)=>o-d),n=t.reduce((o,d)=>o+d,0)/t.length,e=t.reduce((o,d)=>o+(d-n)**2,0)/t.length;return{min:i[0],max:i[i.length-1],mean:n,count:t.length,stddev:Math.sqrt(e),median:Q(i,.5),q1:Q(i,.25),q3:Q(i,.75)}}function pt(t,i){if(!t)return[];const n=t.waferMetadata??(t.perWaferMetadata?et(t.perWaferMetadata.map(e=>({metadata:e}))):void 0);return!n||!Object.keys(n).length?[]:Bt({waferMetadata:n,waferPlacement:"csv",reservedLabels:i}).columns}export function csvField(t){return/[",\n]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}export function buildTestSection(t,i,n,e,o,d){const f=t.filter(r=>!r.partial&&!r.edgeExcluded),c=new Map((e?.perTestStats??[]).map(r=>[r.testNumber,r])),s=new Map((e?.testSpecYield??[]).map(r=>[r.testNumber,r]));let a;if(i?.length?a=i.filter(xt).map(r=>({testNumber:r.testNumber,name:r.name,unit:r.unit,limitLow:r.limitLow,limitHigh:r.limitHigh})):a=Dt(f).map(m=>({testNumber:m,name:`Test ${m}`})),!a.length)return null;const p=a.filter(r=>f.some(m=>{const D=m.testValues?.[r.testNumber];return D!==void 0&&isFinite(D)}));if(!p.length)return null;const h=p.some(r=>r.limitLow!==void 0||r.limitHigh!==void 0),g=[];for(const r of p){const m=c.get(r.testNumber),D=m&&m.stddev!==void 0&&m.median!==void 0&&m.q1!==void 0&&m.q3!==void 0;let y;if(D){const b=m;y={testNumber:r.testNumber,min:b.min,max:b.max,mean:b.mean,count:b.count,stddev:b.stddev,median:b.median,q1:b.q1,q3:b.q3}}else{const b=f.map(F=>F.testValues?.[r.testNumber]).filter(F=>F!==void 0&&isFinite(F));if(!b.length)continue;y={testNumber:r.testNumber,...zt(b)}}let x=null,S=0;if(r.limitLow!==void 0||r.limitHigh!==void 0){const b=s.get(r.testNumber);if(b)({yieldPercent:x,totalDies:S}=b);else{const F=f.map(w=>w.testValues?.[r.testNumber]).filter(w=>w!==void 0&&isFinite(w)),W=F.filter(w=>r.limitLow!==void 0&&w<r.limitLow||r.limitHigh!==void 0&&w>r.limitHigh).length;S=F.length,x=F.length>0?(F.length-W)/F.length*100:null}}g.push({entry:r,stats:y,specYieldPct:x,specN:S})}if(!g.length)return null;const T=l("div"),N=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),B=H(d?.populationLabel?`Test Values (${g.length}) \u2014 ${d.populationLabel}`:`Test Values (${g.length})`);B.style.marginBottom="0",N.appendChild(B);const E=document.createElement("button");E.type="button",E.textContent="Export CSV",Object.assign(E.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"}),E.addEventListener("click",()=>{const r=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&r.push("LSL","USL","Spec Yield %","Spec Yield N");const m=pt(d,r),y=[[...m.map(S=>S.label),...r].map(csvField).join(",")],x=S=>it(S,void 0,"engineering");for(const{entry:S,stats:b,specYieldPct:F,specN:W}of g){const w=[...m.map(M=>M.constant??""),S.name,S.unit??"",String(b.count),x(b.min),x(b.q1),x(b.median),x(b.mean),x(b.q3),x(b.max),x(b.stddev)];h&&w.push(S.limitLow!==void 0?x(S.limitLow):"",S.limitHigh!==void 0?x(S.limitHigh):"",F!==null?F.toFixed(1):"",S.limitLow!==void 0||S.limitHigh!==void 0?String(W):""),y.push(w.map(csvField).join(","))}rt(y.join(`
2
+ `),"test-values.csv","text/csv",o)}),N.appendChild(E),T.appendChild(N);const R=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),L=document.createElement("thead"),u=document.createElement("tr"),$=["Test","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];h&&$.push("LSL","USL","Spec yield");for(const r of $){const m=l("th",{textAlign:r==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${v.menuBorder}`,whiteSpace:"nowrap"},r);u.appendChild(m)}L.appendChild(u),R.appendChild(L);const k=document.createElement("tbody");for(const{entry:r,stats:m,specYieldPct:D,specN:y}of g){const x=F=>it(F,r.unit,n),S=document.createElement("tr"),b=(F,W="right")=>{const w=l("td",{textAlign:W,padding:"4px 8px",borderBottom:`1px solid ${v.menuBorder}`,color:z,whiteSpace:"nowrap"},F);S.appendChild(w)};b(r.name,"left"),b(`${m.count}`),b(x(m.min)),b(x(m.q1)),b(x(m.median)),b(x(m.mean)),b(x(m.q3)),b(x(m.max)),b(x(m.stddev)),h&&(b(r.limitLow!==void 0?x(r.limitLow):"\u2014"),b(r.limitHigh!==void 0?x(r.limitHigh):"\u2014"),b(D!==null?`${D.toFixed(1)}% (N=${y})`:"\u2014")),k.appendChild(S)}R.appendChild(k);const C=l("div",{overflowX:"auto"});return C.appendChild(R),T.appendChild(C),T}export function buildFunctionalTestSection(t,i,n,e,o){const d=n??vt(t,i);if(!d?.length)return null;const f=l("div"),c=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"6px"}),s=H(o?.populationLabel?`Functional Tests (${d.length}) \u2014 ${o.populationLabel}`:`Functional Tests (${d.length})`);s.style.marginBottom="0",c.appendChild(s);const a=document.createElement("button");a.type="button",a.textContent="Export CSV",Object.assign(a.style,{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"}),a.addEventListener("click",()=>{const B=["Test","N","Pass","Fail","Pass Rate %"],E=pt(o,B),R=[[...E.map(L=>L.label),...B].map(csvField).join(",")];for(const L of d)R.push([...E.map(u=>u.constant??""),L.label,String(L.totalDies),String(L.passDies),String(L.failDies),L.passRatePercent!==null?L.passRatePercent.toFixed(1):""].map(csvField).join(","));rt(R.join(`
3
+ `),"functional-tests.csv","text/csv",e)}),c.appendChild(a),f.appendChild(c);const p=l("table",{width:"100%",borderCollapse:"collapse",fontSize:"11px"}),h=document.createElement("thead"),g=document.createElement("tr");for(const B of["Test","N","Pass","Fail","Pass rate"])g.appendChild(l("th",{textAlign:B==="Test"?"left":"right",fontWeight:"700",fontSize:"10px",letterSpacing:"0.03em",textTransform:"uppercase",color:I,padding:"3px 8px 5px",borderBottom:`1px solid ${v.menuBorder}`,whiteSpace:"nowrap"},B));h.appendChild(g),p.appendChild(h);const T=document.createElement("tbody");for(const B of d){const E=document.createElement("tr"),R=(L,u="right")=>{E.appendChild(l("td",{textAlign:u,padding:"4px 8px",borderBottom:`1px solid ${v.menuBorder}`,color:z,whiteSpace:"nowrap"},L))};R(B.label,"left"),R(String(B.totalDies)),R(String(B.passDies)),R(String(B.failDies)),R(B.passRatePercent!==null?`${B.passRatePercent.toFixed(1)}% (N=${B.totalDies})`:"\u2014"),T.appendChild(E)}p.appendChild(T);const N=l("div",{overflowX:"auto"});return N.appendChild(p),f.appendChild(N),f}export function buildLotFunctionalSection(t,i,n,e){const o=n?.length?{perWaferMetadata:n.map(d=>d.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;if(n?.length&&n.every(d=>d.stats.functionalYield!==void 0)){const d=new Map;for(const c of n)for(const s of c.stats.functionalYield??[]){const a=d.get(s.testNumber)??{label:s.label,passDies:0,failDies:0,totalDies:0};a.passDies+=s.passDies,a.failDies+=s.failDies,a.totalDies+=s.totalDies,d.set(s.testNumber,a)}const f=[...d.entries()].map(([c,s])=>({testNumber:c,...s,passRatePercent:s.totalDies>0?s.passDies/s.totalDies*100:null}));if(f.length)return buildFunctionalTestSection(t,i,f,e,o)}return buildFunctionalTestSection(t,i,void 0,e,o)}const A={unusual:0,notable:1,info:2};function X(t){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:G(t),flexShrink:"0"})}function ct(t,i){let n=t.summary;return i&&(n.startsWith(`${i} has `)?n=n.slice(i.length+5):n.startsWith(`${i} `)&&(n=n.slice(i.length+1))),n=P(n),n.length?n[0].toUpperCase()+n.slice(1):n}export function buildFindingsSection(t,i,n,e,o=!1){if(!t.length)return null;const d=t.some(u=>u.severity==="unusual"||u.severity==="notable"),f=d?t.filter(u=>u.severity!=="info").length.toString():void 0,{outer:c,content:s}=o?(()=>{const u=l("div");return{outer:u,content:u}})():lt(`Findings (${t.length})`,d,f);function a(u){return u.reduce(($,k)=>A[k.severity]<A[$]?k.severity:$,"info")}function p(u){const $=new Map;for(const C of u){const r=`${C.comparison.family}\0${C.comparison.left}`,m=$.get(r)??[];m.push(C),$.set(r,m)}const k=[...$.entries()].map(([C,r])=>{const m=[...r].sort((D,y)=>A[D.severity]-A[y.severity]);return{key:C,findings:m,worst:a(m)}});return k.sort((C,r)=>A[C.worst]-A[r.worst]),k}function h(u,$){const C={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[u]??u;return $.toLowerCase().startsWith(C.toLowerCase())?$:`${C}: ${$}`}const g=t.filter(u=>u.comparison.family==="spatial-pattern"),T=new Set([...g.flatMap(u=>u.relatedIds??[]),...t.flatMap(u=>u.absorbedIds??[])]),N=t.filter(u=>u.comparison.family!=="spatial-pattern"&&!T.has(u.id)),B=p(N);function E(u,$=!1,k){const C=e===u.id,r=document.createElement("button");return r.type="button",r.dataset.wmapFinding=u.id,r.textContent=ct(u,k),r.title=u.summary,r.setAttribute("aria-current",C?"true":"false"),Object.assign(r.style,{border:`1px solid ${v.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:C?v.bgActive:v.menuBg,borderRadius:"6px",padding:$?"6px 10px":"8px 10px",textAlign:"left",fontSize:$?"10px":"11px",fontWeight:C?"600":"400",color:v.iconHover,cursor:"pointer",width:"100%",marginBottom:"4px"}),r.addEventListener("click",()=>n(u,r)),r}const R=P(Ct(t)??"");if(R){const u=l("div",{background:v.bgActive,borderRadius:"6px",padding:"8px 10px",marginBottom:"8px",display:"flex",gap:"8px",alignItems:"flex-start"}),$=l("span",{flex:"1",fontSize:"12px",lineHeight:"1.5",color:v.iconHover},R);u.appendChild($);const k=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:"10px",color:v.icon,cursor:"pointer",padding:"0",lineHeight:"1.5",whiteSpace:"nowrap"},"Detail \u25B8");k.type="button",k.addEventListener("click",()=>{const C=at({title:"Findings Summary",onClose:()=>{},anchor:k}),r=l("p",{fontSize:"16px",lineHeight:"1.6",color:v.iconHover,padding:"20px 24px 16px",margin:"0",borderBottom:`1px solid ${v.menuBorder}`,flexShrink:"0"},R);C.contentWrap.appendChild(r);const m=l("div",{overflowY:"auto",padding:"16px 24px",flex:"1"}),D=(y,x)=>{const S=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:"13px",fontWeight:"600",color:z,marginTop:"10px",marginBottom:"4px"});return S.appendChild(X(y)),S.appendChild(l("span",{},x)),S};for(const y of g){m.appendChild(D(y.severity,y.comparison.left)),m.appendChild(l("div",{fontSize:"13px",color:v.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},P(y.summary)));const x=t.filter(S=>y.relatedIds?.includes(S.id));for(const S of x)m.appendChild(l("div",{fontSize:"12px",color:v.icon,padding:"2px 0 2px 23px",marginBottom:"2px"},P(S.summary)))}for(const y of B){const[x,S]=y.key.split("\0");m.appendChild(D(y.worst,h(x,S)));for(const b of y.findings)m.appendChild(l("div",{fontSize:"13px",color:v.iconHover,padding:"3px 0 3px 15px",marginBottom:"2px"},ct(b,S)))}C.contentWrap.appendChild(m),Object.assign(C.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),u.appendChild(k),s.appendChild(u)}let L=!0;for(const u of g){L||s.appendChild(l("div",{height:"1px",background:v.separator,margin:"4px 0"})),L=!1;const $=t.filter(D=>u.relatedIds?.includes(D.id)),k=$.length>0,C=l("div",{position:"relative",marginBottom:k?"2px":"4px"}),r=e===u.id,m=document.createElement("button");if(m.type="button",m.dataset.wmapFinding=u.id,Object.assign(m.style,{border:`1px solid ${v.menuBorder}`,borderLeft:`3px solid ${G(u.severity)}`,background:r?v.bgActive:v.menuBg,borderRadius:"6px",padding:"8px 32px 8px 10px",textAlign:"left",fontSize:"11px",fontWeight:r?"600":"500",color:v.iconHover,cursor:"pointer",width:"100%"}),m.textContent=P(u.summary),m.title=u.summary,m.setAttribute("aria-current",r?"true":"false"),m.addEventListener("click",()=>n(u,m)),C.appendChild(m),k){const D=l("div",{display:"none",paddingLeft:"12px",marginBottom:"4px"});for(const S of $)D.appendChild(E(S,!0));C.appendChild(D);let y=!1;const x=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:"10px",color:v.icon,cursor:"pointer",padding:"2px 4px",lineHeight:"1"},"\u25B8");x.type="button",x.title="Show supporting findings",x.setAttribute("aria-label","Show supporting findings"),x.setAttribute("aria-expanded","false"),x.addEventListener("click",S=>{S.stopPropagation(),y=!y,D.style.display=y?"block":"none",x.textContent=y?"\u25BE":"\u25B8";const b=y?"Hide supporting findings":"Show supporting findings";x.title=b,x.setAttribute("aria-label",b),x.setAttribute("aria-expanded",String(y))}),C.appendChild(x)}s.appendChild(C)}for(const u of B){L||s.appendChild(l("div",{height:"1px",background:v.separator,margin:"4px 0"})),L=!1;const[$,k]=u.key.split("\0"),C=l("div",{display:"flex",alignItems:"center",gap:"6px",fontSize:"11px",fontWeight:"600",color:z,margin:"2px 0 4px"});C.appendChild(X(u.worst)),C.appendChild(l("span",{},h($,k))),s.appendChild(C);for(const r of u.findings)s.appendChild(E(r,!1,k))}return c}const Ht=[{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"}],At=[{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"}],Pt=["unusual","notable","info"],Yt={unusual:"Unusual",notable:"Notable",info:"Info"};function Ot(t,i,n){const e=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"10px",marginBottom:"10px",paddingBottom:"10px",borderBottom:`1px solid ${v.separator}`}),o={unusual:0,notable:0,info:0};for(const s of t)o[s.severity]++;const d=Pt.filter(s=>o[s]>0),f=new Set(i.severity===void 0?d:Array.isArray(i.severity)?i.severity:[i.severity]),c=l("div",{display:"flex",gap:"4px",flexWrap:"wrap"});for(const s of d){const a=document.createElement("button");a.type="button";const p=()=>{const h=f.has(s);a.setAttribute("aria-pressed",h?"true":"false"),Object.assign(a.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${v.menuBorder}`,borderRadius:"10px",background:h?v.bgActive:"none",opacity:h?"1":"0.5",color:v.text,fontSize:"11px",padding:"2px 8px",cursor:"pointer"})};a.appendChild(X(s)),a.appendChild(l("span",{},`${Yt[s]} ${o[s]}`)),a.title=f.has(s)?"Click to hide these findings":"Click to show these findings",p(),a.addEventListener("click",()=>{f.has(s)?f.delete(s):f.add(s),i.severity=f.size===d.length?void 0:[...f],n()}),c.appendChild(a)}return e.appendChild(c),e.appendChild(ot("Kind:",Ht,i.kind??"",s=>{i.kind=s||void 0,n()},{maxWidth:"130px"})),e.appendChild(ot("Region:",At,i.family??"",s=>{i.family=s||void 0,n()},{maxWidth:"150px"})),e}export function buildFindingsSectionWithFilter(t,i,n,e,o){if(!t.findings.length)return null;const d=t.findings.some(h=>h.severity==="unusual"||h.severity==="notable"),f=d?t.findings.filter(h=>h.severity!=="info").length.toString():void 0,{outer:c,content:s}=lt(`Findings (${t.findings.length})`,d,f);s.appendChild(Ot(t.findings,e,o));const a=St(t,e);if(!a.length)return s.appendChild(l("div",{color:I,fontSize:"11px",textAlign:"center",padding:"16px 8px"},"No findings match the current filter.")),c;const p=buildFindingsSection(a,t,i,n,!0);return p&&s.appendChild(p),c}export function buildLotTestSection(t,i,n,e,o){const d=e?.length?{perWaferMetadata:e.map(c=>c.wafer??{}),populationLabel:`${e.length} wafer${e.length===1?"":"s"} pooled`}:void 0;let f;if(e?.length&&e.every(c=>c.stats.perTestStats!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.perTestStats??[]){const p=c.get(a.testNumber);p?(p.n+=a.count,p.sum+=a.mean*a.count,p.min=Math.min(p.min,a.min),p.max=Math.max(p.max,a.max)):c.set(a.testNumber,{n:a.count,sum:a.mean*a.count,min:a.min,max:a.max})}f={perTestStats:[...c.entries()].map(([s,a])=>({testNumber:s,count:a.n,min:a.min,max:a.max,mean:a.sum/a.n}))}}if(e?.length&&e.every(c=>c.stats.testSpecYield!==void 0)){const c=new Map;for(const s of e)for(const a of s.stats.testSpecYield??[]){const p=c.get(a.testNumber);p?(p.passDies+=a.passDies,p.totalDies+=a.totalDies):c.set(a.testNumber,{passDies:a.passDies,totalDies:a.totalDies})}f={...f,testSpecYield:[...c.entries()].map(([s,a])=>({testNumber:s,totalDies:a.totalDies,yieldPercent:a.totalDies>0?a.passDies/a.totalDies*100:null}))}}return buildTestSection(t,i,n,f,o,d)}export function createSummaryPanelEl(t,i=document){const n=t==="top"||t==="bottom",e=l("div",{background:Et,border:Y,borderRadius:"6px",padding:"12px",overflowY:n?"hidden":"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:"system-ui, sans-serif",fontSize:"12px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)"},void 0,i);return n?(e.style.height="180px",e.style.width="100%"):(e.style.width="260px",e.style.maxHeight="100%"),e}export function wrapWithSummaryPanel(t,i,n){const e=n==="top"||n==="bottom",o=l("div",{display:"flex",flexDirection:e?"column":"row",gap:"8px",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",n==="right"||n==="bottom"?(o.appendChild(t),o.appendChild(i)):(o.appendChild(i),o.appendChild(t)),o}function ut(t){return l("div",{fontSize:"13px",fontWeight:"700",color:z,marginBottom:"10px"},t)}function q(t,i){const n=l("button",{background:"none",border:Y,borderRadius:"4px",cursor:"pointer",fontSize:"10px",color:v.iconHover,padding:"2px 7px"},t);return n.type="button",n.addEventListener("click",i),n}function ft(...t){const i=t.filter(e=>!!e);if(!i.length)return null;const n=l("div",{display:"flex",flexWrap:"wrap",gap:"6px",marginBottom:"10px"});for(const e of i)n.appendChild(e);return n}function mt(t,i,n,e,o,d,f,c,s){const a=t.ownerDocument,p=at({title:"Die list",onClose:()=>{},anchor:t,ownerDocument:a});p.contentWrap.style.padding="14px 16px";const h=Rt(i,n,{...f,title:e,onSaveText:c,waferMetadata:o,metadataFields:d,extraColumn:s,ownerDocument:a});h&&p.contentWrap.appendChild(h)}export function renderWaferSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h=[1],ringCount:g=4,colorScheme:T,fallbackFormat:N,onFindingClick:B,activeFindingId:E=null,findingsFilter:R,onFindingsFilterChange:L,onSaveText:u,metadataFields:$,dieListOptions:k}=i;t.appendChild(ut("Wafer Summary"));const C=i.warnings??nt({statsSummary:p});C.length&&t.appendChild(_(C,t.ownerDocument));const r=d&&f?q("Summary report",()=>{J(wt({wafer:e,dies:o,yieldSummary:d,dataCoverage:f,hbinDefs:c,sbinDefs:s,testDefs:a,statsSummary:p,passBins:h,ringCount:g}))}):null,m=(k?.enabled??!0)&&o.length?q("View die list",()=>{mt(t,o,a,`Die list \u2014 ${o.length} dies`,e.metadata,$,k,u)}):null,D=ft(r,m);D&&t.appendChild(D);const y=[],x=p?.stats.isLotStack?p.stats:void 0,S=x?.lotSize!==void 0?{lotSize:x.lotSize,aggrMethod:Lt(x.aggregationMethod)}:void 0;y.push(buildMetadataInfoSection([{metadata:e.metadata??void 0}],S)),d&&f&&y.push(buildYieldSection(d,f,h));const b=o.some(M=>M.hbin!=null),F=o.some(M=>M.sbin!=null);b?y.push(buildBinSection(o,c,"hard",T,p?.stats.hardBinCounts)):F&&y.push(buildBinSection(o,s,"soft",T,p?.stats.softBinCounts)),y.push(buildRingSection(o,e,g,h)),y.push(buildQuadrantSection(o,e,g,h));const W=e.metadata?{waferMetadata:e.metadata}:void 0;y.push(buildTestSection(o,a,N,p?.stats,u,W)),y.push(buildFunctionalTestSection(o,a,p?.stats.functionalYield,u,W)),p&&B&&R&&L&&y.push(buildFindingsSectionWithFilter(p,B,E,R,L));let w=!0;for(const M of y)M&&(w||t.appendChild(dt()),w=!1,t.appendChild(M));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}export function renderLotSummaryContent(t,i){const n=t.scrollTop;t.innerHTML="";const{lotSummary:e,items:o,hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s=[1],ringCount:a=4,colorScheme:p,fallbackFormat:h,onFindingClick:g,activeFindingId:T=null,onWaferClick:N,findingsFilter:B,onFindingsFilterChange:E,onSaveText:R,dieListOptions:L}=i;t.appendChild(ut(`Lot Summary \u2014 ${e.stats.waferCount} wafer${e.stats.waferCount===1?"":"s"}`));const u=i.warnings??nt({lotStatsSummary:e});u.length&&t.appendChild(_(u,t.ownerDocument));const $=q("Summary report",()=>{J(yt({items:o.map((w,M)=>({label:w?.label??`W${M+1}`,wafer:w?.wafer,dies:w?.dies,statsSummary:w?.statsSummary})),hbinDefs:d,sbinDefs:f,testDefs:c,passBins:s,ringCount:a}))}),k=[],C=[],r=[],m=new WeakMap;for(let w=0;w<o.length;w++){const M=o[w];if(!M){C.push([]);continue}M.wafer&&k.push(M.wafer);const V=M.dies??[],ht=M.label??`W${w+1}`;for(const gt of V)m.set(gt,ht);C.push(V),r.push(...V)}const D=L?.enabled??!0?q("View die list",()=>{r.length&&mt(t,r,c,`Die list \u2014 ${r.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,et(o.filter(w=>!!w).map(w=>({metadata:w.wafer?.metadata}))),o.find(w=>w?.metadataFields?.length)?.metadataFields,L,R,{label:"Wafer",get:w=>m.get(w)})}):null,y=ft($,D);y&&t.appendChild(y);const x=r.some(w=>w.hbin!=null),S=r.some(w=>w.sbin!=null),b=o.map(w=>w?.statsSummary).filter(w=>!!w),F=[buildLotOverviewSection(e),buildPerWaferYieldSection(e,o,N),x?buildLotBinSection(r,d,"hard",p):S?buildLotBinSection(r,f,"soft",p):null,buildLotRingSection(C,k,a,s),buildLotQuadrantSection(C,k,a,s),c?.length?buildLotTestSection(r,c,h,b,R):null,c?.length?buildLotFunctionalSection(r,c,b,R):null];g&&B&&E&&F.push(buildFindingsSectionWithFilter(e,g,T,B,E));let W=!0;for(const w of F)w&&(W||t.appendChild(dt()),W=!1,t.appendChild(w));t.appendChild(l("div",{height:"12px",flexShrink:"0"})),t.scrollTop=n}
@@ -5,6 +5,15 @@ export interface ToCanvasOptions {
5
5
  padding?: number;
6
6
  /** Draw a continuous colorbar (value modes) or bin legend (bin modes). Default true. */
7
7
  showColorbar?: boolean;
8
+ /**
9
+ * Draw a diagonal hatch on dies whose bin is not a pass bin (see
10
+ * `ViewRect.binFail`). Default false — opt in from the Colour scheme menu.
11
+ *
12
+ * Gives pass/fail a second channel that is not hue, so the map keeps working
13
+ * for a viewer with a colour-vision deficiency and when printed in
14
+ * greyscale. Composes with any colour scheme; it changes no colours itself.
15
+ */
16
+ markFailingDies?: boolean;
8
17
  /** Width in CSS pixels of the colorbar strip. Default 16. */
9
18
  colorbarWidth?: number;
10
19
  /** Canvas background colour. Default '#f5f5f5'. */
@@ -101,6 +110,8 @@ export declare const BIN_LEGEND_W = 110;
101
110
  export declare const BIN_LEGEND_W_COMPACT = 64;
102
111
  export declare const BIN_LEGEND_ADAPT_COMPACT = 280;
103
112
  export declare const BIN_LEGEND_ADAPT_FLOATING = 180;
113
+ export declare const BIN_LEGEND_MIN_CANVAS_W = 150;
114
+ export declare const BIN_LEGEND_MIN_CANVAS_H = 120;
104
115
  export declare function toCanvas(canvas: HTMLCanvasElement, view: View, options?: ToCanvasOptions): ToCanvasResult;
105
116
  export { fmt, fmtColorbarAxis } from '../renderer/fmt.js';
106
117
  //# sourceMappingURL=toCanvas.d.ts.map
@@ -1 +1 @@
1
- import{findTestDef as ue,buildMapTitle as pe}from"../renderer/buildView.js";import{affineInvert as Fe,affineVector as xe}from"../core/transforms.js";import{compareNatural as Oe}from"../core/utils.js";import{getColorScheme as ye}from"../renderer/colorSchemes.js";import{SPEC_PASS_FILL as Me,SPEC_FAIL_LOW as Ie,SPEC_FAIL_HIGH as be,contrastTextColor as Ne}from"../renderer/colorMap.js";import{fmt as Se,fmtColorbarAxis as Ee}from"../renderer/fmt.js";import{resolveCanvasTheme as Ye}from"./canvasTheme.js";function Te(h,e,F,p,c){h.moveTo(e,F+c*p),h.lineTo(e-p*.9,F-c*p*.6),h.lineTo(e+p*.9,F-c*p*.6),h.closePath()}const Xe=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),we=new Set(["hardBin","softBin","metadata"]),v="10px system-ui, sans-serif",He="600 12px system-ui, sans-serif",$t="11px system-ui, sans-serif",$e="600 11px system-ui, sans-serif",Gt=128,Ge="10px system-ui, sans-serif",ke=4,E=17,w=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180;const Ut=28,xt=5,Vt=8;export function toCanvas(h,e,F={}){const p=Ye(h.parentElement??h),{padding:c=16,showColorbar:U=!0,colorbarWidth:S=16,background:lt=p.background,legendPosition:gt="default",legendOffset:j,showAxes:mt=!1,diePitchMm:Tt,viewport:H,activeBin:Q,fallbackFormat:O,topClearance:Y=0,minRightReserve:kt,hbinDefs:Mt,sbinDefs:it,metadataFields:Lt,showTitle:tt=!0}=F,ut=U&&Xe.has(e.plotMode)&&e.passFailDisplay==="off",bt=U&&we.has(e.plotMode),pt=U&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),at=bt||pt,Rt=bt&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[a])=>o-a):[],At=bt&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Oe)].map(o=>[o,e.metadataCounts.get(o)??0]):[],J=[];if(pt&&e.passFailDisplay==="test"){const o=e.passFailCounts;J.push({key:-1,color:Me,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),J.push({key:-2,color:be,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(pt){const o=e.specCounts,a=ue(e.testDefs,e.activeTest);J.push({key:-1,color:Me,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),a?.limitHigh!==void 0&&J.push({key:-2,color:be,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),a?.limitLow!==void 0&&J.push({key:-3,color:Ie,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const yt=pt?J.length:e.plotMode==="metadata"?At.length:Rt.length,$=(h.ownerDocument.defaultView??window).devicePixelRatio??1,I=Math.floor(h.clientWidth||h.width),V=Math.floor(h.clientHeight||h.height);if(I<=0||V<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const K=gt!=="default"?gt:I<BIN_LEGEND_ADAPT_FLOATING?"floating":I<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",y=K==="default"||K==="compact",G=K==="left",ct=K==="bottom",Ct=K==="top",Pt=K==="floating",Wt=K==="compact"||K==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,oe=Math.floor((V-2*c)/E),ne=yt>oe?oe-1:yt,se=at&&ct?ne*E:0,zt=at&&Ct?ne*E:0,Kt=ut?S+28:at&&y?Wt:0,Jt=at&&G?Wt:0,Zt=mt?32:0,Bt=mt?36:0,Le=kt!=null?Math.max(Kt,kt):Kt,Re=I-2*c-Le-Bt-Jt,le=V-2*c-Zt-se-zt;h.width=Math.round(I*$),h.height=Math.round(V*$);const t=h.getContext("2d");t.scale($,$),t.fillStyle=lt,t.fillRect(0,0,I,V);const q=e.hoverPoints;if(!q.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const _t=e.rectangles[0],jt=_t?_t.width/2:0,Qt=_t?_t.height/2:0,Dt=e.dieBounds,ie=(Dt?.minX??0)-jt,Ae=(Dt?.maxX??0)+jt,Ce=(Dt?.minY??0)-Qt,ae=(Dt?.maxY??0)+Qt,ce=Ae-ie,re=ae-Ce;let et,ot,k;if(H)({originX:et,originY:ot,ppm:k}=H);else{const a=e.notchDir,l=a&&a.y>.1?13:0,r=a&&a.y<-.1?13:0,f=a&&a.x<-.1?13:0,d=a&&a.x>.1?13:0,b=Re-f-d,i=le-Y-l-r;k=Math.min(b/ce,i/re),et=c+Bt+Jt+f+(b-ce*k)/2-ie*k,ot=c+Y+zt+l+(i-re*k)/2+ae*k}const Ft=H?.snapDist??Math.max(jt,Qt,1)*1.5,Ot=et+e.waferCenter.x*k,Pe=ot-e.waferCenter.y*k,vt=e.waferRadius*k,rt=o=>{const a=Math.abs(o-Pe);return a>=vt?0:Math.sqrt(vt*vt-a*a)},ft=(o,a,l,r,f,d,b=He,i="#333")=>{if(!o)return;t.save(),t.fillStyle=i,t.font=b,t.textAlign=r,t.textBaseline=f;const x=r==="right"?a-d:d-a;let s=o;if(x>8&&t.measureText(s).width>x){for(;s.length>1&&t.measureText(s+"\u2026").width>x;)s=s.slice(0,-1);s=s+"\u2026"}x>8&&t.fillText(s,a,l),t.restore()};if(t.save(),t.setTransform(k*$,0,0,-k*$,et*$,ot*$),e.rectangles.length>0){const o=new Map;for(const l of e.rectangles){const r=String(l.fill);let f=o.get(r);f||(f=[],o.set(r,f)),f.push(l)}for(const[l,r]of o){t.beginPath();for(const f of r)t.rect(f.x-f.width/2,f.y-f.height/2,f.width,f.height);t.fillStyle=l,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(k*$),t.beginPath();for(const l of e.rectangles)t.rect(l.x-l.width/2,l.y-l.height/2,l.width,l.height);t.stroke();const a=e.rectangles.filter(l=>l.specMark);if(a.length>0){const l=new Map;for(const f of a){const d=Ne(String(f.fill)),b=`${f.specMark}|${d}`;let i=l.get(b);i||(i=[],l.set(b,i)),i.push(f)}const r=2.5/(k*$);t.lineJoin="round";for(const[f,d]of l){const[b,i]=f.split("|"),x=i==="#000000"?"#ffffff":"#000000",s=b==="failHigh"?1:-1,u=Math.min(d[0].width,d[0].height),X=Math.max(2.5/(k*$),u*.3);t.beginPath();for(const T of d)Te(t,T.x,T.y,X,s);t.strokeStyle=x,t.lineWidth=r,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const a of o.points){for(let l=0;l<a.length;l++)l===0?t.moveTo(a[l].x,a[l].y):t.lineTo(a[l].x,a[l].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*$),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(k*$),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(k*$),t.stroke())}if(t.restore(),e.notchDir){const o=et+e.waferCenter.x*k,a=ot-e.waferCenter.y*k,l=e.notchDir.x,r=-e.notchDir.y,f=e.waferRadius*k,d=4,b=9,i=5,x=o+l*(f+d),s=a+r*(f+d),u=x+l*b,X=s+r*b,T={x:-r,y:l},B=c+Bt+Jt,nt=I-c-Kt,z=c+Y+zt,dt=V-c-se-Zt;t.save(),t.beginPath(),t.rect(B,z,nt-B,dt-z),t.clip(),t.beginPath(),t.moveTo(x,s),t.lineTo(u+T.x*i,X+T.y*i),t.lineTo(u-T.x*i,X-T.y*i),t.closePath(),t.fillStyle=p.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let fe=0;if(e.rectangles.length>0){let o=1;for(const d of e.texts)d.role!=="indicator"&&d.text.length>o&&(o=d.text.length);const a=e.rectangles[0].width*k,l=e.rectangles[0].height*k,r=Math.min(a,l),f=a/o;fe=Math.max(8,Math.min(64,Math.round(Math.min(r*.55,f*1.8))))}for(const o of e.texts){const a=et+o.x*k,l=ot-o.y*k;t.font=`${o.role==="indicator"?o.fontSize:fe}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,a,l)}if(t.restore(),mt&&Ue(t,I,V,et,ot,k,c,Zt,Bt,Tt,e.gridToScreen,e.rotation,p),ut){const o=ye(e.colorScheme),a=20,l=le-Y,r=Math.round(l*.75),f=c+Y+Math.round((l-r)/2),d=I-c-S-a,[b,i]=e.valueRange,x=i-b,s=e.plotMode==="stackedSoftBins"?it:Mt,{primary:u,secondary:X}=tt?pe(e,O,s):{primary:"",secondary:""};if(tt){const n=Math.max(f-6,c+Y+11),g=Ot+Math.max(rt(n),rt(n-12))+8;ft(u,I-c,n,"right","bottom",g)}let T=f+r+4;const B=n=>Ot+Math.max(rt(n),rt(n+12))+8,nt=e.logScale&&b>0?Math.log10(b):0,z=e.logScale&&i>0?Math.log10(i)-nt:1,dt=n=>e.logScale?(1-(Math.log10(n)-nt)/z)*r:(1-(n-b)/x)*r;for(let n=0;n<Gt;n++){const g=1-n/(Gt-1),_=f+n/Gt*r,W=r/Gt+1;t.fillStyle=o.forValue(g),t.fillRect(d,_,S,W)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(d,f,S,r),t.fillStyle=p.text,t.font=v,t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const L=3,N=36,st=14,Xt=e.logScale&&z>0?Ve(b,i,r,N,st,nt,z):e.allIntegerValues?(()=>{const n=Math.max(1,qt(x*N/r)),g=[],_=Math.ceil(b/n)*n;for(let W=_;W<=i+n*1e-6;W+=n){const D=(1-(W-b)/x)*r;D>st&&D<r-st&&g.push(Math.round(W))}return g})():(()=>{const n=x>0?qt(x*N/r):0,g=[];if(n>0){const _=Math.ceil(b/n)*n;for(let W=_;W<=i+n*1e-6;W+=n){const D=(1-(W-b)/x)*r;D>st&&D<r-st&&g.push(W)}}return g})(),A=ue(e.testDefs,e.activeTest),C=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",m=C?"Count":A?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),M=C?void 0:A?.unit,{tickFmt:R}=Ee(i,m,M,O),P=e.allIntegerValues?n=>String(Math.round(n)):R;t.textBaseline="middle";for(const n of Xt){const g=f+dt(n);t.beginPath(),t.moveTo(d+S,g),t.lineTo(d+S+L,g),t.stroke(),t.fillText(P(n),d+S+L+2,g)}if(t.beginPath(),t.moveTo(d+S,f),t.lineTo(d+S+L,f),t.stroke(),t.textBaseline="top",t.fillText(P(i),d+S+L+2,f),t.beginPath(),t.moveTo(d+S,f+r),t.lineTo(d+S+L,f+r),t.stroke(),t.textBaseline="bottom",t.fillText(P(b),d+S+L+2,f+r),!C&&A&&(A.limitLow!==void 0||A.limitHigh!==void 0)){const n=[],g=e.colorbarRangeMode==="spec";for(const[_,W]of[[A.limitLow,"LSL"],[A.limitHigh,"USL"]]){if(_===void 0||e.logScale&&_<=0)continue;const D=dt(_);!g&&(D<-st||D>r+st)||n.push({value:_,label:W,py:Math.max(0,Math.min(r,D))})}if(n.length>0){t.save(),t.font=v,t.textAlign="right",t.textBaseline="middle";for(const{py:_,label:W}of n){const D=f+_;g||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(d,D),t.lineTo(d+S,D),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(d,D),t.lineTo(d+S,D),t.stroke()),t.fillStyle=p.text,t.fillText(W,d-3,D);const wt=W==="USL"?-1:1,Ht=4,De=d-3-t.measureText(W).width-Ht-4;t.beginPath(),Te(t,De,D,Ht,wt),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=p.text,t.fill()}t.restore()}}if(!C){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=p.text,t.font=$e,t.textAlign="right",t.textBaseline="top",t.fillText(n,I-c,T),t.restore(),T+=15)}tt&&X&&ft(X,I-c,T,"right","top",B(T),$t,p.text)}const te=[];let Z;if(at){const o=ye(e.colorScheme),a=K==="compact",l=e.plotMode==="softBin"?it:Mt,r=l?new Map(l.map(s=>[s.bin,s])):null,f=s=>{const u=r?.get(s);return(e.colorScheme==="custom"?u?.color:void 0)??o.forBin(s)},d=(s,u)=>{const X=t.measureText(s).width,T=a?0:t.measureText(String(u)).width,B=w+xt+X+(T?Ut:0);return{labelWidth:X,countWidth:T,totalWidth:B}},b=Lt?.find(s=>s.key===e.activeMetadataKey),i=pt?J.map(s=>{const u=a?s.compactLabel:s.label;return{key:s.key,color:s.color,count:s.count,label:u,tooltipLabel:s.tooltip,...d(u,s.count)}}):e.plotMode==="metadata"?At.map(([s,u])=>{const T=b?.values?.find(z=>z.value===s)?.label??s,B=a?s:T,nt=e.metadataColorMap?.get(s)??"#d6d9dd";return{key:s,color:nt,count:u,label:B,tooltipLabel:`${T} \xB7 ${u} dies`,...d(B,u)}}):Rt.map(([s,u])=>{const X=r?.get(s),T=X?.name?`${s} \xB7 ${X.name}`:`Bin ${s}`,B=a?String(s):T;return{key:s,color:f(s),count:u,label:B,tooltipLabel:`${T} \xB7 ${u} dies`,...d(B,u)}}),x=I-c*2;if(i.length>0){const s=Math.max(1,Math.floor((V-2*c)/E));let u=i.length,X=1,T=u*E,B=[],nt=u,z=0;const dt=ct||Ct;if(dt){const A=Math.max(...i.map(m=>m.totalWidth)),C=Math.max(1,Math.min(i.length,Math.floor((x+8)/(A+8))));for(let m=C;m>=1;m--){const M=Math.ceil(i.length/m);if(M>s)continue;const R=new Array(m).fill(0);for(let n=0;n<i.length;n++){const g=n%m;R[g]=Math.max(R[g],i[n].totalWidth)}if(R.reduce((n,g)=>n+g,0)+(m-1)*8<=x||m===1){X=m,B=R,nt=M,u=M,T=M*E;break}}}else u=Math.min(i.length,s),T=u*E,i.length>s&&(z=i.length-(s-1)),B=[Wt];let L,N;if(Pt){const A=Math.max(...i.map(n=>w+xt+t.measureText(n.label).width+Ut)),C=Math.ceil(A);B=[C];const m=C+Vt*2,M=T+Vt*2,R=j?.x??0,P=j?.y??0;L=Math.min(Math.max(I-c-m+R,c),I-c-m),N=Math.min(Math.max(V-c-M+P,c),V-c-M),Z={x:L,y:N,w:m,h:M},t.save(),t.fillStyle="rgba(255,255,255,0.92)",t.strokeStyle="rgba(0,0,0,0.1)",t.lineWidth=1,t.fillRect(L,N,m,M),t.strokeRect(L,N,m,M),t.restore(),L+=Vt,N+=Vt}else ct?(L=c,N=V-c-T):Ct?(L=c,N=c+Y):G?(L=c+4,N=c+Math.round((V-2*c-T)/2)):(L=I-c-Wt+4,N=c+Math.round((V-2*c-T)/2));if(tt){const A=e.plotMode==="softBin"?it:Mt,{primary:C,secondary:m}=pe(e,O,A),M=6,R=g=>Ot-Math.max(rt(g),rt(g-12))-8,P=g=>y?I-c:R(g),n=Pt?Z.y+Z.h:N+T;if(Ct){const g=n+M;ft(C,L,g,"left","top",Ot-Math.max(rt(g),rt(g+12))-8),m&&ft(m,L,g+16,"left","top",R(g+16),$t,p.text)}else if(Pt)ft(C,Z.x,Z.y-M,"left","bottom",Z.x+Z.w),m&&ft(m,Z.x,n+M,"left","top",Z.x+Z.w,$t,p.text);else{const g=Math.max(N-M,c+Y+12);if(ft(C,L,g,"left","bottom",P(g)),m){const _=n+M;ft(m,L,_,"left","top",P(_),$t,p.text)}}}t.save(),t.font=v;const st=dt?8:0,Xt=(A,C)=>{if(t.measureText(A).width<=C)return A;let m=0,M=A.length;const R="\u2026",P=t.measureText(R).width;for(;m<M;){const n=m+M+1>>1;t.measureText(A.slice(0,n)).width+P<=C?m=n:M=n-1}return m===0?R:A.slice(0,m)+R};if(dt){let A=0;for(let C=0;C<u;C++){let m=L;for(let M=0;M<X;M++){const R=i[A++];if(!R)break;const P=R.key===Q,n=m,g=m+w+xt,_=N+C*E+E/2,W=N+C*E+Math.round((E-w)/2),D=B[M]-w-xt-Ut;t.fillStyle=R.color,t.fillRect(n,W,w,w),t.strokeStyle=P?p.accent:"rgba(0,0,0,0.25)",t.lineWidth=P?2:.75,t.strokeRect(n,W,w,w),t.fillStyle=P?p.accent:p.text,t.font=P?`bold ${v}`:v,t.textAlign="left",t.textBaseline="middle",t.fillText(Xt(R.label,D),g,_),t.fillStyle=p.textMuted,t.font=v,t.textAlign="right",t.fillText(String(R.count),m+B[M]-2,_),te.push({bin:R.key,x:m,y:N+C*E,w:B[M],h:E,label:R.tooltipLabel}),m+=B[M]+st}}}else{const A=B[0],C=K!=="compact",m=A-w-xt-(C?Ut:0),M=L+A-2;let R=i;z>0&&(R=i.slice(0,s-1));let P=N;for(const n of R){const g=n.key===Q,_=L,W=L+w+xt,D=P+E/2,wt=P+Math.round((E-w)/2),Ht=n.label;t.fillStyle=n.color,t.fillRect(_,wt,w,w),t.strokeStyle=g?p.accent:"rgba(0,0,0,0.25)",t.lineWidth=g?2:.75,t.strokeRect(_,wt,w,w),t.fillStyle=g?p.accent:p.text,t.font=g?`bold ${v}`:v,t.textAlign="left",t.textBaseline="middle",t.fillText(Xt(Ht,m),W,D),(C||Pt)&&(t.fillStyle=p.textMuted,t.font=v,t.textAlign="right",t.fillText(String(n.count),M,D)),te.push({bin:n.key,x:L,y:P,w:A,h:E,label:n.tooltipLabel}),P+=E}z>0&&(t.fillStyle=p.textMuted,t.font=v,t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${z} more`,L+w+xt,P+E/2))}}i.length>0&&t.restore()}const We={originX:et,originY:ot,ppm:k,snapDist:Ft},he=e.rectangles[0]?.width??1,de=e.rectangles[0]?.height??1,It=he*1.5,Nt=de*1.5,ht=e.dieBounds,Et=ht?ht.minX:q.length?Math.min(...q.map(o=>o.x)):0,Yt=ht?ht.minY:q.length?Math.min(...q.map(o=>o.y)):0,Be=ht?ht.maxX:q.length?Math.max(...q.map(o=>o.x)):1,_e=ht?ht.maxY:q.length?Math.max(...q.map(o=>o.y)):1,St=Math.max(1,Math.ceil((Be-Et)/It)+1),ee=Math.max(1,Math.ceil((_e-Yt)/Nt)+1),ge=Array.from({length:St*ee},()=>[]);for(let o=0;o<q.length;o++){const a=Math.floor((q[o].x-Et)/It),l=Math.floor((q[o].y-Yt)/Nt),r=Math.max(0,Math.min(St-1,a)),f=Math.max(0,Math.min(ee-1,l));ge[f*St+r].push(o)}function me(o,a,l){const r=Math.max(0,Math.floor((o-l-Et)/It)),f=Math.min(St-1,Math.floor((o+l-Et)/It)),d=Math.max(0,Math.floor((a-l-Yt)/Nt)),b=Math.min(ee-1,Math.floor((a+l-Yt)/Nt)),i=[];for(let x=d;x<=b;x++)for(let s=r;s<=f;s++)for(const u of ge[x*St+s])i.push(u);return i}return{hitTarget:{getDieAtPoint(o,a){const l=(o-et)/k,r=(ot-a)/k,f=Math.max(he,de);for(const i of me(l,r,f)){const x=e.rectangles[i];if(x&&Math.abs(l-x.x)<=x.width/2&&Math.abs(r-x.y)<=x.height/2)return e.dies[i]??null}let d=null,b=Ft*Ft;for(const i of me(l,r,Ft)){const x=q[i].x-l,s=q[i].y-r,u=x*x+s*s;u<b&&(b=u,d=e.dies[i]??null)}return d}},viewport:We,binLegendRows:te,legendBox:Z}}function Ue(h,e,F,p,c,U,S,lt,gt,j,mt,Tt,H){h.save(),h.font=Ge,h.fillStyle=H.text,h.strokeStyle=H.axisLine,h.lineWidth=.5;const Q=F-lt+4,O=S+gt-4,Y=Fe(mt),kt=xe(Y,1,0),Mt=xe(Y,0,1),it=1e-9;function Lt(y){return j?Math.abs(y.y)<it&&Math.abs(y.x)>it?{pitch:j.x,sign:Math.sign(y.x)}:Math.abs(y.x)<it&&Math.abs(y.y)>it?{pitch:j.y,sign:Math.sign(y.y)}:null:null}const tt=Lt(kt),ut=Lt(Mt);function bt(y){return tt?Math.round(y*tt.sign/tt.pitch):y}function pt(y){return ut?Math.round(y*ut.sign/ut.pitch):y}function at(y){if(!y)return qt(50/U);const G=50/(y*U);return Math.max(1,Math.round(G))*y}const Rt=tt?.pitch,At=ut?.pitch,J=at(Rt),yt=at(At);h.textAlign="center",h.textBaseline="top";const $=Math.ceil((S-p)/U/J)*J,I=(e-S-p)/U;for(let y=$;y<=I;y+=J){const G=p+y*U;if(G<S||G>e-S)continue;h.beginPath(),h.moveTo(G,Q-ke),h.lineTo(G,Q),h.stroke();const ct=j?String(bt(y)):Se(y);h.fillText(ct,G,Q+2)}h.textAlign="right",h.textBaseline="middle";const V=Math.ceil((c-(F-S))/U/yt)*yt,K=(c-S)/U;for(let y=V;y<=K;y+=yt){const G=c-y*U;if(G<S||G>F-S)continue;h.beginPath(),h.moveTo(O,G),h.lineTo(O+ke,G),h.stroke();const ct=j?String(pt(y)):Se(y);h.fillText(ct,O-2,G)}h.restore()}function qt(h){const e=Math.pow(10,Math.floor(Math.log10(h))),F=h/e;return(F<1.5?1:F<3.5?2:F<7.5?5:10)*e}function Ve(h,e,F,p,c,U,S){const lt=[],gt=S;if(gt<1){const H=qt((e-h)*p/F);if(H>0){const Q=Math.ceil(h/H)*H;for(let O=Q;O<=e+H*1e-6;O+=H){if(O<=h||O>=e)continue;const Y=(1-(Math.log10(O)-U)/S)*F;Y>c&&Y<F-c&&lt.push(O)}}return lt}const j=gt<3?[1,2,5]:[1],mt=Math.floor(Math.log10(h)),Tt=Math.ceil(Math.log10(e));for(let H=mt;H<=Tt;H++)for(const Q of j){const O=Q*Math.pow(10,H);if(O<=h||O>=e)continue;const Y=(1-(Math.log10(O)-U)/S)*F;Y>c&&Y<F-c&&lt.push(O)}return lt}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";
1
+ import{findTestDef as xe,buildMapTitle as ye}from"../renderer/buildView.js";import{affineInvert as Oe,affineVector as Me}from"../core/transforms.js";import{compareNatural as Ee}from"../core/utils.js";import{getColorScheme as be}from"../renderer/colorSchemes.js";import{SPEC_PASS_FILL as Te,SPEC_FAIL_LOW as Ye,SPEC_FAIL_HIGH as Se,contrastTextColor as ke}from"../renderer/colorMap.js";import{fmt as Le,fmtColorbarAxis as we}from"../renderer/fmt.js";import{resolveCanvasTheme as Xe}from"./canvasTheme.js";function Ae(g,e,N,M,h){g.moveTo(e,N+h*M),g.lineTo(e-M*.9,N-h*M*.6),g.lineTo(e+M*.9,N-h*M*.6),g.closePath()}const He=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),$e=new Set(["hardBin","softBin","metadata"]),v="10px system-ui, sans-serif",Ge="600 12px system-ui, sans-serif",Gt="11px system-ui, sans-serif",Ve="600 11px system-ui, sans-serif",Vt=128,Ue="10px system-ui, sans-serif",Re=4,Y=17,X=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 Ut=28,gt=5,mt=8,qe=15;export function toCanvas(g,e,N={}){const M=Xe(g.parentElement??g),{padding:h=16,showColorbar:$=!0,markFailingDies:G=!1,colorbarWidth:_=16,background:ut=M.background,legendPosition:Z="default",legendOffset:pt,showAxes:xt=!1,diePitchMm:V,viewport:K,activeBin:E,fallbackFormat:z,topClearance:j=0,minRightReserve:kt,hbinDefs:at,sbinDefs:yt,metadataFields:Mt,showTitle:Q=!0}=N,I=Math.floor(g.clientWidth||g.width),H=Math.floor(g.clientHeight||g.height),bt=I>=BIN_LEGEND_MIN_CANVAS_W&&H>=BIN_LEGEND_MIN_CANVAS_H,Lt=$&&bt&&He.has(e.plotMode)&&e.passFailDisplay==="off",Tt=$&&bt&&$e.has(e.plotMode),tt=$&&bt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),et=Tt||tt,At=Tt&&e.plotMode!=="metadata"&&e.binCounts?[...e.binCounts.entries()].sort(([o],[r])=>o-r):[],Rt=Tt&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(Ee)].map(o=>[o,e.metadataCounts.get(o)??0]):[],ot=[];if(tt&&e.passFailDisplay==="test"){const o=e.passFailCounts;ot.push({key:-1,color:Te,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),ot.push({key:-2,color:Se,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(tt){const o=e.specCounts,r=xe(e.testDefs,e.activeTest);ot.push({key:-1,color:Te,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),r?.limitHigh!==void 0&&ot.push({key:-2,color:Se,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),r?.limitLow!==void 0&&ot.push({key:-3,color:Ye,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const Ct=tt?ot.length:e.plotMode==="metadata"?Rt.length:At.length,m=(g.ownerDocument.defaultView??window).devicePixelRatio??1;if(I<=0||H<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const C=Z!=="default"?Z:I<BIN_LEGEND_ADAPT_FLOATING?"floating":I<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",dt=C==="default"||C==="compact",ne=C==="left",zt=C==="bottom",_t=C==="top",Pt=C==="floating",Wt=C==="compact"||C==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,se=Math.floor((H-2*h)/Y),le=Ct>se?se-1:Ct,ie=et&&zt?le*Y:0,Kt=et&&_t?le*Y:0,Jt=Lt?_+28:et&&dt?Wt:0,Zt=et&&ne?Wt:0,jt=xt?32:0,Bt=xt?36:0,Ce=kt!=null?Math.max(Jt,kt):Jt,_e=I-2*h-Ce-Bt-Zt,ae=H-2*h-jt-ie-Kt;g.width=Math.round(I*m),g.height=Math.round(H*m);const t=g.getContext("2d");t.scale(m,m),t.fillStyle=ut,t.fillRect(0,0,I,H);const U=e.hoverPoints;if(!U.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Dt=e.rectangles[0],Qt=Dt?Dt.width/2:0,vt=Dt?Dt.height/2:0,Ft=e.dieBounds,ce=(Ft?.minX??0)-Qt,Pe=(Ft?.maxX??0)+Qt,We=(Ft?.minY??0)-vt,re=(Ft?.maxY??0)+vt,fe=Pe-ce,he=re-We;let nt,st,b;if(K)({originX:nt,originY:st,ppm:b}=K);else{const r=e.notchDir,l=r&&r.y>.1?13:0,a=r&&r.y<-.1?13:0,c=r&&r.x<-.1?13:0,f=r&&r.x>.1?13:0,d=_e-c-f,i=ae-j-l-a;b=Math.min(d/fe,i/he),nt=h+Bt+Zt+c+(d-fe*b)/2-ce*b,st=h+j+Kt+l+(i-he*b)/2+re*b}const It=K?.snapDist??Math.max(Qt,vt,1)*1.5,Nt=nt+e.waferCenter.x*b,Be=st-e.waferCenter.y*b,te=e.waferRadius*b,ct=o=>{const r=Math.abs(o-Be);return r>=te?0:Math.sqrt(te*te-r*r)},rt=(o,r,l,a,c,f,d=Ge,i=M.text)=>{if(!o)return;t.save(),t.fillStyle=i,t.font=d,t.textAlign=a,t.textBaseline=c;const p=a==="right"?r-f:f-r;let s=o;if(p>8&&t.measureText(s).width>p){for(;s.length>1&&t.measureText(s+"\u2026").width>p;)s=s.slice(0,-1);s=s+"\u2026"}p>8&&t.fillText(s,r,l),t.restore()};if(t.save(),t.setTransform(b*m,0,0,-b*m,nt*m,st*m),e.rectangles.length>0){const o=new Map;for(const l of e.rectangles){const a=String(l.fill);let c=o.get(a);c||(c=[],o.set(a,c)),c.push(l)}for(const[l,a]of o){t.beginPath();for(const c of a)t.rect(c.x-c.width/2,c.y-c.height/2,c.width,c.height);t.fillStyle=l,t.fill()}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5/(b*m),t.beginPath();for(const l of e.rectangles)t.rect(l.x-l.width/2,l.y-l.height/2,l.width,l.height);if(t.stroke(),G){const l=e.rectangles.filter(a=>a.binFail);if(l.length>0){const a=new Map;for(const c of l){const f=ke(String(c.fill));let d=a.get(f);d||(d=[],a.set(f,d)),d.push(c)}t.save(),t.lineCap="butt";for(const[c,f]of a){t.strokeStyle=c,t.globalAlpha=.55,t.lineWidth=Math.max(.6/(b*m),Math.min(f[0].width,f[0].height)*.1);for(const d of f){const i=d.width/2,p=d.height/2,s=Math.max(1.6/(b*m),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 x=-(i+p);x<=i+p;x+=s)t.moveTo(d.x-i+x,d.y-p),t.lineTo(d.x-i+x+d.height,d.y+p);t.stroke(),t.restore()}}t.restore()}}const r=e.rectangles.filter(l=>l.specMark);if(r.length>0){const l=new Map;for(const c of r){const f=ke(String(c.fill)),d=`${c.specMark}|${f}`;let i=l.get(d);i||(i=[],l.set(d,i)),i.push(c)}const a=2.5/(b*m);t.lineJoin="round";for(const[c,f]of l){const[d,i]=c.split("|"),p=i==="#000000"?"#ffffff":"#000000",s=d==="failHigh"?1:-1,x=Math.min(f[0].width,f[0].height),w=Math.max(2.5/(b*m),x*.3);t.beginPath();for(const k of f)Ae(t,k.x,k.y,w,s);t.strokeStyle=p,t.lineWidth=a,t.stroke(),t.fillStyle=i,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const r of o.points){for(let l=0;l<r.length;l++)l===0?t.moveTo(r[l].x,r[l].y):t.lineTo(r[l].x,r[l].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/(b*m),t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1/(b*m),t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth/(b*m),t.stroke())}if(t.restore(),e.notchDir){const o=nt+e.waferCenter.x*b,r=st-e.waferCenter.y*b,l=e.notchDir.x,a=-e.notchDir.y,c=e.waferRadius*b,f=4,d=9,i=5,p=o+l*(c+f),s=r+a*(c+f),x=p+l*d,w=s+a*d,k={x:-a,y:l},B=h+Bt+Zt,lt=I-h-Jt,q=h+j+Kt,ht=H-h-ie-jt;t.save(),t.beginPath(),t.rect(B,q,lt-B,ht-q),t.clip(),t.beginPath(),t.moveTo(p,s),t.lineTo(x+k.x*i,w+k.y*i),t.lineTo(x-k.x*i,w-k.y*i),t.closePath(),t.fillStyle=M.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let de=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 r=e.rectangles[0].width*b,l=e.rectangles[0].height*b,a=Math.min(r,l),c=r/o;de=Math.max(8,Math.min(64,Math.round(Math.min(a*.55,c*1.8))))}for(const o of e.texts){const r=nt+o.x*b,l=st-o.y*b;t.font=`${o.role==="indicator"?o.fontSize:de}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,r,l)}if(t.restore(),xt&&ze(t,I,H,nt,st,b,h,jt,Bt,V,e.gridToScreen,e.rotation,M),Lt){const o=be(e.colorScheme),r=20,l=ae-j,a=Math.round(l*.75),c=h+j+Math.round((l-a)/2),f=I-h-_-r,[d,i]=e.valueRange,p=i-d,s=e.plotMode==="stackedSoftBins"?yt:at,{primary:x,secondary:w}=Q?ye(e,z,s):{primary:"",secondary:""};if(Q){const n=Math.max(c-6,h+j+11),u=Nt+Math.max(ct(n),ct(n-12))+8;rt(x,I-h,n,"right","bottom",u)}let k=c+a+4;const B=n=>Nt+Math.max(ct(n),ct(n+12))+8,lt=e.logScale&&d>0?Math.log10(d):0,q=e.logScale&&i>0?Math.log10(i)-lt:1,ht=n=>e.logScale?(1-(Math.log10(n)-lt)/q)*a:(1-(n-d)/p)*a;for(let n=0;n<Vt;n++){const u=1-n/(Vt-1),D=c+n/Vt*a,W=a/Vt+1;t.fillStyle=o.forValue(u),t.fillRect(f,D,_,W)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(f,c,_,a),t.fillStyle=M.text,t.font=v,t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const L=3,O=36,it=14,Xt=e.logScale&&q>0?Ke(d,i,a,O,it,lt,q):e.allIntegerValues?(()=>{const n=Math.max(1,qt(p*O/a)),u=[],D=Math.ceil(d/n)*n;for(let W=D;W<=i+n*1e-6;W+=n){const F=(1-(W-d)/p)*a;F>it&&F<a-it&&u.push(Math.round(W))}return u})():(()=>{const n=p>0?qt(p*O/a):0,u=[];if(n>0){const D=Math.ceil(d/n)*n;for(let W=D;W<=i+n*1e-6;W+=n){const F=(1-(W-d)/p)*a;F>it&&F<a-it&&u.push(W)}}return u})(),A=xe(e.testDefs,e.activeTest),R=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",y=R?"Count":A?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),T=R?void 0:A?.unit,{tickFmt:S}=we(i,y,T,z),P=e.allIntegerValues?n=>String(Math.round(n)):S;t.textBaseline="middle";for(const n of Xt){const u=c+ht(n);t.beginPath(),t.moveTo(f+_,u),t.lineTo(f+_+L,u),t.stroke(),t.fillText(P(n),f+_+L+2,u)}if(t.beginPath(),t.moveTo(f+_,c),t.lineTo(f+_+L,c),t.stroke(),t.textBaseline="top",t.fillText(P(i),f+_+L+2,c),t.beginPath(),t.moveTo(f+_,c+a),t.lineTo(f+_+L,c+a),t.stroke(),t.textBaseline="bottom",t.fillText(P(d),f+_+L+2,c+a),!R&&A&&(A.limitLow!==void 0||A.limitHigh!==void 0)){const n=[],u=e.colorbarRangeMode==="spec";for(const[D,W]of[[A.limitLow,"LSL"],[A.limitHigh,"USL"]]){if(D===void 0||e.logScale&&D<=0)continue;const F=ht(D);!u&&(F<-it||F>a+it)||n.push({value:D,label:W,py:Math.max(0,Math.min(a,F))})}if(n.length>0){t.save(),t.font=v,t.textAlign="right",t.textBaseline="middle";for(const{py:D,label:W}of n){const F=c+D;u||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(f,F),t.lineTo(f+_,F),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(f,F),t.lineTo(f+_,F),t.stroke()),t.fillStyle=M.text,t.fillText(W,f-3,F);const Ht=W==="USL"?-1:1,$t=4,Ne=f-3-t.measureText(W).width-$t-4;t.beginPath(),Ae(t,Ne,F,$t,Ht),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=M.text,t.fill()}t.restore()}}if(!R){const n=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;n&&(t.save(),t.fillStyle=M.text,t.font=Ve,t.textAlign="right",t.textBaseline="top",t.fillText(n,I-h,k),t.restore(),k+=15)}Q&&w&&rt(w,I-h,k,"right","top",B(k),Gt,M.text)}const ee=[];let J;if(et){const o=be(e.colorScheme),r=C==="compact",l=e.plotMode==="softBin"?yt:at,a=l?new Map(l.map(s=>[s.bin,s])):null,c=s=>{const x=a?.get(s);return(e.colorScheme==="custom"?x?.color:void 0)??o.forBin(s)},f=(s,x)=>{const w=t.measureText(s).width,k=r?0:t.measureText(String(x)).width,B=X+gt+w+(k?Ut:0);return{labelWidth:w,countWidth:k,totalWidth:B}},d=Mt?.find(s=>s.key===e.activeMetadataKey),i=tt?ot.map(s=>{const x=r?s.compactLabel:s.label;return{key:s.key,color:s.color,count:s.count,label:x,tooltipLabel:s.tooltip,...f(x,s.count)}}):e.plotMode==="metadata"?Rt.map(([s,x])=>{const k=d?.values?.find(q=>q.value===s)?.label??s,B=r?s:k,lt=e.metadataColorMap?.get(s)??"#d6d9dd";return{key:s,color:lt,count:x,label:B,tooltipLabel:`${k} \xB7 ${x} dies`,...f(B,x)}}):At.map(([s,x])=>{const w=a?.get(s),k=w?.name?`${s} \xB7 ${w.name}`:`Bin ${s}`,B=r?String(s):k;return{key:s,color:c(s),count:x,label:B,tooltipLabel:`${k} \xB7 ${x} dies`,...f(B,x)}}),p=I-h*2;if(i.length>0){const s=Math.max(1,Math.floor((H-2*h)/Y));let x=i.length,w=1,k=x*Y,B=[],lt=x,q=0;const ht=zt||_t;if(ht){const A=Math.max(...i.map(y=>y.totalWidth)),R=Math.max(1,Math.min(i.length,Math.floor((p+8)/(A+8))));for(let y=R;y>=1;y--){const T=Math.ceil(i.length/y);if(T>s)continue;const S=new Array(y).fill(0);for(let n=0;n<i.length;n++){const u=n%y;S[u]=Math.max(S[u],i[n].totalWidth)}if(S.reduce((n,u)=>n+u,0)+(y-1)*8<=p||y===1){w=y,B=S,lt=T,x=T,k=T*Y;break}}}else x=Math.min(i.length,s),k=x*Y,i.length>s&&(q=i.length-(s-1)),B=[Wt];let L,O;if(Pt){const A=Math.max(...i.map(u=>X+gt+t.measureText(u.label).width+Ut)),R=Math.ceil(A);B=[R];const y=Q?qe:0,T=R+mt*2,S=k+y+mt*2,P=pt?.x??0,n=pt?.y??0;L=Math.min(Math.max(I-h-T+P,h),I-h-T),O=Math.min(Math.max(H-h-S+n,h),H-h-S),J={x:L,y:O,w:T,h:S},t.save(),t.globalAlpha=.92,t.fillStyle=M.surface,t.fillRect(L,O,T,S),t.globalAlpha=1,t.strokeStyle=M.axisLine,t.lineWidth=1,t.strokeRect(L,O,T,S),t.restore(),L+=mt,O+=mt+y}else zt?(L=h,O=H-h-k):_t?(L=h,O=h+j):ne?(L=h+4,O=h+Math.round((H-2*h-k)/2)):(L=I-h-Wt+4,O=h+Math.round((H-2*h-k)/2));if(Q){const A=e.plotMode==="softBin"?yt:at,{primary:R,secondary:y}=ye(e,z,A),T=6,S=u=>Nt-Math.max(ct(u),ct(u-12))-8,P=u=>dt?I-h:S(u),n=Pt?J.y+J.h:O+k;if(_t){const u=n+T;rt(R,L,u,"left","top",Nt-Math.max(ct(u),ct(u+12))-8),y&&rt(y,L,u+16,"left","top",S(u+16),Gt,M.text)}else if(Pt)rt(R,J.x+mt,J.y+mt,"left","top",J.x+J.w-mt),y&&rt(y,J.x,n+T,"left","top",J.x+J.w,Gt,M.text);else{const u=Math.max(O-T,h+j+12);if(rt(R,L,u,"left","bottom",P(u)),y){const D=n+T;rt(y,L,D,"left","top",P(D),Gt,M.text)}}}t.save(),t.font=v;const it=ht?8:0,Xt=(A,R)=>{if(t.measureText(A).width<=R)return A;let y=0,T=A.length;const S="\u2026",P=t.measureText(S).width;for(;y<T;){const n=y+T+1>>1;t.measureText(A.slice(0,n)).width+P<=R?y=n:T=n-1}return y===0?S:A.slice(0,y)+S};if(ht){let A=0;for(let R=0;R<x;R++){let y=L;for(let T=0;T<w;T++){const S=i[A++];if(!S)break;const P=S.key===E,n=y,u=y+X+gt,D=O+R*Y+Y/2,W=O+R*Y+Math.round((Y-X)/2),F=B[T]-X-gt-Ut;t.fillStyle=S.color,t.fillRect(n,W,X,X),t.strokeStyle=P?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=P?2:.75,t.strokeRect(n,W,X,X),t.fillStyle=P?M.accent:M.text,t.font=P?`bold ${v}`:v,t.textAlign="left",t.textBaseline="middle",t.fillText(Xt(S.label,F),u,D),t.fillStyle=M.textMuted,t.font=v,t.textAlign="right",t.fillText(String(S.count),y+B[T]-2,D),ee.push({bin:S.key,x:y,y:O+R*Y,w:B[T],h:Y,label:S.tooltipLabel}),y+=B[T]+it}}}else{const A=B[0],R=C!=="compact",y=A-X-gt-(R?Ut:0),T=L+A-2;let S=i;q>0&&(S=i.slice(0,s-1));let P=O;for(const n of S){const u=n.key===E,D=L,W=L+X+gt,F=P+Y/2,Ht=P+Math.round((Y-X)/2),$t=n.label;t.fillStyle=n.color,t.fillRect(D,Ht,X,X),t.strokeStyle=u?M.accent:"rgba(0,0,0,0.25)",t.lineWidth=u?2:.75,t.strokeRect(D,Ht,X,X),t.fillStyle=u?M.accent:M.text,t.font=u?`bold ${v}`:v,t.textAlign="left",t.textBaseline="middle",t.fillText(Xt($t,y),W,F),(R||Pt)&&(t.fillStyle=M.textMuted,t.font=v,t.textAlign="right",t.fillText(String(n.count),T,F)),ee.push({bin:n.key,x:L,y:P,w:A,h:Y,label:n.tooltipLabel}),P+=Y}q>0&&(t.fillStyle=M.textMuted,t.font=v,t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${q} more`,L+X+gt,P+Y/2))}}i.length>0&&t.restore()}const De={originX:nt,originY:st,ppm:b,snapDist:It},ge=e.rectangles[0]?.width??1,me=e.rectangles[0]?.height??1,Ot=ge*1.5,Et=me*1.5,ft=e.dieBounds,Yt=ft?ft.minX:U.length?Math.min(...U.map(o=>o.x)):0,wt=ft?ft.minY:U.length?Math.min(...U.map(o=>o.y)):0,Fe=ft?ft.maxX:U.length?Math.max(...U.map(o=>o.x)):1,Ie=ft?ft.maxY:U.length?Math.max(...U.map(o=>o.y)):1,St=Math.max(1,Math.ceil((Fe-Yt)/Ot)+1),oe=Math.max(1,Math.ceil((Ie-wt)/Et)+1),ue=Array.from({length:St*oe},()=>[]);for(let o=0;o<U.length;o++){const r=Math.floor((U[o].x-Yt)/Ot),l=Math.floor((U[o].y-wt)/Et),a=Math.max(0,Math.min(St-1,r)),c=Math.max(0,Math.min(oe-1,l));ue[c*St+a].push(o)}function pe(o,r,l){const a=Math.max(0,Math.floor((o-l-Yt)/Ot)),c=Math.min(St-1,Math.floor((o+l-Yt)/Ot)),f=Math.max(0,Math.floor((r-l-wt)/Et)),d=Math.min(oe-1,Math.floor((r+l-wt)/Et)),i=[];for(let p=f;p<=d;p++)for(let s=a;s<=c;s++)for(const x of ue[p*St+s])i.push(x);return i}return{hitTarget:{getDieAtPoint(o,r){const l=(o-nt)/b,a=(st-r)/b,c=Math.max(ge,me);for(const i of pe(l,a,c)){const p=e.rectangles[i];if(p&&Math.abs(l-p.x)<=p.width/2&&Math.abs(a-p.y)<=p.height/2)return e.dies[i]??null}let f=null,d=It*It;for(const i of pe(l,a,It)){const p=U[i].x-l,s=U[i].y-a,x=p*p+s*s;x<d&&(d=x,f=e.dies[i]??null)}return f}},viewport:De,binLegendRows:ee,legendBox:J}}function ze(g,e,N,M,h,$,G,_,ut,Z,pt,xt,V){g.save(),g.font=Ue,g.fillStyle=V.text,g.strokeStyle=V.axisLine,g.lineWidth=.5;const K=N-_+4,E=G+ut-4,z=Oe(pt),j=Me(z,1,0),kt=Me(z,0,1),at=1e-9;function yt(m){return Z?Math.abs(m.y)<at&&Math.abs(m.x)>at?{pitch:Z.x,sign:Math.sign(m.x)}:Math.abs(m.x)<at&&Math.abs(m.y)>at?{pitch:Z.y,sign:Math.sign(m.y)}:null:null}const Mt=yt(j),Q=yt(kt);function I(m){return Mt?Math.round(m*Mt.sign/Mt.pitch):m}function H(m){return Q?Math.round(m*Q.sign/Q.pitch):m}function bt(m){if(!m)return qt(50/$);const C=50/(m*$);return Math.max(1,Math.round(C))*m}const Lt=Mt?.pitch,Tt=Q?.pitch,tt=bt(Lt),et=bt(Tt);g.textAlign="center",g.textBaseline="top";const At=Math.ceil((G-M)/$/tt)*tt,Rt=(e-G-M)/$;for(let m=At;m<=Rt;m+=tt){const C=M+m*$;if(C<G||C>e-G)continue;g.beginPath(),g.moveTo(C,K-Re),g.lineTo(C,K),g.stroke();const dt=Z?String(I(m)):Le(m);g.fillText(dt,C,K+2)}g.textAlign="right",g.textBaseline="middle";const ot=Math.ceil((h-(N-G))/$/et)*et,Ct=(h-G)/$;for(let m=ot;m<=Ct;m+=et){const C=h-m*$;if(C<G||C>N-G)continue;g.beginPath(),g.moveTo(E,C),g.lineTo(E+Re,C),g.stroke();const dt=Z?String(H(m)):Le(m);g.fillText(dt,E-2,C)}g.restore()}function qt(g){const e=Math.pow(10,Math.floor(Math.log10(g))),N=g/e;return(N<1.5?1:N<3.5?2:N<7.5?5:10)*e}function Ke(g,e,N,M,h,$,G){const _=[],ut=G;if(ut<1){const V=qt((e-g)*M/N);if(V>0){const K=Math.ceil(g/V)*V;for(let E=K;E<=e+V*1e-6;E+=V){if(E<=g||E>=e)continue;const z=(1-(Math.log10(E)-$)/G)*N;z>h&&z<N-h&&_.push(E)}}return _}const Z=ut<3?[1,2,5]:[1],pt=Math.floor(Math.log10(g)),xt=Math.ceil(Math.log10(e));for(let V=pt;V<=xt;V++)for(const K of Z){const E=K*Math.pow(10,V);if(E<=g||E>=e)continue;const z=(1-(Math.log10(E)-$)/G)*N;z>h&&z<N-h&&_.push(E)}return _}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";
@@ -45,12 +45,19 @@ export declare const INLINE_TEST_LIMIT = 6;
45
45
  /** Above this many rows, a scrollable list (test cascade submenu, chart test picker) gets a filter box. */
46
46
  export declare const MENU_SEARCH_THRESHOLD = 8;
47
47
  export declare const DEFAULT_OVERLAY_Z = 6000;
48
- /** `z-index` value string for a base-level overlay (menus, modal backdrop). */
48
+ /** `z-index` value string for a base-level overlay (modal backdrop, a
49
+ * component's own persistent chrome — e.g. a per-card toolbar). */
49
50
  export declare const Z_BASE = "var(--wmap-z, 6000)";
50
- /** One above base — tooltips, submenus, the modal box above its backdrop. */
51
+ /** One above base — tooltips, the modal box above its backdrop. */
51
52
  export declare const Z_ABOVE = "calc(var(--wmap-z, 6000) + 1)";
52
- /** Two above base — controls that must sit above a maximized modal box. */
53
- export declare const Z_ABOVE2 = "calc(var(--wmap-z, 6000) + 2)";
53
+ /**
54
+ * Two above base — the dedicated layer every transient menu/dropdown/
55
+ * cascade-submenu in this library renders into. See `menuLayerFor` below for
56
+ * why this is a real DOM layer, not just a number to reference.
57
+ */
58
+ export declare const Z_MENU = "calc(var(--wmap-z, 6000) + 2)";
59
+ /** Three above base — controls that must sit above a maximized modal box. */
60
+ export declare const Z_ABOVE2 = "calc(var(--wmap-z, 6000) + 3)";
54
61
  /**
55
62
  * Apply a host-supplied `zIndex` to wmap's overlays by writing `--wmap-z` onto
56
63
  * `document.documentElement`. Returns a disposer that restores the previous
@@ -164,6 +171,7 @@ export declare function saveTextFile(text: string, filename: string, mimeType: s
164
171
  */
165
172
  export declare function nextFrame(fn: () => void, ownerWindow?: Window): void;
166
173
  export declare function overlayRootFor(anchor: Element): Element;
174
+ export declare function menuLayerFor(anchor: Element): HTMLElement;
167
175
  /** The shared tooltip element for `doc` (default: the host page's own
168
176
  * document), lazily created and appended to `doc.body`. */
169
177
  export declare function getTooltip(doc?: Document): HTMLDivElement;
@@ -307,7 +315,18 @@ export type CheckMenuRow = {
307
315
  } | {
308
316
  label: string;
309
317
  active: boolean;
318
+ /** Default true. Without `disabledHint` a disabled row is omitted entirely. */
310
319
  enabled?: boolean;
320
+ /**
321
+ * Reason this row is unavailable. Supplying it keeps the row visible but
322
+ * greyed, with the reason as its tooltip, instead of dropping it.
323
+ *
324
+ * Omitting a row is right when its subject doesn't exist (no reticle data
325
+ * ⇒ nothing to say about a reticle grid). It's wrong when the option is
326
+ * real but temporarily inapplicable — the row vanishing then reads as a
327
+ * missing feature, and the user has no way to learn the condition.
328
+ */
329
+ disabledHint?: string;
311
330
  onClick: (e: MouseEvent) => void;
312
331
  };
313
332
  /**
@@ -398,7 +417,18 @@ export declare function openReparentedModal(elements: HTMLElement[], opts?: Repa
398
417
  * hardBin/softBin restriction (which still changes the die colours, just from
399
418
  * a smaller scheme set).
400
419
  */
401
- export declare function makePaletteBtn(helpers: ToolbarHelpers, getPlotMode: () => PlotMode, getColorScheme: () => string, hasCustomColors: () => boolean, setColorScheme: (v: string) => void): {
420
+ /**
421
+ * Colour-scheme picker, plus the optional non-colour failure marking.
422
+ *
423
+ * `markFail` is supplied by hosts that support it. It sits in this menu rather
424
+ * than getting a button of its own because it answers the same question the
425
+ * schemes do — "how is this data encoded" — and keeping it here means one
426
+ * control rather than a new axis of settings.
427
+ */
428
+ export declare function makePaletteBtn(helpers: ToolbarHelpers, getPlotMode: () => PlotMode, getColorScheme: () => string, hasCustomColors: () => boolean, setColorScheme: (v: string) => void, markFail?: {
429
+ get: () => boolean;
430
+ set: (v: boolean) => void;
431
+ }): {
402
432
  btn: HTMLButtonElement;
403
433
  sync: () => void;
404
434
  };
@@ -432,10 +462,27 @@ export declare function makeLogScaleBtn(helpers: ToolbarHelpers, getOpts: () =>
432
462
  sync: () => void;
433
463
  };
434
464
  export type LegendPosition = 'default' | 'compact' | 'left' | 'top' | 'bottom' | 'floating';
465
+ /**
466
+ * Per-map legend control, shared by the single map and the gallery.
467
+ *
468
+ * `perMap` is supplied only by the gallery, which is the one context where a
469
+ * single lot-level legend can stand in for every card's — and where the width
470
+ * a per-card legend costs is multiplied by the card count. A single map has
471
+ * nothing to stand in for it, so it never gets the toggle.
472
+ *
473
+ * The menu mixes a position group with that toggle rather than being two
474
+ * controls, because "how does the legend appear" is one question to the user
475
+ * even though it is two options underneath.
476
+ */
435
477
  export declare function makeLegendStyleBtn(helpers: ToolbarHelpers, getOpts: () => {
436
478
  plotMode?: PlotMode;
437
479
  legendPosition?: LegendPosition;
438
- }, setLegendPosition: (v: LegendPosition) => void): {
480
+ }, setLegendPosition: (v: LegendPosition) => void, perMap?: {
481
+ get: () => boolean;
482
+ set: (v: boolean) => void;
483
+ /** Non-empty when the toggle cannot apply right now — shown as the reason. */
484
+ blockedReason: () => string | null;
485
+ }): {
439
486
  btn: HTMLButtonElement;
440
487
  sync: () => void;
441
488
  };
@@ -1,4 +1,4 @@
1
- import{getUniqueTestNumbers as ue}from"../renderer/buildView.js";import{dieHasTestData as pe}from"../renderer/buildWaferMap.js";import{prettyKey as fe}from"../core/utils.js";import{listColorSchemes as oe}from"../renderer/colorSchemes.js";import{ICONS as $}from"./icons.js";import{WMAP_VERSION as me,WMAP_BUILD_TIME as be}from"./version.js";let ie=!1;export function logWmapVersionOnce(){ie||(ie=!0,console.log(`[wmap] v${me} (built ${be})`))}export const WMAP_TOKEN_NAMES=["z","icon","icon-hover","icon-active","bg-hover","bg-active","separator","surface","border","menu-hover","menu-active","panel-bg","text-muted","text","text-strong","warn-bg","warn-border","warn-text","err-bg","err-border","err-text","info-bg","info-text","selected","finding-indicator","canvas-bg","bar-fill","bar-fill-muted"];const w=(e,n)=>`var(--wmap-${e}, ${n})`;export const CLR={icon:w("icon","#506784"),iconHover:w("icon-hover","#2a3f5f"),iconActive:w("icon-active","#1a65ca"),bgHover:w("bg-hover","#edf0f8"),bgActive:w("bg-active","#dce8f8"),separator:w("separator","rgba(0,0,0,0.12)"),menuBg:w("surface","#fff"),menuBorder:w("border","rgba(0,0,0,0.12)"),menuHover:w("menu-hover","#f0f4fc"),menuActive:w("menu-active","#dce8f8"),panelBg:w("panel-bg","#fafbfc"),label:w("text-muted","#647687"),value:w("text-strong","#1f2f43"),text:w("text","#333"),warnBg:w("warn-bg","#fffbe6"),warnBorder:w("warn-border","#f0c040"),warnText:w("warn-text","#7a5800"),errBg:w("err-bg","#fef2f2"),errBorder:w("err-border","#dc8a8a"),errText:w("err-text","#7a1c1c"),infoBg:w("info-bg","#dce8f8"),infoText:w("info-text","#334155"),findingHighlight:w("selected","#e07a20"),findingIndicator:w("finding-indicator","#b7551a"),barFill:w("bar-fill","#2a6fc0"),barFillMuted:w("bar-fill-muted","#94a3b8")};export function sevColor(e){return e==="unusual"?"#a84112":e==="notable"?"#8a6500":CLR.icon}export const ROTATIONS=[0,90,180,270],INLINE_TEST_LIMIT=6,MENU_SEARCH_THRESHOLD=8,DEFAULT_OVERLAY_Z=6e3,Z_BASE=`var(--wmap-z, ${DEFAULT_OVERLAY_Z})`,Z_ABOVE=`calc(var(--wmap-z, ${DEFAULT_OVERLAY_Z}) + 1)`,Z_ABOVE2=`calc(var(--wmap-z, ${DEFAULT_OVERLAY_Z}) + 2)`;export function applyOverlayZ(e){if(e==null)return()=>{};const n=document.documentElement,t=n.style.getPropertyValue("--wmap-z");return n.style.setProperty("--wmap-z",String(e)),()=>{t?n.style.setProperty("--wmap-z",t):n.style.removeProperty("--wmap-z")}}export function copyWmapThemeTokens(e,n){const t=getComputedStyle(e);for(const o of WMAP_TOKEN_NAMES){const a=t.getPropertyValue(`--wmap-${o}`).trim();a&&n.style.setProperty(`--wmap-${o}`,a)}}export function syncWmapPopupTheme(e,n,t){const o=()=>{copyWmapThemeTokens(e,n),t?.()},a=new window.MutationObserver(o);a.observe(e,{attributes:!0,attributeFilter:["style","class"]}),a.observe(document.documentElement,{attributes:!0,attributeFilter:["style","class"]});const r=window.matchMedia("(prefers-color-scheme: dark)");return r.addEventListener("change",o),()=>{a.disconnect(),r.removeEventListener("change",o)}}let ee=null;export function setDetachWindowOpener(e){ee=e}export function openDetachWindow(e){return ee?ee(e):window.open("","_blank","width=560,height=600")}export const MODE_LABELS={value:"Test Value",hardBin:"Hard Bin",softBin:"Soft Bin",stackedValues:"Stacked Test Values",stackedBins:"Stacked Hard Bins",stackedSoftBins:"Stacked Soft Bins",metadata:"Metadata"},BIN_LEGEND_MODES=new Set(["hardBin","softBin","metadata"]),STACKED_MODES=new Set(["stackedValues","stackedBins","stackedSoftBins"]);export function saveImageBlob(e,n,t){const o=`${n}.png`;if(t){t(e,o);return}const a=URL.createObjectURL(e),r=document.createElement("a");r.href=a,r.download=o,r.click(),URL.revokeObjectURL(a)}export function saveTextFile(e,n,t,o){if(o){o(e,n,t);return}const a=new Blob([e],{type:t}),r=URL.createObjectURL(a),c=document.createElement("a");c.href=r,c.download=n,c.click(),URL.revokeObjectURL(r)}const he='[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"]';export function nextFrame(e,n=window){const t=n.requestAnimationFrame;typeof t=="function"?t.call(n,e):setTimeout(e,0)}function Oe(e,n,t){e.setAttribute("role","menu"),e.setAttribute("aria-label",n);for(const o of Array.from(e.children)){const a=t(o);a&&(o.setAttribute("role",a),o.tabIndex=-1)}}function G(e,n,t){const o=()=>Array.from(e.querySelectorAll(he));e.addEventListener("keydown",r=>{const c=o();if(c.length===0)return;const i=e.ownerDocument.activeElement,d=i?c.indexOf(i):-1;switch(r.key){case"ArrowDown":r.preventDefault(),c[d<0||d===c.length-1?0:d+1].focus();break;case"ArrowUp":r.preventDefault(),c[d<=0?c.length-1:d-1].focus();break;case"Home":r.preventDefault(),c[0].focus();break;case"End":r.preventDefault(),c[c.length-1].focus();break;case"Enter":case" ":d>=0&&(r.preventDefault(),c[d].click());break;case"Escape":case"Tab":r.preventDefault(),t(),n?.focus();break}});const a=o()[0];a&&nextFrame(()=>a.focus())}export function overlayRootFor(e){let n=e;for(;n;){if(n.classList.contains("wmap-overlay-box")||n.tagName==="DIALOG"&&n.matches(":modal"))return n;n=n.parentElement}return e.ownerDocument.body}const te=new WeakMap;export function getTooltip(e=document){const n=te.get(e);if(n&&n.isConnected)return n;const t=n??e.createElement("div");return n||(Object.assign(t.style,{position:"fixed",pointerEvents:"none",background:"rgba(30, 32, 40, 0.93)",color:"#f0f0f2",border:"1px solid rgba(255,255,255,0.10)",padding:"7px 11px",borderRadius:"5px",fontSize:"13px",lineHeight:"1.55",maxWidth:"280px",maxHeight:"min(60vh, 480px)",overflow:"hidden",whiteSpace:"pre-wrap",zIndex:Z_ABOVE,display:"none",fontFamily:"system-ui, sans-serif",boxShadow:"0 3px 10px rgba(0,0,0,0.45)"}),te.set(e,t)),e.body.appendChild(t),t}export function hideTooltip(e=document){const n=te.get(e);n&&(n.style.display="none")}export function reparentTooltip(e){const n=e?.ownerDocument??document,t=getTooltip(n);(e??n.body).appendChild(t)}export function positionTooltip(e,n,t,o){const a=overlayRootFor(n);e.parentElement!==a&&a.appendChild(e);const r=e.ownerDocument.defaultView??window;e.style.left="0",e.style.top="0";const c=e.offsetWidth,i=e.offsetHeight,d=8;let b=t+14,m=o-8;b+c+d>r.innerWidth&&(b=t-c-6),m+i+d>r.innerHeight&&(m=r.innerHeight-i-d),m<d&&(m=d),e.style.left=`${b}px`,e.style.top=`${m}px`}export function buildDataModeEntries(e,n,t){const o=e.some(pe),a=e.some(m=>m.testValues!==void 0&&Object.keys(m.testValues).length>0),r=e.some(m=>m.hbin!=null),c=e.some(m=>m.sbin!=null),i=o?n?.length?n.map(m=>({plotMode:"value",activeTest:m.testNumber,label:m.unit?`${m.name} (${m.unit})`:m.name,logScale:m.logScale})):ue(e).map(m=>({plotMode:"value",activeTest:m,label:`Test ${m}`})):[],d=[...r?[{plotMode:"hardBin",label:MODE_LABELS.hardBin}]:[],...c?[{plotMode:"softBin",label:MODE_LABELS.softBin}]:[]],b=t.includeStacked?[...a?[{plotMode:"stackedValues",label:MODE_LABELS.stackedValues}]:[],...r?[{plotMode:"stackedBins",label:MODE_LABELS.stackedBins}]:[],...c?[{plotMode:"stackedSoftBins",label:MODE_LABELS.stackedSoftBins}]:[]]:[];return{testEntries:i,binEntries:d,stackedEntries:b}}export function metadataKeyHasData(e,n){return e.some(t=>t.metadata?.[n]!==void 0&&t.metadata?.[n]!==null)}export function metadataModeEntry(e){return{plotMode:"metadata",activeMetadataKey:e.key,label:e.label??fe(e.key)}}export function makeMenuSearchBox(e,n="Filter\u2026",t=document){const o=t.createElement("input");return o.type="text",o.placeholder=n,o.setAttribute("aria-label",n),Object.assign(o.style,{display:"block",width:"calc(100% - 20px)",margin:"2px 10px 6px",padding:"4px 8px",fontSize:"12px",boxSizing:"border-box",background:CLR.menuBg,color:CLR.text,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",outline:"none"}),o.addEventListener("click",a=>a.stopPropagation()),o.addEventListener("mousedown",a=>a.stopPropagation()),o.addEventListener("keydown",a=>a.stopPropagation()),o.addEventListener("input",()=>e(o.value.trim().toLowerCase())),o.addEventListener("focus",()=>{o.style.borderColor=CLR.iconActive}),o.addEventListener("blur",()=>{o.style.borderColor=CLR.menuBorder}),queueMicrotask(()=>o.focus()),o}export function buildModeMenuEl(e,n,t,o,a,r,c,i,d=window,b=[]){const{makeMenuRow:m,makeMenuSection:h}=c,s=document.createElement("div"),l=180,x=e.left+l<=(d.innerWidth??1/0)?e.left:Math.max(4,e.right-l);if(Object.assign(s.style,{position:"fixed",top:`${e.bottom+4}px`,left:`${x}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${l}px`,padding:"4px 0",pointerEvents:"auto"}),n.length)if(s.appendChild(h("Test Value")),n.length<=INLINE_TEST_LIMIT)for(const u of n)s.appendChild(m(u.label,a(u),!0,g=>{g.stopPropagation(),r(u,s)}));else{const u=i==="value",g=m(MODE_LABELS.value+" \u25B6",u,!1,()=>{});g.style.display="flex",g.style.justifyContent="space-between",g.style.alignItems="center";let f=null,y=null;const M=()=>{y!==null&&(clearTimeout(y),y=null)},S=()=>{M(),f?.remove(),f=null},L=()=>{M(),y=setTimeout(S,300)},U=()=>{if(f)return;const W=g.getBoundingClientRect(),A=160,k=320,I=W.right+2+A<=(d.innerWidth??1/0)?W.right+2:Math.max(4,W.left-2-A),B=Math.min(W.top-4,Math.max(4,(d.innerHeight??1/0)-k-4));if(f=document.createElement("div"),Object.assign(f.style,{position:"fixed",top:`${B}px`,left:`${I}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_ABOVE,minWidth:`${A}px`,maxHeight:`${k}px`,overflowY:"auto",padding:"4px 0",pointerEvents:"auto"}),n.length>MENU_SEARCH_THRESHOLD){const D=makeMenuSearchBox(F=>{for(const O of E)O.row.style.display=O.label.includes(F)?"":"none"},"Filter tests\u2026");Object.assign(D.style,{position:"sticky",top:"0",zIndex:"1",background:CLR.menuBg}),f.appendChild(D)}const E=[];for(const D of n){const F=m(D.label,a(D),!1,O=>{O.stopPropagation(),S(),r(D,s)});E.push({row:F,label:D.label.toLowerCase()}),f.appendChild(F)}f.addEventListener("mouseenter",M),f.addEventListener("mouseleave",L),(s.parentElement??d.document.body).appendChild(f),d.document.addEventListener("click",S,{once:!0})};g.addEventListener("mouseenter",()=>{M(),U()}),g.addEventListener("mouseleave",L),s.appendChild(g)}if(t.length){s.appendChild(h("Bins"));for(const u of t)s.appendChild(m(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}if(b.length){s.appendChild(h("Metadata"));for(const u of b)s.appendChild(m(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}if(o.length){s.appendChild(h("Lot Aggregation"));for(const u of o)s.appendChild(m(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}return s.setAttribute("role","menu"),s.setAttribute("aria-label","Plot mode"),s}export function markMenuTrigger(e,n){e.setAttribute("aria-haspopup","menu"),e.setAttribute("aria-expanded",n?"true":"false")}export function wireMenuA11y(e,n,t){G(e,n,t)}export function wireExpandToggle(e,n){const t=e.ownerDocument;let o=!1;function a(b){o!==b&&(o=b,n(o))}function r(){a(!1)}function c(){a(!o),o&&t.addEventListener("click",r,{once:!0})}const i=b=>{b.stopPropagation(),c()},d=b=>{b.key==="Enter"||b.key===" "?(b.preventDefault(),c()):b.key==="Escape"&&r()};return e.setAttribute("role","button"),e.tabIndex<0&&(e.tabIndex=0),e.addEventListener("click",i),e.addEventListener("keydown",d),{isOpen:()=>o,close:r,destroy(){e.removeEventListener("click",i),e.removeEventListener("keydown",d),t.removeEventListener("click",r)}}}export function buildCheckMenuEl(e,n,t,o=window){const{makeMenuRow:a,makeMenuSection:r}=t,c=o.document,i=c.createElement("div"),d=168,m=e.left+d<=(o.innerWidth??1/0)?e.left:Math.max(4,e.right-d);Object.assign(i.style,{position:"fixed",top:`${e.bottom+4}px`,left:`${m}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${d}px`,padding:"4px 0",pointerEvents:"auto"});for(const h of n)if("section"in h)i.appendChild(r(h.section));else{if(!(h.enabled!==!1))continue;const l=c.createElement("div");l.setAttribute("role","menuitemcheckbox"),l.setAttribute("aria-checked",h.active?"true":"false"),l.tabIndex=-1,Object.assign(l.style,{display:"flex",alignItems:"center",gap:"6px",padding:"6px 14px",fontSize:"12px",cursor:"pointer",color:h.active?CLR.iconActive:CLR.text,fontWeight:h.active?"700":"400",background:h.active?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"});const v=c.createElement("span");Object.assign(v.style,{width:"12px",flexShrink:"0",color:CLR.iconActive,visibility:h.active?"visible":"hidden"}),v.textContent="\u2713",v.setAttribute("aria-hidden","true");const x=c.createElement("span");x.textContent=h.label,l.appendChild(v),l.appendChild(x),l.addEventListener("mouseenter",()=>{h.active||(l.style.background=CLR.menuHover)}),l.addEventListener("mouseleave",()=>{l.style.background=h.active?CLR.menuActive:"transparent"}),l.addEventListener("focus",()=>{h.active||(l.style.background=CLR.menuHover)}),l.addEventListener("blur",()=>{l.style.background=h.active?CLR.menuActive:"transparent"}),l.addEventListener("click",u=>{u.stopPropagation(),h.onClick(u)}),i.appendChild(l)}return i}export function createToolbarHelpers(e){const n=e.ownerDocument;let t=null;const o=s=>overlayRootFor(s);function a(s,l,v){const x=n.createElement("button");return x.innerHTML=$[s],x.type="button",x.ariaLabel=l,Object.assign(x.style,{display:"flex",alignItems:"center",justifyContent:"center",width:"28px",height:"28px",padding:"0",border:"none",borderRadius:"3px",background:"transparent",color:CLR.icon,cursor:"pointer",pointerEvents:"auto",transition:"background 0.12s, color 0.12s",flexShrink:"0"}),x.addEventListener("mouseenter",u=>{x.dataset.active||(x.style.background=CLR.bgHover,x.style.color=CLR.iconHover),e.innerHTML=x.ariaLabel??l,e.style.display="block",positionTooltip(e,x,u.clientX,u.clientY)}),x.addEventListener("mousemove",u=>{e.style.display==="block"&&positionTooltip(e,x,u.clientX,u.clientY)}),x.addEventListener("mouseleave",()=>{x.dataset.active||(x.style.background="transparent",x.style.color=CLR.icon),e.style.display="none"}),x.addEventListener("click",()=>{e.style.display="none",v()}),x}function r(s,l){l?(s.dataset.active="1",s.style.background=CLR.bgActive,s.style.color=CLR.iconActive):(delete s.dataset.active,s.style.background="transparent",s.style.color=CLR.icon)}function c(){const s=n.createElement("div");return Object.assign(s.style,{width:"1px",height:"18px",background:CLR.separator,margin:"0 2px",flexShrink:"0"}),s}function i(s,l,v,x){const u=n.createElement("div");return u.textContent=s,u.setAttribute("role","menuitemradio"),u.setAttribute("aria-checked",l?"true":"false"),u.tabIndex=-1,Object.assign(u.style,{padding:`6px 14px 6px ${v?"26px":"14px"}`,fontSize:"12px",cursor:"pointer",color:l?CLR.iconActive:CLR.text,fontWeight:l?"700":"400",background:l?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"}),u.addEventListener("mouseenter",()=>{l||(u.style.background=CLR.menuHover)}),u.addEventListener("mouseleave",()=>{u.style.background=l?CLR.menuActive:"transparent"}),u.addEventListener("focus",()=>{l||(u.style.background=CLR.menuHover)}),u.addEventListener("blur",()=>{u.style.background=l?CLR.menuActive:"transparent"}),u.addEventListener("click",x),u}function d(s){const l=n.createElement("div");return l.textContent=s,l.setAttribute("role","presentation"),Object.assign(l.style,{padding:"5px 14px 2px",fontSize:"10px",fontWeight:"600",letterSpacing:"0.05em",color:CLR.label,textTransform:"uppercase",pointerEvents:"none",userSelect:"none"}),l}function b(s,l,v,x,u){const g=()=>{t&&(t.remove(),t=null),f.setAttribute("aria-expanded","false")},f=a(s,l,()=>{if(t){g();return}const y=n.createElement("div"),M=f.getBoundingClientRect(),S=f.ownerDocument.defaultView??window,L=148,W=M.left+L<=(S.innerWidth??1/0)?M.left:Math.max(4,M.right-L);Object.assign(y.style,{position:"fixed",top:`${M.bottom+4}px`,left:`${W}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${L}px`,padding:"4px 0",pointerEvents:"auto"});for(const A of v()){const k=n.createElement("div");k.textContent=A.label,k.dataset.wmapDropdownValue=A.value;const C=A.value===x();k.setAttribute("role","menuitemradio"),k.setAttribute("aria-checked",C?"true":"false"),k.tabIndex=-1,Object.assign(k.style,{padding:"6px 14px",fontSize:"12px",cursor:"pointer",color:C?CLR.iconActive:CLR.text,fontWeight:C?"700":"400",background:C?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"});const I=()=>{A.value!==x()&&(k.style.background=CLR.menuHover)},B=()=>{k.style.background=A.value===x()?CLR.menuActive:"transparent"};k.addEventListener("mouseenter",I),k.addEventListener("mouseleave",B),k.addEventListener("focus",I),k.addEventListener("blur",B),k.addEventListener("click",E=>{E.stopPropagation(),u(A.value),g()}),y.appendChild(k)}y.setAttribute("role","menu"),y.setAttribute("aria-label",l),o(f).appendChild(y),t=y,f.setAttribute("aria-expanded","true"),G(y,f,g)});return f.setAttribute("aria-haspopup","menu"),f.setAttribute("aria-expanded","false"),f}function m(s,l,v,x){function u(){return buildCheckMenuEl(f.getBoundingClientRect(),v().map(y=>"section"in y?y:{...y,onClick:M=>{y.onClick(M),x(f);const S=t;if(!S)return;const L=u();L.setAttribute("role","menu"),L.setAttribute("aria-label",l),S.replaceWith(L),t=L,G(L,f,g)}}),{makeMenuRow:i,makeMenuSection:d},f.ownerDocument.defaultView??window)}const g=()=>{t&&(t.remove(),t=null),f.setAttribute("aria-expanded","false")},f=a(s,l,()=>{if(t){g();return}const y=u();y.setAttribute("role","menu"),y.setAttribute("aria-label",l),o(f).appendChild(y),t=y,f.setAttribute("aria-expanded","true"),G(y,f,g)});return f.setAttribute("aria-haspopup","menu"),f.setAttribute("aria-expanded","false"),x(f),f}function h(s){if(t&&!t.contains(s.target)&&(t.remove(),t=null,s.target?.getAttribute?.("aria-haspopup")!=="menu"))for(const v of document.querySelectorAll('[aria-haspopup="menu"][aria-expanded="true"]'))v.setAttribute("aria-expanded","false")}return{makeBtn:a,setActive:r,makeSep:c,makeMenuRow:i,makeMenuSection:d,makeDropdown:b,makeCheckMenuBtn:m,closeOpenMenu:h,getOpenMenu:()=>t,setOpenMenu:s=>{t=s}}}const xe=7e3;let ve=0;function ae(){return xe+ ++ve}const ge=32,ye=6;let we=0;function ke(){return we++%ye*ge}function Ee(e,n){if(n===e.body)return()=>{};let t=n;for(;t.parentElement&&t.parentElement!==e.body;)t=t.parentElement;return t===e.body?()=>{}:(t.classList.add("wmap-overlay-ancestor"),()=>t.classList.remove("wmap-overlay-ancestor"))}function re(e){const n=e.mode==="modal",t=e.ownerDocument??document,o=t.defaultView??window,a=t.body.style.overflow;n&&(t.body.style.overflow="hidden");let r=null;n&&(r=t.createElement("div"),r.id="wmap-modal-backdrop",Object.assign(r.style,{position:"fixed",inset:"0",background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:Z_ABOVE,backdropFilter:"blur(3px)"}));const c=t.activeElement,i=t.createElement("div");if(i.className=n?"wmap-modal-box wmap-overlay-box":"wmap-window-box wmap-overlay-box",i.setAttribute("role","dialog"),n&&i.setAttribute("aria-modal","true"),i.setAttribute("aria-label",e.title??"Expanded wafer map"),i.tabIndex=-1,Object.assign(i.style,{position:"relative",background:CLR.menuBg,borderRadius:"12px",overflow:"hidden",display:"flex",flexDirection:"column",width:"min(90vw, 700px)",height:"min(90vh, 700px)",boxShadow:"0 20px 60px rgba(0,0,0,0.4)",minWidth:"320px",minHeight:"240px",maxWidth:"100vw",maxHeight:"100vh",zIndex:n?Z_ABOVE2:String(ae())}),!n){const p=ke();Object.assign(i.style,{position:"fixed",top:`${Math.round(o.innerHeight*.08)+p}px`,left:`${Math.round(o.innerWidth*.08)+p}px`})}const d=t.createElement("div");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"6px",padding:"10px 14px",borderBottom:`1px solid ${CLR.menuBorder}`,flexShrink:"0"});const b={border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",background:CLR.panelBg,cursor:"pointer",color:CLR.label,lineHeight:"1",padding:"0",display:"flex",alignItems:"center",justifyContent:"center",width:"28px",height:"28px"};if(e.title){const p=t.createElement("span");p.textContent=e.title,p.title=e.title,p.dataset.wmapWindowTitle="1",Object.assign(p.style,{fontWeight:"700",fontSize:"14px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:"0"}),d.appendChild(p)}const m=t.createElement("div");m.style.flex="1",d.appendChild(m);let h=null;n||(h=t.createElement("button"),h.type="button",h.innerHTML=$.windowMinimize,h.title="Minimize",h.setAttribute("aria-label","Minimize"),Object.assign(h.style,b),h.addEventListener("click",()=>L(!f)),d.appendChild(h));const s=t.createElement("button");s.type="button",s.innerHTML=$.maximize,s.title="Maximize (F)",s.setAttribute("aria-label","Maximize"),Object.assign(s.style,b),s.addEventListener("click",()=>g(!v));const l=t.createElement("button");l.type="button",l.innerHTML=$.close,l.title="Close (Esc)",l.setAttribute("aria-label","Close"),Object.assign(l.style,b),l.addEventListener("click",C),d.appendChild(s),d.appendChild(l);let v=!1,x="",u="";function g(p){v=p,s.innerHTML=v?$.minimize:$.maximize,s.title=v?"Restore (F)":"Maximize (F)",s.setAttribute("aria-label",v?"Restore":"Maximize"),E.style.display=v?"none":"block",v?(i.style.borderRadius="0",i.style.width="100vw",i.style.height="100vh",n||(x=i.style.top,u=i.style.left,i.style.top="0",i.style.left="0")):(i.style.borderRadius="12px",i.style.width="min(90vw, 700px)",i.style.height="min(90vh, 700px)",n||(i.style.top=x,i.style.left=u)),e.onMaximizeChange?.(v,i)}let f=!1,y="",M="";const S=220;function L(p){f=p,h.innerHTML=f?$.windowRestore:$.windowMinimize,h.title=f?"Restore":"Minimize",h.setAttribute("aria-label",f?"Restore":"Minimize"),E.style.display=f?"none":"block",f?(y=i.style.height,M=i.style.width,i.style.minHeight="0",i.style.height="auto",i.style.minWidth="0",i.style.width=`${S}px`,s.disabled=!0,s.style.opacity="0.4",s.style.cursor="default",B.style.display="none"):(i.style.minHeight="240px",i.style.height=y||"min(90vh, 700px)",i.style.minWidth="320px",i.style.width=M||"min(90vw, 700px)",s.disabled=!1,s.style.opacity="1",s.style.cursor="pointer",B.style.display="flex")}function U(){const p=t.body.style.userSelect;return t.body.style.userSelect="none",()=>{t.body.style.userSelect=p}}n||(d.style.cursor="move",d.addEventListener("pointerdown",p=>{if(v||p.target.closest('button, [role="button"]'))return;p.preventDefault();const T=U(),z=p.clientX,R=p.clientY,H=i.offsetTop,_=i.offsetLeft,Z=o.innerHeight-d.offsetHeight,Q=o.innerWidth-40,X=40-i.offsetWidth;d.setPointerCapture(p.pointerId);const N=V=>{const J=Math.min(Math.max(H+(V.clientY-R),0),Z),de=Math.min(Math.max(_+(V.clientX-z),X),Q);i.style.top=`${J}px`,i.style.left=`${de}px`},P=V=>{T(),d.releasePointerCapture(V.pointerId),d.removeEventListener("pointermove",N),d.removeEventListener("pointerup",P)};d.addEventListener("pointermove",N),d.addEventListener("pointerup",P)}));const W='button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"]),[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"]';function A(p){const T=Array.from(i.querySelectorAll(W)).filter(_=>_.offsetParent!==null||_===t.activeElement);if(T.length===0){p.preventDefault(),i.focus();return}const z=T[0],R=T[T.length-1],H=t.activeElement;p.shiftKey&&(H===z||!i.contains(H))?(p.preventDefault(),R.focus()):!p.shiftKey&&H===R&&(p.preventDefault(),z.focus())}const k=p=>{if(p.key==="Escape"){C();return}if(n&&(p.key==="e"||p.key==="E")){C();return}if(n&&p.key==="Tab"){A(p);return}(p.key==="f"||p.key==="F")&&!f&&g(!v)};function C(){n?t.removeEventListener("keydown",k):i.removeEventListener("keydown",k),q.remove(),ce(),hideTooltip(t),reparentTooltip(t.body),r?r.remove():i.remove(),n&&(t.body.style.overflow=a),c?.focus?.(),e.onClose()}function I(){n||(i.style.zIndex=String(ae()))}const B=t.createElement("div");Object.assign(B.style,{flex:"1",minHeight:"0",minWidth:"0",display:"flex",overflow:"hidden"});const E=t.createElement("div");E.tabIndex=0,E.setAttribute("role","separator"),E.setAttribute("aria-label","Resize window (arrow keys, or drag)"),Object.assign(E.style,{position:"absolute",right:"0",bottom:"0",width:"16px",height:"16px",cursor:"nwse-resize",touchAction:"none"}),E.innerHTML='<svg viewBox="0 0 16 16" width="16" height="16" style="display:block"><path d="M15 15 L15 9 M15 15 L9 15 M15 15 L15 3 M15 15 L3 15" stroke="currentColor" stroke-width="1" opacity="0.35" fill="none"/></svg>',E.style.color=CLR.label;const D=320,F=240,O=20;function Y(p,T){const z=o.innerWidth-i.offsetLeft,R=o.innerHeight-i.offsetTop,H=Math.min(Math.max(i.offsetWidth+p,D),z),_=Math.min(Math.max(i.offsetHeight+T,F),R);i.style.width=`${H}px`,i.style.height=`${_}px`}E.addEventListener("keydown",p=>{if(!(v||f))switch(p.key){case"ArrowRight":p.preventDefault(),Y(O,0);break;case"ArrowLeft":p.preventDefault(),Y(-O,0);break;case"ArrowDown":p.preventDefault(),Y(0,O);break;case"ArrowUp":p.preventDefault(),Y(0,-O);break}}),E.addEventListener("pointerdown",p=>{if(v||f)return;p.preventDefault();const T=U(),z=p.clientX,R=p.clientY,H=i.offsetWidth,_=i.offsetHeight,Z=o.innerWidth-i.offsetLeft,Q=o.innerHeight-i.offsetTop;E.setPointerCapture(p.pointerId);const X=P=>{const V=Math.min(Math.max(H+(P.clientX-z),D),Z),J=Math.min(Math.max(_+(P.clientY-R),F),Q);i.style.width=`${V}px`,i.style.height=`${J}px`},N=P=>{T(),E.releasePointerCapture(P.pointerId),E.removeEventListener("pointermove",X),E.removeEventListener("pointerup",N)};E.addEventListener("pointermove",X),E.addEventListener("pointerup",N)}),i.appendChild(d),i.appendChild(B),i.appendChild(E);const K=e.anchor?overlayRootFor(e.anchor):t.body;r?(r.appendChild(i),K.appendChild(r)):K.appendChild(i);const ce=Ee(t,K),q=t.createElement("style");return q.textContent=`@media print{
1
+ import{getUniqueTestNumbers as fe}from"../renderer/buildView.js";import{dieHasTestData as me}from"../renderer/buildWaferMap.js";import{prettyKey as be}from"../core/utils.js";import{listColorSchemes as oe}from"../renderer/colorSchemes.js";import{ICONS as $}from"./icons.js";import{WMAP_VERSION as he,WMAP_BUILD_TIME as xe}from"./version.js";let ie=!1;export function logWmapVersionOnce(){ie||(ie=!0,console.log(`[wmap] v${he} (built ${xe})`))}export const WMAP_TOKEN_NAMES=["z","icon","icon-hover","icon-active","bg-hover","bg-active","separator","surface","border","menu-hover","menu-active","panel-bg","text-muted","text","text-strong","warn-bg","warn-border","warn-text","err-bg","err-border","err-text","info-bg","info-text","selected","finding-indicator","canvas-bg","bar-fill","bar-fill-muted"];const w=(e,n)=>`var(--wmap-${e}, ${n})`;export const CLR={icon:w("icon","#506784"),iconHover:w("icon-hover","#2a3f5f"),iconActive:w("icon-active","#1a65ca"),bgHover:w("bg-hover","#edf0f8"),bgActive:w("bg-active","#dce8f8"),separator:w("separator","rgba(0,0,0,0.12)"),menuBg:w("surface","#fff"),menuBorder:w("border","rgba(0,0,0,0.12)"),menuHover:w("menu-hover","#f0f4fc"),menuActive:w("menu-active","#dce8f8"),panelBg:w("panel-bg","#fafbfc"),label:w("text-muted","#647687"),value:w("text-strong","#1f2f43"),text:w("text","#333"),warnBg:w("warn-bg","#fffbe6"),warnBorder:w("warn-border","#f0c040"),warnText:w("warn-text","#7a5800"),errBg:w("err-bg","#fef2f2"),errBorder:w("err-border","#dc8a8a"),errText:w("err-text","#7a1c1c"),infoBg:w("info-bg","#dce8f8"),infoText:w("info-text","#334155"),findingHighlight:w("selected","#e07a20"),findingIndicator:w("finding-indicator","#b7551a"),barFill:w("bar-fill","#2a6fc0"),barFillMuted:w("bar-fill-muted","#94a3b8")};export function sevColor(e){return e==="unusual"?"#a84112":e==="notable"?"#8a6500":CLR.icon}export const ROTATIONS=[0,90,180,270],INLINE_TEST_LIMIT=6,MENU_SEARCH_THRESHOLD=8,DEFAULT_OVERLAY_Z=6e3,Z_BASE=`var(--wmap-z, ${DEFAULT_OVERLAY_Z})`,Z_ABOVE=`calc(var(--wmap-z, ${DEFAULT_OVERLAY_Z}) + 1)`,Z_MENU=`calc(var(--wmap-z, ${DEFAULT_OVERLAY_Z}) + 2)`,Z_ABOVE2=`calc(var(--wmap-z, ${DEFAULT_OVERLAY_Z}) + 3)`;export function applyOverlayZ(e){if(e==null)return()=>{};const n=document.documentElement,t=n.style.getPropertyValue("--wmap-z");return n.style.setProperty("--wmap-z",String(e)),()=>{t?n.style.setProperty("--wmap-z",t):n.style.removeProperty("--wmap-z")}}export function copyWmapThemeTokens(e,n){const t=getComputedStyle(e);for(const o of WMAP_TOKEN_NAMES){const a=t.getPropertyValue(`--wmap-${o}`).trim();a&&n.style.setProperty(`--wmap-${o}`,a)}}export function syncWmapPopupTheme(e,n,t){const o=()=>{copyWmapThemeTokens(e,n),t?.()},a=new window.MutationObserver(o);a.observe(e,{attributes:!0,attributeFilter:["style","class"]}),a.observe(document.documentElement,{attributes:!0,attributeFilter:["style","class"]});const r=window.matchMedia("(prefers-color-scheme: dark)");return r.addEventListener("change",o),()=>{a.disconnect(),r.removeEventListener("change",o)}}let ee=null;export function setDetachWindowOpener(e){ee=e}export function openDetachWindow(e){return ee?ee(e):window.open("","_blank","width=560,height=600")}export const MODE_LABELS={value:"Test Value",hardBin:"Hard Bin",softBin:"Soft Bin",stackedValues:"Stacked Test Values",stackedBins:"Stacked Hard Bins",stackedSoftBins:"Stacked Soft Bins",metadata:"Metadata"},BIN_LEGEND_MODES=new Set(["hardBin","softBin","metadata"]),STACKED_MODES=new Set(["stackedValues","stackedBins","stackedSoftBins"]);export function saveImageBlob(e,n,t){const o=`${n}.png`;if(t){t(e,o);return}const a=URL.createObjectURL(e),r=document.createElement("a");r.href=a,r.download=o,r.click(),URL.revokeObjectURL(a)}export function saveTextFile(e,n,t,o){if(o){o(e,n,t);return}const a=new Blob([e],{type:t}),r=URL.createObjectURL(a),d=document.createElement("a");d.href=r,d.download=n,d.click(),URL.revokeObjectURL(r)}const ve='[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"]';export function nextFrame(e,n=window){const t=n.requestAnimationFrame;typeof t=="function"?t.call(n,e):setTimeout(e,0)}function We(e,n,t){e.setAttribute("role","menu"),e.setAttribute("aria-label",n);for(const o of Array.from(e.children)){const a=t(o);a&&(o.setAttribute("role",a),o.tabIndex=-1)}}function X(e,n,t){const o=()=>Array.from(e.querySelectorAll(ve));e.addEventListener("keydown",r=>{const d=o();if(d.length===0)return;const i=e.ownerDocument.activeElement,l=i?d.indexOf(i):-1;switch(r.key){case"ArrowDown":r.preventDefault(),d[l<0||l===d.length-1?0:l+1].focus();break;case"ArrowUp":r.preventDefault(),d[l<=0?d.length-1:l-1].focus();break;case"Home":r.preventDefault(),d[0].focus();break;case"End":r.preventDefault(),d[d.length-1].focus();break;case"Enter":case" ":l>=0&&(r.preventDefault(),d[l].click());break;case"Escape":case"Tab":r.preventDefault(),t(),n?.focus();break}});const a=o()[0];a&&nextFrame(()=>a.focus())}export function overlayRootFor(e){let n=e;for(;n;){if(n.classList.contains("wmap-overlay-box")||n.tagName==="DIALOG"&&n.matches(":modal"))return n;n=n.parentElement}return e.ownerDocument.body}const ae=new WeakMap;export function menuLayerFor(e){const n=overlayRootFor(e),t=ae.get(n);if(t&&t.isConnected)return t;const a=e.ownerDocument.createElement("div");return a.dataset.wmapMenuLayer="1",Object.assign(a.style,{position:"fixed",inset:"0",zIndex:Z_MENU,pointerEvents:"none"}),n.appendChild(a),ae.set(n,a),a}const te=new WeakMap;export function getTooltip(e=document){const n=te.get(e);if(n&&n.isConnected)return n;const t=n??e.createElement("div");return n||(Object.assign(t.style,{position:"fixed",pointerEvents:"none",background:"rgba(30, 32, 40, 0.93)",color:"#f0f0f2",border:"1px solid rgba(255,255,255,0.10)",padding:"7px 11px",borderRadius:"5px",fontSize:"13px",lineHeight:"1.55",maxWidth:"280px",maxHeight:"min(60vh, 480px)",overflow:"hidden",whiteSpace:"pre-wrap",zIndex:Z_ABOVE,display:"none",fontFamily:"system-ui, sans-serif",boxShadow:"0 3px 10px rgba(0,0,0,0.45)"}),te.set(e,t)),e.body.appendChild(t),t}export function hideTooltip(e=document){const n=te.get(e);n&&(n.style.display="none")}export function reparentTooltip(e){const n=e?.ownerDocument??document,t=getTooltip(n);(e??n.body).appendChild(t)}export function positionTooltip(e,n,t,o){const a=overlayRootFor(n);e.parentElement!==a&&a.appendChild(e);const r=e.ownerDocument.defaultView??window;e.style.left="0",e.style.top="0";const d=e.offsetWidth,i=e.offsetHeight,l=8;let x=t+14,f=o-8;x+d+l>r.innerWidth&&(x=t-d-6),f+i+l>r.innerHeight&&(f=r.innerHeight-i-l),f<l&&(f=l),e.style.left=`${x}px`,e.style.top=`${f}px`}export function buildDataModeEntries(e,n,t){const o=e.some(me),a=e.some(f=>f.testValues!==void 0&&Object.keys(f.testValues).length>0),r=e.some(f=>f.hbin!=null),d=e.some(f=>f.sbin!=null),i=o?n?.length?n.map(f=>({plotMode:"value",activeTest:f.testNumber,label:f.unit?`${f.name} (${f.unit})`:f.name,logScale:f.logScale})):fe(e).map(f=>({plotMode:"value",activeTest:f,label:`Test ${f}`})):[],l=[...r?[{plotMode:"hardBin",label:MODE_LABELS.hardBin}]:[],...d?[{plotMode:"softBin",label:MODE_LABELS.softBin}]:[]],x=t.includeStacked?[...a?[{plotMode:"stackedValues",label:MODE_LABELS.stackedValues}]:[],...r?[{plotMode:"stackedBins",label:MODE_LABELS.stackedBins}]:[],...d?[{plotMode:"stackedSoftBins",label:MODE_LABELS.stackedSoftBins}]:[]]:[];return{testEntries:i,binEntries:l,stackedEntries:x}}export function metadataKeyHasData(e,n){return e.some(t=>t.metadata?.[n]!==void 0&&t.metadata?.[n]!==null)}export function metadataModeEntry(e){return{plotMode:"metadata",activeMetadataKey:e.key,label:e.label??be(e.key)}}export function makeMenuSearchBox(e,n="Filter\u2026",t=document){const o=t.createElement("input");return o.type="text",o.placeholder=n,o.setAttribute("aria-label",n),Object.assign(o.style,{display:"block",width:"calc(100% - 20px)",margin:"2px 10px 6px",padding:"4px 8px",fontSize:"12px",boxSizing:"border-box",background:CLR.menuBg,color:CLR.text,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",outline:"none"}),o.addEventListener("click",a=>a.stopPropagation()),o.addEventListener("mousedown",a=>a.stopPropagation()),o.addEventListener("keydown",a=>a.stopPropagation()),o.addEventListener("input",()=>e(o.value.trim().toLowerCase())),o.addEventListener("focus",()=>{o.style.borderColor=CLR.iconActive}),o.addEventListener("blur",()=>{o.style.borderColor=CLR.menuBorder}),queueMicrotask(()=>o.focus()),o}export function buildModeMenuEl(e,n,t,o,a,r,d,i,l=window,x=[]){const{makeMenuRow:f,makeMenuSection:m}=d,s=document.createElement("div"),c=180,h=e.left+c<=(l.innerWidth??1/0)?e.left:Math.max(4,e.right-c);if(Object.assign(s.style,{position:"fixed",top:`${e.bottom+4}px`,left:`${h}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${c}px`,padding:"4px 0",pointerEvents:"auto"}),n.length)if(s.appendChild(m("Test Value")),n.length<=INLINE_TEST_LIMIT)for(const u of n)s.appendChild(f(u.label,a(u),!0,g=>{g.stopPropagation(),r(u,s)}));else{const u=i==="value",g=f(MODE_LABELS.value+" \u25B6",u,!1,()=>{});g.style.display="flex",g.style.justifyContent="space-between",g.style.alignItems="center";let b=null,y=null;const L=()=>{y!==null&&(clearTimeout(y),y=null)},S=()=>{L(),b?.remove(),b=null},M=()=>{L(),y=setTimeout(S,300)},N=()=>{if(b)return;const I=g.getBoundingClientRect(),A=160,k=320,W=I.right+2+A<=(l.innerWidth??1/0)?I.right+2:Math.max(4,I.left-2-A),B=Math.min(I.top-4,Math.max(4,(l.innerHeight??1/0)-k-4));if(b=document.createElement("div"),Object.assign(b.style,{position:"fixed",top:`${B}px`,left:`${W}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_ABOVE,minWidth:`${A}px`,maxHeight:`${k}px`,overflowY:"auto",padding:"4px 0",pointerEvents:"auto"}),n.length>MENU_SEARCH_THRESHOLD){const D=makeMenuSearchBox(j=>{for(const H of E)H.row.style.display=H.label.includes(j)?"":"none"},"Filter tests\u2026");Object.assign(D.style,{position:"sticky",top:"0",zIndex:"1",background:CLR.menuBg}),b.appendChild(D)}const E=[];for(const D of n){const j=f(D.label,a(D),!1,H=>{H.stopPropagation(),S(),r(D,s)});E.push({row:j,label:D.label.toLowerCase()}),b.appendChild(j)}b.addEventListener("mouseenter",L),b.addEventListener("mouseleave",M),(s.parentElement??l.document.body).appendChild(b),l.document.addEventListener("click",S,{once:!0})};g.addEventListener("mouseenter",()=>{L(),N()}),g.addEventListener("mouseleave",M),s.appendChild(g)}if(t.length){s.appendChild(m("Bins"));for(const u of t)s.appendChild(f(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}if(x.length){s.appendChild(m("Metadata"));for(const u of x)s.appendChild(f(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}if(o.length){s.appendChild(m("Lot Aggregation"));for(const u of o)s.appendChild(f(u.label,a(u),!1,g=>{g.stopPropagation(),r(u,s)}))}return s.setAttribute("role","menu"),s.setAttribute("aria-label","Plot mode"),s}export function markMenuTrigger(e,n){e.setAttribute("aria-haspopup","menu"),e.setAttribute("aria-expanded",n?"true":"false")}export function wireMenuA11y(e,n,t){X(e,n,t)}export function wireExpandToggle(e,n){const t=e.ownerDocument;let o=!1;function a(x){o!==x&&(o=x,n(o))}function r(){a(!1)}function d(){a(!o),o&&t.addEventListener("click",r,{once:!0})}const i=x=>{x.stopPropagation(),d()},l=x=>{x.key==="Enter"||x.key===" "?(x.preventDefault(),d()):x.key==="Escape"&&r()};return e.setAttribute("role","button"),e.tabIndex<0&&(e.tabIndex=0),e.addEventListener("click",i),e.addEventListener("keydown",l),{isOpen:()=>o,close:r,destroy(){e.removeEventListener("click",i),e.removeEventListener("keydown",l),t.removeEventListener("click",r)}}}export function buildCheckMenuEl(e,n,t,o=window){const{makeMenuRow:a,makeMenuSection:r}=t,d=o.document,i=d.createElement("div"),l=168,f=e.left+l<=(o.innerWidth??1/0)?e.left:Math.max(4,e.right-l);Object.assign(i.style,{position:"fixed",top:`${e.bottom+4}px`,left:`${f}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${l}px`,padding:"4px 0",pointerEvents:"auto"});for(const m of n)if("section"in m)i.appendChild(r(m.section));else{const s=m.enabled!==!1;if(!s&&!m.disabledHint)continue;const c=d.createElement("div");c.setAttribute("role","menuitemcheckbox"),c.setAttribute("aria-checked",m.active?"true":"false"),c.tabIndex=-1,s||(c.setAttribute("aria-disabled","true"),c.title=m.disabledHint),Object.assign(c.style,{display:"flex",alignItems:"center",gap:"6px",padding:"6px 14px",fontSize:"12px",cursor:s?"pointer":"default",color:s?m.active?CLR.iconActive:CLR.text:CLR.label,fontWeight:m.active?"700":"400",background:m.active?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"});const v=d.createElement("span");Object.assign(v.style,{width:"12px",flexShrink:"0",color:CLR.iconActive,visibility:m.active?"visible":"hidden"}),v.textContent="\u2713",v.setAttribute("aria-hidden","true");const h=d.createElement("span");h.textContent=m.label,c.appendChild(v),c.appendChild(h),s?(c.addEventListener("mouseenter",()=>{m.active||(c.style.background=CLR.menuHover)}),c.addEventListener("mouseleave",()=>{c.style.background=m.active?CLR.menuActive:"transparent"}),c.addEventListener("focus",()=>{m.active||(c.style.background=CLR.menuHover)}),c.addEventListener("blur",()=>{c.style.background=m.active?CLR.menuActive:"transparent"}),c.addEventListener("click",u=>{u.stopPropagation(),m.onClick(u)})):c.addEventListener("click",u=>{u.stopPropagation()}),i.appendChild(c)}return i}export function createToolbarHelpers(e){const n=e.ownerDocument;let t=null;const o=s=>menuLayerFor(s);function a(s,c,v){const h=n.createElement("button");return h.innerHTML=$[s],h.type="button",h.ariaLabel=c,Object.assign(h.style,{display:"flex",alignItems:"center",justifyContent:"center",width:"28px",height:"28px",padding:"0",border:"none",borderRadius:"3px",background:"transparent",color:CLR.icon,cursor:"pointer",pointerEvents:"auto",transition:"background 0.12s, color 0.12s",flexShrink:"0"}),h.addEventListener("mouseenter",u=>{h.dataset.active||(h.style.background=CLR.bgHover,h.style.color=CLR.iconHover),e.innerHTML=h.ariaLabel??c,e.style.display="block",positionTooltip(e,h,u.clientX,u.clientY)}),h.addEventListener("mousemove",u=>{e.style.display==="block"&&positionTooltip(e,h,u.clientX,u.clientY)}),h.addEventListener("mouseleave",()=>{h.dataset.active||(h.style.background="transparent",h.style.color=CLR.icon),e.style.display="none"}),h.addEventListener("click",()=>{e.style.display="none",v()}),h}function r(s,c){c?(s.dataset.active="1",s.style.background=CLR.bgActive,s.style.color=CLR.iconActive):(delete s.dataset.active,s.style.background="transparent",s.style.color=CLR.icon)}function d(){const s=n.createElement("div");return Object.assign(s.style,{width:"1px",height:"18px",background:CLR.separator,margin:"0 2px",flexShrink:"0"}),s}function i(s,c,v,h){const u=n.createElement("div");return u.textContent=s,u.setAttribute("role","menuitemradio"),u.setAttribute("aria-checked",c?"true":"false"),u.tabIndex=-1,Object.assign(u.style,{padding:`6px 14px 6px ${v?"26px":"14px"}`,fontSize:"12px",cursor:"pointer",color:c?CLR.iconActive:CLR.text,fontWeight:c?"700":"400",background:c?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"}),u.addEventListener("mouseenter",()=>{c||(u.style.background=CLR.menuHover)}),u.addEventListener("mouseleave",()=>{u.style.background=c?CLR.menuActive:"transparent"}),u.addEventListener("focus",()=>{c||(u.style.background=CLR.menuHover)}),u.addEventListener("blur",()=>{u.style.background=c?CLR.menuActive:"transparent"}),u.addEventListener("click",h),u}function l(s){const c=n.createElement("div");return c.textContent=s,c.setAttribute("role","presentation"),Object.assign(c.style,{padding:"5px 14px 2px",fontSize:"10px",fontWeight:"600",letterSpacing:"0.05em",color:CLR.label,textTransform:"uppercase",pointerEvents:"none",userSelect:"none"}),c}function x(s,c,v,h,u){const g=()=>{t&&(t.remove(),t=null),b.setAttribute("aria-expanded","false")},b=a(s,c,()=>{if(t){g();return}const y=n.createElement("div"),L=b.getBoundingClientRect(),S=b.ownerDocument.defaultView??window,M=148,I=L.left+M<=(S.innerWidth??1/0)?L.left:Math.max(4,L.right-M);Object.assign(y.style,{position:"fixed",top:`${L.bottom+4}px`,left:`${I}px`,background:CLR.menuBg,border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",zIndex:Z_BASE,minWidth:`${M}px`,padding:"4px 0",pointerEvents:"auto"});for(const A of v()){const k=n.createElement("div");k.textContent=A.label,k.dataset.wmapDropdownValue=A.value;const C=A.value===h();k.setAttribute("role","menuitemradio"),k.setAttribute("aria-checked",C?"true":"false"),k.tabIndex=-1,Object.assign(k.style,{padding:"6px 14px",fontSize:"12px",cursor:"pointer",color:C?CLR.iconActive:CLR.text,fontWeight:C?"700":"400",background:C?CLR.menuActive:"transparent",whiteSpace:"nowrap",outline:"none"});const W=()=>{A.value!==h()&&(k.style.background=CLR.menuHover)},B=()=>{k.style.background=A.value===h()?CLR.menuActive:"transparent"};k.addEventListener("mouseenter",W),k.addEventListener("mouseleave",B),k.addEventListener("focus",W),k.addEventListener("blur",B),k.addEventListener("click",E=>{E.stopPropagation(),u(A.value),g()}),y.appendChild(k)}y.setAttribute("role","menu"),y.setAttribute("aria-label",c),o(b).appendChild(y),t=y,b.setAttribute("aria-expanded","true"),X(y,b,g)});return b.setAttribute("aria-haspopup","menu"),b.setAttribute("aria-expanded","false"),b}function f(s,c,v,h){function u(){return buildCheckMenuEl(b.getBoundingClientRect(),v().map(y=>"section"in y?y:{...y,onClick:L=>{y.onClick(L),h(b);const S=t;if(!S)return;const M=u();M.setAttribute("role","menu"),M.setAttribute("aria-label",c),S.replaceWith(M),t=M,X(M,b,g)}}),{makeMenuRow:i,makeMenuSection:l},b.ownerDocument.defaultView??window)}const g=()=>{t&&(t.remove(),t=null),b.setAttribute("aria-expanded","false")},b=a(s,c,()=>{if(t){g();return}const y=u();y.setAttribute("role","menu"),y.setAttribute("aria-label",c),o(b).appendChild(y),t=y,b.setAttribute("aria-expanded","true"),X(y,b,g)});return b.setAttribute("aria-haspopup","menu"),b.setAttribute("aria-expanded","false"),h(b),b}function m(s){if(t&&!t.contains(s.target)&&(t.remove(),t=null,s.target?.getAttribute?.("aria-haspopup")!=="menu"))for(const v of document.querySelectorAll('[aria-haspopup="menu"][aria-expanded="true"]'))v.setAttribute("aria-expanded","false")}return{makeBtn:a,setActive:r,makeSep:d,makeMenuRow:i,makeMenuSection:l,makeDropdown:x,makeCheckMenuBtn:f,closeOpenMenu:m,getOpenMenu:()=>t,setOpenMenu:s=>{t=s}}}const ge=7e3;let ye=0;function re(){return ge+ ++ye}const we=32,ke=6;let Ee=0;function Le(){return Ee++%ke*we}function Me(e,n){if(n===e.body)return()=>{};let t=n;for(;t.parentElement&&t.parentElement!==e.body;)t=t.parentElement;return t===e.body?()=>{}:(t.classList.add("wmap-overlay-ancestor"),()=>t.classList.remove("wmap-overlay-ancestor"))}function se(e){const n=e.mode==="modal",t=e.ownerDocument??document,o=t.defaultView??window,a=t.body.style.overflow;n&&(t.body.style.overflow="hidden");let r=null;n&&(r=t.createElement("div"),r.id="wmap-modal-backdrop",Object.assign(r.style,{position:"fixed",inset:"0",background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:Z_ABOVE,backdropFilter:"blur(3px)"}));const d=t.activeElement,i=t.createElement("div");if(i.className=n?"wmap-modal-box wmap-overlay-box":"wmap-window-box wmap-overlay-box",i.setAttribute("role","dialog"),n&&i.setAttribute("aria-modal","true"),i.setAttribute("aria-label",e.title??"Expanded wafer map"),i.tabIndex=-1,Object.assign(i.style,{position:"relative",background:CLR.menuBg,borderRadius:"12px",overflow:"hidden",display:"flex",flexDirection:"column",width:"min(90vw, 700px)",height:"min(90vh, 700px)",boxShadow:"0 20px 60px rgba(0,0,0,0.4)",minWidth:"320px",minHeight:"240px",maxWidth:"100vw",maxHeight:"100vh",zIndex:n?Z_ABOVE2:String(re())}),!n){const p=Le();Object.assign(i.style,{position:"fixed",top:`${Math.round(o.innerHeight*.08)+p}px`,left:`${Math.round(o.innerWidth*.08)+p}px`})}const l=t.createElement("div");Object.assign(l.style,{display:"flex",alignItems:"center",gap:"6px",padding:"10px 14px",borderBottom:`1px solid ${CLR.menuBorder}`,flexShrink:"0"});const x={border:`1px solid ${CLR.menuBorder}`,borderRadius:"4px",background:CLR.panelBg,cursor:"pointer",color:CLR.label,lineHeight:"1",padding:"0",display:"flex",alignItems:"center",justifyContent:"center",width:"28px",height:"28px"};if(e.title){const p=t.createElement("span");p.textContent=e.title,p.title=e.title,p.dataset.wmapWindowTitle="1",Object.assign(p.style,{fontWeight:"700",fontSize:"14px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:"0"}),l.appendChild(p)}const f=t.createElement("div");f.style.flex="1",l.appendChild(f);let m=null;n||(m=t.createElement("button"),m.type="button",m.innerHTML=$.windowMinimize,m.title="Minimize",m.setAttribute("aria-label","Minimize"),Object.assign(m.style,x),m.addEventListener("click",()=>M(!b)),l.appendChild(m));const s=t.createElement("button");s.type="button",s.innerHTML=$.maximize,s.title="Maximize (F)",s.setAttribute("aria-label","Maximize"),Object.assign(s.style,x),s.addEventListener("click",()=>g(!v));const c=t.createElement("button");c.type="button",c.innerHTML=$.close,c.title="Close (Esc)",c.setAttribute("aria-label","Close"),Object.assign(c.style,x),c.addEventListener("click",C),l.appendChild(s),l.appendChild(c);let v=!1,h="",u="";function g(p){v=p,s.innerHTML=v?$.minimize:$.maximize,s.title=v?"Restore (F)":"Maximize (F)",s.setAttribute("aria-label",v?"Restore":"Maximize"),E.style.display=v?"none":"block",v?(i.style.borderRadius="0",i.style.width="100vw",i.style.height="100vh",n||(h=i.style.top,u=i.style.left,i.style.top="0",i.style.left="0")):(i.style.borderRadius="12px",i.style.width="min(90vw, 700px)",i.style.height="min(90vh, 700px)",n||(i.style.top=h,i.style.left=u)),e.onMaximizeChange?.(v,i)}let b=!1,y="",L="";const S=220;function M(p){b=p,m.innerHTML=b?$.windowRestore:$.windowMinimize,m.title=b?"Restore":"Minimize",m.setAttribute("aria-label",b?"Restore":"Minimize"),E.style.display=b?"none":"block",b?(y=i.style.height,L=i.style.width,i.style.minHeight="0",i.style.height="auto",i.style.minWidth="0",i.style.width=`${S}px`,s.disabled=!0,s.style.opacity="0.4",s.style.cursor="default",B.style.display="none"):(i.style.minHeight="240px",i.style.height=y||"min(90vh, 700px)",i.style.minWidth="320px",i.style.width=L||"min(90vw, 700px)",s.disabled=!1,s.style.opacity="1",s.style.cursor="pointer",B.style.display="flex")}function N(){const p=t.body.style.userSelect;return t.body.style.userSelect="none",()=>{t.body.style.userSelect=p}}n||(l.style.cursor="move",l.addEventListener("pointerdown",p=>{if(v||p.target.closest('button, [role="button"]'))return;p.preventDefault();const T=N(),z=p.clientX,R=p.clientY,O=i.offsetTop,_=i.offsetLeft,q=o.innerHeight-l.offsetHeight,Q=o.innerWidth-40,G=40-i.offsetWidth;l.setPointerCapture(p.pointerId);const U=V=>{const J=Math.min(Math.max(O+(V.clientY-R),0),q),pe=Math.min(Math.max(_+(V.clientX-z),G),Q);i.style.top=`${J}px`,i.style.left=`${pe}px`},F=V=>{T(),l.releasePointerCapture(V.pointerId),l.removeEventListener("pointermove",U),l.removeEventListener("pointerup",F)};l.addEventListener("pointermove",U),l.addEventListener("pointerup",F)}));const I='button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"]),[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"]';function A(p){const T=Array.from(i.querySelectorAll(I)).filter(_=>_.offsetParent!==null||_===t.activeElement);if(T.length===0){p.preventDefault(),i.focus();return}const z=T[0],R=T[T.length-1],O=t.activeElement;p.shiftKey&&(O===z||!i.contains(O))?(p.preventDefault(),R.focus()):!p.shiftKey&&O===R&&(p.preventDefault(),z.focus())}const k=p=>{if(p.key==="Escape"){C();return}if(n&&(p.key==="e"||p.key==="E")){C();return}if(n&&p.key==="Tab"){A(p);return}(p.key==="f"||p.key==="F")&&!b&&g(!v)};function C(){n?t.removeEventListener("keydown",k):i.removeEventListener("keydown",k),Z.remove(),ue(),hideTooltip(t),reparentTooltip(t.body),r?r.remove():i.remove(),n&&(t.body.style.overflow=a),d?.focus?.(),e.onClose()}function W(){n||(i.style.zIndex=String(re()))}const B=t.createElement("div");Object.assign(B.style,{flex:"1",minHeight:"0",minWidth:"0",display:"flex",overflow:"hidden"});const E=t.createElement("div");E.tabIndex=0,E.setAttribute("role","separator"),E.setAttribute("aria-label","Resize window (arrow keys, or drag)"),Object.assign(E.style,{position:"absolute",right:"0",bottom:"0",width:"16px",height:"16px",cursor:"nwse-resize",touchAction:"none"}),E.innerHTML='<svg viewBox="0 0 16 16" width="16" height="16" style="display:block"><path d="M15 15 L15 9 M15 15 L9 15 M15 15 L15 3 M15 15 L3 15" stroke="currentColor" stroke-width="1" opacity="0.35" fill="none"/></svg>',E.style.color=CLR.label;const D=320,j=240,H=20;function Y(p,T){const z=o.innerWidth-i.offsetLeft,R=o.innerHeight-i.offsetTop,O=Math.min(Math.max(i.offsetWidth+p,D),z),_=Math.min(Math.max(i.offsetHeight+T,j),R);i.style.width=`${O}px`,i.style.height=`${_}px`}E.addEventListener("keydown",p=>{if(!(v||b))switch(p.key){case"ArrowRight":p.preventDefault(),Y(H,0);break;case"ArrowLeft":p.preventDefault(),Y(-H,0);break;case"ArrowDown":p.preventDefault(),Y(0,H);break;case"ArrowUp":p.preventDefault(),Y(0,-H);break}}),E.addEventListener("pointerdown",p=>{if(v||b)return;p.preventDefault();const T=N(),z=p.clientX,R=p.clientY,O=i.offsetWidth,_=i.offsetHeight,q=o.innerWidth-i.offsetLeft,Q=o.innerHeight-i.offsetTop;E.setPointerCapture(p.pointerId);const G=F=>{const V=Math.min(Math.max(O+(F.clientX-z),D),q),J=Math.min(Math.max(_+(F.clientY-R),j),Q);i.style.width=`${V}px`,i.style.height=`${J}px`},U=F=>{T(),E.releasePointerCapture(F.pointerId),E.removeEventListener("pointermove",G),E.removeEventListener("pointerup",U)};E.addEventListener("pointermove",G),E.addEventListener("pointerup",U)}),i.appendChild(l),i.appendChild(B),i.appendChild(E);const K=e.anchor?overlayRootFor(e.anchor):t.body;r?(r.appendChild(i),K.appendChild(r)):K.appendChild(i);const ue=Me(t,K),Z=t.createElement("style");return Z.textContent=`@media print{
2
2
  body{overflow:visible!important;height:auto!important}
3
3
  body>*:not(.wmap-overlay-box):not(#wmap-modal-backdrop):not(.wmap-overlay-ancestor){display:none!important}
4
4
  #wmap-modal-backdrop{position:static!important;background:none!important;backdrop-filter:none!important;display:block!important}
@@ -6,4 +6,4 @@ body>*:not(.wmap-overlay-box):not(#wmap-modal-backdrop):not(.wmap-overlay-ancest
6
6
  .wmap-overlay-box>div:first-child{display:none!important}
7
7
  .wmap-overlay-box>div:nth-child(2){display:block!important;overflow:visible!important;height:auto!important;flex:none!important;min-height:0!important;min-width:0!important}
8
8
  .wmap-overlay-box>div:nth-child(3){display:none!important}
9
- }`,t.head.appendChild(q),reparentTooltip(i),n?(r.addEventListener("click",p=>{p.target===r&&C()}),t.addEventListener("keydown",k)):(i.addEventListener("keydown",k),i.addEventListener("mousedown",I),I()),nextFrame(()=>(l.isConnected?l:i).focus(),o),{backdrop:r,box:i,contentWrap:B,close:C,bringToFront:I}}export function openModal(e){return re({...e,mode:"modal"})}export function openFloatingWindow(e){return re({...e,mode:"window"})}const ne=new WeakSet;export function openReparentedModal(e,n={}){if(e.length===0||e.some(a=>ne.has(a)))return null;const t=e.map(a=>({el:a,parent:a.parentElement,next:a.nextSibling})),o=openModal({ownerDocument:n.ownerDocument,title:n.title,anchor:e[0],onClose:()=>{for(const a of t){if(ne.delete(a.el),!a.parent)continue;const r=a.next&&a.next.parentNode===a.parent?a.next:null;a.parent.insertBefore(a.el,r)}n.onClosed?.()}});for(const a of t)ne.add(a.el),o.contentWrap.appendChild(a.el);return o}export function makePaletteBtn(e,n,t,o,a){const r=e.makeDropdown("palette","Colour scheme",()=>{const d=n()==="hardBin"||n()==="softBin"?oe().filter(b=>b.name==="default"||b.name==="accessible"):oe();return[...o()?[{value:"custom",label:"Custom"}]:[],...d.map(b=>({value:b.name,label:b.label}))]},()=>t(),i=>a(i));function c(){r.style.display=n()==="metadata"?"none":""}return{btn:r,sync:c}}export function requestedPassFailDisplay(e){return e.passFailDisplay??"off"}export function passFailMenuRows(e,n){if(e.functionalActive)return[];const t=[];return e.hasLimits&&t.push({label:"Spec pass/fail",active:e.display==="spec",onClick:()=>n(e.display==="spec"?"off":"spec")}),e.hasRecorded&&t.push({label:"Test pass/fail",active:e.display==="test",onClick:()=>n(e.display==="test"?"off":"test")}),t}export function makeLogScaleBtn(e,n,t){const o=e.makeBtn("logScale","Toggle log scale",()=>{t({logScale:!n().logScale})});function a(){const r=n(),c=r.plotMode,i=c==="value"||c==="stackedValues";o.style.display=i&&requestedPassFailDisplay(r)==="off"&&!r.functionalActive?"":"none",e.setActive(o,!!r.logScale)}return{btn:o,sync:a}}export function makeLegendStyleBtn(e,n,t){const o=e.makeDropdown("legend","Legend style",()=>[{value:"default",label:"Default (right)"},{value:"compact",label:"Compact (right)"},{value:"left",label:"Left"},{value:"top",label:"Top"},{value:"bottom",label:"Bottom"},{value:"floating",label:"Floating"}],()=>n().legendPosition??"default",r=>t(r));function a(){const r=n().plotMode;o.style.display=r==="hardBin"||r==="softBin"||r==="metadata"?"":"none"}return{btn:o,sync:a}}export function makeOverlaysBtn(e,n,t){return e.makeCheckMenuBtn("overlays","Overlays",()=>n(),o=>e.setActive(o,t()))}export function makeOrientationBtn(e,n,t){return e.makeCheckMenuBtn("orient","Orientation",()=>[{section:"Rotate"},{label:"Rotate 90\xB0 clockwise",active:!1,onClick:()=>{const o=n().rotation??0;t({rotation:ROTATIONS[(ROTATIONS.indexOf(o)+1)%4]})}},{section:"Flip"},{label:"Flip horizontal",active:!!n().flipX,onClick:()=>t({flipX:!n().flipX})},{label:"Flip vertical",active:!!n().flipY,onClick:()=>t({flipY:!n().flipY})}],o=>{const{rotation:a,flipX:r,flipY:c}=n();e.setActive(o,!!(a||r||c))})}let j=null;function se(e,n,t,o){const a=n,r=a.__wmapDemoApi;a.__wmapDemoApi=o;const c=e.createElement("div");return c.classList.add("wmap-guide-content"),c.innerHTML=t,{content:c,restoreApi:()=>{a.__wmapDemoApi===o&&(a.__wmapDemoApi=r)}}}function le(e,n){const t=n,o=e.querySelector("script");if(o){const a=e.ownerDocument.createElement("script");a.textContent=o.textContent,e.appendChild(a);const r=e.querySelector(".wmap-guide");return r&&t.__wmapPopulateGuideDemos?.(r),t.__wmapDestroyGuideDemos}}function Me(e,n,t,o){const a=o?.ownerDocument??document,r=a.defaultView??window,{content:c,restoreApi:i}=se(a,r,n,t);Object.assign(c.style,{flex:"1",overflow:"auto",minHeight:"0",minWidth:"0"});let d;const b=openFloatingWindow({title:e,anchor:o,ownerDocument:a,onMaximizeChange:m=>{c.querySelector(".wmap-guide")?.classList.toggle("wmap-guide--max",m)},onClose:()=>{j===b&&(j=null),d?.(),i()}});return b.contentWrap.appendChild(c),d=le(c,r),b}function Le(e,n,t,o){const a=e.document;a.title=n,Object.assign(a.documentElement.style,{height:"100%"}),Object.assign(a.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),copyWmapThemeTokens(document.documentElement,a.documentElement);const r=syncWmapPopupTheme(document.documentElement,a.documentElement),{content:c,restoreApi:i}=se(a,e,t,o);Object.assign(c.style,{flex:"1",overflow:"auto",minHeight:"0",minWidth:"0"}),a.body.appendChild(c);const d=le(c,e);let b=!1;const m=()=>{if(!b){b=!0,clearInterval(h),r();try{d?.()}catch{}i(),j===s&&(j=null)}},h=setInterval(()=>{e.closed&&m()},400);e.addEventListener("pagehide",m);const s={close:()=>{e.closed||e.close(),m()}};return s}export function openUserGuideWindow(e,n,t,o){j&&(j.close(),j=null);const a=t?.title??"Wafer Map \u2014 User Guide",r=(t?.html??"")+n,i=(o?.ownerDocument.defaultView??window).open("","_blank","width=800,height=820");j=i?Le(i,a,r,e):Me(a,r,e,o)}
9
+ }`,t.head.appendChild(Z),reparentTooltip(i),n?(r.addEventListener("click",p=>{p.target===r&&C()}),t.addEventListener("keydown",k)):(i.addEventListener("keydown",k),i.addEventListener("mousedown",W),W()),nextFrame(()=>(c.isConnected?c:i).focus(),o),{backdrop:r,box:i,contentWrap:B,close:C,bringToFront:W}}export function openModal(e){return se({...e,mode:"modal"})}export function openFloatingWindow(e){return se({...e,mode:"window"})}const ne=new WeakSet;export function openReparentedModal(e,n={}){if(e.length===0||e.some(a=>ne.has(a)))return null;const t=e.map(a=>({el:a,parent:a.parentElement,next:a.nextSibling})),o=openModal({ownerDocument:n.ownerDocument,title:n.title,anchor:e[0],onClose:()=>{for(const a of t){if(ne.delete(a.el),!a.parent)continue;const r=a.next&&a.next.parentNode===a.parent?a.next:null;a.parent.insertBefore(a.el,r)}n.onClosed?.()}});for(const a of t)ne.add(a.el),o.contentWrap.appendChild(a.el);return o}export function makePaletteBtn(e,n,t,o,a,r){const d=()=>n()==="hardBin"||n()==="softBin",i=e.makeCheckMenuBtn("palette","Colour scheme",()=>{const x=d()?oe().filter(s=>s.name==="default"||s.name==="accessible"):oe(),f=t(),m=[];r&&m.push({section:"Scheme"}),o()&&m.push({label:"Custom",active:f==="custom",onClick:()=>a("custom")});for(const s of x)m.push({label:s.label,active:f===s.name,onClick:()=>a(s.name)});return r&&(m.push({section:"Encoding"}),m.push({label:"Mark failing dies",active:r.get(),enabled:d(),disabledHint:d()?void 0:"Available on hard/soft bin maps",onClick:()=>r.set(!r.get())})),m},()=>{});function l(){i.style.display=n()==="metadata"?"none":""}return{btn:i,sync:l}}export function requestedPassFailDisplay(e){return e.passFailDisplay??"off"}export function passFailMenuRows(e,n){if(e.functionalActive)return[];const t=[];return e.hasLimits&&t.push({label:"Spec pass/fail",active:e.display==="spec",onClick:()=>n(e.display==="spec"?"off":"spec")}),e.hasRecorded&&t.push({label:"Test pass/fail",active:e.display==="test",onClick:()=>n(e.display==="test"?"off":"test")}),t}export function makeLogScaleBtn(e,n,t){const o=e.makeBtn("logScale","Toggle log scale",()=>{t({logScale:!n().logScale})});function a(){const r=n(),d=r.plotMode,i=d==="value"||d==="stackedValues";o.style.display=i&&requestedPassFailDisplay(r)==="off"&&!r.functionalActive?"":"none",e.setActive(o,!!r.logScale)}return{btn:o,sync:a}}const Ae=[{value:"default",label:"Default (right)"},{value:"compact",label:"Compact (right)"},{value:"left",label:"Left"},{value:"top",label:"Top"},{value:"bottom",label:"Bottom"},{value:"floating",label:"Floating"}];export function makeLegendStyleBtn(e,n,t,o){const a=e.makeCheckMenuBtn("legend","Legend style",()=>{const d=n().legendPosition??"default",i=[];if(le(n().plotMode)){o&&i.push({section:"Position"});for(const l of Ae)i.push({label:l.label,active:d===l.value,onClick:()=>t(l.value)})}if(o){const l=o.blockedReason();i.push({section:"Per map"}),i.push({label:"Legend on each map",active:l?!0:o.get(),enabled:!l,disabledHint:l??void 0,onClick:()=>o.set(!o.get())})}return i},()=>{});function r(){a.style.display=o||le(n().plotMode)?"":"none"}return{btn:a,sync:r}}function le(e){return e==="hardBin"||e==="softBin"||e==="metadata"}export function makeOverlaysBtn(e,n,t){return e.makeCheckMenuBtn("overlays","Overlays",()=>n(),o=>e.setActive(o,t()))}export function makeOrientationBtn(e,n,t){return e.makeCheckMenuBtn("orient","Orientation",()=>[{section:"Rotate"},{label:"Rotate 90\xB0 clockwise",active:!1,onClick:()=>{const o=n().rotation??0;t({rotation:ROTATIONS[(ROTATIONS.indexOf(o)+1)%4]})}},{section:"Flip"},{label:"Flip horizontal",active:!!n().flipX,onClick:()=>t({flipX:!n().flipX})},{label:"Flip vertical",active:!!n().flipY,onClick:()=>t({flipY:!n().flipY})}],o=>{const{rotation:a,flipX:r,flipY:d}=n();e.setActive(o,!!(a||r||d))})}let P=null;function ce(e,n,t,o){const a=n,r=a.__wmapDemoApi;a.__wmapDemoApi=o;const d=e.createElement("div");return d.classList.add("wmap-guide-content"),d.innerHTML=t,{content:d,restoreApi:()=>{a.__wmapDemoApi===o&&(a.__wmapDemoApi=r)}}}function de(e,n){const t=n,o=e.querySelector("script");if(o){const a=e.ownerDocument.createElement("script");a.textContent=o.textContent,e.appendChild(a);const r=e.querySelector(".wmap-guide");return r&&t.__wmapPopulateGuideDemos?.(r),t.__wmapDestroyGuideDemos}}function Ce(e,n,t,o){const a=o?.ownerDocument??document,r=a.defaultView??window,{content:d,restoreApi:i}=ce(a,r,n,t);Object.assign(d.style,{flex:"1",overflow:"auto",minHeight:"0",minWidth:"0"});let l;const x=openFloatingWindow({title:e,anchor:o,ownerDocument:a,onMaximizeChange:f=>{d.querySelector(".wmap-guide")?.classList.toggle("wmap-guide--max",f)},onClose:()=>{P===x&&(P=null),l?.(),i()}});return x.contentWrap.appendChild(d),l=de(d,r),x}function Se(e,n,t,o){const a=e.document;a.title=n,Object.assign(a.documentElement.style,{height:"100%"}),Object.assign(a.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'}),copyWmapThemeTokens(document.documentElement,a.documentElement);const r=syncWmapPopupTheme(document.documentElement,a.documentElement),{content:d,restoreApi:i}=ce(a,e,t,o);Object.assign(d.style,{flex:"1",overflow:"auto",minHeight:"0",minWidth:"0"}),a.body.appendChild(d);const l=de(d,e);let x=!1;const f=()=>{if(!x){x=!0,clearInterval(m),r();try{l?.()}catch{}i(),P===s&&(P=null)}},m=setInterval(()=>{e.closed&&f()},400);e.addEventListener("pagehide",f);const s={close:()=>{e.closed||e.close(),f()}};return s}export function openUserGuideWindow(e,n,t,o){P&&(P.close(),P=null);const a=t?.title??"Wafer Map \u2014 User Guide",r=(t?.html??"")+n,i=(o?.ownerDocument.defaultView??window).open("","_blank","width=800,height=820");P=i?Se(i,a,r,e):Ce(a,r,e,o)}