@zonetrix/viewer 2.10.8 → 2.11.1

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.
@@ -21,14 +21,14 @@ export interface SeatMapViewerProps {
21
21
  onConfigLoad?: (config: SeatMapConfig) => void;
22
22
  onError?: (error: Error) => void;
23
23
  showFloorSelector?: boolean;
24
- floorSelectorPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
24
+ floorSelectorPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
25
25
  floorSelectorClassName?: string;
26
26
  showAllFloorsOption?: boolean;
27
27
  allFloorsLabel?: string;
28
28
  fitToView?: boolean;
29
29
  fitPadding?: number;
30
30
  showZoomControls?: boolean;
31
- zoomControlsPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
31
+ zoomControlsPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
32
32
  zoomControlsClassName?: string;
33
33
  /**
34
34
  * Minimum zoom level.
package/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@ export { useConfigFetcher } from './hooks/useConfigFetcher';
6
6
  export { useContainerSize } from './hooks/useContainerSize';
7
7
  export { useTouchGestures } from './hooks/useTouchGestures';
8
8
  export { useFirebaseSeatStates } from './hooks/useFirebaseSeatStates';
9
- export type { UseFirebaseSeatStatesOptions, UseFirebaseSeatStatesResult } from './hooks/useFirebaseSeatStates';
9
+ export type { UseFirebaseSeatStatesOptions, UseFirebaseSeatStatesResult, } from './hooks/useFirebaseSeatStates';
10
10
  export { useFirebaseConfig } from './hooks/useFirebaseConfig';
11
- export type { UseFirebaseConfigOptions, UseFirebaseConfigResult } from './hooks/useFirebaseConfig';
11
+ export type { UseFirebaseConfigOptions, UseFirebaseConfigResult, } from './hooks/useFirebaseConfig';
12
12
  export { useRealtimeSeatMap } from './hooks/useRealtimeSeatMap';
13
- export type { UseRealtimeSeatMapOptions, UseRealtimeSeatMapResult } from './hooks/useRealtimeSeatMap';
13
+ export type { UseRealtimeSeatMapOptions, UseRealtimeSeatMapResult, } from './hooks/useRealtimeSeatMap';
14
14
  export { initializeFirebaseForViewer, isFirebaseInitialized, clearFirebaseInstance, } from './firebase/client';
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"),X=require("react-konva"),W=require("firebase/database"),at=require("@zonetrix/shared");function Ce(n){const[s,a]=t.useState(null),[r,h]=t.useState(!1),[u,o]=t.useState(null),y=async()=>{if(n){h(!0),o(null);try{const b=await fetch(n);if(!b.ok)throw new Error(`Failed to fetch config: ${b.statusText}`);const l=await b.json();a(l)}catch(b){const l=b instanceof Error?b:new Error("Unknown error occurred");o(l),console.error("Failed to fetch seat map config:",l)}finally{h(!1)}}};return t.useEffect(()=>{y()},[n]),{config:s,loading:r,error:u,refetch:y}}function Re(n){const[s,a]=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&&a({width:h,height:u});const o=new ResizeObserver(y=>{const b=y[0];if(!b)return;const{width:l,height:c}=b.contentRect;l>0&&c>0&&a(f=>f.width===l&&f.height===c?f:{width:l,height:c})});return o.observe(r),()=>{o.disconnect()}},[n]),s}function me(n,s){return Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2))}function we(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function je(n,s){const a=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(),y=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};a.current=me(f,g),r.current=we(f,g),h.current=s.currentScale}},b=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=me(f,g),p=we(f,g);if(a.current!==null&&r.current!==null){const R=m/a.current,E=Math.min(Math.max(s.currentScale*R,s.minScale),s.maxScale),F=o.getBoundingClientRect(),j=p.x-F.left,M=p.y-F.top,D=s.currentScale,L={x:(j-s.currentPosition.x)/D,y:(M-s.currentPosition.y)/D},z=p.x-r.current.x,A=p.y-r.current.y,O={x:j-L.x*E+z,y:M-L.y*E+A};s.onScaleChange(E,O),a.current=m,r.current=p}},l=c=>{c.touches.length<2&&(a.current=null,r.current=null)};return o.addEventListener("touchstart",y,{passive:!1}),o.addEventListener("touchmove",b,{passive:!1}),o.addEventListener("touchend",l),()=>{o.removeEventListener("touchstart",y),o.removeEventListener("touchmove",b),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:a,onClick:r,onMouseEnter:h,onMouseLeave:u})=>{const b={available:a.seatAvailable,reserved:a.seatReserved,selected:a.seatSelected,unavailable:a.seatUnavailable,hidden:a.seatHidden}[s],l=s==="available"||s==="selected",c=t.useCallback(()=>{l&&r(n)},[n,r,l]),f=t.useCallback(p=>{h(n,p);const R=p.target.getStage();R&&l&&(R.container().style.cursor="pointer")},[n,h,l]),g=t.useCallback(p=>{u();const R=p.target.getStage();R&&(R.container().style.cursor="grab")},[u]),m={x:n.position.x,y:n.position.y,fill:b,stroke:"#ffffff",strokeWidth:1,onClick:c,onTap:c,onMouseEnter:f,onMouseLeave:g};return n.shape==="circle"?i.jsx(X.Circle,{...m,radius:12}):i.jsx(X.Rect,{...m,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 a=u=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[u||"stage"]||"🎭",r=n.config.color||s,h=a(n.config.objectType);return i.jsxs(X.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[i.jsx(X.Rect,{width:n.config.width,height:n.config.height,fill:r+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),i.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"}),i.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:a,showAllOption:r,allLabel:h,position:u,className:o})=>{const y=t.useMemo(()=>[...n].sort((g,m)=>g.order-m.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 i.jsxs("div",{className:o,style:l,children:[r&&i.jsx("button",{type:"button",onClick:()=>a(null),style:s===null?f:c,children:h}),y.map(g=>i.jsx("button",{type:"button",onClick:()=>a(g.id),style:s===g.id?f:c,children:g.name},g.id))]})});ke.displayName="FloorSelectorBar";const Ie=t.memo(({scale:n,minScale:s,maxScale:a,onZoomIn:r,onZoomOut:h,position:u,className:o})=>{const b={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<a,g=n>s;return i.jsxs("div",{className:o,style:b,children:[i.jsx("button",{type:"button",onClick:r,disabled:!f,style:f?l:c,title:"Zoom In",children:"+"}),i.jsx("button",{type:"button",onClick:h,disabled:!g,style:g?l:c,title:"Zoom Out",children:"−"})]})});Ie.displayName="ZoomControls";const Le=t.memo(({visible:n,x:s,y:a,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"),y={position:"fixed",left:`${s+15}px`,top:`${a+15}px`,zIndex:1e3,pointerEvents:"none"},b={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},g={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return i.jsx("div",{style:y,children:i.jsxs("div",{style:b,children:[r.sectionName&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Section:"}),i.jsx("span",{style:{...c,color:"#3b82f6"},children:r.sectionName})]}),i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Seat:"}),i.jsx("span",{style:c,children:o})]}),r.price!==void 0&&r.price>0&&u==="available"&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Price:"}),i.jsxs("span",{style:f,children:[h," ",r.price.toFixed(2)]})]}),i.jsxs("div",{style:g,children:["Status: ",u]})]})})});Le.displayName="SeatTooltip";const ct=({config:n,configUrl:s,floorId:a,onFloorChange:r,reservedSeats:h=[],otherReservedSeats:u,unavailableSeats:o=[],selectedSeats:y,myReservedSeats:b=[],onSeatSelect:l,onSeatDeselect:c,onSelectionChange:f,colorOverrides:g,showTooltip:m=!0,zoomEnabled:p=!0,className:R="",onConfigLoad:E,onError:F,showFloorSelector:j,floorSelectorPosition:M="top-left",floorSelectorClassName:D,showAllFloorsOption:L=!0,allFloorsLabel:z="All",fitToView:A=!0,fitPadding:O=40,showZoomControls:ze=!0,zoomControlsPosition:Ne="bottom-right",zoomControlsClassName:Ae,minZoom:be,maxZoom:Y=3,zoomStep:ee=.25,touchEnabled:Xe=!0})=>{const xe=u!==void 0?u:h,le=t.useRef(null),Se=t.useRef(null),k=Re(Se),[U,ve]=t.useState(new Set),[I,q]=t.useState(1),[T,B]=t.useState({x:0,y:0}),[Ye,Pe]=t.useState(null),[We,Be]=t.useState(1),te=t.useRef({width:0,height:0}),[_,ye]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:$e,loading:Oe,error:G}=Ce(s),x=n||$e,ue=a!==void 0,N=ue?a||null:Ye,ne=y!==void 0,Ue=t.useCallback(e=>{ue||Pe(e),r?.(e)},[ue,r]),de=x?.floors||[],Ve=j!==void 0?j:de.length>1,se=t.useMemo(()=>x?{...x.colors,...g}:{...Me,...g},[x,g]),V=t.useMemo(()=>{if(!x)return[];let e=x.seats.filter(d=>d.state!=="hidden");return N&&(e=e.filter(d=>d.floorId===N||!d.floorId&&N==="floor_default")),e},[x,N]),re=t.useMemo(()=>x?.stages?N?x.stages.filter(e=>e.floorId===N||!e.floorId&&N==="floor_default"):x.stages:[],[x,N]),P=t.useMemo(()=>{if(!x||V.length===0&&re.length===0)return null;const e=12;let d=1/0,S=1/0,v=-1/0,w=-1/0;return V.forEach(C=>{d=Math.min(d,C.position.x-e),S=Math.min(S,C.position.y-e),v=Math.max(v,C.position.x+e),w=Math.max(w,C.position.y+e)}),re.forEach(C=>{d=Math.min(d,C.position.x),S=Math.min(S,C.position.y),v=Math.max(v,C.position.x+(C.config?.width||200)),w=Math.max(w,C.position.y+(C.config?.height||100))}),{minX:d,minY:S,maxX:v,maxY:w,width:v-d,height:w-S}},[x,V,re]);t.useEffect(()=>{if(!A||!x||!P||k.width===0||k.height===0)return;const e=Math.abs(k.width-te.current.width),d=Math.abs(k.height-te.current.height);if(!(te.current.width===0)&&e<10&&d<10)return;te.current=k;const v=k.width,w=k.height,C=v-O*2,J=w-O*2,oe=C/P.width,fe=J/P.height,ie=Math.min(oe,fe,Y),tt=P.minX+P.width/2,nt=P.minY+P.height/2,st=v/2,rt=w/2,ot=st-tt*ie,it=rt-nt*ie;q(ie),B({x:ot,y:it}),Be(ie)},[A,x,P,O,Y,k,N]);const $=t.useMemo(()=>{const e=new Set(xe),d=new Set(o),S=new Set(b);return{reserved:e,unavailable:d,myReserved:S}},[xe,o,b]),he=t.useMemo(()=>y?new Set(y):null,[y]),K=t.useCallback(e=>{const d=e.id,S=e.seatNumber||"";return $.unavailable.has(d)||$.unavailable.has(S)?"unavailable":$.reserved.has(d)||$.reserved.has(S)?"reserved":$.myReserved.has(d)||$.myReserved.has(S)||U.has(d)?"selected":e.state},[$,U]);t.useEffect(()=>{x&&E&&E(x)},[x,E]),t.useEffect(()=>{G&&F&&F(G)},[G,F]),t.useEffect(()=>{ne&&he&&ve(he)},[ne,he]);const He=t.useCallback(e=>{const d=K(e);if(d!=="available"&&d!=="selected")return;const S=U.has(e.id);ne||ve(v=>{const w=new Set(v);return S?w.delete(e.id):w.add(e.id),w}),S?c?.(e):(l?.(e),l||console.log("Seat selected:",e))},[K,U,ne,l,c]),Z=t.useMemo(()=>x?V.filter(e=>U.has(e.id)):[],[V,U]);t.useEffect(()=>{f?.(Z)},[Z,f]);const H=be!==void 0?be:We,qe=t.useCallback(()=>{if(!p)return;const e=Math.min(I+ee,Y);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,v=d/2,w=S/2,C={x:(v-T.x)/I,y:(w-T.y)/I};q(e),B({x:v-C.x*e,y:w-C.y*e})}},[p,I,ee,Y,k,x,T]),_e=t.useCallback(()=>{if(!p)return;const e=Math.max(I-ee,H);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,v=d/2,w=S/2,C={x:(v-T.x)/I,y:(w-T.y)/I};q(e),B({x:v-C.x*e,y:w-C.y*e})}},[p,I,ee,H,k,x,T]),Ge=t.useCallback(e=>{B({x:e.target.x(),y:e.target.y()})},[]),Ke=t.useCallback(e=>{if(!p)return;e.evt.preventDefault();const d=le.current;if(!d)return;const S=d.scaleX(),v=d.getPointerPosition();if(!v)return;const w=1.1,C=e.evt.deltaY>0?S/w:S*w,J=Math.min(Math.max(C,H),Y),oe={x:(v.x-T.x)/S,y:(v.y-T.y)/S},fe={x:v.x-oe.x*J,y:v.y-oe.y*J};q(J),B(fe)},[p,T,H,Y]);je(le,{enabled:Xe&&p,minScale:H,maxScale:Y,currentScale:I,currentPosition:T,onScaleChange:(e,d)=>{q(e),B(d)},onPositionChange:e=>{B(e)}});const Ze=t.useCallback((e,d)=>{if(!m)return;const S=d.target.getStage();if(!S)return;const v=S.getPointerPosition();if(!v)return;const w=S.container().getBoundingClientRect();ye({visible:!0,x:w.left+v.x,y:w.top+v.y,seat:e,state:K(e)})},[m,K]),Je=t.useCallback(()=>{ye(e=>({...e,visible:!1}))},[]);if(Oe)return i.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:i.jsx("p",{children:"Loading seat map..."})});if(G)return i.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:i.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",G.message]})});if(!x)return i.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:i.jsx("p",{children:"No configuration provided"})});const Qe=k.width||x.canvas.width,et=k.height||x.canvas.height;return i.jsxs("div",{ref:Se,className:`relative ${R}`,style:{width:"100%",height:"100%"},children:[Ve&&de.length>0&&i.jsx(ke,{floors:de,currentFloorId:N,onFloorChange:Ue,showAllOption:L,allLabel:z,position:M,className:D}),i.jsxs(X.Stage,{ref:le,width:Qe,height:et,scaleX:I,scaleY:I,x:T.x,y:T.y,draggable:!0,onDragEnd:Ge,onWheel:Ke,style:{backgroundColor:x.canvas.backgroundColor,cursor:"grab"},children:[i.jsx(X.Layer,{listening:!1,children:re.map(e=>i.jsx(Fe,{stage:e,stageColor:se.stageColor},e.id))}),i.jsx(X.Layer,{children:V.map(e=>i.jsx(Ee,{seat:e,state:K(e),colors:se,onClick:He,onMouseEnter:Ze,onMouseLeave:Je},e.id))})]}),m&&i.jsx(Le,{visible:_.visible,x:_.x,y:_.y,seat:_.seat,currency:se.currency,state:_.state}),ze&&p&&i.jsx(Ie,{scale:I,minScale:H,maxScale:Y,onZoomIn:qe,onZoomOut:_e,position:Ne,className:Ae}),Z.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 (",Z.length,")"]}),i.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Z.map(e=>i.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${se.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let Q=null;function lt(n){Q=n}function pe(){if(!Q)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return Q}function ce(){return Q!==null}function ut(){Q=null}function ge(n,s){if(n.length!==s.length)return!1;const a=[...n].sort(),r=[...s].sort();return a.every((h,u)=>h===r[u])}function dt(n,s){const a=[],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?a.push(u):r.push(u)))}),{myReserved:a.sort(),otherReserved:r.sort(),unavailable:h.sort()}}const ae={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function Te(n){const{seatMapId:s,currentUserId:a,enabled:r=!0,onStateChange:h,onError:u}=n,o=t.useRef({...ae}),y=t.useRef(h),b=t.useRef(u),l=t.useRef(a);y.current=h,b.current=u,l.current=a;const c=t.useCallback(p=>{if(!r||!s)return(o.current.loading!==!1||o.current.states!==null)&&(o.current={...ae,loading:!1},p()),()=>{};if(!ce()){const M="Firebase not initialized. Call initializeFirebaseForViewer first.";return o.current.error?.message!==M&&(o.current={...ae,loading:!1,error:new Error(M)},p()),()=>{}}const R=pe(),E=W.ref(R,`seatmaps/${s}/seat_states`),F=M=>{const L=M.val()||{},z=dt(L,l.current),A=o.current;(A.loading||!ge(A.myReservedSeats,z.myReserved)||!ge(A.otherReservedSeats,z.otherReserved)||!ge(A.unavailableSeats,z.unavailable))&&(o.current={states:L,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:z.myReserved,otherReservedSeats:z.otherReserved,unavailableSeats:z.unavailable},y.current?.(L),p())},j=M=>{o.current={...o.current,loading:!1,error:M},b.current?.(M),p()};return W.onValue(E,F,j),()=>{W.off(E)}},[s,r]),f=t.useCallback(()=>o.current,[]),g=t.useCallback(()=>ae,[]),m=t.useSyncExternalStore(c,f,g);return{states:m.states,loading:m.loading,error:m.error,lastUpdated:m.lastUpdated,myReservedSeats:m.myReservedSeats,otherReservedSeats:m.otherReservedSeats,unavailableSeats:m.unavailableSeats,reservedSeats:m.otherReservedSeats}}function De(n){const{seatMapId:s,enabled:a=!0,subscribeToChanges:r=!1,onConfigLoad:h,onError:u}=n,[o,y]=t.useState(null),[b,l]=t.useState(!0),[c,f]=t.useState(null),g=t.useRef(h),m=t.useRef(u);g.current=h,m.current=u;const p=t.useCallback(async()=>{if(!s)return;if(!ce()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),l(!1);return}const R=pe(),E=W.ref(R,`seatmaps/${s}`);try{l(!0),f(null);const j=(await W.get(E)).val();if(j){const M=at.fromFirebaseSeatMap(j);y(M),g.current?.(M)}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{l(!1)}},[s]);return t.useEffect(()=>{if(!a||!s){l(!1);return}if(p(),r&&ce()){const R=pe(),E=W.ref(R,`seatmaps/${s}/meta/updated_at`);let F=!0,j=null;const M=D=>{if(F){F=!1,j=D.val();return}const L=D.val();D.exists()&&L!==j&&(j=L,p())};return W.onValue(E,M),()=>{W.off(E)}}},[s,a,r]),{config:o,loading:b,error:c,refetch:p}}function ht(n){const{seatMapId:s,userId:a,enabled:r=!0,subscribeToDesignChanges:h=!1,onConfigLoad:u,onStateChange:o,onError:y}=n,{config:b,loading:l,error:c,refetch:f}=De({seatMapId:s,enabled:r,subscribeToChanges:h,onConfigLoad:u,onError:y}),{states:g,loading:m,error:p,lastUpdated:R,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:j,reservedSeats:M}=Te({seatMapId:s,currentUserId:a,enabled:r,onStateChange:o,onError:y});return{config:b,loading:l||m,error:c||p,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:j,reservedSeats:M,seatStates:g,lastUpdated:R,refetch:f}}exports.DEFAULT_COLORS=Me;exports.SeatMapViewer=ct;exports.clearFirebaseInstance=ut;exports.initializeFirebaseForViewer=lt;exports.isFirebaseInitialized=ce;exports.useConfigFetcher=Ce;exports.useContainerSize=Re;exports.useFirebaseConfig=De;exports.useFirebaseSeatStates=Te;exports.useRealtimeSeatMap=ht;exports.useTouchGestures=je;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),n=require("react"),D=require("react-konva"),A=require("firebase/database"),lt=require("@zonetrix/shared");function Re(s){const[r,t]=n.useState(null),[o,h]=n.useState(!1),[d,i]=n.useState(null),v=async()=>{if(s){h(!0),i(null);try{const x=await fetch(s);if(!x.ok)throw new Error(`Failed to fetch config: ${x.statusText}`);const c=await x.json();t(c)}catch(x){const c=x instanceof Error?x:new Error("Unknown error occurred");i(c),console.error("Failed to fetch seat map config:",c)}finally{h(!1)}}};return n.useEffect(()=>{v()},[s]),{config:r,loading:o,error:d,refetch:v}}function Me(s){const[r,t]=n.useState({width:0,height:0});return n.useEffect(()=>{const o=s.current;if(!o)return;const{width:h,height:d}=o.getBoundingClientRect();h>0&&d>0&&t({width:h,height:d});const i=new ResizeObserver(v=>{const x=v[0];if(!x)return;const{width:c,height:l}=x.contentRect;c>0&&l>0&&t(g=>g.width===c&&g.height===l?g:{width:c,height:l})});return i.observe(o),()=>{i.disconnect()}},[s]),r}function we(s,r){return Math.sqrt(Math.pow(r.x-s.x,2)+Math.pow(r.y-s.y,2))}function Ce(s,r){return{x:(s.x+r.x)/2,y:(s.y+r.y)/2}}function je(s,r){const t=n.useRef(null),o=n.useRef(null),h=n.useRef(1);n.useEffect(()=>{const d=s.current;if(!d||!r.enabled)return;const i=d.container(),v=l=>{if(l.touches.length===2){l.preventDefault();const g={x:l.touches[0].clientX,y:l.touches[0].clientY},b={x:l.touches[1].clientX,y:l.touches[1].clientY};t.current=we(g,b),o.current=Ce(g,b),h.current=r.currentScale}},x=l=>{if(l.touches.length!==2)return;l.preventDefault();const g={x:l.touches[0].clientX,y:l.touches[0].clientY},b={x:l.touches[1].clientX,y:l.touches[1].clientY},w=we(g,b),p=Ce(g,b);if(t.current!==null&&o.current!==null){const R=w/t.current,F=Math.min(Math.max(r.currentScale*R,r.minScale),r.maxScale),k=i.getBoundingClientRect(),M=p.x-k.left,j=p.y-k.top,E=r.currentScale,I={x:(M-r.currentPosition.x)/E,y:(j-r.currentPosition.y)/E},N=p.x-o.current.x,W=p.y-o.current.y,U={x:M-I.x*F+N,y:j-I.y*F+W};r.onScaleChange(F,U),t.current=w,o.current=p}},c=l=>{l.touches.length<2&&(t.current=null,o.current=null)};return i.addEventListener("touchstart",v,{passive:!1}),i.addEventListener("touchmove",x,{passive:!1}),i.addEventListener("touchend",c),()=>{i.removeEventListener("touchstart",v),i.removeEventListener("touchmove",x),i.removeEventListener("touchend",c)}},[s,r])}const Ee={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Fe=n.memo(({seat:s,state:r,colors:t,onClick:o,onMouseEnter:h,onMouseLeave:d})=>{const x={available:t.seatAvailable,reserved:t.seatReserved,selected:t.seatSelected,unavailable:t.seatUnavailable,hidden:t.seatHidden}[r],c=r==="available"||r==="selected",l=n.useCallback(()=>{c&&o(s)},[s,o,c]),g=n.useCallback(p=>{h(s,p);const R=p.target.getStage();R&&c&&(R.container().style.cursor="pointer")},[s,h,c]),b=n.useCallback(p=>{d();const R=p.target.getStage();R&&(R.container().style.cursor="grab")},[d]),w={x:s.position.x,y:s.position.y,fill:x,stroke:"#ffffff",strokeWidth:1,onClick:l,onTap:l,onMouseEnter:g,onMouseLeave:b};return s.shape==="circle"?a.jsx(D.Circle,{...w,radius:12}):a.jsx(D.Rect,{...w,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:s.shape==="square"?0:4})});Fe.displayName="ViewerSeat";const ke=n.memo(({stage:s,stageColor:r})=>{const t=s.config,o=t.shape||"rectangle",h=t.showLabel!==!1,d=t.color||r,i=t.width/t.height,v=i<.5,x=i>2;let c;v?c=t.width*.25:x?c=t.height*.35:c=Math.min(t.width,t.height)*.25;const l=t.label?.length||6,w=t.width*.85/l*1.5,p=Math.max(10,Math.min(24,Math.min(c,w))),R=4,F=Math.max(20,t.width-R*2),k=(t.width-F)/2,M={fill:d+"80",stroke:"#ffffff",strokeWidth:2,perfectDrawEnabled:!1,hitStrokeWidth:0},j=()=>{switch(o){case"circle":{const E=Math.min(t.width,t.height)/2;return a.jsx(D.Circle,{x:t.width/2,y:t.height/2,radius:E,...M})}case"triangle":{const E=Math.min(t.width,t.height)/2;return a.jsx(D.RegularPolygon,{x:t.width/2,y:t.height/2,sides:3,radius:E,rotation:-90,...M})}case"arrow":{const E=t.width/24,I=t.height/24,N=`M${9*E},${18*I} v${-8*I} H${5*E} l${7*E},${-7*I} l${7*E},${7*I} h${-4*E} v${8*I} Z`;return a.jsx(D.Path,{data:N,...M})}default:return a.jsx(D.Rect,{width:t.width,height:t.height,cornerRadius:10,...M})}};return a.jsxs(D.Group,{x:s.position.x,y:s.position.y,rotation:t.rotation||0,children:[j(),h&&a.jsx(D.Text,{text:t.label,x:k,y:R,width:F,height:t.height-R*2,fontSize:p,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle",wrap:"word",ellipsis:!0})]})});ke.displayName="ViewerStage";const Ie=n.memo(({text:s})=>a.jsx(D.Text,{x:s.position.x,y:s.position.y,text:s.config.text,fontSize:s.config.fontSize,fill:s.config.color,rotation:s.config.rotation||0,listening:!1}));Ie.displayName="ViewerText";const Le=n.memo(({floors:s,currentFloorId:r,onFloorChange:t,showAllOption:o,allLabel:h,position:d,className:i})=>{const v=n.useMemo(()=>[...s].sort((b,w)=>b.order-w.order),[s]),c={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]},l={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"},g={...l,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return a.jsxs("div",{className:i,style:c,children:[o&&a.jsx("button",{type:"button",onClick:()=>t(null),style:r===null?g:l,children:h}),v.map(b=>a.jsx("button",{type:"button",onClick:()=>t(b.id),style:r===b.id?g:l,children:b.name},b.id))]})});Le.displayName="FloorSelectorBar";const Te=n.memo(({scale:s,minScale:r,maxScale:t,onZoomIn:o,onZoomOut:h,position:d,className:i})=>{const x={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]},c={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"},l={...c,opacity:.4,cursor:"not-allowed"},g=s<t,b=s>r;return a.jsxs("div",{className:i,style:x,children:[a.jsx("button",{type:"button",onClick:o,disabled:!g,style:g?c:l,title:"Zoom In",children:"+"}),a.jsx("button",{type:"button",onClick:h,disabled:!b,style:b?c:l,title:"Zoom Out",children:"−"})]})});Te.displayName="ZoomControls";const ze=n.memo(({visible:s,x:r,y:t,seat:o,currency:h,state:d})=>{if(!s||!o)return null;const i=o.seatNumber||(o.rowLabel&&o.columnLabel?`${o.rowLabel}-${o.columnLabel}`:"N/A"),v={position:"fixed",left:`${r+15}px`,top:`${t+15}px`,zIndex:1e3,pointerEvents:"none"},x={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"},c={color:"#9ca3af",marginRight:"4px"},l={fontWeight:600},g={color:"#4ade80",fontWeight:600},b={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return a.jsx("div",{style:v,children:a.jsxs("div",{style:x,children:[o.sectionName&&a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:c,children:"Section:"}),a.jsx("span",{style:{...l,color:"#3b82f6"},children:o.sectionName})]}),a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:c,children:"Seat:"}),a.jsx("span",{style:l,children:i})]}),o.price!==void 0&&o.price>0&&d==="available"&&a.jsxs("div",{style:{marginBottom:"4px"},children:[a.jsx("span",{style:c,children:"Price:"}),a.jsxs("span",{style:g,children:[h," ",o.price.toFixed(2)]})]}),a.jsxs("div",{style:b,children:["Status: ",d]})]})})});ze.displayName="SeatTooltip";const ut=({config:s,configUrl:r,floorId:t,onFloorChange:o,reservedSeats:h=[],otherReservedSeats:d,unavailableSeats:i=[],selectedSeats:v,myReservedSeats:x=[],onSeatSelect:c,onSeatDeselect:l,onSelectionChange:g,colorOverrides:b,showTooltip:w=!0,zoomEnabled:p=!0,className:R="",onConfigLoad:F,onError:k,showFloorSelector:M,floorSelectorPosition:j="top-left",floorSelectorClassName:E,showAllFloorsOption:I=!0,allFloorsLabel:N="All",fitToView:W=!0,fitPadding:U=40,showZoomControls:$e=!0,zoomControlsPosition:We="bottom-right",zoomControlsClassName:Pe,minZoom:be,maxZoom:P=3,zoomStep:te=.25,touchEnabled:Xe=!0})=>{const Se=d!==void 0?d:h,ue=n.useRef(null),me=n.useRef(null),L=Me(me),[H,ye]=n.useState(new Set),[T,G]=n.useState(1),[$,Y]=n.useState({x:0,y:0}),[Ae,Ye]=n.useState(null),[Be,Ve]=n.useState(1),ne=n.useRef({width:0,height:0}),[Z,ve]=n.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Ue,loading:He,error:K}=Re(r),f=s||Ue,de=t!==void 0,z=de?t||null:Ae,se=v!==void 0,Oe=n.useCallback(e=>{de||Ye(e),o?.(e)},[de,o]),he=f?.floors||[],qe=M!==void 0?M:he.length>1,re=n.useMemo(()=>f?{...f.colors,...b}:{...Ee,...b},[f,b]),O=n.useMemo(()=>{if(!f)return[];let e=f.seats.filter(u=>u.state!=="hidden");return z&&(e=e.filter(u=>u.floorId===z||!u.floorId&&z==="floor_default")),e},[f,z]),oe=n.useMemo(()=>f?.stages?z?f.stages.filter(e=>e.floorId===z||!e.floorId&&z==="floor_default"):f.stages:[],[f,z]),ie=n.useMemo(()=>f?.texts?z?f.texts.filter(e=>e.floorId===z||!e.floorId&&z==="floor_default"):f.texts:[],[f,z]),X=n.useMemo(()=>{if(!f||O.length===0&&oe.length===0&&ie.length===0)return null;const e=12;let u=1/0,S=1/0,m=-1/0,C=-1/0;return O.forEach(y=>{u=Math.min(u,y.position.x-e),S=Math.min(S,y.position.y-e),m=Math.max(m,y.position.x+e),C=Math.max(C,y.position.y+e)}),oe.forEach(y=>{u=Math.min(u,y.position.x),S=Math.min(S,y.position.y),m=Math.max(m,y.position.x+(y.config?.width||200)),C=Math.max(C,y.position.y+(y.config?.height||100))}),ie.forEach(y=>{const V=y.config.text.length*y.config.fontSize*.6,_=y.config.fontSize;u=Math.min(u,y.position.x),S=Math.min(S,y.position.y),m=Math.max(m,y.position.x+V),C=Math.max(C,y.position.y+_)}),{minX:u,minY:S,maxX:m,maxY:C,width:m-u,height:C-S}},[f,O,oe,ie]);n.useEffect(()=>{if(!W||!f||!X||L.width===0||L.height===0)return;const e=Math.abs(L.width-ne.current.width),u=Math.abs(L.height-ne.current.height);if(!(ne.current.width===0)&&e<10&&u<10)return;ne.current=L;const m=L.width,C=L.height,y=m-U*2,V=C-U*2,_=y/X.width,ge=V/X.height,ae=Math.min(_,ge,P),st=X.minX+X.width/2,rt=X.minY+X.height/2,ot=m/2,it=C/2,at=ot-st*ae,ct=it-rt*ae;G(ae),Y({x:at,y:ct}),Ve(ae)},[W,f,X,U,P,L,z]);const B=n.useMemo(()=>{const e=new Set(Se),u=new Set(i),S=new Set(x);return{reserved:e,unavailable:u,myReserved:S}},[Se,i,x]),fe=n.useMemo(()=>v?new Set(v):null,[v]),J=n.useCallback(e=>{const u=e.id,S=e.seatNumber||"";return B.unavailable.has(u)||B.unavailable.has(S)?"unavailable":B.reserved.has(u)||B.reserved.has(S)?"reserved":B.myReserved.has(u)||B.myReserved.has(S)||H.has(u)?"selected":e.state},[B,H]);n.useEffect(()=>{f&&F&&F(f)},[f,F]),n.useEffect(()=>{K&&k&&k(K)},[K,k]),n.useEffect(()=>{se&&fe&&ye(fe)},[se,fe]);const _e=n.useCallback(e=>{const u=J(e);if(u!=="available"&&u!=="selected")return;const S=H.has(e.id);se||ye(m=>{const C=new Set(m);return S?C.delete(e.id):C.add(e.id),C}),S?l?.(e):(c?.(e),c||console.log("Seat selected:",e))},[J,H,se,c,l]),Q=n.useMemo(()=>f?O.filter(e=>H.has(e.id)):[],[O,H]);n.useEffect(()=>{g?.(Q)},[Q,g]);const q=be!==void 0?be:Be,Ge=n.useCallback(()=>{if(!p)return;const e=Math.min(T+te,P);if(e!==T){const u=L.width||f?.canvas.width||800,S=L.height||f?.canvas.height||600,m=u/2,C=S/2,y={x:(m-$.x)/T,y:(C-$.y)/T};G(e),Y({x:m-y.x*e,y:C-y.y*e})}},[p,T,te,P,L,f,$]),Ze=n.useCallback(()=>{if(!p)return;const e=Math.max(T-te,q);if(e!==T){const u=L.width||f?.canvas.width||800,S=L.height||f?.canvas.height||600,m=u/2,C=S/2,y={x:(m-$.x)/T,y:(C-$.y)/T};G(e),Y({x:m-y.x*e,y:C-y.y*e})}},[p,T,te,q,L,f,$]),Ke=n.useCallback(e=>{Y({x:e.target.x(),y:e.target.y()})},[]),Je=n.useCallback(e=>{if(!p)return;e.evt.preventDefault();const u=ue.current;if(!u)return;const S=u.scaleX(),m=u.getPointerPosition();if(!m)return;const C=1.1,y=e.evt.deltaY>0?S/C:S*C,V=Math.min(Math.max(y,q),P),_={x:(m.x-$.x)/S,y:(m.y-$.y)/S},ge={x:m.x-_.x*V,y:m.y-_.y*V};G(V),Y(ge)},[p,$,q,P]);je(ue,{enabled:Xe&&p,minScale:q,maxScale:P,currentScale:T,currentPosition:$,onScaleChange:(e,u)=>{G(e),Y(u)},onPositionChange:e=>{Y(e)}});const Qe=n.useCallback((e,u)=>{if(!w)return;const S=u.target.getStage();if(!S)return;const m=S.getPointerPosition();if(!m)return;const C=S.container().getBoundingClientRect();ve({visible:!0,x:C.left+m.x,y:C.top+m.y,seat:e,state:J(e)})},[w,J]),et=n.useCallback(()=>{ve(e=>({...e,visible:!1}))},[]);if(He)return a.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:a.jsx("p",{children:"Loading seat map..."})});if(K)return a.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:a.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",K.message]})});if(!f)return a.jsx("div",{className:`flex items-center justify-center h-full ${R}`,children:a.jsx("p",{children:"No configuration provided"})});const tt=L.width||f.canvas.width,nt=L.height||f.canvas.height;return a.jsxs("div",{ref:me,className:`relative ${R}`,style:{width:"100%",height:"100%"},children:[qe&&he.length>0&&a.jsx(Le,{floors:he,currentFloorId:z,onFloorChange:Oe,showAllOption:I,allLabel:N,position:j,className:E}),a.jsxs(D.Stage,{ref:ue,width:tt,height:nt,scaleX:T,scaleY:T,x:$.x,y:$.y,draggable:!0,onDragEnd:Ke,onWheel:Je,style:{backgroundColor:f.canvas.backgroundColor,cursor:"grab"},children:[a.jsx(D.Layer,{listening:!1,children:oe.map(e=>a.jsx(ke,{stage:e,stageColor:re.stageColor},e.id))}),a.jsx(D.Layer,{listening:!1,children:ie.map(e=>a.jsx(Ie,{text:e},e.id))}),a.jsx(D.Layer,{children:O.map(e=>a.jsx(Fe,{seat:e,state:J(e),colors:re,onClick:_e,onMouseEnter:Qe,onMouseLeave:et},e.id))})]}),w&&a.jsx(ze,{visible:Z.visible,x:Z.x,y:Z.y,seat:Z.seat,currency:re.currency,state:Z.state}),$e&&p&&a.jsx(Te,{scale:T,minScale:q,maxScale:P,onZoomIn:Ge,onZoomOut:Ze,position:We,className:Pe}),Q.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 (",Q.length,")"]}),a.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Q.map(e=>a.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${re.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let ee=null;function dt(s){ee=s}function xe(){if(!ee)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return ee}function le(){return ee!==null}function ht(){ee=null}function pe(s,r){if(s.length!==r.length)return!1;const t=[...s].sort(),o=[...r].sort();return t.every((h,d)=>h===o[d])}function ft(s,r){const t=[],o=[],h=[];return Object.entries(s).forEach(([d,i])=>{i&&typeof i=="object"&&i.state&&(i.state==="unavailable"?h.push(d):i.state==="reserved"&&(r&&i.userId===r?t.push(d):o.push(d)))}),{myReserved:t.sort(),otherReserved:o.sort(),unavailable:h.sort()}}const ce={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function De(s){const{seatMapId:r,currentUserId:t,enabled:o=!0,onStateChange:h,onError:d}=s,i=n.useRef({...ce}),v=n.useRef(h),x=n.useRef(d),c=n.useRef(t);v.current=h,x.current=d,c.current=t;const l=n.useCallback(p=>{if(!o||!r)return(i.current.loading!==!1||i.current.states!==null)&&(i.current={...ce,loading:!1},p()),()=>{};if(!le()){const j="Firebase not initialized. Call initializeFirebaseForViewer first.";return i.current.error?.message!==j&&(i.current={...ce,loading:!1,error:new Error(j)},p()),()=>{}}const R=xe(),F=A.ref(R,`seatmaps/${r}/seat_states`),k=j=>{const I=j.val()||{},N=ft(I,c.current),W=i.current;(W.loading||!pe(W.myReservedSeats,N.myReserved)||!pe(W.otherReservedSeats,N.otherReserved)||!pe(W.unavailableSeats,N.unavailable))&&(i.current={states:I,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:N.myReserved,otherReservedSeats:N.otherReserved,unavailableSeats:N.unavailable},v.current?.(I),p())},M=j=>{i.current={...i.current,loading:!1,error:j},x.current?.(j),p()};return A.onValue(F,k,M),()=>{A.off(F)}},[r,o]),g=n.useCallback(()=>i.current,[]),b=n.useCallback(()=>ce,[]),w=n.useSyncExternalStore(l,g,b);return{states:w.states,loading:w.loading,error:w.error,lastUpdated:w.lastUpdated,myReservedSeats:w.myReservedSeats,otherReservedSeats:w.otherReservedSeats,unavailableSeats:w.unavailableSeats,reservedSeats:w.otherReservedSeats}}function Ne(s){const{seatMapId:r,enabled:t=!0,subscribeToChanges:o=!1,onConfigLoad:h,onError:d}=s,[i,v]=n.useState(null),[x,c]=n.useState(!0),[l,g]=n.useState(null),b=n.useRef(h),w=n.useRef(d);b.current=h,w.current=d;const p=n.useCallback(async()=>{if(!r)return;if(!le()){g(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),c(!1);return}const R=xe(),F=A.ref(R,`seatmaps/${r}`);try{c(!0),g(null);const M=(await A.get(F)).val();if(M){const j=lt.fromFirebaseSeatMap(M);v(j),b.current?.(j)}else g(new Error(`Seat map ${r} not found in Firebase`))}catch(k){const M=k instanceof Error?k:new Error("Unknown error");g(M),w.current?.(M)}finally{c(!1)}},[r]);return n.useEffect(()=>{if(!t||!r){c(!1);return}if(p(),o&&le()){const R=xe(),F=A.ref(R,`seatmaps/${r}/meta/updated_at`);let k=!0,M=null;const j=E=>{if(k){k=!1,M=E.val();return}const I=E.val();E.exists()&&I!==M&&(M=I,p())};return A.onValue(F,j),()=>{A.off(F)}}},[r,t,o]),{config:i,loading:x,error:l,refetch:p}}function gt(s){const{seatMapId:r,userId:t,enabled:o=!0,subscribeToDesignChanges:h=!1,onConfigLoad:d,onStateChange:i,onError:v}=s,{config:x,loading:c,error:l,refetch:g}=Ne({seatMapId:r,enabled:o,subscribeToChanges:h,onConfigLoad:d,onError:v}),{states:b,loading:w,error:p,lastUpdated:R,myReservedSeats:F,otherReservedSeats:k,unavailableSeats:M,reservedSeats:j}=De({seatMapId:r,currentUserId:t,enabled:o,onStateChange:i,onError:v});return{config:x,loading:c||w,error:l||p,myReservedSeats:F,otherReservedSeats:k,unavailableSeats:M,reservedSeats:j,seatStates:b,lastUpdated:R,refetch:g}}exports.DEFAULT_COLORS=Ee;exports.SeatMapViewer=ut;exports.clearFirebaseInstance=ht;exports.initializeFirebaseForViewer=dt;exports.isFirebaseInitialized=le;exports.useConfigFetcher=Re;exports.useContainerSize=Me;exports.useFirebaseConfig=Ne;exports.useFirebaseSeatStates=De;exports.useRealtimeSeatMap=gt;exports.useTouchGestures=je;