@zonetrix/viewer 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ export interface SeatMapViewerProps {
8
8
  reservedSeats?: string[];
9
9
  unavailableSeats?: string[];
10
10
  selectedSeats?: string[];
11
+ myReservedSeats?: string[];
11
12
  onSeatSelect?: (seat: SeatData) => void;
12
13
  onSeatDeselect?: (seat: SeatData) => void;
13
14
  onSelectionChange?: (seats: SeatData[]) => void;
@@ -2,6 +2,8 @@ import { FirebaseSeatStates } from '@zonetrix/shared';
2
2
  export interface UseFirebaseSeatStatesOptions {
3
3
  /** The seat map ID to subscribe to */
4
4
  seatMapId: string | null;
5
+ /** Current user ID for user-aware state derivation */
6
+ currentUserId?: string;
5
7
  /** Whether the subscription is enabled (default: true) */
6
8
  enabled?: boolean;
7
9
  /** Callback when states change */
@@ -18,23 +20,30 @@ export interface UseFirebaseSeatStatesResult {
18
20
  error: Error | null;
19
21
  /** Timestamp of last update */
20
22
  lastUpdated: number | null;
21
- /** Derived arrays for SeatMapViewer props */
22
- reservedSeats: string[];
23
+ /** Seats reserved by current user (show as selected) */
24
+ myReservedSeats: string[];
25
+ /** Seats reserved by other users (show as reserved) */
26
+ otherReservedSeats: string[];
27
+ /** Seats unavailable for everyone */
23
28
  unavailableSeats: string[];
29
+ /** @deprecated Use otherReservedSeats instead */
30
+ reservedSeats: string[];
24
31
  }
25
32
  /**
26
33
  * Subscribe to real-time seat state updates from Firebase
27
34
  *
28
35
  * @example
29
36
  * ```tsx
30
- * const { reservedSeats, unavailableSeats, loading } = useFirebaseSeatStates({
37
+ * const { myReservedSeats, otherReservedSeats, unavailableSeats, loading } = useFirebaseSeatStates({
31
38
  * seatMapId: '123',
39
+ * currentUserId: 'user-abc',
32
40
  * });
33
41
  *
34
42
  * return (
35
43
  * <SeatMapViewer
36
44
  * config={config}
37
- * reservedSeats={reservedSeats}
45
+ * myReservedSeats={myReservedSeats}
46
+ * reservedSeats={otherReservedSeats}
38
47
  * unavailableSeats={unavailableSeats}
39
48
  * />
40
49
  * );
@@ -3,6 +3,8 @@ import { FirebaseSeatStates } from '@zonetrix/shared';
3
3
  export interface UseRealtimeSeatMapOptions {
4
4
  /** The seat map ID to load and subscribe to */
5
5
  seatMapId: string | null;
6
+ /** Current user ID for user-aware state derivation */
7
+ userId?: string;
6
8
  /** Whether the hook is enabled (default: true) */
7
9
  enabled?: boolean;
8
10
  /** Subscribe to design changes in real-time (default: false) */
@@ -21,10 +23,14 @@ export interface UseRealtimeSeatMapResult {
21
23
  loading: boolean;
22
24
  /** Any error that occurred */
23
25
  error: Error | null;
24
- /** Array of reserved seat IDs (for SeatMapViewer props) */
25
- reservedSeats: string[];
26
- /** Array of unavailable seat IDs (for SeatMapViewer props) */
26
+ /** Seats reserved by current user (show as selected) */
27
+ myReservedSeats: string[];
28
+ /** Seats reserved by other users (show as reserved) */
29
+ otherReservedSeats: string[];
30
+ /** Seats unavailable for everyone */
27
31
  unavailableSeats: string[];
32
+ /** @deprecated Use otherReservedSeats instead */
33
+ reservedSeats: string[];
28
34
  /** Raw seat states map */
29
35
  seatStates: FirebaseSeatStates | null;
30
36
  /** Timestamp of last state update */
@@ -39,14 +45,15 @@ export interface UseRealtimeSeatMapResult {
39
45
  * ```tsx
40
46
  * import { useRealtimeSeatMap, SeatMapViewer } from '@zonetrix/viewer';
41
47
  *
42
- * function BookingPage({ seatMapId }) {
48
+ * function BookingPage({ seatMapId, userId }) {
43
49
  * const {
44
50
  * config,
45
- * reservedSeats,
51
+ * myReservedSeats,
52
+ * otherReservedSeats,
46
53
  * unavailableSeats,
47
54
  * loading,
48
55
  * error
49
- * } = useRealtimeSeatMap({ seatMapId });
56
+ * } = useRealtimeSeatMap({ seatMapId, userId });
50
57
  *
51
58
  * if (loading) return <LoadingSpinner />;
52
59
  * if (error) return <ErrorMessage error={error} />;
@@ -55,7 +62,8 @@ export interface UseRealtimeSeatMapResult {
55
62
  * return (
56
63
  * <SeatMapViewer
57
64
  * config={config}
58
- * reservedSeats={reservedSeats}
65
+ * myReservedSeats={myReservedSeats}
66
+ * reservedSeats={otherReservedSeats}
59
67
  * unavailableSeats={unavailableSeats}
60
68
  * onSeatSelect={handleSeatSelect}
61
69
  * />
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),t=require("react"),T=require("react-konva"),Y=require("firebase/database"),nt=require("@zonetrix/shared");function we(n){const[s,c]=t.useState(null),[o,g]=t.useState(!1),[p,d]=t.useState(null),m=async()=>{if(n){g(!0),d(null);try{const h=await fetch(n);if(!h.ok)throw new Error(`Failed to fetch config: ${h.statusText}`);const a=await h.json();c(a)}catch(h){const a=h instanceof Error?h:new Error("Unknown error occurred");d(a),console.error("Failed to fetch seat map config:",a)}finally{g(!1)}}};return t.useEffect(()=>{m()},[n]),{config:s,loading:o,error:p,refetch:m}}function Ce(n){const[s,c]=t.useState({width:0,height:0});return t.useEffect(()=>{const o=n.current;if(!o)return;const{width:g,height:p}=o.getBoundingClientRect();g>0&&p>0&&c({width:g,height:p});const d=new ResizeObserver(m=>{const h=m[0];if(!h)return;const{width:a,height:i}=h.contentRect;a>0&&i>0&&c(f=>f.width===a&&f.height===i?f:{width:a,height:i})});return d.observe(o),()=>{d.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 ve(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function je(n,s){const c=t.useRef(null),o=t.useRef(null),g=t.useRef(1);t.useEffect(()=>{const p=n.current;if(!p||!s.enabled)return;const d=p.container(),m=i=>{if(i.touches.length===2){i.preventDefault();const f={x:i.touches[0].clientX,y:i.touches[0].clientY},l={x:i.touches[1].clientX,y:i.touches[1].clientY};c.current=me(f,l),o.current=ve(f,l),g.current=s.currentScale}},h=i=>{if(i.touches.length!==2)return;i.preventDefault();const f={x:i.touches[0].clientX,y:i.touches[0].clientY},l={x:i.touches[1].clientX,y:i.touches[1].clientY},C=me(f,l),v=ve(f,l);if(c.current!==null&&o.current!==null){const j=C/c.current,F=Math.min(Math.max(s.currentScale*j,s.minScale),s.maxScale),R=d.getBoundingClientRect(),M=v.x-R.left,L=v.y-R.top,P=s.currentScale,W={x:(M-s.currentPosition.x)/P,y:(L-s.currentPosition.y)/P},A=v.x-o.current.x,N=v.y-o.current.y,ne={x:M-W.x*F+A,y:L-W.y*F+N};s.onScaleChange(F,ne),c.current=C,o.current=v}},a=i=>{i.touches.length<2&&(c.current=null,o.current=null)};return d.addEventListener("touchstart",m,{passive:!1}),d.addEventListener("touchmove",h,{passive:!1}),d.addEventListener("touchend",a),()=>{d.removeEventListener("touchstart",m),d.removeEventListener("touchmove",h),d.removeEventListener("touchend",a)}},[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:c,onClick:o,onMouseEnter:g,onMouseLeave:p})=>{const h={available:c.seatAvailable,reserved:c.seatReserved,selected:c.seatSelected,unavailable:c.seatUnavailable,hidden:c.seatHidden}[s],a=s==="available"||s==="selected",i=t.useCallback(()=>{a&&o(n)},[n,o,a]),f=t.useCallback(v=>{g(n,v);const j=v.target.getStage();j&&a&&(j.container().style.cursor="pointer")},[n,g,a]),l=t.useCallback(v=>{p();const j=v.target.getStage();j&&(j.container().style.cursor="grab")},[p]),C={x:n.position.x,y:n.position.y,fill:h,stroke:"#ffffff",strokeWidth:1,onClick:i,onTap:i,onMouseEnter:f,onMouseLeave:l};return n.shape==="circle"?r.jsx(T.Circle,{...C,radius:12}):r.jsx(T.Rect,{...C,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 c=p=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[p||"stage"]||"🎭",o=n.config.color||s,g=c(n.config.objectType);return r.jsxs(T.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[r.jsx(T.Rect,{width:n.config.width,height:n.config.height,fill:o+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),r.jsx(T.Text,{text:g,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),r.jsx(T.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 Re=t.memo(({floors:n,currentFloorId:s,onFloorChange:c,showAllOption:o,allLabel:g,position:p,className:d})=>{const m=t.useMemo(()=>[...n].sort((l,C)=>l.order-C.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}}[p]},i={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={...i,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return r.jsxs("div",{className:d,style:a,children:[o&&r.jsx("button",{type:"button",onClick:()=>c(null),style:s===null?f:i,children:g}),m.map(l=>r.jsx("button",{type:"button",onClick:()=>c(l.id),style:s===l.id?f:i,children:l.name},l.id))]})});Re.displayName="FloorSelectorBar";const ke=t.memo(({scale:n,minScale:s,maxScale:c,onZoomIn:o,onZoomOut:g,position:p,className:d})=>{const h={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}}[p]},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"},i={...a,opacity:.4,cursor:"not-allowed"},f=n<c,l=n>s;return r.jsxs("div",{className:d,style:h,children:[r.jsx("button",{type:"button",onClick:o,disabled:!f,style:f?a:i,title:"Zoom In",children:"+"}),r.jsx("button",{type:"button",onClick:g,disabled:!l,style:l?a:i,title:"Zoom Out",children:"−"})]})});ke.displayName="ZoomControls";const Ie=t.memo(({visible:n,x:s,y:c,seat:o,currency:g,state:p})=>{if(!n||!o)return null;const d=o.seatNumber||(o.rowLabel&&o.columnLabel?`${o.rowLabel}-${o.columnLabel}`:"N/A"),m={position:"fixed",left:`${s+15}px`,top:`${c+15}px`,zIndex:1e3,pointerEvents:"none"},h={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"},i={fontWeight:600},f={color:"#4ade80",fontWeight:600},l={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return r.jsx("div",{style:m,children:r.jsxs("div",{style:h,children:[o.sectionName&&r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Section:"}),r.jsx("span",{style:{...i,color:"#3b82f6"},children:o.sectionName})]}),r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Seat:"}),r.jsx("span",{style:i,children:d})]}),o.price!==void 0&&o.price>0&&p==="available"&&r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Price:"}),r.jsxs("span",{style:f,children:[g," ",o.price.toFixed(2)]})]}),r.jsxs("div",{style:l,children:["Status: ",p]})]})})});Ie.displayName="SeatTooltip";const st=({config:n,configUrl:s,floorId:c,onFloorChange:o,reservedSeats:g=[],unavailableSeats:p=[],selectedSeats:d,onSeatSelect:m,onSeatDeselect:h,onSelectionChange:a,colorOverrides:i,showTooltip:f=!0,zoomEnabled:l=!0,className:C="",onConfigLoad:v,onError:j,showFloorSelector:F,floorSelectorPosition:R="top-left",floorSelectorClassName:M,showAllFloorsOption:L=!0,allFloorsLabel:P="All",fitToView:W=!0,fitPadding:A=40,showZoomControls:N=!0,zoomControlsPosition:ne="bottom-right",zoomControlsClassName:U,minZoom:q,maxZoom:D=3,zoomStep:$=.25,touchEnabled:se=!0})=>{const de=t.useRef(null),be=t.useRef(null),E=Ce(be),[V,Se]=t.useState(new Set),[k,_]=t.useState(1),[I,B]=t.useState({x:0,y:0}),[ze,Te]=t.useState(null),[Ne,Xe]=t.useState(1),oe=t.useRef({width:0,height:0}),[G,ye]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Ye,loading:Pe,error:K}=we(s),x=n||Ye,he=c!==void 0,z=he?c||null:ze,ie=d!==void 0,We=t.useCallback(e=>{he||Te(e),o?.(e)},[he,o]),fe=x?.floors||[],Ae=F!==void 0?F:fe.length>1,re=t.useMemo(()=>x?{...x.colors,...i}:{...Me,...i},[x,i]),O=t.useMemo(()=>{if(!x)return[];let e=x.seats.filter(u=>u.state!=="hidden");return z&&(e=e.filter(u=>u.floorId===z||!u.floorId&&z==="floor_default")),e},[x,z]),ae=t.useMemo(()=>x?.stages?z?x.stages.filter(e=>e.floorId===z||!e.floorId&&z==="floor_default"):x.stages:[],[x,z]),X=t.useMemo(()=>{if(!x||O.length===0&&ae.length===0)return null;const e=12;let u=1/0,S=1/0,b=-1/0,y=-1/0;return O.forEach(w=>{u=Math.min(u,w.position.x-e),S=Math.min(S,w.position.y-e),b=Math.max(b,w.position.x+e),y=Math.max(y,w.position.y+e)}),ae.forEach(w=>{u=Math.min(u,w.position.x),S=Math.min(S,w.position.y),b=Math.max(b,w.position.x+(w.config?.width||200)),y=Math.max(y,w.position.y+(w.config?.height||100))}),{minX:u,minY:S,maxX:b,maxY:y,width:b-u,height:y-S}},[x,O,ae]);t.useEffect(()=>{if(!W||!x||!X||E.width===0||E.height===0)return;const e=Math.abs(E.width-oe.current.width),u=Math.abs(E.height-oe.current.height);if(!(oe.current.width===0)&&e<10&&u<10)return;oe.current=E;const b=E.width,y=E.height,w=b-A*2,ee=y-A*2,ce=w/X.width,pe=ee/X.height,le=Math.min(ce,pe,D),Ke=X.minX+X.width/2,Ze=X.minY+X.height/2,Je=b/2,Qe=y/2,et=Je-Ke*le,tt=Qe-Ze*le;_(le),B({x:et,y:tt}),Xe(le)},[W,x,X,A,D,E,z]);const Z=t.useMemo(()=>{const e=new Set(g),u=new Set(p);return{reserved:e,unavailable:u}},[g,p]),ge=t.useMemo(()=>d?new Set(d):null,[d]),J=t.useCallback(e=>{const u=e.id,S=e.seatNumber||"";return Z.unavailable.has(u)||Z.unavailable.has(S)?"unavailable":Z.reserved.has(u)||Z.reserved.has(S)?"reserved":V.has(u)?"selected":e.state},[Z,V]);t.useEffect(()=>{x&&v&&v(x)},[x,v]),t.useEffect(()=>{K&&j&&j(K)},[K,j]),t.useEffect(()=>{ie&&ge&&Se(ge)},[ie,ge]);const $e=t.useCallback(e=>{const u=J(e);if(u!=="available"&&u!=="selected")return;const S=V.has(e.id);ie||Se(b=>{const y=new Set(b);return S?y.delete(e.id):y.add(e.id),y}),S?h?.(e):(m?.(e),m||console.log("Seat selected:",e))},[J,V,ie,m,h]),Q=t.useMemo(()=>x?O.filter(e=>V.has(e.id)):[],[O,V]);t.useEffect(()=>{a?.(Q)},[Q,a]);const H=q!==void 0?q:Ne,Be=t.useCallback(()=>{if(!l)return;const e=Math.min(k+$,D);if(e!==k){const u=E.width||x?.canvas.width||800,S=E.height||x?.canvas.height||600,b=u/2,y=S/2,w={x:(b-I.x)/k,y:(y-I.y)/k};_(e),B({x:b-w.x*e,y:y-w.y*e})}},[l,k,$,D,E,x,I]),Ve=t.useCallback(()=>{if(!l)return;const e=Math.max(k-$,H);if(e!==k){const u=E.width||x?.canvas.width||800,S=E.height||x?.canvas.height||600,b=u/2,y=S/2,w={x:(b-I.x)/k,y:(y-I.y)/k};_(e),B({x:b-w.x*e,y:y-w.y*e})}},[l,k,$,H,E,x,I]),Oe=t.useCallback(e=>{B({x:e.target.x(),y:e.target.y()})},[]),He=t.useCallback(e=>{if(!l)return;e.evt.preventDefault();const u=de.current;if(!u)return;const S=u.scaleX(),b=u.getPointerPosition();if(!b)return;const y=1.1,w=e.evt.deltaY>0?S/y:S*y,ee=Math.min(Math.max(w,H),D),ce={x:(b.x-I.x)/S,y:(b.y-I.y)/S},pe={x:b.x-ce.x*ee,y:b.y-ce.y*ee};_(ee),B(pe)},[l,I,H,D]);je(de,{enabled:se&&l,minScale:H,maxScale:D,currentScale:k,currentPosition:I,onScaleChange:(e,u)=>{_(e),B(u)},onPositionChange:e=>{B(e)}});const Ue=t.useCallback((e,u)=>{if(!f)return;const S=u.target.getStage();if(!S)return;const b=S.getPointerPosition();if(!b)return;const y=S.container().getBoundingClientRect();ye({visible:!0,x:y.left+b.x,y:y.top+b.y,seat:e,state:J(e)})},[f,J]),qe=t.useCallback(()=>{ye(e=>({...e,visible:!1}))},[]);if(Pe)return r.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:r.jsx("p",{children:"Loading seat map..."})});if(K)return r.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:r.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",K.message]})});if(!x)return r.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:r.jsx("p",{children:"No configuration provided"})});const _e=E.width||x.canvas.width,Ge=E.height||x.canvas.height;return r.jsxs("div",{ref:be,className:`relative ${C}`,style:{width:"100%",height:"100%"},children:[Ae&&fe.length>0&&r.jsx(Re,{floors:fe,currentFloorId:z,onFloorChange:We,showAllOption:L,allLabel:P,position:R,className:M}),r.jsxs(T.Stage,{ref:de,width:_e,height:Ge,scaleX:k,scaleY:k,x:I.x,y:I.y,draggable:!0,onDragEnd:Oe,onWheel:He,style:{backgroundColor:x.canvas.backgroundColor,cursor:"grab"},children:[r.jsx(T.Layer,{listening:!1,children:ae.map(e=>r.jsx(Fe,{stage:e,stageColor:re.stageColor},e.id))}),r.jsx(T.Layer,{children:O.map(e=>r.jsx(Ee,{seat:e,state:J(e),colors:re,onClick:$e,onMouseEnter:Ue,onMouseLeave:qe},e.id))})]}),f&&r.jsx(Ie,{visible:G.visible,x:G.x,y:G.y,seat:G.seat,currency:re.currency,state:G.state}),N&&l&&r.jsx(ke,{scale:k,minScale:H,maxScale:D,onZoomIn:Be,onZoomOut:Ve,position:ne,className:U}),Q.length>0&&r.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[r.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",Q.length,")"]}),r.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Q.map(e=>r.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${re.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let te=null;function ot(n){te=n}function xe(){if(!te)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return te}function ue(){return te!==null}function it(){te=null}function Le(n){const{seatMapId:s,enabled:c=!0,onStateChange:o,onError:g}=n,[p,d]=t.useState(null),[m,h]=t.useState(!0),[a,i]=t.useState(null),[f,l]=t.useState(null),[C,v]=t.useState([]),[j,F]=t.useState([]),R=t.useRef(o),M=t.useRef(g);return R.current=o,M.current=g,t.useEffect(()=>{if(!c||!s){h(!1);return}if(!ue()){h(!1),i(new Error("Firebase not initialized. Call initializeFirebaseForViewer first."));return}const L=xe(),P=Y.ref(L,`seat_states/${s}`);h(!0),i(null);const W=N=>{const U=N.val()||{};d(U),h(!1),l(Date.now());const q=[],D=[];Object.entries(U).forEach(([$,se])=>{se==="reserved"?q.push($):se==="unavailable"&&D.push($)}),v(q),F(D),R.current?.(U)},A=N=>{i(N),h(!1),M.current?.(N)};return Y.onValue(P,W,A),()=>{Y.off(P)}},[s,c]),{states:p,loading:m,error:a,lastUpdated:f,reservedSeats:C,unavailableSeats:j}}function De(n){const{seatMapId:s,enabled:c=!0,subscribeToChanges:o=!1,onConfigLoad:g,onError:p}=n,[d,m]=t.useState(null),[h,a]=t.useState(!0),[i,f]=t.useState(null),l=t.useRef(g),C=t.useRef(p);l.current=g,C.current=p;const v=t.useCallback(async()=>{if(!s)return;if(!ue()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),a(!1);return}const j=xe(),F=Y.ref(j,`seatmaps/${s}`);try{a(!0),f(null);const M=(await Y.get(F)).val();if(M){const L=nt.fromFirebaseSeatMap(M);m(L),l.current?.(L)}else f(new Error(`Seat map ${s} not found in Firebase`))}catch(R){const M=R instanceof Error?R:new Error("Unknown error");f(M),C.current?.(M)}finally{a(!1)}},[s]);return t.useEffect(()=>{if(!c||!s){a(!1);return}if(v(),o&&ue()){const j=xe(),F=Y.ref(j,`seatmaps/${s}/meta/updated_at`);let R=!0;const M=L=>{if(R){R=!1;return}L.exists()&&v()};return Y.onValue(F,M),()=>{Y.off(F)}}},[s,c,o,v]),{config:d,loading:h,error:i,refetch:v}}function rt(n){const{seatMapId:s,enabled:c=!0,subscribeToDesignChanges:o=!1,onConfigLoad:g,onStateChange:p,onError:d}=n,{config:m,loading:h,error:a,refetch:i}=De({seatMapId:s,enabled:c,subscribeToChanges:o,onConfigLoad:g,onError:d}),{states:f,loading:l,error:C,lastUpdated:v,reservedSeats:j,unavailableSeats:F}=Le({seatMapId:s,enabled:c,onStateChange:p,onError:d});return{config:m,loading:h||l,error:a||C,reservedSeats:j,unavailableSeats:F,seatStates:f,lastUpdated:v,refetch:i}}exports.DEFAULT_COLORS=Me;exports.SeatMapViewer=st;exports.clearFirebaseInstance=it;exports.initializeFirebaseForViewer=ot;exports.isFirebaseInitialized=ue;exports.useConfigFetcher=we;exports.useContainerSize=Ce;exports.useFirebaseConfig=De;exports.useFirebaseSeatStates=Le;exports.useRealtimeSeatMap=rt;exports.useTouchGestures=je;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),t=require("react"),N=require("react-konva"),$=require("firebase/database"),ot=require("@zonetrix/shared");function je(n){const[s,c]=t.useState(null),[o,f]=t.useState(!1),[d,i]=t.useState(null),v=async()=>{if(n){f(!0),i(null);try{const p=await fetch(n);if(!p.ok)throw new Error(`Failed to fetch config: ${p.statusText}`);const a=await p.json();c(a)}catch(p){const a=p instanceof Error?p:new Error("Unknown error occurred");i(a),console.error("Failed to fetch seat map config:",a)}finally{f(!1)}}};return t.useEffect(()=>{v()},[n]),{config:s,loading:o,error:d,refetch:v}}function Re(n){const[s,c]=t.useState({width:0,height:0});return t.useEffect(()=>{const o=n.current;if(!o)return;const{width:f,height:d}=o.getBoundingClientRect();f>0&&d>0&&c({width:f,height:d});const i=new ResizeObserver(v=>{const p=v[0];if(!p)return;const{width:a,height:l}=p.contentRect;a>0&&l>0&&c(h=>h.width===a&&h.height===l?h:{width:a,height:l})});return i.observe(o),()=>{i.disconnect()}},[n]),s}function ve(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 Me(n,s){const c=t.useRef(null),o=t.useRef(null),f=t.useRef(1);t.useEffect(()=>{const d=n.current;if(!d||!s.enabled)return;const i=d.container(),v=l=>{if(l.touches.length===2){l.preventDefault();const h={x:l.touches[0].clientX,y:l.touches[0].clientY},g={x:l.touches[1].clientX,y:l.touches[1].clientY};c.current=ve(h,g),o.current=we(h,g),f.current=s.currentScale}},p=l=>{if(l.touches.length!==2)return;l.preventDefault();const h={x:l.touches[0].clientX,y:l.touches[0].clientY},g={x:l.touches[1].clientX,y:l.touches[1].clientY},w=ve(h,g),m=we(h,g);if(c.current!==null&&o.current!==null){const j=w/c.current,R=Math.min(Math.max(s.currentScale*j,s.minScale),s.maxScale),M=i.getBoundingClientRect(),E=m.x-M.left,k=m.y-M.top,X=s.currentScale,Y={x:(E-s.currentPosition.x)/X,y:(k-s.currentPosition.y)/X},B=m.x-o.current.x,z=m.y-o.current.y,A={x:E-Y.x*R+B,y:k-Y.y*R+z};s.onScaleChange(R,A),c.current=w,o.current=m}},a=l=>{l.touches.length<2&&(c.current=null,o.current=null)};return i.addEventListener("touchstart",v,{passive:!1}),i.addEventListener("touchmove",p,{passive:!1}),i.addEventListener("touchend",a),()=>{i.removeEventListener("touchstart",v),i.removeEventListener("touchmove",p),i.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:c,onClick:o,onMouseEnter:f,onMouseLeave:d})=>{const p={available:c.seatAvailable,reserved:c.seatReserved,selected:c.seatSelected,unavailable:c.seatUnavailable,hidden:c.seatHidden}[s],a=s==="available"||s==="selected",l=t.useCallback(()=>{a&&o(n)},[n,o,a]),h=t.useCallback(m=>{f(n,m);const j=m.target.getStage();j&&a&&(j.container().style.cursor="pointer")},[n,f,a]),g=t.useCallback(m=>{d();const j=m.target.getStage();j&&(j.container().style.cursor="grab")},[d]),w={x:n.position.x,y:n.position.y,fill:p,stroke:"#ffffff",strokeWidth:1,onClick:l,onTap:l,onMouseEnter:h,onMouseLeave:g};return n.shape==="circle"?r.jsx(N.Circle,{...w,radius:12}):r.jsx(N.Rect,{...w,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 c=d=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[d||"stage"]||"🎭",o=n.config.color||s,f=c(n.config.objectType);return r.jsxs(N.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[r.jsx(N.Rect,{width:n.config.width,height:n.config.height,fill:o+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),r.jsx(N.Text,{text:f,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),r.jsx(N.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:c,showAllOption:o,allLabel:f,position:d,className:i})=>{const v=t.useMemo(()=>[...n].sort((g,w)=>g.order-w.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]},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"},h={...l,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return r.jsxs("div",{className:i,style:a,children:[o&&r.jsx("button",{type:"button",onClick:()=>c(null),style:s===null?h:l,children:f}),v.map(g=>r.jsx("button",{type:"button",onClick:()=>c(g.id),style:s===g.id?h:l,children:g.name},g.id))]})});Ie.displayName="FloorSelectorBar";const Le=t.memo(({scale:n,minScale:s,maxScale:c,onZoomIn:o,onZoomOut:f,position:d,className:i})=>{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"},l={...a,opacity:.4,cursor:"not-allowed"},h=n<c,g=n>s;return r.jsxs("div",{className:i,style:p,children:[r.jsx("button",{type:"button",onClick:o,disabled:!h,style:h?a:l,title:"Zoom In",children:"+"}),r.jsx("button",{type:"button",onClick:f,disabled:!g,style:g?a:l,title:"Zoom Out",children:"−"})]})});Le.displayName="ZoomControls";const De=t.memo(({visible:n,x:s,y:c,seat:o,currency:f,state:d})=>{if(!n||!o)return null;const i=o.seatNumber||(o.rowLabel&&o.columnLabel?`${o.rowLabel}-${o.columnLabel}`:"N/A"),v={position:"fixed",left:`${s+15}px`,top:`${c+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"},l={fontWeight:600},h={color:"#4ade80",fontWeight:600},g={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return r.jsx("div",{style:v,children:r.jsxs("div",{style:p,children:[o.sectionName&&r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Section:"}),r.jsx("span",{style:{...l,color:"#3b82f6"},children:o.sectionName})]}),r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Seat:"}),r.jsx("span",{style:l,children:i})]}),o.price!==void 0&&o.price>0&&d==="available"&&r.jsxs("div",{style:{marginBottom:"4px"},children:[r.jsx("span",{style:a,children:"Price:"}),r.jsxs("span",{style:h,children:[f," ",o.price.toFixed(2)]})]}),r.jsxs("div",{style:g,children:["Status: ",d]})]})})});De.displayName="SeatTooltip";const rt=({config:n,configUrl:s,floorId:c,onFloorChange:o,reservedSeats:f=[],unavailableSeats:d=[],selectedSeats:i,myReservedSeats:v=[],onSeatSelect:p,onSeatDeselect:a,onSelectionChange:l,colorOverrides:h,showTooltip:g=!0,zoomEnabled:w=!0,className:m="",onConfigLoad:j,onError:R,showFloorSelector:M,floorSelectorPosition:E="top-left",floorSelectorClassName:k,showAllFloorsOption:X=!0,allFloorsLabel:Y="All",fitToView:B=!0,fitPadding:z=40,showZoomControls:A=!0,zoomControlsPosition:G="bottom-right",zoomControlsClassName:he,minZoom:O,maxZoom:T=3,zoomStep:P=.25,touchEnabled:fe=!0})=>{const K=t.useRef(null),oe=t.useRef(null),F=Re(oe),[H,ye]=t.useState(new Set),[I,Z]=t.useState(1),[L,V]=t.useState({x:0,y:0}),[Ne,Xe]=t.useState(null),[Ye,Ae]=t.useState(1),re=t.useRef({width:0,height:0}),[J,me]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Pe,loading:We,error:Q}=je(s),x=n||Pe,ge=c!==void 0,D=ge?c||null:Ne,ie=i!==void 0,$e=t.useCallback(e=>{ge||Xe(e),o?.(e)},[ge,o]),pe=x?.floors||[],Be=M!==void 0?M:pe.length>1,ae=t.useMemo(()=>x?{...x.colors,...h}:{...Ee,...h},[x,h]),q=t.useMemo(()=>{if(!x)return[];let e=x.seats.filter(u=>u.state!=="hidden");return D&&(e=e.filter(u=>u.floorId===D||!u.floorId&&D==="floor_default")),e},[x,D]),ce=t.useMemo(()=>x?.stages?D?x.stages.filter(e=>e.floorId===D||!e.floorId&&D==="floor_default"):x.stages:[],[x,D]),W=t.useMemo(()=>{if(!x||q.length===0&&ce.length===0)return null;const e=12;let u=1/0,b=1/0,S=-1/0,y=-1/0;return q.forEach(C=>{u=Math.min(u,C.position.x-e),b=Math.min(b,C.position.y-e),S=Math.max(S,C.position.x+e),y=Math.max(y,C.position.y+e)}),ce.forEach(C=>{u=Math.min(u,C.position.x),b=Math.min(b,C.position.y),S=Math.max(S,C.position.x+(C.config?.width||200)),y=Math.max(y,C.position.y+(C.config?.height||100))}),{minX:u,minY:b,maxX:S,maxY:y,width:S-u,height:y-b}},[x,q,ce]);t.useEffect(()=>{if(!B||!x||!W||F.width===0||F.height===0)return;const e=Math.abs(F.width-re.current.width),u=Math.abs(F.height-re.current.height);if(!(re.current.width===0)&&e<10&&u<10)return;re.current=F;const S=F.width,y=F.height,C=S-z*2,ne=y-z*2,le=C/W.width,be=ne/W.height,ue=Math.min(le,be,T),Je=W.minX+W.width/2,Qe=W.minY+W.height/2,et=S/2,tt=y/2,nt=et-Je*ue,st=tt-Qe*ue;Z(ue),V({x:nt,y:st}),Ae(ue)},[B,x,W,z,T,F,D]);const U=t.useMemo(()=>{const e=new Set(f),u=new Set(d),b=new Set(v);return{reserved:e,unavailable:u,myReserved:b}},[f,d,v]),xe=t.useMemo(()=>i?new Set(i):null,[i]),ee=t.useCallback(e=>{const u=e.id,b=e.seatNumber||"";return U.unavailable.has(u)||U.unavailable.has(b)?"unavailable":U.reserved.has(u)||U.reserved.has(b)?"reserved":U.myReserved.has(u)||U.myReserved.has(b)||H.has(u)?"selected":e.state},[U,H]);t.useEffect(()=>{x&&j&&j(x)},[x,j]),t.useEffect(()=>{Q&&R&&R(Q)},[Q,R]),t.useEffect(()=>{ie&&xe&&ye(xe)},[ie,xe]);const Oe=t.useCallback(e=>{const u=ee(e);if(u!=="available"&&u!=="selected")return;const b=H.has(e.id);ie||ye(S=>{const y=new Set(S);return b?y.delete(e.id):y.add(e.id),y}),b?a?.(e):(p?.(e),p||console.log("Seat selected:",e))},[ee,H,ie,p,a]),te=t.useMemo(()=>x?q.filter(e=>H.has(e.id)):[],[q,H]);t.useEffect(()=>{l?.(te)},[te,l]);const _=O!==void 0?O:Ye,Ve=t.useCallback(()=>{if(!w)return;const e=Math.min(I+P,T);if(e!==I){const u=F.width||x?.canvas.width||800,b=F.height||x?.canvas.height||600,S=u/2,y=b/2,C={x:(S-L.x)/I,y:(y-L.y)/I};Z(e),V({x:S-C.x*e,y:y-C.y*e})}},[w,I,P,T,F,x,L]),Ue=t.useCallback(()=>{if(!w)return;const e=Math.max(I-P,_);if(e!==I){const u=F.width||x?.canvas.width||800,b=F.height||x?.canvas.height||600,S=u/2,y=b/2,C={x:(S-L.x)/I,y:(y-L.y)/I};Z(e),V({x:S-C.x*e,y:y-C.y*e})}},[w,I,P,_,F,x,L]),He=t.useCallback(e=>{V({x:e.target.x(),y:e.target.y()})},[]),qe=t.useCallback(e=>{if(!w)return;e.evt.preventDefault();const u=K.current;if(!u)return;const b=u.scaleX(),S=u.getPointerPosition();if(!S)return;const y=1.1,C=e.evt.deltaY>0?b/y:b*y,ne=Math.min(Math.max(C,_),T),le={x:(S.x-L.x)/b,y:(S.y-L.y)/b},be={x:S.x-le.x*ne,y:S.y-le.y*ne};Z(ne),V(be)},[w,L,_,T]);Me(K,{enabled:fe&&w,minScale:_,maxScale:T,currentScale:I,currentPosition:L,onScaleChange:(e,u)=>{Z(e),V(u)},onPositionChange:e=>{V(e)}});const _e=t.useCallback((e,u)=>{if(!g)return;const b=u.target.getStage();if(!b)return;const S=b.getPointerPosition();if(!S)return;const y=b.container().getBoundingClientRect();me({visible:!0,x:y.left+S.x,y:y.top+S.y,seat:e,state:ee(e)})},[g,ee]),Ge=t.useCallback(()=>{me(e=>({...e,visible:!1}))},[]);if(We)return r.jsx("div",{className:`flex items-center justify-center h-full ${m}`,children:r.jsx("p",{children:"Loading seat map..."})});if(Q)return r.jsx("div",{className:`flex items-center justify-center h-full ${m}`,children:r.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",Q.message]})});if(!x)return r.jsx("div",{className:`flex items-center justify-center h-full ${m}`,children:r.jsx("p",{children:"No configuration provided"})});const Ke=F.width||x.canvas.width,Ze=F.height||x.canvas.height;return r.jsxs("div",{ref:oe,className:`relative ${m}`,style:{width:"100%",height:"100%"},children:[Be&&pe.length>0&&r.jsx(Ie,{floors:pe,currentFloorId:D,onFloorChange:$e,showAllOption:X,allLabel:Y,position:E,className:k}),r.jsxs(N.Stage,{ref:K,width:Ke,height:Ze,scaleX:I,scaleY:I,x:L.x,y:L.y,draggable:!0,onDragEnd:He,onWheel:qe,style:{backgroundColor:x.canvas.backgroundColor,cursor:"grab"},children:[r.jsx(N.Layer,{listening:!1,children:ce.map(e=>r.jsx(ke,{stage:e,stageColor:ae.stageColor},e.id))}),r.jsx(N.Layer,{children:q.map(e=>r.jsx(Fe,{seat:e,state:ee(e),colors:ae,onClick:Oe,onMouseEnter:_e,onMouseLeave:Ge},e.id))})]}),g&&r.jsx(De,{visible:J.visible,x:J.x,y:J.y,seat:J.seat,currency:ae.currency,state:J.state}),A&&w&&r.jsx(Le,{scale:I,minScale:_,maxScale:T,onZoomIn:Ve,onZoomOut:Ue,position:G,className:he}),te.length>0&&r.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[r.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",te.length,")"]}),r.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:te.map(e=>r.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${ae.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let se=null;function it(n){se=n}function Se(){if(!se)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return se}function de(){return se!==null}function at(){se=null}function Ce(n,s){const c=[],o=[],f=[];return Object.entries(n).forEach(([d,i])=>{i&&typeof i=="object"&&i.state&&(i.state==="unavailable"?f.push(d):i.state==="reserved"&&(s&&i.userId===s?c.push(d):o.push(d)))}),{myReservedSeats:c,otherReservedSeats:o,unavailableSeats:f}}function ze(n){const{seatMapId:s,currentUserId:c,enabled:o=!0,onStateChange:f,onError:d}=n,[i,v]=t.useState(null),[p,a]=t.useState(!0),[l,h]=t.useState(null),[g,w]=t.useState(null),[m,j]=t.useState([]),[R,M]=t.useState([]),[E,k]=t.useState([]),X=t.useRef(f),Y=t.useRef(d),B=t.useRef(c);return X.current=f,Y.current=d,B.current=c,t.useEffect(()=>{if(!o||!s){a(!1);return}if(!de()){a(!1),h(new Error("Firebase not initialized. Call initializeFirebaseForViewer first."));return}const z=Se(),A=$.ref(z,`seat_states/${s}`);a(!0),h(null);const G=O=>{const P=O.val()||{};v(P),a(!1),w(Date.now());const{myReservedSeats:fe,otherReservedSeats:K,unavailableSeats:oe}=Ce(P,B.current);j(fe),M(K),k(oe),X.current?.(P)},he=O=>{h(O),a(!1),Y.current?.(O)};return $.onValue(A,G,he),()=>{$.off(A)}},[s,o]),t.useEffect(()=>{if(i){const{myReservedSeats:z,otherReservedSeats:A,unavailableSeats:G}=Ce(i,c);j(z),M(A),k(G)}},[c,i]),{states:i,loading:p,error:l,lastUpdated:g,myReservedSeats:m,otherReservedSeats:R,unavailableSeats:E,reservedSeats:R}}function Te(n){const{seatMapId:s,enabled:c=!0,subscribeToChanges:o=!1,onConfigLoad:f,onError:d}=n,[i,v]=t.useState(null),[p,a]=t.useState(!0),[l,h]=t.useState(null),g=t.useRef(f),w=t.useRef(d);g.current=f,w.current=d;const m=t.useCallback(async()=>{if(!s)return;if(!de()){h(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),a(!1);return}const j=Se(),R=$.ref(j,`seatmaps/${s}`);try{a(!0),h(null);const E=(await $.get(R)).val();if(E){const k=ot.fromFirebaseSeatMap(E);v(k),g.current?.(k)}else h(new Error(`Seat map ${s} not found in Firebase`))}catch(M){const E=M instanceof Error?M:new Error("Unknown error");h(E),w.current?.(E)}finally{a(!1)}},[s]);return t.useEffect(()=>{if(!c||!s){a(!1);return}if(m(),o&&de()){const j=Se(),R=$.ref(j,`seatmaps/${s}/meta/updated_at`);let M=!0;const E=k=>{if(M){M=!1;return}k.exists()&&m()};return $.onValue(R,E),()=>{$.off(R)}}},[s,c,o,m]),{config:i,loading:p,error:l,refetch:m}}function ct(n){const{seatMapId:s,userId:c,enabled:o=!0,subscribeToDesignChanges:f=!1,onConfigLoad:d,onStateChange:i,onError:v}=n,{config:p,loading:a,error:l,refetch:h}=Te({seatMapId:s,enabled:o,subscribeToChanges:f,onConfigLoad:d,onError:v}),{states:g,loading:w,error:m,lastUpdated:j,myReservedSeats:R,otherReservedSeats:M,unavailableSeats:E,reservedSeats:k}=ze({seatMapId:s,currentUserId:c,enabled:o,onStateChange:i,onError:v});return{config:p,loading:a||w,error:l||m,myReservedSeats:R,otherReservedSeats:M,unavailableSeats:E,reservedSeats:k,seatStates:g,lastUpdated:j,refetch:h}}exports.DEFAULT_COLORS=Ee;exports.SeatMapViewer=rt;exports.clearFirebaseInstance=at;exports.initializeFirebaseForViewer=it;exports.isFirebaseInitialized=de;exports.useConfigFetcher=je;exports.useContainerSize=Re;exports.useFirebaseConfig=Te;exports.useFirebaseSeatStates=ze;exports.useRealtimeSeatMap=ct;exports.useTouchGestures=Me;