@zonetrix/viewer 2.10.1 → 2.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,6 +31,7 @@ export interface UseFirebaseSeatStatesResult {
31
31
  }
32
32
  /**
33
33
  * Subscribe to real-time seat state updates from Firebase
34
+ * Uses useSyncExternalStore for stable snapshot handling
34
35
  *
35
36
  * @example
36
37
  * ```tsx
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),t=require("react"),P=require("react-konva"),B=require("firebase/database"),rt=require("@zonetrix/shared");function Re(n){const[s,o]=t.useState(null),[r,h]=t.useState(!1),[d,l]=t.useState(null),v=async()=>{if(n){h(!0),l(null);try{const p=await fetch(n);if(!p.ok)throw new Error(`Failed to fetch config: ${p.statusText}`);const a=await p.json();o(a)}catch(p){const a=p instanceof Error?p:new Error("Unknown error occurred");l(a),console.error("Failed to fetch seat map config:",a)}finally{h(!1)}}};return t.useEffect(()=>{v()},[n]),{config:s,loading:r,error:d,refetch:v}}function je(n){const[s,o]=t.useState({width:0,height:0});return t.useEffect(()=>{const r=n.current;if(!r)return;const{width:h,height:d}=r.getBoundingClientRect();h>0&&d>0&&o({width:h,height:d});const l=new ResizeObserver(v=>{const p=v[0];if(!p)return;const{width:a,height:c}=p.contentRect;a>0&&c>0&&o(f=>f.width===a&&f.height===c?f:{width:a,height:c})});return l.observe(r),()=>{l.disconnect()}},[n]),s}function we(n,s){return Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2))}function Ce(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function Me(n,s){const o=t.useRef(null),r=t.useRef(null),h=t.useRef(1);t.useEffect(()=>{const d=n.current;if(!d||!s.enabled)return;const l=d.container(),v=c=>{if(c.touches.length===2){c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},g={x:c.touches[1].clientX,y:c.touches[1].clientY};o.current=we(f,g),r.current=Ce(f,g),h.current=s.currentScale}},p=c=>{if(c.touches.length!==2)return;c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},g={x:c.touches[1].clientX,y:c.touches[1].clientY},m=we(f,g),w=Ce(f,g);if(o.current!==null&&r.current!==null){const R=m/o.current,E=Math.min(Math.max(s.currentScale*R,s.minScale),s.maxScale),F=l.getBoundingClientRect(),j=w.x-F.left,I=w.y-F.top,L=s.currentScale,T={x:(j-s.currentPosition.x)/L,y:(I-s.currentPosition.y)/L},V=w.x-r.current.x,W=w.y-r.current.y,q={x:j-T.x*E+V,y:I-T.y*E+W};s.onScaleChange(E,q),o.current=m,r.current=w}},a=c=>{c.touches.length<2&&(o.current=null,r.current=null)};return l.addEventListener("touchstart",v,{passive:!1}),l.addEventListener("touchmove",p,{passive:!1}),l.addEventListener("touchend",a),()=>{l.removeEventListener("touchstart",v),l.removeEventListener("touchmove",p),l.removeEventListener("touchend",a)}},[n,s])}const Ee={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Fe=t.memo(({seat:n,state:s,colors:o,onClick:r,onMouseEnter:h,onMouseLeave:d})=>{const p={available:o.seatAvailable,reserved:o.seatReserved,selected:o.seatSelected,unavailable:o.seatUnavailable,hidden:o.seatHidden}[s],a=s==="available"||s==="selected",c=t.useCallback(()=>{a&&r(n)},[n,r,a]),f=t.useCallback(w=>{h(n,w);const R=w.target.getStage();R&&a&&(R.container().style.cursor="pointer")},[n,h,a]),g=t.useCallback(w=>{d();const R=w.target.getStage();R&&(R.container().style.cursor="grab")},[d]),m={x:n.position.x,y:n.position.y,fill:p,stroke:"#ffffff",strokeWidth:1,onClick:c,onTap:c,onMouseEnter:f,onMouseLeave:g};return n.shape==="circle"?i.jsx(P.Circle,{...m,radius:12}):i.jsx(P.Rect,{...m,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:n.shape==="square"?0:4})});Fe.displayName="ViewerSeat";const ke=t.memo(({stage:n,stageColor:s})=>{const o=d=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[d||"stage"]||"🎭",r=n.config.color||s,h=o(n.config.objectType);return i.jsxs(P.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[i.jsx(P.Rect,{width:n.config.width,height:n.config.height,fill:r+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),i.jsx(P.Text,{text:h,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),i.jsx(P.Text,{text:n.config.label,x:0,y:n.config.height*.4,width:n.config.width,height:n.config.height*.6,fontSize:20,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]})});ke.displayName="ViewerStage";const Ie=t.memo(({floors:n,currentFloorId:s,onFloorChange:o,showAllOption:r,allLabel:h,position:d,className:l})=>{const v=t.useMemo(()=>[...n].sort((g,m)=>g.order-m.order),[n]),a={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[d]},c={padding:"10px 16px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease",minHeight:"44px",touchAction:"manipulation"},f={...c,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return i.jsxs("div",{className:l,style:a,children:[r&&i.jsx("button",{type:"button",onClick:()=>o(null),style:s===null?f:c,children:h}),v.map(g=>i.jsx("button",{type:"button",onClick:()=>o(g.id),style:s===g.id?f:c,children:g.name},g.id))]})});Ie.displayName="FloorSelectorBar";const Le=t.memo(({scale:n,minScale:s,maxScale:o,onZoomIn:r,onZoomOut:h,position:d,className:l})=>{const p={position:"absolute",display:"flex",flexDirection:"column",gap:"4px",padding:"8px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[d]},a={width:"44px",height:"44px",minWidth:"44px",minHeight:"44px",fontSize:"22px",fontWeight:"bold",border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.2s ease",touchAction:"manipulation"},c={...a,opacity:.4,cursor:"not-allowed"},f=n<o,g=n>s;return i.jsxs("div",{className:l,style:p,children:[i.jsx("button",{type:"button",onClick:r,disabled:!f,style:f?a:c,title:"Zoom In",children:"+"}),i.jsx("button",{type:"button",onClick:h,disabled:!g,style:g?a:c,title:"Zoom Out",children:"−"})]})});Le.displayName="ZoomControls";const De=t.memo(({visible:n,x:s,y:o,seat:r,currency:h,state:d})=>{if(!n||!r)return null;const l=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),v={position:"fixed",left:`${s+15}px`,top:`${o+15}px`,zIndex:1e3,pointerEvents:"none"},p={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},a={color:"#9ca3af",marginRight:"4px"},c={fontWeight:600},f={color:"#4ade80",fontWeight:600},g={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return i.jsx("div",{style:v,children:i.jsxs("div",{style:p,children:[r.sectionName&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:a,children:"Section:"}),i.jsx("span",{style:{...c,color:"#3b82f6"},children:r.sectionName})]}),i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:a,children:"Seat:"}),i.jsx("span",{style:c,children:l})]}),r.price!==void 0&&r.price>0&&d==="available"&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:a,children:"Price:"}),i.jsxs("span",{style:f,children:[h," ",r.price.toFixed(2)]})]}),i.jsxs("div",{style:g,children:["Status: ",d]})]})})});De.displayName="SeatTooltip";const ot=({config:n,configUrl:s,floorId:o,onFloorChange:r,reservedSeats:h=[],unavailableSeats:d=[],selectedSeats:l,myReservedSeats:v=[],onSeatSelect:p,onSeatDeselect:a,onSelectionChange:c,colorOverrides:f,showTooltip:g=!0,zoomEnabled:m=!0,className:w="",onConfigLoad:R,onError:E,showFloorSelector:F,floorSelectorPosition:j="top-left",floorSelectorClassName:I,showAllFloorsOption:L=!0,allFloorsLabel:T="All",fitToView:V=!0,fitPadding:W=40,showZoomControls:q=!0,zoomControlsPosition:fe="bottom-right",zoomControlsClassName:se,minZoom:re,maxZoom:z=3,zoomStep:A=.25,touchEnabled:ve=!0})=>{const X=t.useRef(null),O=t.useRef(null),M=je(O),[Y,he]=t.useState(new Set),[k,J]=t.useState(1),[D,U]=t.useState({x:0,y:0}),[Ne,Ae]=t.useState(null),[Xe,Ye]=t.useState(1),oe=t.useRef({width:0,height:0}),[K,me]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Pe,loading:We,error:Z}=Re(s),b=n||Pe,ge=o!==void 0,N=ge?o||null:Ne,ie=l!==void 0,Oe=t.useCallback(e=>{ge||Ae(e),r?.(e)},[ge,r]),pe=b?.floors||[],$e=F!==void 0?F:pe.length>1,ae=t.useMemo(()=>b?{...b.colors,...f}:{...Ee,...f},[b,f]),_=t.useMemo(()=>{if(!b)return[];let e=b.seats.filter(u=>u.state!=="hidden");return N&&(e=e.filter(u=>u.floorId===N||!u.floorId&&N==="floor_default")),e},[b,N]),ce=t.useMemo(()=>b?.stages?N?b.stages.filter(e=>e.floorId===N||!e.floorId&&N==="floor_default"):b.stages:[],[b,N]),$=t.useMemo(()=>{if(!b||_.length===0&&ce.length===0)return null;const e=12;let u=1/0,x=1/0,y=-1/0,S=-1/0;return _.forEach(C=>{u=Math.min(u,C.position.x-e),x=Math.min(x,C.position.y-e),y=Math.max(y,C.position.x+e),S=Math.max(S,C.position.y+e)}),ce.forEach(C=>{u=Math.min(u,C.position.x),x=Math.min(x,C.position.y),y=Math.max(y,C.position.x+(C.config?.width||200)),S=Math.max(S,C.position.y+(C.config?.height||100))}),{minX:u,minY:x,maxX:y,maxY:S,width:y-u,height:S-x}},[b,_,ce]);t.useEffect(()=>{if(!V||!b||!$||M.width===0||M.height===0)return;const e=Math.abs(M.width-oe.current.width),u=Math.abs(M.height-oe.current.height);if(!(oe.current.width===0)&&e<10&&u<10)return;oe.current=M;const y=M.width,S=M.height,C=y-W*2,te=S-W*2,le=C/$.width,xe=te/$.height,ue=Math.min(le,xe,z),Ze=$.minX+$.width/2,Qe=$.minY+$.height/2,et=y/2,tt=S/2,nt=et-Ze*ue,st=tt-Qe*ue;J(ue),U({x:nt,y:st}),Ye(ue)},[V,b,$,W,z,M,N]);const H=t.useMemo(()=>{const e=new Set(h),u=new Set(d),x=new Set(v);return{reserved:e,unavailable:u,myReserved:x}},[h,d,v]),be=t.useMemo(()=>l?new Set(l):null,[l]),Q=t.useCallback(e=>{const u=e.id,x=e.seatNumber||"";return H.unavailable.has(u)||H.unavailable.has(x)?"unavailable":H.reserved.has(u)||H.reserved.has(x)?"reserved":H.myReserved.has(u)||H.myReserved.has(x)||Y.has(u)?"selected":e.state},[H,Y]);t.useEffect(()=>{b&&R&&R(b)},[b,R]),t.useEffect(()=>{Z&&E&&E(Z)},[Z,E]),t.useEffect(()=>{ie&&be&&he(be)},[ie,be]);const Be=t.useCallback(e=>{const u=Q(e);if(u!=="available"&&u!=="selected")return;const x=Y.has(e.id);ie||he(y=>{const S=new Set(y);return x?S.delete(e.id):S.add(e.id),S}),x?a?.(e):(p?.(e),p||console.log("Seat selected:",e))},[Q,Y,ie,p,a]),ee=t.useMemo(()=>b?_.filter(e=>Y.has(e.id)):[],[_,Y]);t.useEffect(()=>{c?.(ee)},[ee,c]);const G=re!==void 0?re:Xe,Ve=t.useCallback(()=>{if(!m)return;const e=Math.min(k+A,z);if(e!==k){const u=M.width||b?.canvas.width||800,x=M.height||b?.canvas.height||600,y=u/2,S=x/2,C={x:(y-D.x)/k,y:(S-D.y)/k};J(e),U({x:y-C.x*e,y:S-C.y*e})}},[m,k,A,z,M,b,D]),Ue=t.useCallback(()=>{if(!m)return;const e=Math.max(k-A,G);if(e!==k){const u=M.width||b?.canvas.width||800,x=M.height||b?.canvas.height||600,y=u/2,S=x/2,C={x:(y-D.x)/k,y:(S-D.y)/k};J(e),U({x:y-C.x*e,y:S-C.y*e})}},[m,k,A,G,M,b,D]),He=t.useCallback(e=>{U({x:e.target.x(),y:e.target.y()})},[]),qe=t.useCallback(e=>{if(!m)return;e.evt.preventDefault();const u=X.current;if(!u)return;const x=u.scaleX(),y=u.getPointerPosition();if(!y)return;const S=1.1,C=e.evt.deltaY>0?x/S:x*S,te=Math.min(Math.max(C,G),z),le={x:(y.x-D.x)/x,y:(y.y-D.y)/x},xe={x:y.x-le.x*te,y:y.y-le.y*te};J(te),U(xe)},[m,D,G,z]);Me(X,{enabled:ve&&m,minScale:G,maxScale:z,currentScale:k,currentPosition:D,onScaleChange:(e,u)=>{J(e),U(u)},onPositionChange:e=>{U(e)}});const _e=t.useCallback((e,u)=>{if(!g)return;const x=u.target.getStage();if(!x)return;const y=x.getPointerPosition();if(!y)return;const S=x.container().getBoundingClientRect();me({visible:!0,x:S.left+y.x,y:S.top+y.y,seat:e,state:Q(e)})},[g,Q]),Ge=t.useCallback(()=>{me(e=>({...e,visible:!1}))},[]);if(We)return i.jsx("div",{className:`flex items-center justify-center h-full ${w}`,children:i.jsx("p",{children:"Loading seat map..."})});if(Z)return i.jsx("div",{className:`flex items-center justify-center h-full ${w}`,children:i.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",Z.message]})});if(!b)return i.jsx("div",{className:`flex items-center justify-center h-full ${w}`,children:i.jsx("p",{children:"No configuration provided"})});const Je=M.width||b.canvas.width,Ke=M.height||b.canvas.height;return i.jsxs("div",{ref:O,className:`relative ${w}`,style:{width:"100%",height:"100%"},children:[$e&&pe.length>0&&i.jsx(Ie,{floors:pe,currentFloorId:N,onFloorChange:Oe,showAllOption:L,allLabel:T,position:j,className:I}),i.jsxs(P.Stage,{ref:X,width:Je,height:Ke,scaleX:k,scaleY:k,x:D.x,y:D.y,draggable:!0,onDragEnd:He,onWheel:qe,style:{backgroundColor:b.canvas.backgroundColor,cursor:"grab"},children:[i.jsx(P.Layer,{listening:!1,children:ce.map(e=>i.jsx(ke,{stage:e,stageColor:ae.stageColor},e.id))}),i.jsx(P.Layer,{children:_.map(e=>i.jsx(Fe,{seat:e,state:Q(e),colors:ae,onClick:Be,onMouseEnter:_e,onMouseLeave:Ge},e.id))})]}),g&&i.jsx(De,{visible:K.visible,x:K.x,y:K.y,seat:K.seat,currency:ae.currency,state:K.state}),q&&m&&i.jsx(Le,{scale:k,minScale:G,maxScale:z,onZoomIn:Ve,onZoomOut:Ue,position:fe,className:se}),ee.length>0&&i.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[i.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",ee.length,")"]}),i.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:ee.map(e=>i.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${ae.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let ne=null;function it(n){ne=n}function Se(){if(!ne)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return ne}function de(){return ne!==null}function at(){ne=null}function ye(n,s){if(n.length!==s.length)return!1;for(let o=0;o<n.length;o++)if(n[o]!==s[o])return!1;return!0}function ct(n,s){return ye(n.myReserved,s.myReserved)&&ye(n.otherReserved,s.otherReserved)&&ye(n.unavailable,s.unavailable)}function lt(n,s){const o=[],r=[],h=[];return Object.entries(n).forEach(([d,l])=>{l&&typeof l=="object"&&l.state&&(l.state==="unavailable"?h.push(d):l.state==="reserved"&&(s&&l.userId===s?o.push(d):r.push(d)))}),{myReserved:o,otherReserved:r,unavailable:h}}function Te(n){const{seatMapId:s,currentUserId:o,enabled:r=!0,onStateChange:h,onError:d}=n,[l,v]=t.useState(null),[p,a]=t.useState(!0),[c,f]=t.useState(null),[g,m]=t.useState(null),[w,R]=t.useState([]),[E,F]=t.useState([]),[j,I]=t.useState([]),L=t.useRef(h),T=t.useRef(d),V=t.useRef(o);L.current=h,T.current=d,V.current=o;const W=t.useRef({myReserved:[],otherReserved:[],unavailable:[]}),q=t.useRef(null);return t.useEffect(()=>{if(!r||!s){a(!1);return}if(!de()){a(!1),f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first."));return}const fe=Se(),se=B.ref(fe,`seat_states/${s}`);a(!0),f(null);const re=A=>{const X=A.val()||{},O=lt(X,V.current),M=W.current,Y=JSON.stringify(q.current)!==JSON.stringify(X);Y&&(v(X),q.current=X),a(!1),!ct(M,O)&&(m(Date.now()),R(O.myReserved),F(O.otherReserved),I(O.unavailable),W.current=O),Y&&L.current?.(X)},z=A=>{f(A),a(!1),T.current?.(A)};return B.onValue(se,re,z),()=>{B.off(se)}},[s,r]),{states:l,loading:p,error:c,lastUpdated:g,myReservedSeats:w,otherReservedSeats:E,unavailableSeats:j,reservedSeats:E}}function ze(n){const{seatMapId:s,enabled:o=!0,subscribeToChanges:r=!1,onConfigLoad:h,onError:d}=n,[l,v]=t.useState(null),[p,a]=t.useState(!0),[c,f]=t.useState(null),g=t.useRef(h),m=t.useRef(d);g.current=h,m.current=d;const w=t.useCallback(async()=>{if(!s)return;if(!de()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),a(!1);return}const R=Se(),E=B.ref(R,`seatmaps/${s}`);try{a(!0),f(null);const j=(await B.get(E)).val();if(j){const I=rt.fromFirebaseSeatMap(j);v(I),g.current?.(I)}else f(new Error(`Seat map ${s} not found in Firebase`))}catch(F){const j=F instanceof Error?F:new Error("Unknown error");f(j),m.current?.(j)}finally{a(!1)}},[s]);return t.useEffect(()=>{if(!o||!s){a(!1);return}if(w(),r&&de()){const R=Se(),E=B.ref(R,`seatmaps/${s}/meta/updated_at`);let F=!0,j=null;const I=L=>{if(F){F=!1,j=L.val();return}const T=L.val();L.exists()&&T!==j&&(j=T,w())};return B.onValue(E,I),()=>{B.off(E)}}},[s,o,r]),{config:l,loading:p,error:c,refetch:w}}function ut(n){const{seatMapId:s,userId:o,enabled:r=!0,subscribeToDesignChanges:h=!1,onConfigLoad:d,onStateChange:l,onError:v}=n,{config:p,loading:a,error:c,refetch:f}=ze({seatMapId:s,enabled:r,subscribeToChanges:h,onConfigLoad:d,onError:v}),{states:g,loading:m,error:w,lastUpdated:R,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:j,reservedSeats:I}=Te({seatMapId:s,currentUserId:o,enabled:r,onStateChange:l,onError:v});return{config:p,loading:a||m,error:c||w,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:j,reservedSeats:I,seatStates:g,lastUpdated:R,refetch:f}}exports.DEFAULT_COLORS=Ee;exports.SeatMapViewer=ot;exports.clearFirebaseInstance=at;exports.initializeFirebaseForViewer=it;exports.isFirebaseInitialized=de;exports.useConfigFetcher=Re;exports.useContainerSize=je;exports.useFirebaseConfig=ze;exports.useFirebaseSeatStates=Te;exports.useRealtimeSeatMap=ut;exports.useTouchGestures=Me;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),t=require("react"),X=require("react-konva"),W=require("firebase/database"),it=require("@zonetrix/shared");function Ce(n){const[s,i]=t.useState(null),[r,h]=t.useState(!1),[u,o]=t.useState(null),w=async()=>{if(n){h(!0),o(null);try{const p=await fetch(n);if(!p.ok)throw new Error(`Failed to fetch config: ${p.statusText}`);const l=await p.json();i(l)}catch(p){const l=p instanceof Error?p:new Error("Unknown error occurred");o(l),console.error("Failed to fetch seat map config:",l)}finally{h(!1)}}};return t.useEffect(()=>{w()},[n]),{config:s,loading:r,error:u,refetch:w}}function Re(n){const[s,i]=t.useState({width:0,height:0});return t.useEffect(()=>{const r=n.current;if(!r)return;const{width:h,height:u}=r.getBoundingClientRect();h>0&&u>0&&i({width:h,height:u});const o=new ResizeObserver(w=>{const p=w[0];if(!p)return;const{width:l,height:c}=p.contentRect;l>0&&c>0&&i(f=>f.width===l&&f.height===c?f:{width:l,height:c})});return o.observe(r),()=>{o.disconnect()}},[n]),s}function ye(n,s){return Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2))}function me(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function je(n,s){const i=t.useRef(null),r=t.useRef(null),h=t.useRef(1);t.useEffect(()=>{const u=n.current;if(!u||!s.enabled)return;const o=u.container(),w=c=>{if(c.touches.length===2){c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},b={x:c.touches[1].clientX,y:c.touches[1].clientY};i.current=ye(f,b),r.current=me(f,b),h.current=s.currentScale}},p=c=>{if(c.touches.length!==2)return;c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},b={x:c.touches[1].clientX,y:c.touches[1].clientY},g=ye(f,b),x=me(f,b);if(i.current!==null&&r.current!==null){const C=g/i.current,j=Math.min(Math.max(s.currentScale*C,s.minScale),s.maxScale),E=o.getBoundingClientRect(),M=x.x-E.left,F=x.y-E.top,z=s.currentScale,L={x:(M-s.currentPosition.x)/z,y:(F-s.currentPosition.y)/z},D=x.x-r.current.x,N=x.y-r.current.y,ee={x:M-L.x*j+D,y:F-L.y*j+N};s.onScaleChange(j,ee),i.current=g,r.current=x}},l=c=>{c.touches.length<2&&(i.current=null,r.current=null)};return o.addEventListener("touchstart",w,{passive:!1}),o.addEventListener("touchmove",p,{passive:!1}),o.addEventListener("touchend",l),()=>{o.removeEventListener("touchstart",w),o.removeEventListener("touchmove",p),o.removeEventListener("touchend",l)}},[n,s])}const Me={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Ee=t.memo(({seat:n,state:s,colors:i,onClick:r,onMouseEnter:h,onMouseLeave:u})=>{const p={available:i.seatAvailable,reserved:i.seatReserved,selected:i.seatSelected,unavailable:i.seatUnavailable,hidden:i.seatHidden}[s],l=s==="available"||s==="selected",c=t.useCallback(()=>{l&&r(n)},[n,r,l]),f=t.useCallback(x=>{h(n,x);const C=x.target.getStage();C&&l&&(C.container().style.cursor="pointer")},[n,h,l]),b=t.useCallback(x=>{u();const C=x.target.getStage();C&&(C.container().style.cursor="grab")},[u]),g={x:n.position.x,y:n.position.y,fill:p,stroke:"#ffffff",strokeWidth:1,onClick:c,onTap:c,onMouseEnter:f,onMouseLeave:b};return n.shape==="circle"?a.jsx(X.Circle,{...g,radius:12}):a.jsx(X.Rect,{...g,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:n.shape==="square"?0:4})});Ee.displayName="ViewerSeat";const Fe=t.memo(({stage:n,stageColor:s})=>{const i=u=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[u||"stage"]||"🎭",r=n.config.color||s,h=i(n.config.objectType);return a.jsxs(X.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[a.jsx(X.Rect,{width:n.config.width,height:n.config.height,fill:r+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),a.jsx(X.Text,{text:h,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),a.jsx(X.Text,{text:n.config.label,x:0,y:n.config.height*.4,width:n.config.width,height:n.config.height*.6,fontSize:20,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]})});Fe.displayName="ViewerStage";const ke=t.memo(({floors:n,currentFloorId:s,onFloorChange:i,showAllOption:r,allLabel:h,position:u,className:o})=>{const w=t.useMemo(()=>[...n].sort((b,g)=>b.order-g.order),[n]),l={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[u]},c={padding:"10px 16px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease",minHeight:"44px",touchAction:"manipulation"},f={...c,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return a.jsxs("div",{className:o,style:l,children:[r&&a.jsx("button",{type:"button",onClick:()=>i(null),style:s===null?f:c,children:h}),w.map(b=>a.jsx("button",{type:"button",onClick:()=>i(b.id),style:s===b.id?f:c,children:b.name},b.id))]})});ke.displayName="FloorSelectorBar";const Ie=t.memo(({scale:n,minScale:s,maxScale:i,onZoomIn:r,onZoomOut:h,position:u,className:o})=>{const p={position:"absolute",display:"flex",flexDirection:"column",gap:"4px",padding:"8px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[u]},l={width:"44px",height:"44px",minWidth:"44px",minHeight:"44px",fontSize:"22px",fontWeight:"bold",border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.2s ease",touchAction:"manipulation"},c={...l,opacity:.4,cursor:"not-allowed"},f=n<i,b=n>s;return a.jsxs("div",{className:o,style:p,children:[a.jsx("button",{type:"button",onClick:r,disabled:!f,style:f?l:c,title:"Zoom In",children:"+"}),a.jsx("button",{type:"button",onClick:h,disabled:!b,style:b?l:c,title:"Zoom Out",children:"−"})]})});Ie.displayName="ZoomControls";const Le=t.memo(({visible:n,x:s,y:i,seat:r,currency:h,state:u})=>{if(!n||!r)return null;const o=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),w={position:"fixed",left:`${s+15}px`,top:`${i+15}px`,zIndex:1e3,pointerEvents:"none"},p={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},l={color:"#9ca3af",marginRight:"4px"},c={fontWeight:600},f={color:"#4ade80",fontWeight:600},b={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return a.jsx("div",{style:w,children:a.jsxs("div",{style:p,children:[r.sectionName&&a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:l,children:"Section:"}),a.jsx("span",{style:{...c,color:"#3b82f6"},children:r.sectionName})]}),a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:l,children:"Seat:"}),a.jsx("span",{style:c,children:o})]}),r.price!==void 0&&r.price>0&&u==="available"&&a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:l,children:"Price:"}),a.jsxs("span",{style:f,children:[h," ",r.price.toFixed(2)]})]}),a.jsxs("div",{style:b,children:["Status: ",u]})]})})});Le.displayName="SeatTooltip";const at=({config:n,configUrl:s,floorId:i,onFloorChange:r,reservedSeats:h=[],unavailableSeats:u=[],selectedSeats:o,myReservedSeats:w=[],onSeatSelect:p,onSeatDeselect:l,onSelectionChange:c,colorOverrides:f,showTooltip:b=!0,zoomEnabled:g=!0,className:x="",onConfigLoad:C,onError:j,showFloorSelector:E,floorSelectorPosition:M="top-left",floorSelectorClassName:F,showAllFloorsOption:z=!0,allFloorsLabel:L="All",fitToView:D=!0,fitPadding:N=40,showZoomControls:ee=!0,zoomControlsPosition:ze="bottom-right",zoomControlsClassName:Ne,minZoom:be,maxZoom:Y=3,zoomStep:te=.25,touchEnabled:Ae=!0})=>{const ue=t.useRef(null),xe=t.useRef(null),k=Re(xe),[$,Se]=t.useState(new Set),[I,H]=t.useState(1),[T,B]=t.useState({x:0,y:0}),[Xe,Ye]=t.useState(null),[Pe,We]=t.useState(1),ne=t.useRef({width:0,height:0}),[q,ve]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Be,loading:Ue,error:_}=Ce(s),S=n||Be,de=i!==void 0,A=de?i||null:Xe,se=o!==void 0,$e=t.useCallback(e=>{de||Ye(e),r?.(e)},[de,r]),he=S?.floors||[],Oe=E!==void 0?E:he.length>1,re=t.useMemo(()=>S?{...S.colors,...f}:{...Me,...f},[S,f]),O=t.useMemo(()=>{if(!S)return[];let e=S.seats.filter(d=>d.state!=="hidden");return A&&(e=e.filter(d=>d.floorId===A||!d.floorId&&A==="floor_default")),e},[S,A]),oe=t.useMemo(()=>S?.stages?A?S.stages.filter(e=>e.floorId===A||!e.floorId&&A==="floor_default"):S.stages:[],[S,A]),P=t.useMemo(()=>{if(!S||O.length===0&&oe.length===0)return null;const e=12;let d=1/0,v=1/0,y=-1/0,m=-1/0;return O.forEach(R=>{d=Math.min(d,R.position.x-e),v=Math.min(v,R.position.y-e),y=Math.max(y,R.position.x+e),m=Math.max(m,R.position.y+e)}),oe.forEach(R=>{d=Math.min(d,R.position.x),v=Math.min(v,R.position.y),y=Math.max(y,R.position.x+(R.config?.width||200)),m=Math.max(m,R.position.y+(R.config?.height||100))}),{minX:d,minY:v,maxX:y,maxY:m,width:y-d,height:m-v}},[S,O,oe]);t.useEffect(()=>{if(!D||!S||!P||k.width===0||k.height===0)return;const e=Math.abs(k.width-ne.current.width),d=Math.abs(k.height-ne.current.height);if(!(ne.current.width===0)&&e<10&&d<10)return;ne.current=k;const y=k.width,m=k.height,R=y-N*2,Z=m-N*2,ie=R/P.width,ge=Z/P.height,ae=Math.min(ie,ge,Y),et=P.minX+P.width/2,tt=P.minY+P.height/2,nt=y/2,st=m/2,rt=nt-et*ae,ot=st-tt*ae;H(ae),B({x:rt,y:ot}),We(ae)},[D,S,P,N,Y,k,A]);const U=t.useMemo(()=>{const e=new Set(h),d=new Set(u),v=new Set(w);return{reserved:e,unavailable:d,myReserved:v}},[h,u,w]),fe=t.useMemo(()=>o?new Set(o):null,[o]),G=t.useCallback(e=>{const d=e.id,v=e.seatNumber||"";return U.unavailable.has(d)||U.unavailable.has(v)?"unavailable":U.reserved.has(d)||U.reserved.has(v)?"reserved":U.myReserved.has(d)||U.myReserved.has(v)||$.has(d)?"selected":e.state},[U,$]);t.useEffect(()=>{S&&C&&C(S)},[S,C]),t.useEffect(()=>{_&&j&&j(_)},[_,j]),t.useEffect(()=>{se&&fe&&Se(fe)},[se,fe]);const Ve=t.useCallback(e=>{const d=G(e);if(d!=="available"&&d!=="selected")return;const v=$.has(e.id);se||Se(y=>{const m=new Set(y);return v?m.delete(e.id):m.add(e.id),m}),v?l?.(e):(p?.(e),p||console.log("Seat selected:",e))},[G,$,se,p,l]),K=t.useMemo(()=>S?O.filter(e=>$.has(e.id)):[],[O,$]);t.useEffect(()=>{c?.(K)},[K,c]);const V=be!==void 0?be:Pe,He=t.useCallback(()=>{if(!g)return;const e=Math.min(I+te,Y);if(e!==I){const d=k.width||S?.canvas.width||800,v=k.height||S?.canvas.height||600,y=d/2,m=v/2,R={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-R.x*e,y:m-R.y*e})}},[g,I,te,Y,k,S,T]),qe=t.useCallback(()=>{if(!g)return;const e=Math.max(I-te,V);if(e!==I){const d=k.width||S?.canvas.width||800,v=k.height||S?.canvas.height||600,y=d/2,m=v/2,R={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-R.x*e,y:m-R.y*e})}},[g,I,te,V,k,S,T]),_e=t.useCallback(e=>{B({x:e.target.x(),y:e.target.y()})},[]),Ge=t.useCallback(e=>{if(!g)return;e.evt.preventDefault();const d=ue.current;if(!d)return;const v=d.scaleX(),y=d.getPointerPosition();if(!y)return;const m=1.1,R=e.evt.deltaY>0?v/m:v*m,Z=Math.min(Math.max(R,V),Y),ie={x:(y.x-T.x)/v,y:(y.y-T.y)/v},ge={x:y.x-ie.x*Z,y:y.y-ie.y*Z};H(Z),B(ge)},[g,T,V,Y]);je(ue,{enabled:Ae&&g,minScale:V,maxScale:Y,currentScale:I,currentPosition:T,onScaleChange:(e,d)=>{H(e),B(d)},onPositionChange:e=>{B(e)}});const Ke=t.useCallback((e,d)=>{if(!b)return;const v=d.target.getStage();if(!v)return;const y=v.getPointerPosition();if(!y)return;const m=v.container().getBoundingClientRect();ve({visible:!0,x:m.left+y.x,y:m.top+y.y,seat:e,state:G(e)})},[b,G]),Ze=t.useCallback(()=>{ve(e=>({...e,visible:!1}))},[]);if(Ue)return a.jsx("div",{className:`flex items-center justify-center h-full ${x}`,children:a.jsx("p",{children:"Loading seat map..."})});if(_)return a.jsx("div",{className:`flex items-center justify-center h-full ${x}`,children:a.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",_.message]})});if(!S)return a.jsx("div",{className:`flex items-center justify-center h-full ${x}`,children:a.jsx("p",{children:"No configuration provided"})});const Je=k.width||S.canvas.width,Qe=k.height||S.canvas.height;return a.jsxs("div",{ref:xe,className:`relative ${x}`,style:{width:"100%",height:"100%"},children:[Oe&&he.length>0&&a.jsx(ke,{floors:he,currentFloorId:A,onFloorChange:$e,showAllOption:z,allLabel:L,position:M,className:F}),a.jsxs(X.Stage,{ref:ue,width:Je,height:Qe,scaleX:I,scaleY:I,x:T.x,y:T.y,draggable:!0,onDragEnd:_e,onWheel:Ge,style:{backgroundColor:S.canvas.backgroundColor,cursor:"grab"},children:[a.jsx(X.Layer,{listening:!1,children:oe.map(e=>a.jsx(Fe,{stage:e,stageColor:re.stageColor},e.id))}),a.jsx(X.Layer,{children:O.map(e=>a.jsx(Ee,{seat:e,state:G(e),colors:re,onClick:Ve,onMouseEnter:Ke,onMouseLeave:Ze},e.id))})]}),b&&a.jsx(Le,{visible:q.visible,x:q.x,y:q.y,seat:q.seat,currency:re.currency,state:q.state}),ee&&g&&a.jsx(Ie,{scale:I,minScale:V,maxScale:Y,onZoomIn:He,onZoomOut:qe,position:ze,className:Ne}),K.length>0&&a.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[a.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",K.length,")"]}),a.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:K.map(e=>a.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${re.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let Q=null;function ct(n){Q=n}function pe(){if(!Q)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return Q}function le(){return Q!==null}function lt(){Q=null}function J(n,s){if(n.length!==s.length)return!1;const i=[...n].sort(),r=[...s].sort();return i.every((h,u)=>h===r[u])}function we(n,s){const i=[],r=[],h=[];return Object.entries(n).forEach(([u,o])=>{o&&typeof o=="object"&&o.state&&(o.state==="unavailable"?h.push(u):o.state==="reserved"&&(s&&o.userId===s?i.push(u):r.push(u)))}),{myReserved:i.sort(),otherReserved:r.sort(),unavailable:h.sort()}}const ce={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function Te(n){const{seatMapId:s,currentUserId:i,enabled:r=!0,onStateChange:h,onError:u}=n,o=t.useRef({...ce}),w=t.useRef(h),p=t.useRef(u),l=t.useRef(i);w.current=h,p.current=u,l.current=i;const c=t.useCallback(x=>{if(!r||!s)return o.current={...ce,loading:!1},()=>{};if(!le())return o.current={...ce,loading:!1,error:new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")},()=>{};const C=pe(),j=W.ref(C,`seat_states/${s}`),E=F=>{const L=F.val()||{},D=we(L,l.current),N=o.current;(N.loading||!J(N.myReservedSeats,D.myReserved)||!J(N.otherReservedSeats,D.otherReserved)||!J(N.unavailableSeats,D.unavailable))&&(o.current={states:L,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:D.myReserved,otherReservedSeats:D.otherReserved,unavailableSeats:D.unavailable},w.current?.(L),x())},M=F=>{o.current={...o.current,loading:!1,error:F},p.current?.(F),x()};return W.onValue(j,E,M),()=>{W.off(j)}},[s,r]),f=t.useCallback(()=>o.current,[]),b=t.useCallback(()=>ce,[]),g=t.useSyncExternalStore(c,f,b);return t.useEffect(()=>{if(g.states&&i!==void 0){const x=we(g.states,i),C=o.current;(!J(C.myReservedSeats,x.myReserved)||!J(C.otherReservedSeats,x.otherReserved))&&(o.current={...C,myReservedSeats:x.myReserved,otherReservedSeats:x.otherReserved,unavailableSeats:x.unavailable,lastUpdated:Date.now()})}},[i]),{states:g.states,loading:g.loading,error:g.error,lastUpdated:g.lastUpdated,myReservedSeats:g.myReservedSeats,otherReservedSeats:g.otherReservedSeats,unavailableSeats:g.unavailableSeats,reservedSeats:g.otherReservedSeats}}function De(n){const{seatMapId:s,enabled:i=!0,subscribeToChanges:r=!1,onConfigLoad:h,onError:u}=n,[o,w]=t.useState(null),[p,l]=t.useState(!0),[c,f]=t.useState(null),b=t.useRef(h),g=t.useRef(u);b.current=h,g.current=u;const x=t.useCallback(async()=>{if(!s)return;if(!le()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),l(!1);return}const C=pe(),j=W.ref(C,`seatmaps/${s}`);try{l(!0),f(null);const M=(await W.get(j)).val();if(M){const F=it.fromFirebaseSeatMap(M);w(F),b.current?.(F)}else f(new Error(`Seat map ${s} not found in Firebase`))}catch(E){const M=E instanceof Error?E:new Error("Unknown error");f(M),g.current?.(M)}finally{l(!1)}},[s]);return t.useEffect(()=>{if(!i||!s){l(!1);return}if(x(),r&&le()){const C=pe(),j=W.ref(C,`seatmaps/${s}/meta/updated_at`);let E=!0,M=null;const F=z=>{if(E){E=!1,M=z.val();return}const L=z.val();z.exists()&&L!==M&&(M=L,x())};return W.onValue(j,F),()=>{W.off(j)}}},[s,i,r]),{config:o,loading:p,error:c,refetch:x}}function ut(n){const{seatMapId:s,userId:i,enabled:r=!0,subscribeToDesignChanges:h=!1,onConfigLoad:u,onStateChange:o,onError:w}=n,{config:p,loading:l,error:c,refetch:f}=De({seatMapId:s,enabled:r,subscribeToChanges:h,onConfigLoad:u,onError:w}),{states:b,loading:g,error:x,lastUpdated:C,myReservedSeats:j,otherReservedSeats:E,unavailableSeats:M,reservedSeats:F}=Te({seatMapId:s,currentUserId:i,enabled:r,onStateChange:o,onError:w});return{config:p,loading:l||g,error:c||x,myReservedSeats:j,otherReservedSeats:E,unavailableSeats:M,reservedSeats:F,seatStates:b,lastUpdated:C,refetch:f}}exports.DEFAULT_COLORS=Me;exports.SeatMapViewer=at;exports.clearFirebaseInstance=lt;exports.initializeFirebaseForViewer=ct;exports.isFirebaseInitialized=le;exports.useConfigFetcher=Ce;exports.useContainerSize=Re;exports.useFirebaseConfig=De;exports.useFirebaseSeatStates=Te;exports.useRealtimeSeatMap=ut;exports.useTouchGestures=je;