PageSourceSearch

https://app.withsammy.ai/assets/TakeoffPage-DK3MFlgX.js

js withsammy.ai collected 2026-09-24 11:04:44 UTC 137,863 bytes, 31 lines download raw bytes

1import{I as st,r as l,as as St,v as Q,j as e,z as Wn,X as $s,az as ka,aA as wn,aB as kn,aw as ie,aD as _n,P as Us,aM as Pt,aN as Ot,aO as Vt,aP as $t,N as _a,W as Kt,aS as Ht,aa as Jn,C as rn,a4 as sn,a_ as Gn,aR as Qs,au as ja,a3 as Pn,bB as Sa,aT as Ws,x as Ss,bp as Ns,a6 as Na,u as Ca,G as Ma,aq as Ea,T as qt,b5 as pt,s as Cs,aV as Fa,Y as Ta,Z as Da,$ as Ia,a0 as Ra,aQ as nn}from"./index-DUfqHKrs.js";import{u as Aa,g as La,b as Be,a as rt,C as lt,c as Ms,d as Pa,e as On,I as Oa,M as Va,S as $a,U as Ua,R as Qa}from"./index-DKjUOn6T.js";import{g as Gs,v as qs,G as Wa}from"./pdf-CBY-y8Vp.js";import{j as Es,k as Ga,l as Ut,p as bt,m as Ft,n as zt,o as Et,q as Tt,r as qa,s as ln,t as Sn,u as Ha,v as qn,w as Hn,x as zn,y as Kn,z as Bn,A as Xn,B as za,C as Ka,D as Ba,E as Xa,F as Ya,f as Za,G as Ja,H as er,I as tr,J as nr,K as sr,L as ar,M as rr,N as lr,O as or,P as ir,Q as cr,R as ur,S as dr,T as mr,U as fr,V as hr,W as pr}from"./takeoffService-BROO9VBj.js";import{T as xr}from"./target-C-m7Iqan.js";import{R as Nn}from"./ruler-B-XpVTK1.js";import{M as an}from"./minus-_b-306aF.js";import{M as Hs}from"./maximize-2-DQo7Ejs2.js";import{S as zs,a as Ks,b as Bs,c as Xs,d as Cn}from"./select-DR8cnra2.js";import{g as Bt,a as gr,A as yr,i as br}from"./takeoffSlotMap-3jfMGGRH.js";import{L as vr}from"./layers-Dwy_D8bm.js";import{E as Yn}from"./eye-off-BAwBo68A.js";import{T as on}from"./trash-2--ZktFfLA.js";import{C as wr}from"./copy-nycby51s.js";import{T as Fs}from"./tag-21PvPWiI.js";import{A as Ts}from"./arrow-up-right-Dxhzyvtw.js";import{T as kr}from"./trending-up-Xw24Q2Rv.js";import{u as _r}from"./useEstimateStrategy-BUJgxAIC.js";import"./chevron-up-Cuvo0jgM.js";const jr=st("Bug",[["path",{d:"m8 2 1.88 1.88",key:"fmnt4t"}],["path",{d:"M14.12 3.88 16 2",key:"qol33r"}],["path",{d:"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1",key:"d7y7pr"}],["path",{d:"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6",key:"xs1cw7"}],["path",{d:"M12 20v-9",key:"1qisl0"}],["path",{d:"M6.53 9C4.6 8.8 3 7.1 3 5",key:"32zzws"}],["path",{d:"M6 13H2",key:"82j7cp"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4",key:"4p0ekp"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4",key:"18gb23"}],["path",{d:"M22 13h-4",key:"1jl80f"}],["path",{d:"M17.2 17c2.1.1 3.8 1.9 3.8 4",key:"k3fwyw"}]]);const Sr=st("ChevronsDownUp",[["path",{d:"m7 20 5-5 5 5",key:"13a0gw"}],["path",{d:"m7 4 5 5 5-5",key:"1kwcof"}]]);const Nr=st("ClipboardCopy",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2",key:"4jdomd"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v4",key:"3hqy98"}],["path",{d:"M21 14H11",key:"1bme5i"}],["path",{d:"m15 10-4 4 4 4",key:"5dvupr"}]]);const Cr=st("Crosshair",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12",key:"l9bcsi"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12",key:"13hhkx"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2",key:"10w3f3"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18",key:"15g9kq"}]]);const Ds=st("Focus",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2",key:"aa7l1z"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2",key:"4qcy5o"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2",key:"6vwrx8"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2",key:"ioqczr"}]]);const Mr=st("FolderInput",[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1",key:"fm4g5t"}],["path",{d:"M2 13h10",key:"pgb2dq"}],["path",{d:"m9 16 3-3-3-3",key:"6m91ic"}]]);const Er=st("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);const Zn=st("Move",[["path",{d:"M12 2v20",key:"t6zp3m"}],["path",{d:"m15 19-3 3-3-3",key:"11eu04"}],["path",{d:"m19 9 3 3-3 3",key:"1mg7y2"}],["path",{d:"M2 12h20",key:"9i4pu4"}],["path",{d:"m5 9-3 3 3 3",key:"j64kie"}],["path",{d:"m9 5 3-3 3 3",key:"l8vdw6"}]]);const Fr=st("Palette",[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z",key:"12rzf8"}]]);const Tr=st("PanelLeftClose",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m16 15-3-3 3-3",key:"14y99z"}]]);const Dr=st("PanelLeftOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m14 9 3 3-3 3",key:"8010ee"}]]);const Ir=st("Pentagon",[["path",{d:"M10.83 2.38a2 2 0 0 1 2.34 0l8 5.74a2 2 0 0 1 .73 2.25l-3.04 9.26a2 2 0 0 1-1.9 1.37H7.04a2 2 0 0 1-1.9-1.37L2.1 10.37a2 2 0 0 1 .73-2.25z",key:"2hea0t"}]]);const Rr=st("Scissors",[["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}
1],["path",{d:"M8.12 8.12 12 12",key:"1alkpv"}],["path",{d:"M20 4 8.12 15.88",key:"xgtan2"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M14.8 14.8 20 20",key:"ptml3r"}]]);const Ar=st("Spline",[["circle",{cx:"19",cy:"5",r:"2",key:"mhkx31"}],["circle",{cx:"5",cy:"19",r:"2",key:"v8kfzx"}],["path",{d:"M5 17A12 12 0 0 1 17 5",key:"1okkup"}]]);Wa.workerSrc=new URL("/assets/pdf.worker.min-iDqQPrd3.mjs",import.meta.url).toString();const Is=8192;function Lr(a){return a<=1?1:a<=2?2:4}function Pr({url:a,pageNumber:p,containerWidth:F,containerHeight:u,zoom:b=1}){const[h,S]=l.useState(null),[I,E]=l.useState(0),[g,V]=l.useState(0),[M,$]=l.useState(0),[je,ce]=l.useState(0),[c,v]=l.useState(0),[T,_]=l.useState(!1),[w,L]=l.useState(null),fe=l.useRef(null),Z=l.useRef(null),re=l.useRef(new Map),W=l.useRef(null),he=l.useCallback(async()=>{if(!a||Z.current===a&&fe.current)return;const J=await Gs({url:a,cMapUrl:`https://cdn.jsdelivr.net/npm/pdfjs-dist@${qs}/cmaps/`,cMapPacked:!0}).promise;fe.current=J,Z.current=a,re.current.clear(),E(J.numPages)},[a]);return l.useEffect(()=>{if(!a||!F||!u){S(null);return}let J=!1;return(async()=>{_(!0),L(null);try{await he();const Se=fe.current;if(!Se||J)return;const Ue=Math.max(1,Math.min(p,Se.numPages)),Qe=Lr(b),He=`${Ue}:${F}x${u}:t${Qe}`,we=re.current.get(He);if(we){const at=new Image;at.src=we.dataUrl,await at.decode(),J||(S(at),V(we.width),$(we.height),ce(we.nativeW),v(we.nativeH),_(!1));return}const ee=await Se.getPage(Ue);if(J)return;const Ae=ee.getViewport({scale:1});J||(ce(Ae.width),v(Ae.height));const P=F/Ae.width,Oe=u/Ae.height,ue=Math.min(P,Oe),Le=window.devicePixelRatio||1;let Ge=ue*Qe*Le;const d=Math.max(Ae.width*Ge,Ae.height*Ge);d>Is&&(Ge*=Is/d);const O=ee.getViewport({scale:Ge}),z=document.createElement("canvas");if(z.width=Math.floor(O.width),z.height=Math.floor(O.height),!z.getContext("2d")||J)return;W.current&&W.current.cancel();const pe=ee.render({canvas:z,viewport:O});if(W.current=pe,await pe.promise,J)return;const q=z.toDataURL("image/png"),Fe=Math.floor(Ae.width*ue),ge=Math.floor(Ae.height*ue);re.current.set(He,{dataUrl:q,width:Fe,height:ge,nativeW:Ae.width,nativeH:Ae.height});const ze=new Image;ze.src=q,await ze.decode(),J||(S(ze),V(Fe),$(ge))}catch(Se){if(J||(Se==null?void 0:Se.name)==="RenderingCancelledException")return;L(Se instanceof Error?Se:new Error(String(Se)))}finally{J||_(!1)}})(),()=>{J=!0,W.current&&(W.current.cancel(),W.current=null)}},[a,p,F,u,b,he]),l.useEffect(()=>()=>{fe.current&&(fe.current.destroy(),fe.current=null)},[]),{imageElement:h,pageCount:I,renderWidth:g,renderHeight:M,nativeWidth:je,nativeHeight:c,isLoading:T,error:w}}const Vn=.25,$n=8,Rs=1.08,Un=6,Or=15,As="#3B82F6",Qn=.3,Vr=5;function $r(a,p){return Math.sqrt((p.x-a.x)**2+(p.y-a.y)**2)}function Ls(a,p,F){return $r(a,p)*F<Or}function Lt(a){const p=[];for(const F of a)p.push(F.x,F.y);return p}function yt(a,p,F=!1){if(!p)return{snapped:a,snapH:!1,snapV:!1};const u=Math.abs(a.x-p.x),b=Math.abs(a.y-p.y);if(Math.sqrt(u*u+b*b)===0)return{snapped:a,snapH:!1,snapV:!1};const I=Math.atan2(b,u)*180/Math.PI,E=F?45:Vr;return I<E?{snapped:{x:a.x,y:p.y},snapH:!0,snapV:!1}:I>90-E?{snapped:{x:p.x,y:a.y},snapH:!1,snapV:!0}:{snapped:a,snapH:!1,snapV:!1}}const Ur=St.forwardRef(function({fileUrl:p,mimeType:F,pageNumber:u,onPageCountChange:b,activeTool:h,dispatch:S,calibrationPoints:I,savedCalibration:E,drawingPoints:g,isDrawing:V,cursorPosition:M,measurements:$,selectedMeasurementId:je,hoveredMeasurementId:ce,onCompleteMeasurement:c,groupColourMap:v,groupOpacityMap:T,hiddenGroupIds:_,activeDrawingColour:w,onZoomChange:L,onFitScaleChange:fe,onContextMenu:Z,onMoveMeasurement:re,subtractTargetId:W,subtractStart:he,onSubtractCommit:J,subtractDrawingPoints:le,onSubtractHoleCommit:Se,onClearScale:Ue},Qe){const He=l.useRef(null),we=l.useRef(null),[ee,Ae]=l.useState({width:0,height:0}),[P,Oe]=l.useState(1),[ue,Le]=l.useState({x:0,y:0}),[Ge,d]=l.useState(!1),[O,z]=l.useState(!1),[U,pe]=l.useState(null),[q,Fe]=l.useState(!1),ge=F==="application/pdf",[ze,at]=l.useState(1);l.useEffect(()=>{const r=setTimeout(()=>at(P),300);return()=>clearTimeout(r)},[P]),l.useEffect(()=>{if(!He.current)return;const r=new ResizeObserver(o=>{const{width:C,height:y}=o[0].contentRect;Ae({width:C,height:y})});return r.observe(He.current),()=>r.disconnect()},[]);const{imageElement:Re,pageCount:ne,nativeWidth:Te,nativeHeight:de,isLoading:xt,error:Nt}=Pr({url:ge?p:null,pageNumber:u,containerWidth:ee.width,containerHeight:ee.height,zoom:ze});l.useEffect(()=>{ne>0&&(b==null||b(ne))},[ne,b]);const[te,gt]=Aa(!ge&&p?p:"","anonymous"),Dt=ge?Re:te,Xt=ge?xt:gt==="loading",Mn=ge?!!Nt:gt==="failed",ut=l.useMemo(()=>
1{const r=ge?Te:(te==null?void 0:te.naturalWidth)||(te==null?void 0:te.width)||0,o=ge?de:(te==null?void 0:te.naturalHeight)||(te==null?void 0:te.height)||0;if(!ee.width||!ee.height||!r||!o)return{width:0,height:0};const C=Math.min(ee.width/r,ee.height/o);return{width:Math.floor(r*C),height:Math.floor(o*C)}},[ge,Te,de,te,ee]),tt=l.useMemo(()=>({x:(ee.width-ut.width)/2,y:(ee.height-ut.height)/2}),[ee,ut]),x=l.useMemo(()=>({width:ge?Te:(te==null?void 0:te.naturalWidth)||(te==null?void 0:te.width)||0,height:ge?de:(te==null?void 0:te.naturalHeight)||(te==null?void 0:te.height)||0}),[ge,Te,de,te]),D=l.useMemo(()=>!ut.width||!x.width?1:ut.width/x.width,[ut.width,x.width]);l.useEffect(()=>{Oe(1),Le({x:0,y:0})},[u]);const ot=l.useCallback(r=>{const o=we.current;if(!o||!ut.width||!ut.height||!ee.width)return null;const C=o.getPointerPosition();if(!C)return null;const y=((C.x-ue.x)/P-tt.x)/D,Y=((C.y-ue.y)/P-tt.y)/D;return{x:y,y:Y}},[P,ue,tt,D,ut,ee.width]),En=l.useCallback(r=>{r.evt.preventDefault();const o=we.current;if(!o)return;const C=o.getPointerPosition();if(!C)return;const y=P,Y=r.evt.deltaY>0?-1:1,ae=Math.min($n,Math.max(Vn,Y>0?y*Rs:y/Rs)),X={x:(C.x-ue.x)/y,y:(C.y-ue.y)/y};Oe(ae),Le({x:C.x-X.x*ae,y:C.y-X.y*ae})},[P,ue]);l.useEffect(()=>{const r=y=>{const Y=y;return Y?Y.tagName==="INPUT"||Y.tagName==="TEXTAREA"||Y.isContentEditable:!1},o=y=>{y.key==="Shift"&&Fe(!0),!r(y.target)&&y.code==="Space"&&!y.repeat&&(y.preventDefault(),z(!0))},C=y=>{y.key==="Shift"&&Fe(!1),y.code==="Space"&&(z(!1),d(!1))};return window.addEventListener("keydown",o),window.addEventListener("keyup",C),()=>{window.removeEventListener("keydown",o),window.removeEventListener("keyup",C)}},[]);const vt=l.useRef({x:0,y:0}),Fn=l.useCallback(r=>{if(r.evt.button===1||O&&r.evt.button===0){r.evt.preventDefault(),d(!0),vt.current={x:r.evt.clientX,y:r.evt.clientY};return}if(r.evt.button===0){if(h==="area"||h==="rectangle"||h==="linear"||h==="count"){const o=ot(r);if(!o)return;if(h==="area"){if(g.length>=3&&Ls(o,g[0],P*D)){c(g,h),S({type:"COMPLETE_MEASUREMENT"});return}const C=g.length>0?g[g.length-1]:null,{snapped:y}=yt(o,C,r.evt.shiftKey);S({type:"ADD_DRAWING_POINT",payload:y})}else if(h==="rectangle")V?(c([g[0],o],h),S({type:"COMPLETE_MEASUREMENT"})):S({type:"ADD_DRAWING_POINT",payload:o});else if(h==="linear"){const C=g.length>0?g[g.length-1]:null,{snapped:y}=yt(o,C,r.evt.shiftKey);S({type:"ADD_DRAWING_POINT",payload:y})}else h==="count"&&(c([o],h),S({type:"COMPLETE_MEASUREMENT"}));return}if(h==="subtract"){const o=ot(r);if(!o)return;const y=12/Math.max(P*D,1e-4),Y=W?$.find(H=>H.id===W):null;if(Y&&Y.geometry.type==="polygon"){const H=le&&le.length>0?le[le.length-1]:null,{snapped:Ee}=yt(o,H,r.evt.shiftKey);S({type:"SUBTRACT_HOLE_ADD_POINT",payload:Ee});return}let X=null;for(const H of $){if(H.measurement_type!=="linear"||H.geometry.type!=="linear"||H.group_id&&(_!=null&&_.has(H.group_id)))continue;const Ee=Es(H.geometry,o);!Ee||Ee.distance>y||(!X||Ee.distance<X.distance)&&(X={measurementId:H.id,...Ee})}if(X){if(!W||!he){S({type:"SUBTRACT_LOCK_TARGET",payload:{measurementId:X.measurementId,startPoint:X.point}});return}if(X.measurementId!==W){S({type:"SUBTRACT_RESET"}),Q.error("Subtraction cancelled — both clicks must be on the same line");return}const H=$.find(De=>De.id===W);if(!H||H.geometry.type!=="linear"){S({type:"SUBTRACT_RESET"});return}const Ee=Es(H.geometry,he);if(!Ee){S({type:"SUBTRACT_RESET"});return}if(Ee.segmentIndex!==X.segmentIndex){S({type:"SUBTRACT_RESET"}),Q.error("Subtraction cancelled — both clicks must be on the same segment");return}if(Math.abs(Ee.t-X.t)<.001){Q.error("Splice too small — try again");return}J&&J(W,Ee.segmentIndex,Ee.t,X.t),S({type:"SUBTRACT_RESET"});return}let se=null;for(const H of $)H.geometry.type==="polygon"&&(H.group_id&&(_!=null&&_.has(H.group_id))||Ga(o,H.geometry.points)&&(se?se.geometry.type==="polygon"&&Ut(H.geometry.points)<Ut(se.geometry.points)&&(se=H):se=H));if(se){S({type:"SUBTRACT_HOLE_START",payload:{measurementId:se.id,firstPoint:o}});return}return}if(h==="calibrate"){const o=ot(r);if(o)if(I.length===1){const{snapped:C}=yt(o,I[0],r.evt.shiftKey);S({type:"SET_CALIBRATION_POINT",payload:C})}else S({type:"SET_CALIBRATION_POINT",payload:o});return}if(h==="select"){const o=r.target,C=we.current;o===C&&S({type:"SELECT_MEASUREMENT",payload:null}),r.evt.preventDefault(),d(!0),vt.current={x:r.evt.clientX,y:r.evt.clientY}}if(h==="move"){const o=r.target,C=we.current;o===C&&(r.evt.preventDefault(),d(!0),vt.current={x:r.evt.clientX,y:r.evt.clientY})}}},[O,h,ot,S,g,V,P,D,c,$,_,W,he,le,J,I]),Tn=l.useCallback(r=>
1{if(Ge){const o=r.evt.clientX-vt.current.x,C=r.evt.clientY-vt.current.y;vt.current={x:r.evt.clientX,y:r.evt.clientY},Le(y=>({x:y.x+o,y:y.y+C}));return}if((h==="area"||h==="rectangle"||h==="linear")&&V){const o=ot(r);o&&S({type:"SET_CURSOR_POSITION",payload:o})}if(h==="calibrate"&&I.length===1){const o=ot(r);o&&S({type:"SET_CURSOR_POSITION",payload:o})}if(h==="subtract"){const o=ot(r);o&&S({type:"SET_CURSOR_POSITION",payload:o})}},[Ge,h,V,I.length,ot,S]),Dn=l.useCallback(()=>{d(!1)},[]),Yt=l.useCallback(r=>{h==="area"&&g.length>=3?(r.evt.preventDefault(),c(g,h),S({type:"COMPLETE_MEASUREMENT"})):h==="linear"&&g.length>=2?(r.evt.preventDefault(),c(g,h),S({type:"COMPLETE_MEASUREMENT"})):h==="subtract"&&W&&le&&le.length>=3&&Se?(r.evt.preventDefault(),Se(W,le),S({type:"SUBTRACT_RESET"})):h==="subtract"&&W&&le&&le.length>0&&le.length<3&&Q.error("A subtraction needs at least 3 points.")},[h,g,c,S,W,le,Se]),Qt=l.useCallback(r=>{if(r.evt.preventDefault(),!Z)return;const o=r.target&&typeof r.target.id=="function"?r.target.id():void 0;if(o&&o.startsWith("vertex:")){const Y=o.split(":"),ae=Y[1],X=parseInt(Y[2],10);if(ae&&Number.isFinite(X)){Z({kind:"vertex",measurementId:ae,vertexIndex:X},r.evt.clientX,r.evt.clientY);return}}if(o&&o.startsWith("rectCorner:")){const Y=o.split(":")[1];if(Y){Z({kind:"measurement",measurementId:Y},r.evt.clientX,r.evt.clientY);return}}const C=o?$.find(Y=>Y.id===o):null;if(C){Z({kind:"measurement",measurementId:C.id},r.evt.clientX,r.evt.clientY);return}const y=ot(r);Z({kind:"empty",pagePoint:y??void 0},r.evt.clientX,r.evt.clientY)},[Z,$,ot]),Xe=l.useRef({active:!1,lastDist:0,lastCenterX:0,lastCenterY:0});l.useEffect(()=>{const r=He.current;if(!r)return;const o={zoom:P,panX:ue.x,panY:ue.y},C=ae=>{if(ae.touches.length>=2){ae.preventDefault(),Xe.current.active=!0;const X=ae.touches[0],se=ae.touches[1];Xe.current.lastDist=Math.hypot(X.clientX-se.clientX,X.clientY-se.clientY),Xe.current.lastCenterX=(X.clientX+se.clientX)/2,Xe.current.lastCenterY=(X.clientY+se.clientY)/2}},y=ae=>{if(!Xe.current.active||ae.touches.length<2)return;ae.preventDefault();const X=ae.touches[0],se=ae.touches[1],H=Math.hypot(X.clientX-se.clientX,X.clientY-se.clientY),Ee=(X.clientX+se.clientX)/2,De=(X.clientY+se.clientY)/2,N=H/Xe.current.lastDist,it=Math.min($n,Math.max(Vn,o.zoom*N)),Rt=Ee-(Xe.current.lastCenterX-o.panX)*(it/o.zoom),Ke=De-(Xe.current.lastCenterY-o.panY)*(it/o.zoom);o.zoom=it,o.panX=Rt,o.panY=Ke,Oe(it),Le({x:Rt,y:Ke}),Xe.current.lastDist=H,Xe.current.lastCenterX=Ee,Xe.current.lastCenterY=De},Y=()=>{Xe.current.active=!1};return r.addEventListener("touchstart",C,{passive:!1}),r.addEventListener("touchmove",y,{passive:!1}),r.addEventListener("touchend",Y,{passive:!1}),r.addEventListener("touchcancel",Y,{passive:!1}),()=>{r.removeEventListener("touchstart",C),r.removeEventListener("touchmove",y),r.removeEventListener("touchend",Y),r.removeEventListener("touchcancel",Y)}},[]),l.useEffect(()=>{He.current},[P,ue]);const cn=U||(Ge||O?"grab":h==="calibrate"||(h==="area"||h==="rectangle"||h==="linear"||h==="count")||h==="subtract"?"crosshair":h==="move"?"move":"default"),wt=l.useCallback(()=>{Oe(1),Le({x:0,y:0})},[]);St.useImperativeHandle(Qe,()=>({zoomTo(r){const o=Math.min($n,Math.max(Vn,r)),C=ee.width/2,y=ee.height/2,Y=C-(C-ue.x)*o/P,ae=y-(y-ue.y)*o/P;Oe(o),Le({x:Y,y:ae})},fitToPage(){Oe(1),Le({x:0,y:0})},recenterAt(r){const o=ee.width/2,C=ee.height/2;Le({x:o-tt.x*P-r.x*P*D,y:C-tt.y*P-r.y*P*D})}}),[ee,ue,P,tt,D]),l.useEffect(()=>{L==null||L(P)},[P,L]),l.useEffect(()=>{fe==null||fe(D)},[D,fe]);const It=l.useMemo(()=>E?`${E.real_world_distance} ${E.real_world_unit}`:null,[E]),Wt=l.useMemo(()=>E?{x:(E.calibration_point_1_x+E.calibration_point_2_x)/2,y:(E.calibration_point_1_y+E.calibration_point_2_y)/2}:null,[E]),m=1/(P*D),dt=l.useMemo(()=>h!=="area"||g.length<3||!M?!1:Ls(M,g[0],P*D),[h,g,M,P,D]),mt=l.useMemo(()=>{if(!V||!M)return[];if(h==="area"||h==="linear"){const r=g.length>0?g[g.length-1]:null,{snapped:o}=yt(M,r,q),C=[...g,o];return Lt(C)}return[]},[V,M,h,g,q]),kt=l.useMemo(()=>{if(h!=="rectangle"||!V||g.length<1||!M)return null;const r=g[0],o=M;return{x:Math.min(r.x,o.x),y:Math.min(r.y,o.y),width:Math.abs(o.x-r.x),height:Math.abs(o.y-r.y)}},[h,V,g,M]),Zt=l.useMemo(()=>
1{if(!V||!M)return null;if(h==="area"&&g.length>=2){const r=g[g.length-1],{snapped:o}=yt(M,r,q),C=[...g,o],y=Ut(C);if(E){const Y=bt(y,E.pixels_per_unit,E.real_world_unit);return Ft(Y)}return`${y.toFixed(0)} px²`}if(h==="rectangle"&&g.length===1){const r=g[0],o=Math.abs(M.x-r.x)*Math.abs(M.y-r.y);if(E){const C=bt(o,E.pixels_per_unit,E.real_world_unit);return Ft(C)}return`${o.toFixed(0)} px²`}if(h==="linear"&&g.length>=1){const r=g[g.length-1],{snapped:o}=yt(M,r,q),C=[...g,o],y=zt(C);if(E){const Y=Et(y,E.pixels_per_unit,E.real_world_unit);return Tt(Y)}return`${y.toFixed(0)} px`}return null},[V,M,h,g,E,q]),nt=l.useMemo(()=>{if(!M)return null;let r=null;if(V&&(h==="area"||h==="linear")&&g.length>0?r=g[g.length-1]:h==="subtract"&&W&&le&&le.length>0&&(r=le[le.length-1]),!r)return null;const{snapH:o,snapV:C}=yt(M,r,q);return!o&&!C?null:{snapH:o,snapV:C,prevPoint:r}},[V,M,g,h,W,le,q]),un=l.useMemo(()=>{const r=new Map;let o=1;for(const C of $)C.measurement_type==="count"&&(r.set(C.id,o),o++);return r},[$]),B=l.useMemo(()=>!_||_.size===0?$:$.filter(r=>!r.group_id||!_.has(r.group_id)),[$,_]),j=w||As,A=l.useCallback(r=>{var Rt,Ke,dn,mn,fn,hn;const o=r.id===je,C=r.id===ce,y=r.group_id&&(v==null?void 0:v.get(r.group_id))||As,Y=(r.group_id&&(T==null?void 0:T.get(r.group_id)))??Qn,ae=(o?3:2)*m,X=10*m,se=h==="move",H=()=>{h==="select"&&S({type:"SELECT_MEASUREMENT",payload:r.id})},Ee=()=>{(h==="select"||h==="move")&&S({type:"HOVER_MEASUREMENT",payload:r.id})},De=()=>{(h==="select"||h==="move")&&S({type:"HOVER_MEASUREMENT",payload:null})},N=r.geometry,it=Me=>We=>{if(!re)return;const Ne=We.target;let Ve=0,ye=0;if(Me==="polygon"||Me==="linear"?(Ve=Ne.x(),ye=Ne.y()):Me==="rectangle"&&N.type==="rectangle"?(Ve=Ne.x()-N.origin.x,ye=Ne.y()-N.origin.y):Me==="point"&&N.type==="point"&&(Ve=Ne.x()-N.position.x,ye=Ne.y()-N.position.y),Ve===0&&ye===0)return;let Ie;if(Me==="polygon"&&N.type==="polygon")Ie={type:"polygon",points:N.points.map(xe=>({x:xe.x+Ve,y:xe.y+ye})),holes:N.holes?N.holes.map(xe=>xe.map($e=>({x:$e.x+Ve,y:$e.y+ye}))):void 0};else if(Me==="rectangle"&&N.type==="rectangle")Ie={type:"rectangle",origin:{x:N.origin.x+Ve,y:N.origin.y+ye},width:N.width,height:N.height};else if(Me==="linear"&&N.type==="linear")Ie={type:"linear",segments:N.segments.map(xe=>xe.map($e=>({x:$e.x+Ve,y:$e.y+ye})))};else if(Me==="point"&&N.type==="point")Ie={type:"point",position:{x:N.position.x+Ve,y:N.position.y+ye}};else return;Me==="polygon"||Me==="linear"?Ne.position({x:0,y:0}):Me==="rectangle"&&N.type==="rectangle"?Ne.position({x:N.origin.x,y:N.origin.y}):Me==="point"&&N.type==="point"&&Ne.position({x:N.position.x,y:N.position.y}),re(r.id,Ie)};if(N.type==="polygon"){const Me=Lt(N.points),We=qa(N.points),Ne=ln(r),Ve=!!((Rt=r.adjustments)!=null&&Rt.height||(Ke=r.adjustments)!=null&&Ke.pitch),ye=Ve&&Ne.value!=null?Sn(Ne.value,Ne.unit):r.real_world_value!=null?Ft(r.real_world_value):r.pixel_value!=null?`${r.pixel_value.toFixed(0)} px²`:"",Ie=(()=>{const G=[];return r.label&&G.push(r.label),Ve&&Ne.formula&&G.push(Ne.formula),ye&&G.push(ye),G.join(`
2`)})(),xe=!!N.holes&&N.holes.length>0,$e=`${y}${Math.round(Y*255).toString(16).padStart(2,"0")}`,_t=o||C?"#FFFFFF":y,Ye=N.points,ke=N.holes??[];return e.jsxs(St.Fragment,{children:[xe?e.jsx(La,{id:r.id,fill:$e,stroke:_t,strokeWidth:ae,hitStrokeWidth:X,fillRule:"evenodd",draggable:se,onDragEnd:se?it("polygon"):void 0,onClick:H,onTap:H,onMouseEnter:Ee,onMouseLeave:De,sceneFunc:(G,oe)=>{if(G.beginPath(),Ye.length>0){G.moveTo(Ye[0].x,Ye[0].y);for(let Ce=1;Ce<Ye.length;Ce++)G.lineTo(Ye[Ce].x,Ye[Ce].y);G.closePath()}for(const Ce of ke)if(Ce.length!==0){G.moveTo(Ce[0].x,Ce[0].y);for(let be=1;be<Ce.length;be++)G.lineTo(Ce[be].x,Ce[be].y);G.closePath()}G.fillStrokeShape(oe)}}):e.jsx(Be,{id:r.id,points:Me,closed:!0,fill:$e,stroke:_t,strokeWidth:ae,hitStrokeWidth:X,draggable:se,onDragEnd:se?it("polygon"):void 0,onClick:H,onTap:H,onMouseEnter:Ee,onMouseLeave:De}),xe&&ke.map((G,oe)=>{const Ce=Lt(G);return e.jsx(Be,{points:Ce,closed:!0,stroke:o||C?"#FFFFFF":y,strokeWidth:1.5*m,dash:o||C?[5*m,3*m]:void 0,listening:!1},`hole-${r.id}-${oe}`)}),Ie&&e.jsx(rt,{x:We.x-75*m,y:We.y-(r.label?16:7)*m,width:150*m,text:Ie,fontSize:13*m,fill:"#FFFFFF",fontStyle:"bold",align:"center",listening:!1,shadowColor:"#000000",shadowBlur:3*m,shadowOpacity:.7}),o&&N.points.map((G,oe)=>e.jsx(lt,{id:`vertex:${r.id}:${oe}`,x:G.x,y:G.y,radius:4*m,hitStrokeWidth:10*m,fill:"#FFFFFF",stroke:y,strokeWidth:1.5*m,draggable:!0,onMouseEnter:()=>pe("move"),onMouseLeave:()=>pe(null),onDragStart:()=>pe("move"),onDragEnd:Ce=>{if(pe(null),!re||N.type!=="polygon")return;const be=Ce.target,Pe=be.x(),ct=be.y();if(Pe===G.x&&ct===G.y)return;const jt=N.points.map((qe,At)=>At===oe?{x:Pe,y:ct}:qe);be.position({x:G.x,y:G.y}),re(r.id,{type:"polygon",points:jt})}},`sel-${r.id}-${oe}`))]},r.id)}if(N.type==="rectangle"){const Me=ln(r),We=!!((dn=r.adjustments)!=null&&dn.height||(mn=r.adjustments)!=null&&mn.pitch),Ne=We&&Me.value!=null?Sn(Me.value,Me.unit):r.real_world_value!=null?Ft(r.real_world_value):r.pixel_value!=null?`${r.pixel_value.toFixed(0)} px²`:"",Ve=(()=>{const Ie=[];return r.label&&Ie.push(r.label),We&&Me.formula&&Ie.push(Me.formula),Ne&&Ie.push(Ne),Ie.join(`
3`)})(),ye={x:N.origin.x+N.width/2,y:N.origin.y+N.height/2};return e.jsxs(St.Fragment,{children:[e.jsx(Ms,{id:r.id,x:N.origin.x,y:N.origin.y,width:N.width,height:N.height,fill:`${y}${Math.round(Y*255).toString(16).padStart(2,"0")}`,stroke:o||C?"#FFFFFF":y,strokeWidth:ae,hitStrokeWidth:X,draggable:se,onDragEnd:se?it("rectangle"):void 0,onClick:H,onTap:H,onMouseEnter:Ee,onMouseLeave:De}),Ve&&e.jsx(rt,{x:ye.x-75*m,y:ye.y-(r.label?16:7)*m,width:150*m,text:Ve,fontSize:13*m,fill:"#FFFFFF",fontStyle:"bold",align:"center",listening:!1,shadowColor:"#000000",shadowBlur:3*m,shadowOpacity:.7}),o&&(()=>{const Ie=[{x:N.origin.x,y:N.origin.y},{x:N.origin.x+N.width,y:N.origin.y},{x:N.origin.x+N.width,y:N.origin.y+N.height},{x:N.origin.x,y:N.origin.y+N.height}];return Ie.map((xe,$e)=>e.jsx(lt,{id:`rectCorner:${r.id}:${$e}`,x:xe.x,y:xe.y,radius:4*m,hitStrokeWidth:10*m,fill:"#FFFFFF",stroke:y,strokeWidth:1.5*m,draggable:!0,onMouseEnter:()=>pe($e===0||$e===2?"nwse-resize":"nesw-resize"),onMouseLeave:()=>pe(null),onDragStart:()=>pe($e===0||$e===2?"nwse-resize":"nesw-resize"),onDragEnd:_t=>{if(pe(null),!re||N.type!=="rectangle")return;const Ye=_t.target,ke=Ye.x(),G=Ye.y();if(ke===xe.x&&G===xe.y)return;const oe=Ie[($e+2)%4],Ce={x:Math.min(oe.x,ke),y:Math.min(oe.y,G)},be=Math.abs(oe.x-ke),Pe=Math.abs(oe.y-G);if(be===0||Pe===0){Ye.position({x:xe.x,y:xe.y});return}Ye.position({x:xe.x,y:xe.y}),re(r.id,{type:"rectangle",origin:Ce,width:be,height:Pe})}},`sel-${r.id}-${$e}`))})()]},r.id)}if(N.type==="linear"){const Me=r.real_world_value!=null?Tt(r.real_world_value):r.pixel_value!=null?`${r.pixel_value.toFixed(0)} px`:"",We=ln(r),Ne=!!((fn=r.adjustments)!=null&&fn.height||(hn=r.adjustments)!=null&&hn.pitch),ye=Ne&&We.value!=null?Sn(We.value,We.unit):Me,Ie=N.segments[N.segments.length-1],xe=Ie&&Ie.length>0?Ie[Ie.length-1]:null,_t=N.segments.length===1?N.segments[0]:[],Ye=(o||C)&&r.subtractions&&r.subtractions.length>0;return e.jsxs(St.Fragment,{children:[Ye&&r.subtractions.map(ke=>{if(ke.vertices.length<2)return null;const[G,oe]=ke.vertices;return e.jsxs(St.Fragment,{children:[e.jsx(Be,{points:[G.x,G.y,oe.x,oe.y],stroke:"#9CA3AF",strokeWidth:2*m,dash:[5*m,3*m],lineCap:"round",listening:!1}),ke.label&&e.jsx(rt,{x:(G.x+oe.x)/2,y:(G.y+oe.y)/2-14*m,text:`${ke.label} — ${Tt(ke.value)}`,fontSize:10*m,fill:"#6B7280",fontStyle:"italic",align:"center",offsetX:40*m,listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9})]},`sub-${ke.id}`)}),N.segments.map((ke,G)=>{const oe=Lt(ke),Ce=G===N.segments.length-1;return e.jsxs(St.Fragment,{children:[(o||C)&&e.jsx(Be,{points:oe,closed:!1,stroke:y,strokeWidth:(o?8:6)*m,opacity:.3,lineCap:"round",lineJoin:"round",listening:!1}),e.jsx(Be,{id:r.id,points:oe,closed:!1,stroke:y,strokeWidth:(o?3:2.5)*m,hitStrokeWidth:X,lineCap:"round",lineJoin:"round",draggable:se,onDragEnd:se?it("linear"):void 0,onClick:H,onTap:H,onMouseEnter:Ee,onMouseLeave:De}),ke.length>1&&ke.slice(0,-1).map((be,Pe)=>{const ct=ke[Pe+1],jt={x:(be.x+ct.x)/2,y:(be.y+ct.y)/2},qe=Ha(be,ct);let At;if(E){const pn=Et(qe,E.pixels_per_unit,E.real_world_unit);At=Tt(pn)}else At=`${qe.toFixed(0)} px`;return e.jsx(rt,{x:jt.x,y:jt.y-14*m,text:At,fontSize:10*m,fill:y,fontStyle:"bold",align:"center",offsetX:20*m,listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9},`seg-${r.id}-${G}-${Pe}`)}),Ce&&(ye||r.label||Ne)&&xe&&(()=>{const be=Ne?We.formula:null,Pe=[];if(r.label&&Pe.push(r.label),be&&Pe.push(be),ye&&Pe.push(be?ye:`Total: ${ye}`),be){const ct=(r.label?44:30)*m;return e.jsxs(e.Fragment,{children:[r.label&&e.jsx(rt,{x:xe.x+10*m,y:xe.y-ct,text:r.label,fontSize:12*m,fill:y,fontStyle:"bold",listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9}),e.jsx(rt,{x:xe.x+10*m,y:xe.y-(r.label,30*m),text:be,fontSize:10*m,fill:y,opacity:.7,fontStyle:"italic",listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9}),ye&&e.jsx(rt,{x:xe.x+10*m,y:xe.y-16*m,text:ye,fontSize:12*m,fill:y,fontStyle:"bold",listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9})]})}return e.jsx(rt,{x:xe.x+10*m,y:xe.y-(r.label&&ye?30:18)*m,text:r.label&&ye?`${r.label}
4Total: ${ye}`:r.label||`Total: ${ye}`,fontSize:12*m,fill:y,fontStyle:"bold",listening:!1,shadowColor:"#FFFFFF",shadowBlur:3*m,shadowOpacity:.9})})(),ke.map((be,Pe)=>e.jsx(lt,{x:be.x,y:be.y,radius:3.5*m,fill:y,stroke:"#FFFFFF",strokeWidth:1.5*m,listening:!1},`v-${r.id}-${G}-${Pe}`))]},`seg-frag-${r.id}-${G}`)}),o&&_t.map((ke,G)=>e.jsx(lt,{id:`vertex:${r.id}:${G}`,x:ke.x,y:ke.y,radius:4*m,hitStrokeWidth:10*m,fill:"#FFFFFF",stroke:y,strokeWidth:1.5*m,draggable:!0,onMouseEnter:()=>pe("move"),onMouseLeave:()=>pe(null),onDragStart:()=>pe("move"),onDragEnd:oe=>{if(pe(null),!re||N.type!=="linear"||N.segments.length!==1)return;const Ce=oe.target,be=Ce.x(),Pe=Ce.y();if(be===ke.x&&Pe===ke.y)return;const ct=N.segments[0].map((jt,qe)=>qe===G?{x:be,y:Pe}:jt);Ce.position({x:ke.x,y:ke.y}),re(r.id,{type:"linear",segments:[ct]})}},`sel-${r.id}-${G}`))]},r.id)}if(N.type==="point"){const We=un.get(r.id)??1;return e.jsxs(St.Fragment,{children:[e.jsx(lt,{id:r.id,x:N.position.x,y:N.position.y,radius:12*m,fill:y,stroke:o||C?"#FFFFFF":y,strokeWidth:(o?2.5:1.5)*m,draggable:se,onDragEnd:se?it("point"):void 0,onClick:H,onTap:H,onMouseEnter:Ee,onMouseLeave:De}),e.jsx(rt,{x:N.position.x,y:N.position.y,offsetX:We>=10?7*m:4*m,offsetY:5*m,text:String(We),fontSize:10*m,fill:"#FFFFFF",fontStyle:"bold",listening:!1}),r.label&&e.jsx(rt,{x:N.position.x-75*m,y:N.position.y+16*m,width:150*m,text:r.label,fontSize:11*m,fill:"#FFFFFF",fontStyle:"bold",align:"center",listening:!1,shadowColor:"#000000",shadowBlur:3*m,shadowOpacity:.7})]},r.id)}return null},[je,ce,m,h,S,E,un,v,T,re]);return e.jsxs("div",{ref:He,className:"flex-1 min-h-0 bg-gray-900 relative overflow-hidden",style:{touchAction:"none"},onContextMenu:r=>r.preventDefault(),children:[Xt&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center z-10",children:e.jsx(Wn,{className:"h-8 w-8 animate-spin text-white/60"})}),Mn&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center z-10",children:e.jsx("p",{className:"text-red-400 text-sm",children:(Nt==null?void 0:Nt.message)||"Failed to load plan"})}),!p&&!Xt&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center z-10",children:e.jsx("p",{className:"text-white/40 text-sm",children:"No plan file loaded"})}),Dt&&ee.width>0&&e.jsxs(Pa,{ref:we,width:ee.width,height:ee.height,style:{cursor:cn},onWheel:En,onMouseDown:Fn,onMouseMove:Tn,onMouseUp:Dn,onDblClick:Yt,onContextMenu:Qt,children:[e.jsx(On,{x:tt.x*P+ue.x,y:tt.y*P+ue.y,scaleX:P*D,scaleY:P*D,listening:!1,children:e.jsx(Oa,{image:Dt,width:x.width,height:x.height})}),e.jsxs(On,{x:tt.x*P+ue.x,y:tt.y*P+ue.y,scaleX:P*D,scaleY:P*D,children:[E&&e.jsxs(e.Fragment,{children:[e.jsx(Be,{points:[E.calibration_point_1_x,E.calibration_point_1_y,E.calibration_point_2_x,E.calibration_point_2_y],stroke:"#9CA3AF",strokeWidth:1.5*m,dash:[6*m,4*m],listening:!1}),e.jsx(lt,{x:E.calibration_point_1_x,y:E.calibration_point_1_y,radius:Un*m,fill:"#9CA3AF",opacity:.6,listening:!1}),e.jsx(lt,{x:E.calibration_point_2_x,y:E.calibration_point_2_y,radius:Un*m,fill:"#9CA3AF",opacity:.6,listening:!1}),Wt&&It&&e.jsx(rt,{x:Wt.x,y:Wt.y-16*m,text:It,fontSize:12*m,fill:"#9CA3AF",align:"center",offsetX:0,listening:!1})]}),B.map(A)]}),e.jsxs(On,{x:tt.x*P+ue.x,y:tt.y*P+ue.y,scaleX:P*D,scaleY:P*D,children:[h==="calibrate"&&I.map((r,o)=>e.jsxs(St.Fragment,{children:[e.jsx(lt,{x:r.x,y:r.y,radius:Un*m,fill:"#3B82F6",stroke:"#FFFFFF",strokeWidth:1.5*m}),e.jsx(rt,{x:r.x+10*m,y:r.y-8*m,text:o===0?"A":"B",fontSize:12*m,fill:"#3B82F6",fontStyle:"bold",listening:!1})]},o)),h==="calibrate"&&I.length===2&&e.jsx(Be,{points:[I[0].x,I[0].y,I[1].x,I[1].y],stroke:"#3B82F6",strokeWidth:2*m,dash:[6*m,4*m],listening:!1}),h==="calibrate"&&I.length===1&&M&&(()=>{const{snapped:r,snapH:o,snapV:C}=yt(M,I[0],q),y=[I[0].x,I[0].y,r.x,r.y],Y=o||C;return e.jsx(e.Fragment,{children:e.jsx(Be,{points:y,stroke:Y?"#10B981":"#3B82F6",strokeWidth:2*m,dash:[6*m,4*m],listening:!1})})})(),h==="area"&&V&&mt.length>=4&&e.jsx(Be,{points:mt,closed:mt.length>=6,fill:`${j}${Math.round(Qn*.5*255).toString(16).padStart(2,"0")}`,stroke:j,strokeWidth:2*m,dash:[6*m,4*m],listening:!1}),h==="area"&&V&&g.length>0&&M&&mt.length<6&&e.jsx(Be,{points:Lt([g[g.length-1],M]),stroke:j,strokeWidth:1.5*m,dash:[4*m,3*m],listening:!1}),h==="area"&&g.map((r,o)=>e.jsx(lt,{x:r.x,y:r.y,radius:(o===0&&dt?8:4)*m,fill:o===0&&dt?"#FFFFFF":j,stroke:o===0&&dt?j:"#FFFFFF",strokeWidth:1.5*m,listening:!1},`dp-${o}`)),h==="linear"&&V&&mt.length>=4&&e.jsx(Be,{points:mt,closed:!1,stroke:j,strokeWidth:2.5*m,dash:[6*m,4*m],lineCap:"round",lineJoin:"round",listening:!1}),h==="linear"&&V&&g.length>0&&M&&mt.length<4&&e.jsx(Be,{points:Lt([g[g.length-1],M]),stroke:j,strokeWidth:2*m,dash:[4*m,3*m],lineCap:"round",listening:!1}),h==="linear"&&g.map((r,o)=>e.jsx(lt,{x:r.x,y:r.y,radius:4*m,fill:j,stroke:"#FFFFFF",strokeWidth:1.5*m,listening:!1},`dp-l-${o}`)),h==="subtract"&&W&&he&&e.jsxs(e.Fragment,{children:[e.jsx(lt,{x:he.x,y:he.y,radius:5*m,fill:"#EF4444",stroke:"#FFFFFF",strokeWidth:1.5*m,listening:!1}
4),M&&e.jsx(Be,{points:[he.x,he.y,M.x,M.y],stroke:"#EF4444",strokeWidth:2*m,dash:[6*m,4*m],lineCap:"round",listening:!1})]}),h==="subtract"&&W&&le&&le.length>0&&e.jsxs(e.Fragment,{children:[(()=>{const r=le,o=[...r];if(M){const C=r[r.length-1],{snapped:y}=yt(M,C,q);o.push(y)}return r.length>=2&&o.push(r[0]),e.jsx(Be,{points:Lt(o),stroke:"#EF4444",strokeWidth:2*m,dash:[6*m,4*m],lineCap:"round",lineJoin:"round",fill:r.length>=3?"#EF444420":void 0,closed:r.length>=3,listening:!1})})(),le.map((r,o)=>e.jsx(lt,{x:r.x,y:r.y,radius:4*m,fill:"#EF4444",stroke:"#FFFFFF",strokeWidth:1.5*m,listening:!1},`sub-vert-${o}`))]}),kt&&e.jsx(Ms,{x:kt.x,y:kt.y,width:kt.width,height:kt.height,fill:`${j}${Math.round(Qn*.5*255).toString(16).padStart(2,"0")}`,stroke:j,strokeWidth:2*m,dash:[6*m,4*m],listening:!1}),h==="rectangle"&&V&&g.length===1&&e.jsx(lt,{x:g[0].x,y:g[0].y,radius:4*m,fill:j,stroke:"#FFFFFF",strokeWidth:1.5*m,listening:!1}),nt&&M&&e.jsxs(e.Fragment,{children:[nt.snapH&&e.jsx(Be,{points:[nt.prevPoint.x,nt.prevPoint.y,M.x,nt.prevPoint.y],stroke:"#10B981",strokeWidth:1*m,dash:[4*m,3*m],listening:!1}),nt.snapV&&e.jsx(Be,{points:[nt.prevPoint.x,nt.prevPoint.y,nt.prevPoint.x,M.y],stroke:"#10B981",strokeWidth:1*m,dash:[4*m,3*m],listening:!1})]}),Zt&&M&&e.jsx(rt,{x:M.x+15*m,y:M.y-20*m,text:Zt,fontSize:12*m,fill:"#FFFFFF",fontStyle:"bold",listening:!1,shadowColor:"#000000",shadowBlur:3*m,shadowOpacity:.8})]})]}),P!==1&&e.jsxs("button",{onClick:wt,className:"absolute bottom-4 right-4 bg-black/60 text-white/80 hover:text-white text-xs px-2 py-1 rounded tabular-nums z-20",title:"Reset zoom (fit to page)",children:[(P*100).toFixed(0),"%"]}),(E==null?void 0:E.scale_ratio_label)&&e.jsxs("div",{className:"absolute bottom-4 left-4 flex items-center gap-1 bg-black/60 text-white/70 text-xs px-2 py-1 rounded z-20",children:[e.jsx("span",{title:"Current plan scale",children:E.scale_ratio_label}),Ue&&e.jsx("button",{onClick:Ue,className:"ml-0.5 -mr-1 rounded p-0.5 text-white/50 hover:text-white hover:bg-white/10",title:"Clear scale","aria-label":"Clear scale calibration",children:e.jsx($s,{className:"h-3 w-3"})})]})]})}),Ps=[.25,.5,.75,1,1.5,2,4],Qr=[{id:"select",label:"Select",shortcut:"V",icon:Va},{id:"move",label:"Move",shortcut:"M",icon:Zn},{id:"area",label:"Area (Polygon)",shortcut:"A",icon:Ir},{id:"rectangle",label:"Rectangle",shortcut:"R",icon:$a},{id:"linear",label:"Linear (Polyline)",shortcut:"L",icon:Ar},{id:"subtract",label:"Subtract",shortcut:"X",icon:Rr},{id:"count",label:"Count",shortcut:"C",icon:xr},{id:"calibrate",label:"Calibrate Scale",shortcut:"S",icon:Nn}];function Wr({activeTool:a,onToolChange:p,isCalibrated:F,zoom:u,onZoomTo:b,onFitToPage:h}){return e.jsx(ka,{delayDuration:300,children:e.jsxs("div",{role:"toolbar","aria-label":"Drawing tools",className:"absolute left-4 top-1/2 -translate-y-1/2 z-30 flex flex-col gap-1 bg-gray-800/90 backdrop-blur-sm border border-white/10 rounded-lg p-1 shadow-lg",children:[Qr.map(S=>{const I=a===S.id,E=S.icon;return e.jsxs(wn,{children:[e.jsx(kn,{asChild:!0,children:e.jsxs(ie,{variant:"ghost",size:"sm",onClick:()=>p(S.id),"aria-label":`${S.label} (${S.shortcut})`,"aria-pressed":I,className:`
5                    relative w-9 h-9 p-0
6                    ${I?"bg-blue-600 text-white hover:bg-blue-700 hover:text-white":"text-white/60 hover:text-white hover:bg-white/10"}
7                  `,children:[e.jsx(E,{className:"h-4 w-4"}),S.id==="calibrate"&&!F&&e.jsx("span",{className:"absolute -top-0.5 -right-0.5 w-2 h-2 bg-amber-400 rounded-full"})]})}),e.jsxs(_n,{side:"right",className:"flex items-center gap-2",children:[e.jsx("span",{children:S.label}),e.jsx("kbd",{className:"text-[10px] bg-white/10 px-1 py-0.5 rounded",children:S.shortcut})]})]},S.id)}),e.jsx("div",{className:"border-t border-white/10 my-0.5"}),e.jsxs(wn,{children:[e.jsx(kn,{asChild:!0,children:e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>{const S=Ps.filter(I=>I<u-.01);S.length>0&&b(S[S.length-1])},"aria-label":"Zoom out",className:"w-9 h-9 p-0 text-white/60 hover:text-white hover:bg-white/10",children:e.jsx(an,{className:"h-4 w-4"})})}),e.jsx(_n,{side:"right",children:"Zoom out"})]}),e.jsxs("div",{className:"text-white/70 text-[10px] tabular-nums font-medium text-center py-0.5 
7select-none",children:[(u*100).toFixed(0),"%"]}),e.jsxs(wn,{children:[e.jsx(kn,{asChild:!0,children:e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>{const S=Ps.filter(I=>I>u+.01);S.length>0&&b(S[0])},"aria-label":"Zoom in",className:"w-9 h-9 p-0 text-white/60 hover:text-white hover:bg-white/10",children:e.jsx(Us,{className:"h-4 w-4"})})}),e.jsx(_n,{side:"right",children:"Zoom in"})]}),e.jsxs(wn,{children:[e.jsx(kn,{asChild:!0,children:e.jsx(ie,{variant:"ghost",size:"sm",onClick:h,"aria-label":"Fit to screen",className:"w-9 h-9 p-0 text-white/60 hover:text-white hover:bg-white/10",children:e.jsx(Hs,{className:"h-4 w-4"})})}),e.jsx(_n,{side:"right",children:"Fit to screen"})]})]})})}const Os=[10,20,25,50,75,100,150,200,250,500,1e3];function Gr(a,p){return Math.sqrt((p.x-a.x)**2+(p.y-a.y)**2)}function qr(a,p){if(a<=0||p<=0)return"";const F=p/a;let u=Os[0],b=Math.abs(F-u);for(const I of Os){const E=Math.abs(F-I);E<b&&(b=E,u=I)}const h=u*.1;return`${b>h?"~":""}1:${u}`}function Hr({open:a,onConfirm:p,onCancel:F,points:u}){const[b,h]=l.useState(""),[S,I]=l.useState("mm"),E=l.useRef(null),[g,V]=l.useState({x:0,y:0}),M=l.useRef(null);l.useEffect(()=>{if(a){h(""),I("mm"),V({x:0,y:0});const L=setTimeout(()=>{var fe;return(fe=E.current)==null?void 0:fe.focus()},100);return()=>clearTimeout(L)}},[a]);const $=L=>{if(L.target.closest("button, input, textarea, select, [role='combobox'], [role='dialog'][data-state='open'] [role='listbox'], a"))return;L.preventDefault(),M.current={startX:L.clientX,startY:L.clientY,baseX:g.x,baseY:g.y};const Z=W=>{if(!M.current)return;const he=W.clientX-M.current.startX,J=W.clientY-M.current.startY;V({x:M.current.baseX+he,y:M.current.baseY+J})},re=()=>{M.current=null,window.removeEventListener("mousemove",Z),window.removeEventListener("mouseup",re)};window.addEventListener("mousemove",Z),window.addEventListener("mouseup",re)},je=Gr(u[0],u[1]),ce=parseFloat(b),c=!isNaN(ce)&&ce>0,v=c?S==="m"?ce*1e3:ce:0,T=qr(je,v),_=()=>{c&&p(ce,S)},w=L=>{L.key==="Enter"&&c&&_()};return e.jsx(Pt,{open:a,onOpenChange:L=>{L||F()},children:e.jsxs(Ot,{className:"sm:max-w-[380px] cursor-move",style:g.x!==0||g.y!==0?{transform:`translate(calc(-50% + ${g.x}px), calc(-50% + ${g.y}px))`}:void 0,onMouseDown:$,children:[e.jsx(Vt,{children:e.jsx($t,{children:"Set Scale"})}),e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(_a,{htmlFor:"cal-distance",children:"Distance between points"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Kt,{ref:E,id:"cal-distance",type:"number",min:"0",step:"any",placeholder:"e.g. 3600",value:b,onChange:L=>h(L.target.value),onKeyDown:w,className:"flex-1"}),e.jsxs(zs,{value:S,onValueChange:L=>I(L),children:[e.jsx(Ks,{className:"w-20",children:e.jsx(Bs,{})}),e.jsxs(Xs,{children:[e.jsx(Cn,{value:"mm",children:"mm"}),e.jsx(Cn,{value:"m",children:"m"})]})]})]})]}),c&&e.jsxs("div",{className:"text-sm text-muted-foreground space-y-1",children:[e.jsxs("p",{children:["Computed scale: ",e.jsx("span",{className:"font-medium text-foreground",children:T})]}),e.jsxs("p",{children:["1 pixel = ",(v/je).toFixed(2)," mm"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Tip: Use a dimension at least 6m (6000 mm) long for best accuracy."})]}),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:F,children:"Cancel"}),e.jsx(ie,{onClick:_,disabled:!c,children:"Apply Scale"})]})]})})}function zr(a){let p=0,F=0,u=0;for(const h of a)(h.measurement_type==="area"||h.measurement_type==="rectangle")&&h.real_world_value!=null?p+=h.real_world_value:h.measurement_type==="linear"&&h.real_world_value!=null?F+=h.real_world_value:h.measurement_type==="count"&&u++;const b=[];return p>0&&b.push(Ft(p)),F>0&&b.push(Tt(F)),u>0&&b.push(`${u} EA`),b.length>0?b.join(" · "):"0"}function Kr(a){if(a.measurement_type==="count")return"";const p=ln(a);return p.value!=null?Sn(p.value,p.unit):a.pixel_value!=null?`${a.pixel_value.toFixed(0)} px`:""}const Br=l.forwardRef(function({groups:p,measurements:F,allSessionMeasurements:u,pages:b,currentPageId:h,activeGroupId:S,onSelectGroup:I,onCreateGroup:E,onDeleteGroup:g,onToggleVisibility:V,onSelectMeasurement:M,onDeleteMeasurement:$,onNavigateToPage:je,onContextMenuGroup:ce,onContextMenuMeasurement:c,isCollapsed:v,onToggleCollapsed:T,checklist:_},w){const[L,fe]=l.useState(new Set);l.useImperativeHandle(w,()=>({expandAll:()=>fe(new Set(p.map(d=>d.id))),collapseAll:()=>fe(new Set)}),[p]);const[Z,re]=l.useState(!1),[W,he]=l.useState(""),[J,le]=l.useState("all"),Se=b.length>1,Ue=l.useMemo(()=>{const d=new Map;for(const O of b)d.set(O.id,{pageNumber:O.page_number,label:O.page_label||`Page ${O.page_number}`});return d},[b]),Qe=l.useMemo(()=>
7{if(J==="all")return u;const d=J==="current"?h:J;return d?u.filter(O=>O.page_id===d):F},[J,u,F,h]),He=l.useMemo(()=>{const d=new Map;for(const O of Qe){const z=O.group_id;d.has(z)||d.set(z,[]),d.get(z).push(O)}return d},[Qe]),we=l.useMemo(()=>{let d=0,O=0,z=0;for(const U of Qe)(U.measurement_type==="area"||U.measurement_type==="rectangle")&&U.real_world_value!=null?d+=U.real_world_value:U.measurement_type==="linear"&&U.real_world_value!=null?O+=U.real_world_value:U.measurement_type==="count"&&z++;return{totalArea:d,totalLinear:O,totalCount:z}},[Qe]),ee=l.useCallback(d=>{fe(O=>{const z=new Set(O);return z.has(d)?z.delete(d):z.add(d),z})},[]),Ae=l.useCallback(()=>{W.trim()&&(E(W.trim()),he(""),re(!1))},[W,E]),P=l.useCallback(d=>{d.key==="Enter"?(d.preventDefault(),Ae()):d.key==="Escape"&&(re(!1),he(""))},[Ae]),Oe=l.useCallback(d=>{const O=Ue.get(d.page_id);O&&d.page_id!==h?(je(O.pageNumber),setTimeout(()=>M(d.id),150)):M(d.id)},[Ue,h,je,M]),ue=He.get(null)??[];if(v)return e.jsx("div",{className:"w-10 shrink-0 bg-gray-900 border-r border-white/10 flex flex-col items-center pt-2",children:e.jsx(ie,{variant:"ghost",size:"sm",onClick:T,className:"text-white/60 hover:text-white hover:bg-white/10 w-8 h-8 p-0",title:"Open groups panel",children:e.jsx(Dr,{className:"h-4 w-4"})})});const Le=(d,O)=>{var Te;const z=Kr(d),U=Ue.get(d.page_id),pe=d.page_id!==h,q=(((Te=d.subtractions)==null?void 0:Te.length)??0)>0,Fe=!!d.adjustments&&Object.keys(d.adjustments).length>0,ge=q||Fe,ze=de=>de.unit==="sqm"?Ft(de.value):de.unit==="lm"?Tt(de.value):`${de.value.toFixed(2)} ${de.unit}`,at=ln(d),Re=ge?[z?`Reported: ${z}`:null,at.formula?`  ${at.formula}`:null,...(d.subtractions??[]).map(de=>`  − ${de.label?de.label:"Subtraction"}: ${ze(de)}`)].filter(Boolean).join(`
8`):void 0,ne=pe&&U?`Click to go to ${U.label}`:Re;return e.jsxs("div",{className:"flex items-center justify-between gap-1 py-0.5 group/item cursor-pointer hover:bg-white/[0.03] rounded px-1 -mx-1",onClick:()=>Oe(d),onContextMenu:de=>{c&&(de.preventDefault(),de.stopPropagation(),c(d.id,de.clientX,de.clientY))},title:ne,children:[e.jsx("span",{className:`text-[10px] truncate flex-1 ${d.label?"text-white/80 font-medium":"text-white/50"}`,children:d.label||d.measurement_type}),ge&&e.jsx("span",{className:"text-amber-400/80 text-[9px] font-mono shrink-0",title:Re,"aria-label":"Has subtractions or adjustments",children:"[ƒ]"}),d.semantic_role&&(()=>{const de=Bt(d.semantic_role);return de?e.jsx("span",{className:"text-sky-400/80 shrink-0",title:`Feeds Strategy dimension: ${de.label}`,"aria-label":`Tagged for Strategy: ${de.label}`,children:e.jsx(Nn,{className:"h-2.5 w-2.5"})}):null})(),O&&U&&e.jsx("span",{className:"text-white/20 text-[9px] shrink-0",children:U.label}),z&&e.jsx("span",{className:"text-white/40 text-[10px] shrink-0",children:z}),e.jsx("button",{onClick:de=>{de.stopPropagation(),$(d.id)},className:"text-white/10 group-hover/item:text-white/30 hover:!text-red-400 shrink-0 ml-1",children:e.jsx(on,{className:"h-2.5 w-2.5"})})]},d.id)},Ge=d=>{if(d.length===0)return null;if(J==="all"&&Se){const O=new Map;for(const U of d)O.has(U.page_id)||O.set(U.page_id,[]),O.get(U.page_id).push(U);const z=[...O.keys()].sort((U,pe)=>{const q=Ue.get(U),Fe=Ue.get(pe);return((q==null?void 0:q.pageNumber)??0)-((Fe==null?void 0:Fe.pageNumber)??0)});return e.jsx("div",{className:"pl-7 pr-2 pb-1.5",children:z.map(U=>{const pe=O.get(U)??[],q=Ue.get(U),Fe=U===h;return e.jsxs("div",{children:[e.jsx("div",{className:`text-[9px] font-medium mt-1 mb-0.5 px-1 cursor-pointer hover:text-white/50 ${Fe?"text-blue-400/60":"text-white/25"}`,onClick:()=>q&&je(q.pageNumber),children:(q==null?void 0:q.label)??"Unknown page"}),e.jsx("div",{className:"pl-3",children:pe.map(ge=>Le(ge,!1))})]},U)})})}return e.jsx("div",{className:"pl-7 pr-2 pb-1.5",children:d.map(O=>Le(O,!1))})};return e.jsxs("div",{className:"w-[260px] shrink-0 bg-gray-900 border-r border-white/10 flex flex-col overflow-hidden",children:[_,e.jsxs("div",{className:"flex items-center justify-between px-3 py-2 border-b border-white/10 shrink-0",children:[e.jsx("span",{className:"text-white/80 text-xs font-medium",children:"Groups"}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:T,className:"text-white/60 hover:text-white hover:bg-white/10 w-6 h-6 p-0",title:"Close groups panel",children:e.jsx(Tr,{className:"h-3.5 w-3.5"})})]}),Se&&e.jsx("div",{className:"px-2 py-1.5 border-b border-white/10 shrink-0",children:e.jsxs(zs,{value:J,onValueChange:d=>le(d),children:[e.jsx(Ks,{className:"h-6 text-[10px] bg-gray-800 border-white/10 text-white/70",children:e.jsx(Bs,{})}),e.jsxs(Xs,{children:[e.jsx(Cn,{value:"all",children:"All Pages"}),b.sort((d,O)=>d.page_number-O.page_number).map(d=>e.jsxs(Cn,{value:d.id,children:[d.page_label||`Page ${d.page_number}`,d.id===h?" (current)":""]},d.id))]})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto min-h-0",children:[p.map(d=>{const O=d.id===S,z=L.has(d.id),U=He.get(d.id)??[],pe=U.length>0;return e.jsxs("div",{className:!pe&&J!=="all"?"opacity-50":"",children:[e.jsxs("div",{className:`flex items-center gap-1.5 px-2 py-1.5 cursor-pointer border-l-2 ${O?"border-l-blue-500 bg-white/5":"border-l-transparent hover:bg-white/[0.03]"}`,onClick:()=>I(O?null:d.id),onContextMenu:q=>{ce&&(q.preventDefault(),q.stopPropagation(),ce(d.id,q.clientX,q.clientY))},children:[e.jsx("button",{onClick:q=>{q.stopPropagation(),ee(d.id)},className:"text-white/40 hover:text-white/70 shrink-0",children:z?e.jsx(Jn,{className:"h-3 w-3"}):e.jsx(rn,{className:"h-3 w-3"})}),e.jsx("span",{className:"w-2.5 h-2.5 rounded-sm shrink-0",style:{backgroundColor:d.colour}}),e.jsx("span",{className:"text-white/80 text-xs truncate flex-1",children:d.name}),e.jsx(vr,{className:"h-3 w-3 text-white/30 shrink-0"}),e.jsx("button",{onClick:q=>{q.stopPropagation(),V(d.id,!d.is_visible)},className:"text-white/30 hover:text-white/60 shrink-0",title:d.is_visible?"Hide measurements":"Show measurements",children:d.is_visible?e.jsx(sn,{className:"h-3 w-3"}):e.jsx(Yn,{className:"h-3 w-3 text-white/20"})}),e.jsx("button",{onClick:q=>{q.stopPropagation(),g(d.id)},className:"text-white/20 hover:text-red-400 shrink-0",title:"Delete group",children:e.jsx(on,{className:"h-3 w-3"})})]}),e.jsxs("div",{className:"flex items-center justify-between px-7 pb-1",children:[e.jsxs("span",{className:"text-white/30 text-[10px]",children:[U.length," item",U.length!==1?"s":""]}),e.jsx("span",{className:"text-white/50 text-[10px] font-medium",children:zr(U)})]}),z&&Ge(U)]},d.id)}),ue.length>0&&e.jsxs("div",{className:"border-t border-white/5 mt-1 pt-1",children:[e.jsx("div",{className:"px-2 py-1",children:e.jsxs("span",{className:"text-white/30 text-[10px]",children:["Ungrouped (",ue.length,")"]})}),e.jsx("div",{className:"px-2 pb-1",children:ue.map(d=>Le(d,J==="all"&&Se))})]})]}),Z?e.jsxs("div",{className:"px-2 py-2 border-t border-white/10 shrink-0 space-y-1.5",children:[e.jsx(Kt,{value:W,onChange:d=>he(d.target.value),onKeyDown:P,placeholder:"Group name...",className:"h-7 text-xs bg-gray-800 border-white/10 text-white",autoFocus:!0}),e.jsxs("div",{className:"flex gap-1.5",children:[e.jsx(ie,{size:"sm",onClick:Ae,disabled:!W.trim(),className:"h-7 text-xs px-2 flex-1",children:"Add"}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>{re(!1),he("")},className:"h-7 text-xs px-2 text-white/60 hover:text-white",children:"×"})]})]}):e.jsx("div",{className:"px-2 py-2 border-t border-white/10 shrink-0",children:e.jsxs(ie,{variant:"ghost",size:"sm",onClick:()=>re(!0),className:"w-full h-7 text-xs text-white/50 hover:text-white hover:bg-white/10 justify-start gap-1.5",children:[e.jsx(Us,{className:"h-3 w-3"}),"New Group"]})}),(we.totalArea>0||we.totalLinear>0||we.totalCount>0)&&e.jsxs("div",{className:"px-3 py-2 border-t border-white/10 shrink-0 space-y-0.5",children:[e.jsx("span",{className:"text-white/40 text-[10px] font-medium",children:J==="all"?"Summary":"Page Summary"}),e.jsxs("div",{className:"space-y-0.5",children:[we.totalArea>0&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-white/30 text-[10px]",children:"Areas"}),e.jsx("span",{className:"text-white/50 text-[10px]",children:Ft(we.totalArea)})]}),we.totalLinear>0&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-white/30 text-[10px]",children:"Linear"}),e.jsx("span",{className:"text-white/50 text-[10px]",children:Tt(we.totalLinear)})]}),we.totalCount>0&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-white/30 text-[10px]",children:"Counts"}),e.jsxs("span",{className:"text-white/50 text-[10px]",children:[we.totalCount," EA"]})]})]})]})]})}),Xr=64,Yr=.15;async function Zr(a,p){try{const F=await a.getPage(p),u=F.getViewport({scale:Yr}),b=document.createElement("canvas");return b.width=Math.floor(u.width),b.height=Math.floor(u.height),b.getContext("2d")?(await F.render({canvas:b,viewport:u}).promise,b.toDataURL("image/png")):null}catch{return null}}function Jr({pages:a,currentPageNumber:p,onPageChange:F,fileUrl:u,mimeType:b,calibrationMap:h}){const S=l.useRef(null),[I,E]=l.useState(new Map),[g,V]=l.useState({start:1,end:10}),M=l.useRef(null),$=l.useRef(null),[je,ce]=l.useState(!1),c=b==="application/pdf",v=a.length,T=l.useCallback(()=>{const w=S.current;if(!w)return;const L=w.scrollLeft,fe=w.clientWidth,Z=80,re=Math.max(1,Math.floor(L/Z)),W=Math.min(v,Math.ceil((L+fe)/Z)+2);V({start:re,end:W})},[v]);l.useEffect(()=>{T()},[T]),l.useEffect(()=>{if(v===0)return;const w=S.current;if(!w)return;
8const L=w.querySelector(`[data-page="${p}"]`);L&&L.scrollIntoView({behavior:"smooth",block:"nearest",inline:"center"});const fe=setTimeout(T,350);return()=>clearTimeout(fe)},[p,v,T]),l.useEffect(()=>{if(!c||!u||v<=1)return;if($.current===u&&M.current){ce(!0);return}let w=!1;return ce(!1),Gs({url:u,cMapUrl:`https://cdn.jsdelivr.net/npm/pdfjs-dist@${qs}/cmaps/`,cMapPacked:!0}).promise.then(L=>{if(w){L.destroy();return}M.current=L,$.current=u,ce(!0)}).catch(()=>{}),()=>{w=!0}},[c,u,v]),l.useEffect(()=>{if(!c||!je||!M.current||v<=1)return;const w=M.current;let L=!1;return(async()=>{for(let Z=g.start;Z<=Math.min(g.end,v);Z++){if(Z<1||Z>v)continue;let re=!1;if(E(he=>(re=he.has(Z),he)),re)continue;const W=await Zr(w,Z);if(L)return;W&&E(he=>{const J=new Map(he);return J.set(Z,W),J})}})(),()=>{L=!0}},[c,je,g,v]);const _=l.useMemo(()=>{const w=new Map;for(const L of a)w.set(L.page_number,h.get(L.id)??L.is_calibrated);return w},[a,h]);return v===0?null:e.jsxs("div",{className:"shrink-0 overflow-hidden bg-gray-900/95 border-t border-white/10 backdrop-blur-sm",children:[e.jsx("div",{ref:S,className:"flex items-center gap-2 px-3 py-2 overflow-x-auto scrollbar-thin scrollbar-thumb-white/10",onScroll:T,children:a.map(w=>{const L=w.page_number===p,fe=_.get(w.page_number)??!1,Z=I.get(w.page_number);return e.jsxs("button",{"data-page":w.page_number,onClick:()=>F(w.page_number),className:`
9                relative shrink-0 rounded overflow-hidden transition-all
10                ${L?"ring-2 ring-blue-500 ring-offset-1 ring-offset-gray-900":"ring-1 ring-white/10 hover:ring-white/30"}
11              `,style:{width:72,height:Xr},title:w.page_label||`Page ${w.page_number}`,children:[Z?e.jsx("img",{src:Z,alt:`Page ${w.page_number}`,className:"w-full h-full object-cover"}):e.jsx("div",{className:"w-full h-full bg-gray-800 flex items-center justify-center",children:e.jsx("span",{className:"text-white/30 text-xs",children:w.page_number})}),e.jsx("div",{className:"absolute top-0.5 right-0.5",children:fe?e.jsx(Gn,{className:"h-3 w-3 text-green-400 drop-shadow"}):e.jsx(Qs,{className:"h-3 w-3 text-amber-400 drop-shadow"})}),L&&e.jsx("div",{className:"absolute bottom-0 inset-x-0 h-0.5 bg-blue-500"})]},w.id)})}),e.jsx("div",{className:"flex items-center gap-2 px-3 pb-1 overflow-x-auto",children:a.map(w=>e.jsx("div",{className:"shrink-0 text-center",style:{width:72},children:e.jsx("span",{className:`text-[9px] truncate block ${w.page_number===p?"text-white/70":"text-white/30"}`,children:w.page_label||`Page ${w.page_number}`})},`label-${w.id}`))})]})}const el=240,tl=220;function nl({open:a,x:p,y:F,target:u,onClose:b,onDelete:h,onDuplicate:S,onMove:I,onRename:E,onSetHeight:g,onClearHeight:V,heightLabel:M,onSetPitch:$,onClearPitch:je,copyValue:ce,onCopyValue:c,group:v,anyGroupHidden:T,onHideGroup:_,onShowOnlyGroup:w,onShowAllGroups:L,onRecenterHere:fe,onFitToPage:Z,onCalibrate:re,onDeleteVertex:W,onInsertVertexAfter:he,onContinuePolyline:J,moveToGroupOptions:le,currentGroupId:Se,onMoveToGroup:Ue,tagForStrategyOptions:Qe,currentSemanticRole:He,onTagForStrategy:we,groupTarget:ee,onRenameGroup:Ae,onToggleGroupVisibility:P,onShowOnlyThisGroup:Oe,onChangeGroupColour:ue,groupColourPalette:Le,onExpandAllGroups:Ge,onCollapseAllGroups:d,onDeleteGroup:O}){const z=l.useRef(null),[U,pe]=l.useState(!1),[q,Fe]=l.useState(!1),[ge,ze]=l.useState(!1);if(l.useEffect(()=>{if(!a){pe(!1),Fe(!1),ze(!1);return}const ne=xt=>{z.current&&!z.current.contains(xt.target)&&b()},Te=xt=>{xt.key==="Escape"&&b()},de=()=>b();return document.addEventListener("mousedown",ne),document.addEventListener("keydown",Te),window.addEventListener("wheel",de,{passive:!0}),()=>{document.removeEventListener("mousedown",ne),document.removeEventListener("keydown",Te),window.removeEventListener("wheel",de)}},[a,b]),!a||!u)return null;const at=Math.min(p,window.innerWidth-el-8),Re=Math.min(F,window.innerHeight-tl-8);return ja.createPortal(e.jsxs("div",{ref:z,className:"fixed z-[100] min-w-[180px] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",style:{left:at,top:Re},onContextMenu:ne=>ne.preventDefault(),children:[u.kind==="measurement"&&e.jsxs(e.Fragment,{children:[I&&e.jsxs("button",{type:"button",onClick:()=>{I(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Zn,{className:"h-4 w-4"}),"Move"]}),e.jsxs("button",{type:"button",onClick:()=>{S==null||S(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(wr,{className:"h-4 w-4"}),"Duplicate"]}),E&&e.jsxs("button",{type:"button",onClick:()=>{E(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Fs,{className:"h-4 w-4"}),"Rename…"]}),g&&e.jsxs("button",{type:"button",onClick:()=>{g(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Ts,{className:"h-4 w-4"}),(M==null?void 0:M.set)??"Set height…"]}),V&&e.jsxs("button",{type:"button",onClick:()=>{V(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(an,{className:"h-4 w-4"}),(M==null?void 0:M.clear)??"Clear height"]}),$&&e.jsxs("button",{type:"button",onClick:()=>{$(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(kr,{className:"h-4 w-4"}),"Set pitch…"]}),je&&e.jsxs("button",{type:"button",onClick:()=>{je(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(an,{className:"h-4 w-4"}),"Clear pitch"]}),ce&&e.jsxs("button",{type:"button",onClick:()=>{navigator.clipboard.writeText(ce).then(()=>c==null?void 0:c(ce)).catch(()=>{}),b()},className:"flex w-full items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Nr,{className:"h-4 w-4"}),"Copy value"]}),e.jsx("span",{className:"text-xs text-muted-foreground tabular-nums",children:ce})]}),(le&&le.length>0||Qe&&Qe.length>0||v||T)&&e.jsx("div",{className:"my-1 h-px bg-border"}),le&&le.length>0&&Ue&&e.jsxs("div",{className:"relative",onMouseEnter:()=>pe(!0),onMouseLeave:()=>pe(!1),children:[e.jsxs("button",{type:"button",className:"flex w-full items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[open=true]:bg-accent","data-open":U,children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Mr,{className:"h-4 w-4"}),"Move to group"]}),e.jsx(rn,{className:"h-4 w-4 opacity-60"})]}),U&&e.jsxs("div",{className:"absolute left-full top-0 ml-1 min-w-[200px] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",children:[le.map(ne=>{const Te=ne.id===Se;return e.jsxs("button",{type:"button",onClick:()=>{Te||Ue(ne.id),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx("span",{className:"h-3 w-3 shrink-0 rounded-sm border border-black/10",style:{backgroundColor:ne.colour}}),e.jsx("span",{className:"flex-1 truncate text-left",children:ne.name}),Te&&e.jsx(Pn,{className:"h-3.5 w-3.5 opacity-70"})]},ne.id)}),e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("button",{type:"button",onClick:()=>{Se!==null&&Ue(null),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-muted-foreground outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx("span",{className:"h-3 w-3 shrink-0 rounded-sm border border-dashed border-muted-foreground"}),e.jsx("span",{className:"flex-1 truncate text-left",children:"Ungrouped"}),Se===null&&e.jsx(Pn,{className:"h-3.5 w-3.5 opacity-70"})]})]})]}),Qe&&Qe.length>0&&we&&e.jsxs("div",{className:"relative",onMouseEnter:()=>ze(!0),onMouseLeave:()=>ze(!1),children:[e.jsxs("button",{type:"button",className:"flex w-full items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[open=true]:bg-accent","data-open":ge,children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Nn,{className:"h-4 w-4"}),"Tag for Strategy"]}
11),e.jsx(rn,{className:"h-4 w-4 opacity-60"})]}),ge&&e.jsxs("div",{className:"absolute left-full top-0 ml-1 min-w-[220px] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",children:[Qe.map(ne=>{const Te=ne.id===He;return e.jsxs("button",{type:"button",onClick:()=>{Te||we(ne.id),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx("span",{className:"flex-1 truncate text-left",children:ne.label}),e.jsx("span",{className:"text-xs text-muted-foreground",children:ne.unit}),Te&&e.jsx(Pn,{className:"h-3.5 w-3.5 opacity-70"})]},ne.id)}),He&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("button",{type:"button",onClick:()=>{we(null),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-muted-foreground outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(an,{className:"h-4 w-4"}),"Remove tag"]})]})]})]}),v&&_&&e.jsxs("button",{type:"button",onClick:()=>{_(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Yn,{className:"h-4 w-4"}),e.jsxs("span",{className:"truncate",children:["Hide ",v.name]})]}),v&&w&&e.jsxs("button",{type:"button",onClick:()=>{w(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Ds,{className:"h-4 w-4"}),e.jsxs("span",{className:"truncate",children:["Show only ",v.name]})]}),T&&L&&e.jsxs("button",{type:"button",onClick:()=>{L(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(sn,{className:"h-4 w-4"}),"Show all groups"]}),e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("button",{type:"button",onClick:()=>{h==null||h(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive outline-none hover:bg-destructive hover:text-destructive-foreground focus:bg-destructive focus:text-destructive-foreground",children:[e.jsx(on,{className:"h-4 w-4"}),"Delete"]})]}),u.kind==="empty"&&e.jsxs(e.Fragment,{children:[fe&&e.jsxs("button",{type:"button",onClick:()=>{fe(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Cr,{className:"h-4 w-4"}),"Recenter here"]}),Z&&e.jsxs("button",{type:"button",onClick:()=>{Z(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Hs,{className:"h-4 w-4"}),"Fit to page"]}),re&&e.jsxs("button",{type:"button",onClick:()=>{re(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Nn,{className:"h-4 w-4"}),"Calibrate scale"]}),T&&L&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("button",{type:"button",onClick:()=>{L(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(sn,{className:"h-4 w-4"}),"Show all groups"]})]})]}),u.kind==="group"&&ee&&e.jsxs(e.Fragment,{children:[Ae&&e.jsxs("button",{type:"button",onClick:()=>{Ae(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Fs,{className:"h-4 w-4"}),"Rename…"]}),P&&e.jsxs("button",{type:"button",onClick:()=>{P(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[ee.isVisible?e.jsx(Yn,{className:"h-4 w-4"}):e.jsx(sn,{className:"h-4 w-4"}),e.jsx("span",{className:"truncate",children:ee.isVisible?`Hide ${ee.name}`:`Show ${ee.name}`})]}),Oe&&e.jsxs("button",{type:"button",onClick:()=>{Oe(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Ds,{className:"h-4 w-4"}),e.jsxs("span",{className:"truncate",children:["Show only ",ee.name]})]}),T&&L&&e.jsxs("button",{type:"button",onClick:()=>{L(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(sn,{className:"h-4 w-4"}),"Show all groups"]}),ue&&Le&&Le.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("div",{className:"relative",onMouseEnter:()=>Fe(!0),onMouseLeave:()=>Fe(!1),children:[e.jsxs("button",{type:"button",className:"flex w-full items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[open=true]:bg-accent","data-open":q,children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(Fr,{className:"h-4 w-4"}),"Change colour"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"h-3 w-3 rounded-sm border border-black/10",style:{backgroundColor:ee.colour}}),e.jsx(rn,{className:"h-4 w-4 opacity-60"})]})]}),q&&e.jsx("div",{className:"absolute left-full top-0 ml-1 rounded-md border bg-popover p-2 text-popover-foreground shadow-lg",style:{width:152},children:e.jsx("div",{className:"flex flex-wrap",style:{gap:8},children:Le.map(ne=>{const Te=ne.toLowerCase()===ee.colour.toLowerCase();return e.jsx("button",{type:"button",onClick:()=>{Te||ue(ne),b()},className:"rounded-sm border border-black/10 outline-none shrink-0 transition-transform hover:scale-110 data-[current=true]:ring-2 data-[current=true]:ring-ring data-[current=true]:ring-offset-2 data-[current=true]:ring-offset-popover",style:{backgroundColor:ne,width:24,height:24},"data-current":Te,title:ne},ne)})})})]})]}),(Ge||d)&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-1 h-px bg-border"}),Ge&&e.jsxs("button",{type:"button",onClick:()=>{Ge(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Sa,{className:"h-4 w-4"}),"Expand all"]}),d&&e.jsxs("button",{type:"button",onClick:()=>{d(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Sr,{className:"h-4 w-4"}),"Collapse all"]})]}),O&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-1 h-px bg-border"}),e.jsxs("button",{type:"button",onClick:()=>{O(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive outline-none hover:bg-destructive hover:text-destructive-foreground focus:bg-destructive focus:text-destructive-foreground",children:[e.jsx(on,{className:"h-4 w-4"}),"Delete group"]})]})]}),u.kind==="vertex"&&e.jsxs(e.Fragment,{children:[J&&e.jsxs("button",{type:"button",onClick:()=>{J(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Ts,{className:"h-4 w-4"}),"Continue polyline"]}),he&&e.jsxs("button",{type:"button",onClick:()=>{he(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Er,{className:"h-4 w-4"}),"Insert vertex after"]}),W&&e.jsxs("button",{type:"button",onClick:()=>{W(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive outline-none hover:bg-destructive hover:text-destructive-foreground focus:bg-destructive focus:text-destructive-foreground",children:[e.jsx(an,{className:"h-4 w-4"}),"Delete vertex"]}),e.jsx("div",{className:"my-1 h-px bg-border"}),I&&e.jsxs("button",{type:"button",onClick:()=>{I(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",children:[e.jsx(Zn,{className:"h-4 w-4"}),"Move shape"]}),h&&e.jsxs("button",{type:"button",onClick:()=>{h(),b()},className:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive outline-none hover:bg-destructive hover:text-destructive-foreground focus:bg-destructive focus:text-destructive-foreground",children:[e.jsx(on,{className:"h-4 w-4"}),"Delete shape"]})]})]}),document.body)}const sl={activeTool:"select",isDrawing:!1,drawingPoints:[],cursorPosition:null,selectedMeasurementId:null,hoveredMeasurementId:null,isCalibrating:!1,calibrationPoints:[],activeGroupId:null,extendingMeasurementId:null,extendingFromEnd:null,extendingSeedLength:0,subtractTargetId:null,subtractStart:null,subtractDrawingPoints:[]};function al(a,p){switch(p.type){case"SET_TOOL":return{...a,activeTool:p.payload,isDrawing:!1,drawingPoints:[],cursorPosition:null,selectedMeasurementId:null,isCalibrating:p.payload==="calibrate",calibrationPoints:[],extendingMeasurementId:null,extendingFromEnd:null,extendingSeedLength:0,subtractTargetId:null,subtractStart:null,subtractDrawingPoints:[]};case"ADD_DRAWING_POINT":{const F=[...a.drawingPoints,p.payload];return{...a,isDrawing:!0,drawingPoints:F}}case"REMOVE_LAST_POINT":return a.extendingMeasurementId&&a.drawingPoints.length<=a.extendingSeedLength?a:a.drawingPoints.length<=1?{...a,isDrawing:!1,drawingPoints:[],cursorPosition:null}:{...a,drawingPoints:a.drawingPoints.slice(0,-1)};case"COMPLETE_MEASUREMENT":return{...a,isDrawing:!1,drawingPoints:[],cursorPosition:null,extendingMeasurementId:null,extendingFromEnd:null,extendingSeedLength:0};case"CANCEL_DRAWING":return{...a,isDrawing:!1,drawingPoints:[],cursorPosition:null,extendingMeasurementId:null,extendingFromEnd:null,extendingSeedLength:0};case"SET_CURSOR_POSITION":return{...a,cursorPosition:p.payload};case"SELECT_MEASUREMENT":return{...a,selectedMeasurementId:p.payload};case"HOVER_MEASUREMENT":return{...a,hoveredMeasurementId:p.payload};case"SET_CALIBRATION_POINT":{const F=[...a.calibrationPoints,p.payload];return{...a,calibrationPoints:F}}case"COMPLETE_CALIBRATION":return{...a,activeTool:"select",isCalibrating:!1,calibrationPoints:[]};case"CANCEL_CALIBRATION":return{...a,activeTool:"select",isCalibrating:!1,calibrationPoints:[]};case"SET_ACTIVE_GROUP":return{...a,activeGroupId:p.payload};case"START_EXTEND_POLYLINE":return{...a,activeTool:"linear",isDrawing:!0,drawingPoints:p.payload.points,cursorPosition:null,selectedMeasurementId:null,extendingMeasurementId:p.payload.measurementId,extendingFromEnd:p.payload.fromEnd,extendingSeedLength:p.payload.points.length};case"SUBTRACT_LOCK_TARGET":return{...a,subtractTargetId:p.payload.measurementId,subtractStart:p.payload.startPoint,
11subtractDrawingPoints:[]};case"SUBTRACT_HOLE_START":return{...a,subtractTargetId:p.payload.measurementId,subtractStart:null,subtractDrawingPoints:[p.payload.firstPoint]};case"SUBTRACT_HOLE_ADD_POINT":return a.subtractTargetId?{...a,subtractDrawingPoints:[...a.subtractDrawingPoints,p.payload]}:a;case"SUBTRACT_HOLE_REMOVE_LAST_POINT":return a.subtractDrawingPoints.length===0?a:a.subtractDrawingPoints.length===1?{...a,subtractTargetId:null,subtractStart:null,subtractDrawingPoints:[]}:{...a,subtractDrawingPoints:a.subtractDrawingPoints.slice(0,-1)};case"SUBTRACT_RESET":return{...a,subtractTargetId:null,subtractStart:null,subtractDrawingPoints:[]};default:return a}}function rl(){return l.useReducer(al,sl)}const ll=50;function ol(){const a=Ws(),p=l.useRef([]),F=l.useRef([]),u=l.useCallback(c=>{p.current.push(c),p.current.length>ll&&p.current.shift(),F.current=[]},[]),b=l.useCallback((c,v,T)=>{u({type:"measurement_created",measurementId:c,pageId:v,createParams:T})},[u]),h=l.useCallback((c,v)=>{const T={pageId:c.page_id,groupId:c.group_id,measurementType:c.measurement_type,label:c.label??void 0,geometry:c.geometry,pixelValue:c.pixel_value,realWorldValue:c.real_world_value,realWorldUnit:c.real_world_unit,semanticRole:c.semantic_role};u({type:"measurement_deleted",measurement:c,pageId:v,createParams:T})},[u]),S=l.useCallback(c=>{u({type:"measurement_geometry_changed",measurementId:c.measurementId,pageId:c.pageId,oldGeometry:c.oldGeometry,newGeometry:c.newGeometry,oldPixelValue:c.oldPixelValue??null,newPixelValue:c.newPixelValue??null,oldRealWorldValue:c.oldRealWorldValue??null,newRealWorldValue:c.newRealWorldValue??null})},[u]),I=l.useCallback(c=>{u({type:"measurement_label_changed",measurementId:c.measurementId,pageId:c.pageId,oldLabel:c.oldLabel,newLabel:c.newLabel})},[u]),E=l.useCallback(c=>{u({type:"measurement_adjustment_changed",measurementId:c.measurementId,pageId:c.pageId,oldAdjustments:c.oldAdjustments,newAdjustments:c.newAdjustments})},[u]),g=l.useCallback(c=>{u({type:"measurement_group_changed",measurementId:c.measurementId,pageId:c.pageId,oldGroupId:c.oldGroupId,newGroupId:c.newGroupId})},[u]),V=l.useCallback(async()=>{const c=p.current.pop();if(!c)return;const v=["takeoff-measurements",c.pageId];if(c.type==="measurement_created"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).filter(w=>w.id!==c.measurementId));try{await qn(c.measurementId);const _=T==null?void 0:T.find(w=>w.id===c.measurementId);_&&F.current.push({type:"measurement_deleted",measurement:_,pageId:c.pageId,createParams:c.createParams})}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_deleted"){const T=a.getQueryData(v);a.setQueryData(v,_=>[..._??[],c.measurement]);try{const _=await Hn(c.createParams);F.current.push({type:"measurement_created",measurementId:_.id,pageId:c.pageId,createParams:c.createParams})}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_geometry_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,geometry:c.oldGeometry,pixel_value:c.oldPixelValue,real_world_value:c.oldRealWorldValue}:w));try{await zn(c.measurementId,c.oldGeometry,{pixelValue:c.oldPixelValue,realWorldValue:c.oldRealWorldValue}),F.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_group_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,group_id:c.oldGroupId}:w));try{await Kn(c.measurementId,c.oldGroupId),F.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_label_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,label:c.oldLabel}:w));try{await Bn(c.measurementId,c.oldLabel),F.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}
11else if(c.type==="measurement_adjustment_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,adjustments:c.oldAdjustments}:w));try{await Xn(c.measurementId,c.oldAdjustments),F.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Undo failed:",_),Q.error("Undo failed")}finally{a.invalidateQueries({queryKey:v})}}},[a]),M=l.useCallback(async()=>{const c=F.current.pop();if(!c)return;const v=["takeoff-measurements",c.pageId];if(c.type==="measurement_created"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).filter(w=>w.id!==c.measurementId));try{await qn(c.measurementId),p.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Redo failed:",_),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_deleted"){const T=a.getQueryData(v),_={...c.measurement,id:`optimistic-redo-${Date.now()}`};a.setQueryData(v,w=>[...w??[],_]);try{const w=await Hn(c.createParams);p.current.push({type:"measurement_created",measurementId:w.id,pageId:c.pageId,createParams:c.createParams})}catch(w){T&&a.setQueryData(v,T),console.error("Redo failed:",w),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_geometry_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,geometry:c.newGeometry,pixel_value:c.newPixelValue,real_world_value:c.newRealWorldValue}:w));try{await zn(c.measurementId,c.newGeometry,{pixelValue:c.newPixelValue,realWorldValue:c.newRealWorldValue}),p.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Redo failed:",_),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_group_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,group_id:c.newGroupId}:w));try{await Kn(c.measurementId,c.newGroupId),p.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Redo failed:",_),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_label_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,label:c.newLabel}:w));try{await Bn(c.measurementId,c.newLabel),p.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Redo failed:",_),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}else if(c.type==="measurement_adjustment_changed"){const T=a.getQueryData(v);a.setQueryData(v,_=>(_??[]).map(w=>w.id===c.measurementId?{...w,adjustments:c.newAdjustments}:w));try{await Xn(c.measurementId,c.newAdjustments),p.current.push(c)}catch(_){T&&a.setQueryData(v,T),console.error("Redo failed:",_),Q.error("Redo failed")}finally{a.invalidateQueries({queryKey:v})}}},[a]),$=l.useCallback(()=>{p.current=[],F.current=[]},[]),je=p.current.length>0,ce=F.current.length>0;return{recordCreate:b,recordDelete:h,recordGeometryChange:S,recordGroupChange:g,recordLabelChange:I,recordAdjustmentChange:E,undo:V,redo:M,clearStacks:$,canUndo:je,canRedo:ce}}function jn(a){return Number.isInteger(a)?String(a):a.toFixed(2).replace(/\.?0+$/,"")}function il(a,p,F){const u=a.naturalMeasurementTool?"Tap to start measuring.":"Set this on the Strategy card in your estimate chat — it isn't traced off the plans.";if((p==null?void 0:p.source)==="user_edited")return{def:a,state:"confirmed",valueText:jn(p.value),tooltip:`${a.description}
12
13You set this value on the Strategy card — measuring won't override it.`};if(F&&F.confidence!=="conflict"&&F.confidence!=="unit_mismatch"){const b=F.measurementIds.length;return{def:a,state:"measured",valueText:jn(F.value),tooltip:`${a.description}
14
15Measured from ${b} tagged measurement${b!==1?"s":""}. ${u}`}}return F?{def:a,state:"check",valueText:jn(F.value),tooltip:a.description+`
16
17`+(F.confidence==="conflict"?"Tagged measurements disagree on this value — review them before relying on it.":"A tagged measurement's type doesn't match this dimension — review the tags.")+` ${u}`}:p&&(p.source==="assumed"||p.source==="assumed_from_plans")?{def:a,state:"assumed",valueText:jn(p.value),tooltip:`${a.description}
18
19Sammy assumed this value${p.rationale?` (${p.rationale})`:""} — measure it to be exact. ${u}`}:{def:a,state:"missing",valueText:null,tooltip:`${a.description}
20
21Not captured yet. ${u}`}}const cl={measured:e.jsx(Gn,{className:"h-3 w-3 text-sky-400 shrink-0"}),confirmed:e.jsx(Gn,{className:"h-3 w-3 text-white/50 shrink-0"}),check:e.jsx(Qs,{className:"h-3 w-3 text-amber-400 shrink-0"}),assumed:e.jsx(Ns,{className:"h-3 w-3 text-amber-400/70 shrink-0"}),missing:e.jsx(Ns,{className:"h-3 w-3 text-white/25 shrink-0"})},ul={measured:"text-sky-300",confirmed:"text-white/70",check:"text-amber-300",assumed:"text-amber-200/90",missing:"text-white/30"};function dl({menu:a,takeoff:p,slotMap:F,activeSlotId:u,onActivateSlot:b}){const[h,S]=l.useState(!0),I=l.useMemo(()=>Array.from(new Set([...a.required,...a.common])).map(V=>{const M=Bt(V);return M?il(M,p==null?void 0:p[V],F[V]):null}).filter(V=>V!==null),[a,p,F]);if(I.length===0)return null;const E=I.filter(g=>g.state==="measured"||g.state==="confirmed").length;return e.jsxs("div",{className:"border-b border-white/10 shrink-0",children:[e.jsxs("button",{type:"button",onClick:()=>S(g=>!g),className:"w-full flex items-center gap-1.5 px-3 py-2 text-left hover:bg-white/[0.03]",children:[h?e.jsx(Jn,{className:"h-3 w-3 text-white/40 shrink-0"}):e.jsx(rn,{className:"h-3 w-3 text-white/40 shrink-0"}),e.jsx("span",{className:"text-white/80 text-xs font-medium flex-1",children:"What to measure"}),e.jsxs("span",{className:"text-white/40 text-[10px] tabular-nums",children:[E,"/",I.length]})]}),h&&e.jsxs("div",{className:"px-2 pb-2",children:[e.jsx("p",{className:"text-[10px] text-white/35 px-1 pb-1.5 leading-snug",children:"Tap a dimension, then draw — it feeds your Strategy."}),I.map(g=>{const V=!!g.def.naturalMeasurementTool,M=u===g.def.id,$=Ss("w-full flex items-center gap-1.5 px-1.5 py-1 rounded text-left border-l-2",M?"border-l-blue-500 bg-white/5":"border-l-transparent",V?"cursor-pointer hover:bg-white/[0.05]":"cursor-default"),je=e.jsxs(e.Fragment,{children:[cl[g.state],e.jsx("span",{className:"text-[11px] text-white/75 truncate flex-1",children:g.def.label}),e.jsxs("span",{className:Ss("text-[10px] tabular-nums shrink-0",ul[g.state]),children:[g.valueText??"—",g.valueText&&e.jsxs("span",{className:"text-white/35",children:[" ",g.def.unit]})]})]});return V?e.jsx("button",{type:"button",onClick:()=>b(g.def.id),title:g.tooltip,className:$,children:je},g.def.id):e.jsx("div",{title:g.tooltip,className:$,children:je},g.def.id)})]})]})}const Vs=[10,20,25,50,75,100,150,200,250,500,1e3];function ml(a,p){if(a<=0||p<=0)return"";const F=p/a;let u=Vs[0],b=Math.abs(F-u);for(const I of Vs){const E=Math.abs(F-I);E<b&&(b=E,u=I)}const h=u*.1;return`${b>h?"~":""}1:${u}`}function Il(){var rs,ls,os,is,cs,us,ds,ms,fs,hs,ps,xs,gs,ys,bs,vs,ws,ks,_s,js;const{sessionId:a}=Na(),p=Ca(),F=Ma(),u=Ws();console.log("[TakeoffPage] Mounted/rendered, sessionId:",a);const b=(rs=F.state)==null?void 0:rs.returnTo,h=(ls=F.state)==null?void 0:ls.returnState,S=(os=F.state)==null?void 0:os.initialMediaId,I=l.useRef(null),E=l.useRef(null),[g,V]=Ea(),M=parseInt(g.get("page")??"1",10),$=Number.isFinite(M)&&M>=1?M:1,je=g.get("source"),ce=g.get("slot"),c=ce&&br(ce)?Bt(ce):null;l.useEffect(()=>{ce&&!c&&console.warn(`[TakeoffPage] unknown ?slot= id "${ce}" — ignoring`)},[ce,c]);const v=l.useCallback(t=>{V(n=>{const s=new URLSearchParams(n);return t<=1?s.delete("page"):s.set("page",String(t)),s},{replace:!0})},[V]),T=l.useCallback(t=>{V(n=>{const s=new URLSearchParams(n);return t?s.set("source",t):s.delete("source"),s.delete("page"),s},{replace:!0})},[V]),[_,w]=l.useState(null),[L,fe]=l.useState(0),[Z,re]=l.useState(!1),[W,he]=l.useState(!1),[J,le]=l.useState(!1),[Se,Ue]=l.useState(1),[Qe,He]=l.useState(1),[we,ee]=l.useState(!1),[Ae,P]=l.useState(!1),[Oe,ue]=l.useState(null),[Le,Ge]=l.useState(!1),[d,O]=l.useState({open:!1,x:0,y:0,target:null}),[z,U]=l.useState(null),[pe,q]=l.useState(""),[Fe,ge]=l.useState(null),[ze,at]=l.useState(""),[Re,ne]=l.useState(null),[Te,de]=l.useState(""),[xt,Nt]=l.useState("m"),[te,gt]=l.useState(null),[Dt,Xt]=l.useState(""),[Mn,ut]=l.useState(()=>{try{return localStorage.getItem("takeoff:panTipDismissed")==="1"}catch{return!1}}),tt=l.useCallback(()=>{ut(!0);try{localStorage.setItem("takeoff:panTipDismissed","1")}catch{}},[]),[x,D]=rl(),{recordCreate:ot,recordDelete:En,recordGeometryChange:vt,recordGroupChange:Fn,recordLabelChange:Tn,recordAdjustmentChange:Dn,undo:Yt,redo:Qt,clearStacks:Xe}=ol(),{data:R,isLoading:cn,error:wt}=qt({queryKey:["takeoff-session",a],queryFn:()=>dr(a),enabled:!!a});console.log("[TakeoffPage] Session query:",{isLoading:cn,error:wt==null?void 0:wt.message,hasSession:!!R,pageCount:(is=R==null?void 0:R.takeoff_pages)==null?void 0:is.length});const It=(R==null?void 0:R.estimate_id)??null,{data:Wt}=qt({queryKey:["takeoff-estimate-media-ids",It],queryFn:async()=>{const{data:t,error:n}=await Cs.from("estimate_media").select("id").eq("estimate_id",It);if(n)throw n;return new Set((t||[]).map(s=>s.id))},enabled:!!It}),m=((cs=R==null?void 0:R.takeoff_pages)==null?void 0:cs[0])??null,dt=je??(m==null?void 0:m.source_media_id)??null,mt=(()=>
21{if(!(R!=null&&R.takeoff_pages))return[];const t=new Map;for(const n of R.takeoff_pages)!n.source_media_id||t.has(n.source_media_id)||Wt&&!Wt.has(n.source_media_id)||t.set(n.source_media_id,{id:n.source_media_id,label:n.page_label||`Plan ${t.size+1}`,sortOrder:n.sort_order??0});return Array.from(t.values()).sort((n,s)=>n.sortOrder-s.sortOrder)})(),kt=l.useRef(!1),Zt=!!S&&!kt.current&&je!==S,nt=Zt?null:(dt?(us=R==null?void 0:R.takeoff_pages)==null?void 0:us.find(t=>t.source_media_id===dt&&t.page_number===$):(ds=R==null?void 0:R.takeoff_pages)==null?void 0:ds.find(t=>t.page_number===$))??null,un=Zt?null:dt?((ms=R==null?void 0:R.takeoff_pages)==null?void 0:ms.filter(t=>t.source_media_id===dt).sort((t,n)=>t.page_number-n.page_number)[0])??null:m,B=nt??un,j=(nt==null?void 0:nt.id)??null;l.useEffect(()=>{kt.current||!S||!(R!=null&&R.takeoff_pages)||!R.takeoff_pages.find(n=>n.source_media_id===S)||(je!==S&&T(S),kt.current=!0)},[S,R==null?void 0:R.takeoff_pages,je,T]),console.log("[TakeoffPage] Page state:",{currentPageNumber:$,currentPageId:j,firstPageId:m==null?void 0:m.id,activeSourceMediaId:dt,fileUrl:_==null?void 0:_.substring(0,60)});const{data:A}=qt({queryKey:["takeoff-calibration",j],queryFn:()=>mr(j),enabled:!!j}),r=!!A,{data:o=[]}=qt({queryKey:["takeoff-measurements",j],queryFn:()=>fr(j),enabled:!!j}),{data:C=[]}=qt({queryKey:["takeoff-measurements-session",a],queryFn:()=>hr(a),enabled:!!a}),{data:y=[],isSuccess:Y}=qt({queryKey:["takeoff-groups",a],queryFn:()=>pr(a),enabled:!!a}),{data:ae}=_r(It),X=pt({mutationFn:Hn,onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i={id:`optimistic-${Date.now()}`,page_id:t.pageId,group_id:t.groupId||null,measurement_type:t.measurementType,label:t.label||null,geometry:t.geometry,pixel_value:t.pixelValue,real_world_value:t.realWorldValue,real_world_unit:t.realWorldUnit,subtractions:t.subtractions??null,adjustments:t.adjustments??null,semantic_role:t.semanticRole??null,sort_order:(s==null?void 0:s.length)??0,created_at:new Date().toISOString(),updated_at:new Date().toISOString()};return u.setQueryData(n,f=>[...f??[],i]),{previous:s}},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to save measurement:",t),Q.error("Failed to save measurement")},onSuccess:(t,n)=>{j&&ot(t.id,j,n)},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),se=pt({mutationFn:qn,onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(f=>f.id===t);return u.setQueryData(n,f=>(f??[]).filter(k=>k.id!==t)),D({type:"SELECT_MEASUREMENT",payload:null}),{previous:s,deletedMeasurement:i}},onSuccess:(t,n,s)=>{s!=null&&s.deletedMeasurement&&j&&En(s.deletedMeasurement,j)},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to delete measurement:",t),Q.error("Failed to delete measurement")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),H=pt({mutationFn:t=>lr(t),onMutate:async t=>{const n=["takeoff-groups",a];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i={id:`optimistic-group-${Date.now()}`,session_id:t.sessionId,name:t.name,measurement_type:null,colour:"#3B82F6",fill_opacity:.3,unit:null,semantic_role:t.semanticRole??null,unit_rate:null,unit_rate_type:null,waste_factor_percent:null,sort_order:(s==null?void 0:s.length)??0,is_visible:!0,created_at:new Date().toISOString(),updated_at:new Date().toISOString()};return u.setQueryData(n,f=>[...f??[],i]),{previous:s}},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-groups",a],s.previous),console.error("Failed to create group:",t),Q.error("Failed to create group")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-groups",a]})}}),Ee=pt({mutationFn:or,onMutate:async t=>{const n=["takeoff-groups",a];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n);return u.setQueryData(n,i=>(i??[]).filter(f=>f.id!==t)),x.activeGroupId===t&&D({type:"SET_ACTIVE_GROUP",payload:null}),{previous:s}},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-groups",a],s.previous),console.error("Failed to delete group:",t),Q.error("Failed to delete group")},onSettled:()=>
21{u.invalidateQueries({queryKey:["takeoff-groups",a]}),u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),De=pt({mutationFn:t=>ir(t.groupId,t.updates),onMutate:async({groupId:t,updates:n})=>{const s=["takeoff-groups",a];await u.cancelQueries({queryKey:s});const i=u.getQueryData(s);return u.setQueryData(s,f=>(f??[]).map(k=>k.id===t?{...k,is_visible:n.isVisible??k.is_visible,name:n.name??k.name,colour:n.colour??k.colour}:k)),{previous:i}},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-groups",a],s.previous),Q.error("Failed to update group")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-groups",a]})}}),N=l.useMemo(()=>{const t=new Map;for(const n of y)t.set(n.id,n.colour);return t},[y]),it=l.useMemo(()=>{const t=new Map;for(const n of y)t.set(n.id,n.fill_opacity);return t},[y]),Rt=l.useMemo(()=>{const t=new Set;for(const n of y)n.is_visible||t.add(n.id);return t},[y]),Ke=l.useMemo(()=>y.find(t=>t.id===x.activeGroupId)??null,[y,x.activeGroupId]),dn=Ke==null?void 0:Ke.colour,mn=l.useMemo(()=>{const t=C.filter(n=>{const s=n.review_status;return s==null||s==="accepted"}).map(n=>({id:n.id,label:n.label,semantic_role:n.semantic_role,measurement_type:n.measurement_type,real_world_value:n.real_world_value,adjustments:n.adjustments}));return gr(t)},[C]),fn=(Ke==null?void 0:Ke.semantic_role)??null;l.useEffect(()=>{y.length>0&&!x.activeGroupId&&(y.some(n=>n.id===x.activeGroupId)||D({type:"SET_ACTIVE_GROUP",payload:y[0].id}))},[y,x.activeGroupId,D]);const hn=l.useCallback(t=>{D({type:"SET_ACTIVE_GROUP",payload:t})},[D]),Me=l.useCallback(t=>{a&&H.mutate({sessionId:a,name:t},{onSuccess:n=>{D({type:"SET_ACTIVE_GROUP",payload:n.id})}})},[a,H,D]),We=l.useCallback(t=>{Ee.mutate(t)},[Ee]),Ne=l.useCallback(t=>{const n=Bt(t);if(!n||!a)return;n.naturalMeasurementTool&&D({type:"SET_TOOL",payload:n.naturalMeasurementTool});const s=y.find(i=>i.semantic_role===n.id);s?D({type:"SET_ACTIVE_GROUP",payload:s.id}):H.mutate({sessionId:a,name:n.label,semanticRole:n.id},{onSuccess:i=>{D({type:"SET_ACTIVE_GROUP",payload:i.id})}})},[a,y,D,H]),Ve=l.useRef(!1);l.useEffect(()=>{Ve.current||!c||!a||!R||!Y||(Ve.current=!0,Ne(c.id))},[c,a,R,Y,Ne]);const ye=pt({mutationFn:t=>cr(t.measurementId,t.semanticRole),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n);return u.setQueryData(n,i=>(i??[]).map(f=>f.id===t.measurementId?{...f,semantic_role:t.semanticRole}:f)),{previous:s}},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to tag measurement:",t),Q.error("Failed to tag measurement")},onSuccess:(t,n)=>{if(n.semanticRole){const s=Bt(n.semanticRole);s&&Q.success(`Tagged — this measurement now feeds "${s.label}" in your Strategy.`)}},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),Ie=l.useCallback((t,n)=>{ye.mutate({measurementId:t,semanticRole:n})},[ye]),xe=l.useMemo(()=>{var s;const t=(s=ae==null?void 0:ae.strategy)==null?void 0:s.takeoffMenu;return(t?Array.from(new Set([...t.required,...t.common])):yr).map(i=>Bt(i)).filter(i=>!!i).map(i=>({id:i.id,label:i.label,unit:i.unit}))},[ae]),$e=l.useMemo(()=>{var n;if(((n=d.target)==null?void 0:n.kind)!=="measurement")return null;const t=o.find(s=>{var i;return s.id===((i=d.target)==null?void 0:i.measurementId)});return(t==null?void 0:t.semantic_role)??null},[d.target,o]),_t=l.useCallback((t,n)=>{De.mutate({groupId:t,updates:{isVisible:n}})},[De]),Ye=l.useCallback(t=>{D({type:"SET_TOOL",payload:"select"}),D({type:"SELECT_MEASUREMENT",payload:t})},[D]),ke=l.useCallback(t=>{se.mutate(t)},[se]),G=l.useCallback(t=>{if(!j)return;const n=o.find(f=>f.id===t);if(!n)return;const s=20/Math.max(Se*Qe,1e-4);let i;if(n.geometry.type==="polygon")i={type:"polygon",points:n.geometry.points.map(f=>({x:f.x+s,y:f.y+s}))};else if(n.geometry.type==="rectangle")i={type:"rectangle",origin:{x:n.geometry.origin.x+s,y:n.geometry.origin.y+s},width:n.geometry.width,height:n.geometry.height};else if(n.geometry.type==="linear")i={type:"linear",segments:n.geometry.segments.map(f=>f.map(k=>({x:k.x+s,y:k.y+s})))};else if(n.geometry.type==="point")i={type:"point",position:{x:n.geometry.position.x+s,y:n.geometry.position.y+s}};else return;X.mutate({pageId:j,groupId:n.group_id||void 0,measurementType:n.measurement_type,label:n.label||void 0,geometry:i,pixelValue:n.pixel_value,realWorldValue:n.real_world_value,realWorldUnit:n.real_world_unit,semanticRole:n.semantic_role||void 0}),Q.success("Duplicated")},[j,o,Se,Qe,X]),oe=pt({mutationFn:t=>zn(t.id,t.newGeometry,{pixelValue:t.newPixelValue,realWorldValue:t.
21newRealWorldValue}),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(f=>f.id===t.id);return u.setQueryData(n,f=>(f??[]).map(k=>k.id===t.id?{...k,geometry:t.newGeometry,pixel_value:t.newPixelValue!==void 0?t.newPixelValue:k.pixel_value,real_world_value:t.newRealWorldValue!==void 0?t.newRealWorldValue:k.real_world_value}:k)),{previous:s,before:i}},onSuccess:(t,n,s)=>{s!=null&&s.before&&j&&vt({measurementId:n.id,pageId:j,oldGeometry:s.before.geometry,newGeometry:n.newGeometry,oldPixelValue:s.before.pixel_value,newPixelValue:n.newPixelValue!==void 0?n.newPixelValue:s.before.pixel_value,oldRealWorldValue:s.before.real_world_value,newRealWorldValue:n.newRealWorldValue!==void 0?n.newRealWorldValue:s.before.real_world_value})},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to move measurement:",t),Q.error("Failed to move measurement")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),Ce=pt({mutationFn:t=>Kn(t.measurementId,t.newGroupId),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(f=>f.id===t.measurementId);return u.setQueryData(n,f=>(f??[]).map(k=>k.id===t.measurementId?{...k,group_id:t.newGroupId}:k)),{previous:s,before:i}},onSuccess:(t,n,s)=>{s!=null&&s.before&&j&&Fn({measurementId:n.measurementId,pageId:j,oldGroupId:s.before.group_id,newGroupId:n.newGroupId})},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to reassign group:",t),Q.error("Failed to move measurement")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),be=l.useCallback((t,n)=>{Ce.mutate({measurementId:t,newGroupId:n})},[Ce]),Pe=pt({mutationFn:t=>Bn(t.measurementId,t.label),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(k=>k.id===t.measurementId),f=t.label&&t.label.trim()?t.label.trim():null;return u.setQueryData(n,k=>(k??[]).map(K=>K.id===t.measurementId?{...K,label:f}:K)),{previous:s,before:i,cleaned:f}},onSuccess:(t,n,s)=>{s!=null&&s.before&&j&&Tn({measurementId:n.measurementId,pageId:j,oldLabel:s.before.label,newLabel:s.cleaned??null})},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to rename:",t),Q.error("Failed to rename measurement")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),ct=l.useCallback(t=>{const n=o.find(s=>s.id===t);n&&(U({id:t,current:n.label??""}),q(n.label??""))},[o]),jt=l.useCallback(()=>{if(!z)return;const t=pe.trim();if(t===(z.current??"")){U(null);return}Pe.mutate({measurementId:z.id,label:t.length===0?null:t}),U(null)},[z,pe,Pe]),qe=pt({mutationFn:t=>Xn(t.id,t.adjustments),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(f=>f.id===t.id);return u.setQueryData(n,f=>(f??[]).map(k=>k.id===t.id?{...k,adjustments:t.adjustments}:k)),{previous:s,before:i}},onSuccess:(t,n,s)=>{s!=null&&s.before&&j&&Dn({measurementId:n.id,pageId:j,oldAdjustments:s.before.adjustments,newAdjustments:n.adjustments})},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to update adjustment:",t),Q.error("Failed to update adjustment")},onSettled:()=>{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),At=l.useCallback(t=>{var i;const n=o.find(f=>f.id===t);if(!n||n.measurement_type!=="linear"&&n.measurement_type!=="area"&&n.measurement_type!=="rectangle")return;const s=((i=n.adjustments)==null?void 0:i.height)??null;ne({id:t,measurementType:n.measurement_type}),de(s?String(s.value):""),Nt(s?s.unit:"m")},[o]),pn=l.useCallback(()=>
21{if(!Re)return;const t=o.find(f=>f.id===Re.id);if(!t){ne(null);return}const n=Te.trim();if(n===""){const f={...t.adjustments??{}};delete f.height;const k=Object.keys(f).length>0?f:null;qe.mutate({id:Re.id,adjustments:k}),ne(null);return}const s=parseFloat(n);if(!Number.isFinite(s)||s<=0){Q.error("Enter a positive number");return}const i={...t.adjustments??{},height:{value:s,unit:xt}};qe.mutate({id:Re.id,adjustments:i}),ne(null)},[Re,Te,xt,o,qe]),Ys=l.useCallback(t=>{var f;const n=o.find(k=>k.id===t);if(!n||!((f=n.adjustments)!=null&&f.height))return;const s={...n.adjustments};delete s.height;const i=Object.keys(s).length>0?s:null;qe.mutate({id:t,adjustments:i})},[o,qe]),Zs=l.useCallback(t=>{var i;const n=o.find(f=>f.id===t);if(!n||n.measurement_type!=="linear"&&n.measurement_type!=="area"&&n.measurement_type!=="rectangle")return;const s=((i=n.adjustments)==null?void 0:i.pitch)??null;gt({id:t,measurementType:n.measurement_type}),Xt(s?String(s.value):"")},[o]),es=l.useCallback(()=>{if(!te)return;const t=o.find(f=>f.id===te.id);if(!t){gt(null);return}const n=Dt.trim();if(n===""){const f={...t.adjustments??{}};delete f.pitch;const k=Object.keys(f).length>0?f:null;qe.mutate({id:te.id,adjustments:k}),gt(null);return}const s=parseFloat(n);if(!Number.isFinite(s)||s<=0||s>=90){Q.error("Enter a pitch between 0 and 90 degrees");return}const i={...t.adjustments??{},pitch:{value:s,unit:"deg"}};qe.mutate({id:te.id,adjustments:i}),gt(null)},[te,Dt,o,qe]),Js=l.useCallback(t=>{var f;const n=o.find(k=>k.id===t);if(!n||!((f=n.adjustments)!=null&&f.pitch))return;const s={...n.adjustments};delete s.pitch;const i=Object.keys(s).length>0?s:null;qe.mutate({id:t,adjustments:i})},[o,qe]),ea=l.useCallback(t=>{const n=y.find(s=>s.id===t);n&&(ge({id:t,current:n.name}),at(n.name))},[y]),ts=l.useCallback(()=>{if(!Fe)return;const t=ze.trim();if(t.length===0||t===Fe.current){ge(null);return}De.mutate({groupId:Fe.id,updates:{name:t}}),ge(null)},[Fe,ze,De]),ta=l.useCallback((t,n)=>{De.mutate({groupId:t,updates:{colour:n}})},[De]),na=l.useCallback((t,n)=>{let s,i;if(n.type==="polygon")s=Ut(n.points),i=A?bt(s,A.pixels_per_unit,A.real_world_unit):null;else if(n.type==="rectangle")s=n.width*n.height,i=A?bt(s,A.pixels_per_unit,A.real_world_unit):null;else if(n.type==="linear"){let f=0;for(const k of n.segments)f+=zt(k);s=f,i=A?Et(s,A.pixels_per_unit,A.real_world_unit):null}oe.mutate({id:t,newGeometry:n,newPixelValue:s,newRealWorldValue:i})},[oe,A]),sa=l.useCallback((t,n)=>{const s=o.find(i=>i.id===t);if(s){if(s.geometry.type==="polygon"){if(s.geometry.points.length<=3){Q.error("A polygon needs at least 3 points");return}const i=s.geometry.points.filter((K,me)=>me!==n),f=Ut(i),k=A?bt(f,A.pixels_per_unit,A.real_world_unit):null;oe.mutate({id:t,newGeometry:{type:"polygon",points:i},newPixelValue:f,newRealWorldValue:k})}else if(s.geometry.type==="linear"){if(s.geometry.segments.length!==1)return;const i=s.geometry.segments[0];if(i.length<=2){Q.error("A line needs at least 2 points");return}const f=i.filter((me,_e)=>_e!==n),k=zt(f),K=A?Et(k,A.pixels_per_unit,A.real_world_unit):null;oe.mutate({id:t,newGeometry:{type:"linear",segments:[f]},newPixelValue:k,newRealWorldValue:K})}}},[o,A,oe]),aa=l.useCallback((t,n)=>{const s=o.find(i=>i.id===t);if(s){if(s.geometry.type==="polygon"){const i=s.geometry.points,f=(n+1)%i.length,k=i[n],K=i[f],me={x:(k.x+K.x)/2,y:(k.y+K.y)/2},_e=[...i.slice(0,n+1),me,...i.slice(n+1)],et=Ut(_e),ve=A?bt(et,A.pixels_per_unit,A.real_world_unit):null;oe.mutate({id:t,newGeometry:{type:"polygon",points:_e},newPixelValue:et,newRealWorldValue:ve})}else if(s.geometry.type==="linear"){if(s.geometry.segments.length!==1)return;const i=s.geometry.segments[0];if(n>=i.length-1){Q.error("Can't insert after the last vertex of a line");return}const f=i[n],k=i[n+1],K={x:(f.x+k.x)/2,y:(f.y+k.y)/2},me=[...i.slice(0,n+1),K,...i.slice(n+1)],_e=zt(me),et=A?Et(_e,A.pixels_per_unit,A.real_world_unit):null;oe.mutate({id:t,newGeometry:{type:"linear",segments:[me]},newPixelValue:_e,newRealWorldValue:et})}}},[o,A,oe]),ra=l.useMemo(()=>x.extendingMeasurementId?o.filter(t=>t.id!==x.extendingMeasurementId):o,[o,x.extendingMeasurementId]),la=l.useCallback((t,n)=>{const s=o.find(k=>k.id===t);if(!s||s.geometry.type!=="linear"||s.geometry.segments.length!==1)return;const i=s.geometry.segments[0],f=n==="first"?[...i].reverse():[...i];D({type:"START_EXTEND_POLYLINE",payload:{measurementId:t,fromEnd:n,points:f}})},[o,D]),xn=pt({mutationFn:t=>ur(t.id,{geometry:t.geometry,subtractions:t.subtractions,pixelValue:t.pixelValue,realWorldValue:t.realWorldValue}),onMutate:async t=>{const n=["takeoff-measurements",j];await u.cancelQueries({queryKey:n});const s=u.getQueryData(n),i=s==null?void 0:s.find(f=>f.id===t.id);return u.setQueryData(n,f=>(f??[]).map(k=>k.id===t.id?{...k,geometry:t.geometry,subtractions:t.subtractions,pixel_value:t.pixelValue,real_world_value:t.realWorldValue}:k)),{previous:s,before:i}},onSuccess:(t,n,s)=>{s!=null&&s.before&&j&&vt({measurementId:n.id,pageId:j,oldGeometry:s.before.geometry,newGeometry:n.geometry,oldPixelValue:s.before.pixel_value,newPixelValue:n.pixelValue,oldRealWorldValue:s.before.real_world_value,newRealWorldValue:n.realWorldValue})},onError:(t,n,s)=>{s!=null&&s.previous&&u.setQueryData(["takeoff-measurements",j],s.previous),console.error("Failed to apply subtraction:",t),Q.error("Failed to apply subtraction")},onSettled:()=>
21{u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]})}}),oa=l.useCallback((t,n,s,i)=>{const f=o.find(Mt=>Mt.id===t);if(!f||f.geometry.type!=="linear")return;const k=za(f.geometry,n,s,i);if(!k){Q.error("Splice too small — try again");return}let K=0;for(const Mt of k.geometry.segments)K+=zt(Mt);const me=A?Et(K,A.pixels_per_unit,A.real_world_unit):null,_e=Math.abs(i-s),et=A?Et(_e,A.pixels_per_unit,A.real_world_unit):_e,ve={id:typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`sub-${Date.now()}-${Math.random().toString(16).slice(2)}`,label:null,vertices:[k.splicedVertices[0],k.splicedVertices[1]],value:et,unit:A?"lm":"px",created_at:new Date().toISOString()},Ct=[...f.subtractions??[],ve];xn.mutate({id:t,geometry:k.geometry,subtractions:Ct,pixelValue:K,realWorldValue:me})},[o,A,xn]),In=l.useCallback((t,n)=>{const s=o.find(Ct=>Ct.id===t);if(!s||s.geometry.type!=="polygon")return;const i=Ka(s.geometry,n);if(!i.ok){Q.error(i.error);return}const f=Ba(s.geometry,i.ring),k=Xa(f.points,f.holes),K=A?bt(k,A.pixels_per_unit,A.real_world_unit):null,me=Ya(i.ring),_e=A?bt(me,A.pixels_per_unit,A.real_world_unit):me,et={id:typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`sub-${Date.now()}-${Math.random().toString(16).slice(2)}`,label:null,vertices:i.ring,value:_e,unit:A?"sqm":"px",created_at:new Date().toISOString()},ve=[...s.subtractions??[],et];xn.mutate({id:t,geometry:f,subtractions:ve,pixelValue:k,realWorldValue:K})},[o,A,xn]),ia=l.useCallback((t,n,s)=>{O({open:!0,x:n,y:s,target:t})},[]),ca=l.useCallback((t,n,s)=>{O({open:!0,x:n,y:s,target:{kind:"group",groupId:t}})},[]),ua=l.useCallback((t,n,s)=>{O({open:!0,x:n,y:s,target:{kind:"measurement",measurementId:t}})},[]),da=l.useCallback(()=>{O(t=>({...t,open:!1}))},[]),Ze=l.useMemo(()=>{var i;if(((i=d.target)==null?void 0:i.kind)!=="vertex")return null;const t=d.target.measurementId,n=d.target.vertexIndex;if(!t||n==null)return null;const s=o.find(f=>f.id===t);if(!s)return null;if(s.geometry.type==="polygon")return{measurementId:t,vertexIndex:n,canDelete:s.geometry.points.length>3,canInsertAfter:!0,extendEnd:null};if(s.geometry.type==="linear"){if(s.geometry.segments.length!==1)return null;const f=s.geometry.segments[0],k=f.length-1,K=n===0?"first":n===k?"last":null;return{measurementId:t,vertexIndex:n,canDelete:f.length>2,canInsertAfter:n<k,extendEnd:K}}return null},[d.target,o]),gn=l.useMemo(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement"||!d.target.measurementId)return{options:[],currentGroupId:null,measurementId:null};const t=o.find(i=>{var f;return i.id===((f=d.target)==null?void 0:f.measurementId)});return t?{options:y.map(i=>({id:i.id,name:i.name,colour:i.colour})),currentGroupId:t.group_id,measurementId:t.id}:{options:[],currentGroupId:null,measurementId:null}},[d.target,o,y]),Jt=l.useMemo(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return null;const t=o.find(i=>{var f;return i.id===((f=d.target)==null?void 0:f.measurementId)});if(!(t!=null&&t.group_id))return null;const n=y.find(i=>i.id===t.group_id);return n?{id:n.id,name:n.name}:null},[d.target,o,y]),ns=l.useMemo(()=>y.some(t=>!t.is_visible),[y]),Je=l.useMemo(()=>{var n;if(((n=d.target)==null?void 0:n.kind)!=="group"||!d.target.groupId)return null;const t=y.find(s=>{var i;return s.id===((i=d.target)==null?void 0:i.groupId)});return t?{id:t.id,name:t.name,colour:t.colour,isVisible:t.is_visible}:null},[d.target,y]),ma=l.useCallback(t=>{De.mutate({groupId:t,updates:{isVisible:!1}})},[De]),ss=l.useCallback(t=>{for(const n of y){const s=n.id===t;n.is_visible!==s&&De.mutate({groupId:n.id,updates:{isVisible:s}})}},[y,De]),fa=l.useCallback(()=>{for(const t of y)t.is_visible||De.mutate({groupId:t.id,updates:{isVisible:!0}})},[y,De]),ha=l.useMemo(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return null;const t=d.target.measurementId;if(!t)return null;const n=o.find(i=>i.id===t);return!n||n.measurement_type==="count"||n.real_world_value==null?null:n.measurement_type==="linear"?Tt(n.real_world_value):Ft(n.real_world_value)},[d.target,o]);l.useEffect(()=>{if(!B||L<=1||!R)return;const t=new Set(R.takeoff_pages.filter(i=>i.source_media_id===B.source_media_id).map(i=>i.page_number)),n=[];for(let i=1;i<=L;i++)t.has(i)||n.push(i);if(n.length===0)return;let s=!1;return Promise.all(n.map(i=>Za({sessionId:B.session_id,pageNumber:i,pageLabel:`Page ${i}`,sourceType:B.source_type,sourceStorageBucket:B.source_storage_bucket,sourceStoragePath:B.source_storage_path,sourceMimeType:B.source_mime_type,sourceMediaId:B.source_media_id??void 0}))).then(()=>
21{s||u.invalidateQueries({queryKey:["takeoff-session",a]})}).catch(i=>{console.error("Failed to create page records:",i)}),()=>{s=!0}},[B,L,R,a,u]);const yn=(B==null?void 0:B.source_storage_bucket)??null,bn=(B==null?void 0:B.source_storage_path)??null;l.useEffect(()=>{if(!yn||!bn){console.log("[TakeoffPage] No source bucket/path, clearing fileUrl"),w(null);return}console.log("[TakeoffPage] Fetching signed URL for:",yn,bn);let t=!1;return Ja(yn,bn).then(n=>{t||(console.log("[TakeoffPage] Signed URL resolved:",n==null?void 0:n.substring(0,80)),w(n))}).catch(n=>{console.error("[TakeoffPage] Failed to get signed URL:",n),t||w(null)}),()=>{t=!0}},[yn,bn]),l.useEffect(()=>{x.calibrationPoints.length===2&&!Z&&re(!0)},[x.calibrationPoints,Z]);const vn=l.useCallback((t,n)=>{if(!j){Q.error("This page is still syncing — try that again in a moment.");return}const s=x.activeGroupId||void 0,i=(Ke==null?void 0:Ke.semantic_role)??void 0;if(n==="area"&&t.length>=3){const f={type:"polygon",points:t.map(_e=>({x:_e.x,y:_e.y}))},k=Ut(t);let K=null,me=null;A&&(K=bt(k,A.pixels_per_unit,A.real_world_unit),me="sqm"),X.mutate({pageId:j,groupId:s,measurementType:"area",geometry:f,pixelValue:k,realWorldValue:K,realWorldUnit:me,semanticRole:i})}else if(n==="rectangle"&&t.length===2){const f=t[0],k=t[1],K={x:Math.min(f.x,k.x),y:Math.min(f.y,k.y)},me=Math.abs(k.x-f.x),_e=Math.abs(k.y-f.y),et={type:"rectangle",origin:K,width:me,height:_e},ve=me*_e;let Ct=null,Mt=null;A&&(Ct=bt(ve,A.pixels_per_unit,A.real_world_unit),Mt="sqm"),X.mutate({pageId:j,groupId:s,measurementType:"rectangle",geometry:et,pixelValue:ve,realWorldValue:Ct,realWorldUnit:Mt,semanticRole:i})}else if(n==="linear"&&t.length>=2){const f=x.extendingMeasurementId&&x.extendingFromEnd==="first"?[...t].reverse():t,k=er(f.map(_e=>({x:_e.x,y:_e.y}))),K=zt(f),me=A?Et(K,A.pixels_per_unit,A.real_world_unit):null;x.extendingMeasurementId?t.length>x.extendingSeedLength&&oe.mutate({id:x.extendingMeasurementId,newGeometry:k,newPixelValue:K,newRealWorldValue:me}):X.mutate({pageId:j,groupId:s,measurementType:"linear",geometry:k,pixelValue:K,realWorldValue:me,realWorldUnit:"lm",semanticRole:i})}else if(n==="count"&&t.length===1){const f={type:"point",position:{x:t[0].x,y:t[0].y}};X.mutate({pageId:j,groupId:s,measurementType:"count",geometry:f,pixelValue:null,realWorldValue:null,realWorldUnit:null,semanticRole:i})}},[j,A,X,oe,x.activeGroupId,Ke,x.extendingMeasurementId,x.extendingFromEnd,x.extendingSeedLength]),pa=l.useCallback(async(t,n)=>{if(x.calibrationPoints.length<2)return;if(!j){Q.error("This page is still syncing — try that again in a moment.");return}const s=x.calibrationPoints[0],i=x.calibrationPoints[1],f=Math.sqrt((i.x-s.x)**2+(i.y-s.y)**2),k=n==="m"?t*1e3:t,K=f/k,_e=(B==null?void 0:B.source_mime_type)==="application/pdf"?f*25.4/72:f,et=ml(_e,k);try{await tr({pageId:j,point1:s,point2:i,realWorldDistance:t,realWorldUnit:n,pixelsPerUnit:K,scaleRatioLabel:et}),A&&(await nr(j,K,n),u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]}
21)),u.invalidateQueries({queryKey:["takeoff-calibration",j]}),u.invalidateQueries({queryKey:["takeoff-session",a]}),re(!1),D({type:"COMPLETE_CALIBRATION"}),Q.success("Scale set. Measure a known dimension to verify.")}catch(ve){console.error("Failed to save calibration:",ve),Q.error("Failed to save calibration")}},[x.calibrationPoints,j,B==null?void 0:B.source_mime_type,A,u,a,D]),Rn=l.useCallback(async()=>{if(j)try{await sr(j),u.invalidateQueries({queryKey:["takeoff-calibration",j]}),u.invalidateQueries({queryKey:["takeoff-measurements",j]}),u.invalidateQueries({queryKey:["takeoff-measurements-session",a]}),u.invalidateQueries({queryKey:["takeoff-session",a]}),he(!1),Q.success("Scale cleared. Set a new scale to re-measure this page.")}catch(t){console.error("Failed to clear calibration:",t),Q.error("Failed to clear scale")}},[j,a,u]),xa=l.useCallback(()=>{j&&(o.length>0?he(!0):Rn())},[j,o.length,Rn]),ga=l.useCallback(()=>{re(!1),D({type:"CANCEL_CALIBRATION"})},[D]),ft=l.useCallback(t=>{D({type:"SET_TOOL",payload:t})},[D]),ht=(B==null?void 0:B.source_mime_type)==="application/pdf"?L:R!=null&&R.takeoff_pages?!B||B.source_media_id==null?R.takeoff_pages.length:R.takeoff_pages.filter(t=>t.source_media_id===B.source_media_id).length:0,Gt=l.useCallback(t=>{D({type:"CANCEL_DRAWING"}),D({type:"SELECT_MEASUREMENT",payload:null}),Xe(),v(t)},[D,Xe,v]);l.useEffect(()=>{ht>0&&$>ht&&v(ht)},[ht,$,v]);const An=l.useCallback(()=>{Gt(Math.max(1,$-1))},[Gt,$]),Ln=l.useCallback(()=>{Gt(Math.min(ht,$+1))},[Gt,ht,$]),ya=l.useMemo(()=>{const t=new Map;if(R!=null&&R.takeoff_pages)for(const n of R.takeoff_pages)t.set(n.id,n.is_calibrated);return t},[R]);l.useEffect(()=>{const t=n=>{const s=n.target;if(Z||W||s.tagName==="INPUT"||s.tagName==="TEXTAREA"||s.isContentEditable)return;const i=n.metaKey||n.ctrlKey;if(i&&!n.shiftKey&&n.key.toLowerCase()==="z"){n.preventDefault(),Yt();return}if(i&&n.shiftKey&&n.key.toLowerCase()==="z"){n.preventDefault(),Qt();return}if(i&&n.key.toLowerCase()==="y"){n.preventDefault(),Qt();return}if(!i){switch(n.key.toLowerCase()){case"v":ft("select");break;case"m":ft("move");break;case"a":ft("area");break;case"r":ft("rectangle");break;case"l":ft("linear");break;case"c":ft("count");break;case"x":ft("subtract");break;case"s":ft("calibrate");break;case"g":le(f=>!f);break;case"escape":x.activeTool==="calibrate"?D({type:"CANCEL_CALIBRATION"}):x.activeTool==="subtract"&&x.subtractTargetId?D({type:"SUBTRACT_RESET"}):x.isDrawing?D({type:"CANCEL_DRAWING"}):x.selectedMeasurementId&&D({type:"SELECT_MEASUREMENT",payload:null});break;case"backspace":x.activeTool==="subtract"&&x.subtractDrawingPoints.length>0?(n.preventDefault(),D({type:"SUBTRACT_HOLE_REMOVE_LAST_POINT"})):x.isDrawing?(n.preventDefault(),D({type:"REMOVE_LAST_POINT"})):x.selectedMeasurementId&&x.activeTool==="select"&&(n.preventDefault(),se.mutate(x.selectedMeasurementId));break;case"delete":x.selectedMeasurementId&&x.activeTool==="select"&&(n.preventDefault(),se.mutate(x.selectedMeasurementId));break;case"enter":x.activeTool==="area"&&x.drawingPoints.length>=3?(vn(x.drawingPoints,"area"),D({type:"COMPLETE_MEASUREMENT"})):x.activeTool==="linear"&&x.drawingPoints.length>=2?(vn(x.drawingPoints,"linear"),D({type:"COMPLETE_MEASUREMENT"})):x.activeTool==="subtract"&&x.subtractTargetId&&x.subtractDrawingPoints.length>=3?(In(x.subtractTargetId,x.subtractDrawingPoints),D({type:"SUBTRACT_RESET"})):x.activeTool==="subtract"&&x.subtractTargetId&&x.subtractDrawingPoints.length>0&&x.subtractDrawingPoints.length<3&&Q.error("A subtraction needs at least 3 points.");break}n.key==="PageUp"||n.key==="["?(n.preventDefault(),An()):(n.key==="PageDown"||n.key==="]")&&(n.preventDefault(),Ln())}};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[ft,x.activeTool,x.isDrawing,x.selectedMeasurementId,x.drawingPoints,x.subtractTargetId,x.subtractDrawingPoints,Z,W,D,se,vn,In,Yt,Qt,An,Ln]);const en=l.useCallback(()=>{b?p(b,{state:h,replace:!0}):window.history.length>1?p(-1):p("/")},[p,b,h]),ba=l.useCallback(()=>{const t=C.length;t>0&&Q.success(`${t} measurement${t!==1?"s":""} saved. Sammy will use these when you generate your estimate.`),en()},[C.length,en]),va=l.useCallback(async()=>{var t,n;if(a){P(!0),Ge(!0);try{const{data:s,error:i}
21=await Cs.rpc("get_takeoff_group_summaries",{p_session_id:a});if(i)throw i;const f=s||[],k=(me,_e)=>me===null?`0 ${_e}`:`${Number(me.toFixed(2))} ${_e}`;let K=`MEASURED QUANTITIES FROM PLAN TAKEOFF:
22`;for(const me of f){K+=me.group_name?`
23Measurement Group: "${me.group_name}"
24`:`
25Ungrouped measurements:
26`;const _e=((t=me.item_labels)==null?void 0:t.subtotals)??[];for(const ve of _e)K+=`  ${ve.measurement_type}: ${k(ve.value,ve.unit)} (${ve.count} measurement${ve.count!==1?"s":""})
27`;me.waste_factor_percent&&(K+=`  Waste factor: ${me.waste_factor_percent}% (apply to the area/linear order quantities)
28`);const et=((n=me.item_labels)==null?void 0:n.items)??[];if(et.length>0){K+=`  Named items:
29`;for(const ve of et){const Ct=ve.value==null&&ve.unit==="EA"?"1 EA":k(ve.value,ve.unit),Mt=ve.formula?` (${ve.formula})`:"";if(K+=`    - "${ve.label}": ${Ct}${Mt}
30`,ve.subtractions&&ve.subtractions.length>0)for(const tn of ve.subtractions){const wa=tn.label&&tn.label.trim()?tn.label:"subtraction";K+=`        − ${wa}: ${k(tn.value,tn.unit)}
31`}}}}f.length===0&&(K="(No measurements yet — draw some measurements to see the takeoff data Sammy will receive)"),ue({summaries:f,prompt:K})}catch(s){console.error("[TakeoffPage] Debug RPC error:",s),ue({summaries:[],prompt:`Error: ${s}`})}finally{Ge(!1)}}},[a]),as=(()=>{if(x.activeTool==="calibrate")return x.calibrationPoints.length===0?"Click the first point of a known dimension":"Click the second point — hold Shift to lock to horizontal/vertical";if(x.activeTool==="area")return x.isDrawing?x.drawingPoints.length<3?"Click to place vertices (min 3)":"Click first vertex, Enter, or double-click to close":"Click to place the first vertex";if(x.activeTool==="rectangle")return x.isDrawing?"Click to place the opposite corner":"Click to place the first corner";if(x.activeTool==="linear")return x.extendingMeasurementId?"Continuing polyline — click to add points, double-click or Enter to finish":x.isDrawing?x.drawingPoints.length<2?"Click to place points (min 2)":"Double-click or Enter to complete":"Click to place the first point";if(x.activeTool==="count")return"Click to place a count marker";if(x.activeTool==="subtract"){if(x.subtractTargetId){if(x.subtractStart)return"Click the second point on the same line to splice";if(x.subtractDrawingPoints.length>0)return x.subtractDrawingPoints.length<3?"Click to place hole vertices (min 3) — double-click or Enter to commit":"Click to add more vertices, or double-click / Enter to close the hole"}return"Click on a line to splice it, or inside an area to cut a hole"}return null})();return cn?(console.log("[TakeoffPage] Rendering: loading state"),e.jsx("div",{className:"fixed inset-0 bg-gray-950 flex items-center justify-center",children:e.jsx(Wn,{className:"h-8 w-8 animate-spin text-white/60"})})):wt||!R?(console.error("[TakeoffPage] Rendering: error state",{error:wt,hasSession:!!R}),e.jsxs("div",{className:"fixed inset-0 bg-gray-950 flex flex-col items-center justify-center gap-4",children:[e.jsx("p",{className:"text-red-400 text-sm",children:wt instanceof Error?wt.message:"Failed to load takeoff session"}),e.jsx(ie,{variant:"outline",size:"sm",onClick:en,children:"Go back"})]})):m?e.jsxs("div",{className:"fixed inset-0 bg-gray-950 flex flex-col",style:{touchAction:"none",overscrollBehavior:"none"},children:[e.jsxs("div",{className:"flex items-center justify-between px-4 h-12 bg-gray-950 border-b border-white/10 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs(ie,{variant:"ghost",size:"sm",onClick:en,className:"text-white/70 hover:text-white hover:bg-white/10 -ml-2",children:[e.jsx(Fa,{className:"h-4 w-4 mr-1"}),"Back"]}),e.jsx("span",{className:"text-white/80 text-sm font-medium truncate max-w-[200px]",children:R.name}),mt.length>1&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-white/30 text-sm",children:"/"}),e.jsxs(Ta,{children:[e.jsx(Da,{asChild:!0,children:e.jsxs(ie,{variant:"ghost",size:"sm",className:"text-white/80 hover:text-white hover:bg-white/10 -mx-1 px-2 gap-1.5 max-w-[260px]",children:[e.jsx("span",{className:"truncate",children:((fs=mt.f
31ind(t=>t.id===dt))==null?void 0:fs.label)??"Select plan"}),e.jsx(Jn,{className:"h-3.5 w-3.5 shrink-0 text-white/50"})]})}),e.jsx(Ia,{align:"start",className:"bg-gray-900 border-white/10 text-white/80 min-w-[240px]",children:mt.map(t=>e.jsx(Ra,{onClick:()=>T(t.id),className:t.id===dt?"bg-white/10 text-white focus:bg-white/15":"text-white/70 focus:bg-white/10 focus:text-white",children:e.jsx("span",{className:"truncate",children:t.label})},t.id))})]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>Yt(),className:"text-white/50 hover:text-white hover:bg-white/10 w-7 h-7 p-0",title:"Undo (Ctrl+Z)",children:e.jsx(Ua,{className:"h-3.5 w-3.5"})}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>Qt(),className:"text-white/50 hover:text-white hover:bg-white/10 w-7 h-7 p-0",title:"Redo (Ctrl+Shift+Z)",children:e.jsx(Qa,{className:"h-3.5 w-3.5"})}),as&&e.jsx("div",{className:"text-white/70 text-xs",children:as})]}),ht>1&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(ie,{variant:"ghost",size:"sm",onClick:An,disabled:$<=1,className:"text-white/60 hover:text-white hover:bg-white/10 px-2",children:"<"}),e.jsxs("span",{className:"text-white/60 text-xs tabular-nums min-w-[60px] text-center",children:["Page ",$," / ",ht]}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:Ln,disabled:$>=ht,className:"text-white/60 hover:text-white hover:bg-white/10 px-2",children:">"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[C.length>0&&e.jsxs("span",{className:"text-white/40 text-xs tabular-nums",children:[C.length," measured"]}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:va,className:"text-white/30 hover:text-white hover:bg-white/10 w-7 h-7 p-0",title:"Debug: View takeoff data",children:e.jsx(jr,{className:"h-3.5 w-3.5"})}),e.jsx(ie,{size:"sm",onClick:ba,className:"h-7 text-xs px-3",children:"Done"})]})]}),c&&!we&&e.jsxs("div",{className:"flex items-center justify-center gap-3 px-4 py-1.5 bg-sky-900/40 border-b border-sky-600/30 shrink-0",children:[e.jsxs("span",{className:"text-sky-200 text-xs",children:['Measurements saved in the "',c.label,'" group will fill the'," ",e.jsx("strong",{children:c.label})," dimension in your Strategy."]}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>ee(!0),className:"text-sky-200 hover:text-sky-100 hover:bg-sky-800/30 text-xs h-6 px-2",children:"Got it"})]}),!r&&x.activeTool!=="calibrate"&&e.jsxs("div",{className:"flex items-center justify-center gap-3 px-4 py-1.5 bg-amber-900/40 border-b border-amber-600/30 shrink-0",children:[e.jsx("span",{className:"text-amber-200 text-xs",children:"This page has no scale set. Measurements will be in pixels until calibrated."}),e.jsx(ie,{variant:"ghost",size:"sm",onClick:()=>ft("calibrate"),className:"text-amber-200 hover:text-amber-100 hover:bg-amber-800/30 text-xs h-6 px-2",children:"Set Scale"})]}),e.jsxs("div",{className:"flex-1 min-h-0 relative flex flex-row",children:[e.jsx(Br,{ref:E,groups:y,measurements:o,allSessionMeasurements:C,pages:(R==null?void 0:R.takeoff_pages)??[],currentPageId:j,activeGroupId:x.activeGroupId,onSelectGroup:hn,onCreateGroup:Me,onDeleteGroup:We,onToggleVisibility:_t,onSelectMeasurement:Ye,onDeleteMeasurement:ke,onNavigateToPage:Gt,onContextMenuGroup:ca,onContextMenuMeasurement:ua,isCollapsed:J,onToggleCollapsed:()=>le(t=>!t),checklist:(hs=ae==null?void 0:ae.strategy)!=null&&hs.takeoffMenu&&!ae.ratifiedAt?e.jsx(dl,{menu:ae.strategy.takeoffMenu,takeoff:ae.strategy.takeoff,slotMap:mn,activeSlotId:fn,onActivateSlot:Ne}):void 0}),e.jsxs("div",{className:"flex-1 min-w-0 min-h-0 relative flex flex-col",children:[e.jsx(Ur,{ref:I,fileUrl:_,mimeType:(B==null?void 0:B.source_mime_type)??m.source_mime_type,pageNumber:$,onPageCountChange:fe,activeTool:x.activeTool,dispatch:D,calibrationPoints:x.calibrationPoints,savedCalibration:A??null,drawingPoints:x.drawingPoints,isDrawing:x.isDrawing,cursorPosition:x.cursorPosition,measurements:ra,selectedMeasurementId:x.selectedMeasurementId,hoveredMeasurementId:x.hoveredMeasurementId,onCompleteMeasurement:vn,groupColourMap:N,groupOpacityMap:it,hiddenGroupIds:Rt,activeDrawingColour:dn,onZoomChange:Ue,onFitScaleChange:He,onContextMenu:ia,onMoveMeasurement:na,subtractTargetId:x.subtractTargetId,subtractStart:x.subtractStart,subtractDrawingPoints:x.subtractDrawingPoints,onSubtractCommit:oa,onSubtractHoleCommit:In,onClearScale:xa}),e.jsx(Wr,{activeTool:x.activeTool,onToolChange:ft,isCalibrated:r,zoom:Se,onZoomTo:t=>{var n;return(n=I.current)==null?void 0:n.zoomTo(t)},onFitToPage:()=>{var t;return(t=I.current)==null?void 0:t.fitToPage()}}),x.activeTool!=="select"&&!Mn&&e.jsx("div",{className:`pointer-events-none absolute left-1/2 -translate-x-1/2 z-30 ${ht>1?"bottom-24":"bottom-6"}`,role:"status","aria-live":"polite",children:e.jsxs("div",{className:"pointer-events-auto flex items-center gap-2 rounded-full bg-black/60 backdrop-blur-md py-1.5 pl-3 pr-1.5 text-[11px] text-white/70 shadow-lg ring-1 ring-white/10",children:[e.jsx("span",{children:"Hold"}),e.jsx("kbd",{className:"rounded bg-white/10 px-1.5 py-0.5 font-mono text-[10px] text-white/90",children:"Space"}),e.jsx("span",{children:"key and click to move around the page"}),e.jsx("button",{type:"button",onClick:tt,"aria-label":"Dismiss tip",className:"ml-1 flex h-5 w-5 items-center justify-center rounded-full text-white/40 transition-colors hover:bg-white/10 hover:text-white/80",children:e.jsx($s,{className:"h-3 w-3"})})]})}),ht>1&&(R==null?void 0:R.takeoff_pages)&&e.jsx(Jr,{pages:B!=null&&B.source_media_id?R.takeoff_pages.filter(t=>t.source_media_id===B.source_media_id):R.takeoff_pages,currentPageNumber:$,onPageChange:Gt,fileUrl:_,mimeType:(B==null?void 0:B.source_mime_type)??m.source_mime_type,calibrationMap:ya})]})]}),x.calibrationPoints.length===2&&e.jsx(Hr,{open:Z,onConfirm:pa,onCancel:ga,points:[x.calibrationPoints[0],x.calibrationPoints[1]]}),e.jsx(Pt,{open:!!z,onOpenChange:t=>{t||U(null)},children:e.jsxs(Ot,{className:"sm:max-w-sm",children:[e.jsxs(Vt,{children:[e.jsx($t,{children:"Rename measurement"}),e.jsx(nn,{children:"Set a custom label shown on the canvas and in the groups panel. Leave blank to clear."})]}
31),e.jsx(Kt,{value:pe,onChange:t=>q(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),jt()):t.key==="Escape"&&(t.preventDefault(),U(null))},placeholder:"e.g. Kitchen wall, Bedroom 1, etc.",autoFocus:!0}),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:()=>U(null),children:"Cancel"}),e.jsx(ie,{onClick:jt,children:"Save"})]})]})}),e.jsx(Pt,{open:!!Fe,onOpenChange:t=>{t||ge(null)},children:e.jsxs(Ot,{className:"sm:max-w-sm",children:[e.jsxs(Vt,{children:[e.jsx($t,{children:"Rename group"}),e.jsx(nn,{children:"Set a new name for this measurement group. Used in the panel and in proposal/order summaries."})]}),e.jsx(Kt,{value:ze,onChange:t=>at(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),ts()):t.key==="Escape"&&(t.preventDefault(),ge(null))},placeholder:"e.g. External walls, Skirting, Downlights",autoFocus:!0}),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:()=>ge(null),children:"Cancel"}),e.jsx(ie,{onClick:ts,disabled:!ze.trim(),children:"Save"})]})]})}),e.jsx(Pt,{open:!!Re,onOpenChange:t=>{t||ne(null)},children:e.jsxs(Ot,{className:"sm:max-w-sm",children:[e.jsxs(Vt,{children:[e.jsx($t,{children:(Re==null?void 0:Re.measurementType)==="area"||(Re==null?void 0:Re.measurementType)==="rectangle"?"Set thickness":"Set height"}),e.jsx(nn,{children:(Re==null?void 0:Re.measurementType)==="linear"?"Linear measurements with a height become wall sqm — length × height. Leave blank to clear.":"Area measurements with a thickness become m³ — area × thickness. Leave blank to clear."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Kt,{type:"number",inputMode:"decimal",min:"0",step:"0.1",value:Te,onChange:t=>de(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),pn()):t.key==="Escape"&&(t.preventDefault(),ne(null))},placeholder:"2.4",autoFocus:!0,className:"flex-1"}),e.jsxs("div",{className:"inline-flex rounded-md border bg-background overflow-hidden",children:[e.jsx("button",{type:"button",onClick:()=>Nt("m"),className:`px-3 py-2 text-sm ${xt==="m"?"bg-primary text-primary-foreground":"hover:bg-accent"}`,children:"m"}),e.jsx("button",{type:"button",onClick:()=>Nt("mm"),className:`px-3 py-2 text-sm ${xt==="mm"?"bg-primary text-primary-foreground":"hover:bg-accent"}`,children:"mm"})]})]}),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:()=>ne(null),children:"Cancel"}),e.jsx(ie,{onClick:pn,children:"Save"})]})]})}),e.jsx(Pt,{open:!!te,onOpenChange:t=>{t||gt(null)},children:e.jsxs(Ot,{className:"sm:max-w-sm",children:[e.jsxs(Vt,{children:[e.jsx($t,{children:"Set pitch"}),e.jsx(nn,{children:(te==null?void 0:te.measurementType)==="linear"?"Plan lengths are horizontal projections — a pitch reports the true raking length (length × pitch factor). Leave blank to clear.":"Plan areas are horizontal projections — a pitch reports the true sloped area (area × pitch factor). Leave blank to clear."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Kt,{type:"number",inputMode:"decimal",min:"0",max:"89.9",step:"0.5",value:Dt,onChange:t=>Xt(t.target.value),onKeyDown:t=>{t.key==="Enter"?(t.preventDefault(),es()):t.key==="Escape"&&(t.preventDefault(),gt(null))},placeholder:"22.5",autoFocus:!0,className:"flex-1"}),e.jsx("span",{className:"text-sm text-muted-foreground shrink-0",children:"degrees"})]}),(()=>{const t=parseFloat(Dt.trim()),n=ar(Number.isFinite(t)?{value:t}:null);return n!=null?e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Multiplier: ×",n.toFixed(3)]}):null})(),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:()=>gt(null),children:"Cancel"}),e.jsx(ie,{onClick:es,children:"Save"})]})]})}),e.jsx(Pt,{open:W,onOpenChange:t=>{t||he(!1)},children:e.jsxs(Ot,{className:"sm:max-w-sm",children:[e.jsxs(Vt,{children:[e.jsx($t,{children:"Clear scale?"}),e.jsxs(nn,{children:["This removes the real-world values from ",o.length," ","measurement",o.length===1?"":"s"," on this page. The shapes stay drawn — set a new scale to restore their measurements."]})]}),e.jsxs(Ht,{children:[e.jsx(ie,{variant:"outline",onClick:()=>he(!1),children:"Cancel"}),e.jsx(ie,{variant:"destructive",onClick:()=>{Rn()},children:"Clear scale"})]})]})}),e.jsx(nl,{open:d.open,x:d.x,y:d.y,target:d.target,onClose:da,onDelete:(((ps=d.target)==null?void 0:ps.kind)==="measurement"||((xs=d.target)==null?void 0:xs.kind)==="vertex")&&d.target.measurementId?()=>se.mutate(d.target.measurementId):void 0,onDuplicate:((gs=d.target)==null?void 0:gs.kind)==="measurement"&&d.target.measurementId?()=>G(d.target.measurementId):void 0,onMove:(((ys=d.target)==null?void 0:ys.kind)==="measurement"||((bs=d.target)==null?void 0:bs.kind)==="vertex")&&d.target.measurementId?()=>{D({type:"SET_TOOL",payload:"move"}),D({type:"SELECT_MEASUREMENT",payload:d.target.measurementId})}:void 0,onRename:((vs=d.target)==null?void 0:vs.kind)==="measurement"&&d.target.measurementId?()=>ct(d.target.measurementId):void 0,onSetHeight:(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return;const t=d.target.measurementId;if(!t)return;const n=o.find(i=>i.id===t);if(n&&!(n.measurement_type!=="linear"&&n.measurement_type!=="area"&&n.measurement_type!=="rectangle"))return()=>At(t)})(),onClearHeight:(()=>{var s,i;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return;const t=d.target.measurementId;if(!t)return;const n=o.find(f=>f.id===t);if(!(!n||!((i=n.adjustments)!=null&&i.height)))return()=>Ys(t)})(),heightLabel:(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return;const t=d.target.measurementId;if(!t)return;const n=o.find(i=>i.id===t);if(n)return n.measurement_type==="area"||n.measurement_type==="rectangle"?{set:"Set thickness…",clear:"Clear thickness"}:{set:"Set height…",clear:"Clear height"}})(),onSetPitch:(()=>{var s;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return;const t=d.target.measurementId;if(!t)return;const n=o.find(i=>i.id===t);if(n&&!(n.measurement_type!=="linear"&&n.measurement_type!=="area"&&n.measurement_type!=="rectangle"))return()=>Zs(t)})(),onClearPitch:(()=>{var s,i;if(((s=d.target)==null?void 0:s.kind)!=="measurement")return;const t=d.target.measurementId;if(!t)return;const n=o.find(f=>f.id===t);if(!(!n||!((i=n.adjustments)!=null&&i.pitch)))return()=>Js(t)})(),copyValue:ha,onCopyValue:t=>Q.success(`Copied: ${t}`),group:Jt,anyGroupHidden:ns,onHideGroup:Jt?()=>ma(Jt.id):void 0,onShowOnlyGroup:Jt?()=>ss(Jt.id):void 0,onShowAllGroups:ns?fa:void 0,onRecenterHere:((ws=d.target)==null?void 0:ws.kind)==="empty"&&d.target.pagePoint?()=>{var t;return(t=I.current)==null?void 0:t.recenterAt(d.target.pagePoint)}:void 0,onFitToPage:((ks=d.target)==null?void 0:ks.kind)==="empty"?()=>{var t;return(t=I.current)==null?void 0:t.fitToPage()}:void 0,onCalibrate:((_s=d.target)==null?void 0:_s.kind)==="empty"?()=>D({type:"SET_TOOL",payload:"calibrate"}):void 0,onDeleteVertex:Ze!=null&&Ze.canDelete?()=>sa(Ze.measurementId,Ze.vertexIndex):void 0,onInsertVertexAfter:Ze!=null&&Ze.canInsertAfter?()=>aa(Ze.measurementId,Ze.vertexIndex):void 0,onContinuePolyline:Ze!=null&&Ze.extendEnd?()=>la(Ze.measurementId,Ze.extendEnd):void 0,moveToGroupOptions:gn.options,currentGroupId:gn.currentGroupId,onMoveToGroup:gn.measurementId?t=>be(gn.measurementId,t):void 0,tagForStrategyOptions:xe,currentSemanticRole:$e,onTagForStrategy:((js=d.target)==null?void 0:js.kind)==="measurement"&&d.target.measurementId?t=>Ie(d.target.measurementId,t):void 0,groupTarget:Je,onRenameGroup:Je?()=>ea(Je.id):void 0,onToggleGroupVisibility:Je?()=>_t(Je.id,!Je.isVisible):void 0,onShowOnlyThisGroup:Je?()=>ss(Je.id):void 0,onChangeGroupColour:Je?t=>
31ta(Je.id,t):void 0,groupColourPalette:Je?rr:void 0,onExpandAllGroups:Je?()=>{var t;return(t=E.current)==null?void 0:t.expandAll()}:void 0,onCollapseAllGroups:Je?()=>{var t;return(t=E.current)==null?void 0:t.collapseAll()}:void 0,onDeleteGroup:Je?()=>We(Je.id):void 0}),e.jsx(Pt,{open:Ae,onOpenChange:P,children:e.jsxs(Ot,{className:"max-w-2xl max-h-[85vh] overflow-hidden flex flex-col",children:[e.jsx(Vt,{children:e.jsx($t,{children:"Takeoff Data (Dev Debug)"})}),e.jsx("div",{className:"overflow-y-auto flex-1 space-y-4",children:Le?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(Wn,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):Oe?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold mb-2",children:"Group Summaries (RPC output)"}),Oe.summaries.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No measurements yet."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs border-collapse",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b",children:[e.jsx("th",{className:"text-left p-1.5 font-medium",children:"Group"}),e.jsx("th",{className:"text-left p-1.5 font-medium",children:"Sub-totals (per type)"}),e.jsx("th",{className:"text-right p-1.5 font-medium",children:"Waste %"}),e.jsx("th",{className:"text-right p-1.5 font-medium",children:"# Meas"})]})}),e.jsx("tbody",{children:Oe.summaries.map((t,n)=>{var s;return e.jsxs("tr",{className:"border-b border-muted",children:[e.jsx("td",{className:"p-1.5 font-medium",children:t.group_name??"Ungrouped"}),e.jsx("td",{className:"p-1.5 text-muted-foreground",children:(((s=t.item_labels)==null?void 0:s.subtotals)??[]).map(i=>`${Number((i.value??0).toFixed(2))} ${i.unit}`).join(" · ")||"-"}),e.jsx("td",{className:"p-1.5 text-right tabular-nums",children:t.waste_factor_percent?`${t.waste_factor_percent}%`:"-"}),e.jsx("td",{className:"p-1.5 text-right tabular-nums",children:t.measurement_count})]},n)})})]})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold mb-2",children:"Prompt Context (sent to Sammy)"}),e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-md overflow-x-auto whitespace-pre-wrap font-mono",children:Oe.prompt})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold mb-2",children:"Raw JSON"}),e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-md overflow-x-auto whitespace-pre-wrap font-mono",children:JSON.stringify(Oe.summaries,null,2)})]})]}):null})]})})]}):(console.warn("[TakeoffPage] Rendering: no firstPage in session",R),e.jsxs("div",{className:"fixed inset-0 bg-gray-950 flex flex-col items-center justify-center gap-4",children:[e.jsx("p",{className:"text-white/60 text-sm",children:"This takeoff session has no plan pages."}),e.jsx(ie,{variant:"outline",size:"sm",onClick:en,children:"Go back"})]}))}export{Il as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.