@zonetrix/viewer 2.13.1 → 2.13.2

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.
@@ -0,0 +1,30 @@
1
+ import { Database } from 'firebase/database';
2
+ /**
3
+ * Initialize the Firebase database instance for the viewer
4
+ * This should be called by the host application after Firebase is initialized
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { initializeApp } from 'firebase/app';
9
+ * import { getDatabase } from 'firebase/database';
10
+ * import { initializeFirebaseForViewer } from '@zonetrix/viewer';
11
+ *
12
+ * const app = initializeApp(firebaseConfig);
13
+ * const db = getDatabase(app);
14
+ * initializeFirebaseForViewer(db);
15
+ * ```
16
+ */
17
+ export declare function initializeFirebaseForViewer(database: Database): void;
18
+ /**
19
+ * Get the Firebase database instance
20
+ * @throws Error if Firebase hasn't been initialized
21
+ */
22
+ export declare function getFirebaseDatabase(): Database;
23
+ /**
24
+ * Check if Firebase has been initialized for the viewer
25
+ */
26
+ export declare function isFirebaseInitialized(): boolean;
27
+ /**
28
+ * Clear the Firebase database instance (useful for testing)
29
+ */
30
+ export declare function clearFirebaseInstance(): void;
@@ -0,0 +1,41 @@
1
+ import { SeatMapConfig } from '../types';
2
+ export interface UseFirebaseConfigOptions {
3
+ /** The seat map ID to load */
4
+ seatMapId: string | null;
5
+ /** Whether loading is enabled (default: true) */
6
+ enabled?: boolean;
7
+ /** Subscribe to design changes in real-time (default: false) */
8
+ subscribeToChanges?: boolean;
9
+ /** Callback when config loads or changes */
10
+ onConfigLoad?: (config: SeatMapConfig) => void;
11
+ /** Callback on error */
12
+ onError?: (error: Error) => void;
13
+ }
14
+ export interface UseFirebaseConfigResult {
15
+ /** The loaded configuration */
16
+ config: SeatMapConfig | null;
17
+ /** Whether loading is in progress */
18
+ loading: boolean;
19
+ /** Any error that occurred */
20
+ error: Error | null;
21
+ /** Manually refetch the config */
22
+ refetch: () => Promise<void>;
23
+ }
24
+ /**
25
+ * Load seat map configuration from Firebase
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * // One-time load
30
+ * const { config, loading, error } = useFirebaseConfig({
31
+ * seatMapId: '123',
32
+ * });
33
+ *
34
+ * // With real-time design updates (for admin/editor preview)
35
+ * const { config } = useFirebaseConfig({
36
+ * seatMapId: '123',
37
+ * subscribeToChanges: true,
38
+ * });
39
+ * ```
40
+ */
41
+ export declare function useFirebaseConfig(options: UseFirebaseConfigOptions): UseFirebaseConfigResult;
@@ -0,0 +1,53 @@
1
+ import { FirebaseSeatStates } from '@zonetrix/shared';
2
+ export interface UseFirebaseSeatStatesOptions {
3
+ /** The seat map ID to subscribe to */
4
+ seatMapId: string | null;
5
+ /** Current user ID for user-aware state derivation */
6
+ currentUserId?: string;
7
+ /** Whether the subscription is enabled (default: true) */
8
+ enabled?: boolean;
9
+ /** Callback when states change */
10
+ onStateChange?: (states: FirebaseSeatStates) => void;
11
+ /** Callback on error */
12
+ onError?: (error: Error) => void;
13
+ }
14
+ export interface UseFirebaseSeatStatesResult {
15
+ /** Current seat states map */
16
+ states: FirebaseSeatStates | null;
17
+ /** Whether initial load is in progress */
18
+ loading: boolean;
19
+ /** Any error that occurred */
20
+ error: Error | null;
21
+ /** Timestamp of last update */
22
+ lastUpdated: number | null;
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 */
28
+ unavailableSeats: string[];
29
+ /** @deprecated Use otherReservedSeats instead */
30
+ reservedSeats: string[];
31
+ }
32
+ /**
33
+ * Subscribe to real-time seat state updates from Firebase
34
+ * Uses useSyncExternalStore for stable snapshot handling
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * const { myReservedSeats, otherReservedSeats, unavailableSeats, loading } = useFirebaseSeatStates({
39
+ * seatMapId: '123',
40
+ * currentUserId: 'user-abc',
41
+ * });
42
+ *
43
+ * return (
44
+ * <SeatMapViewer
45
+ * config={config}
46
+ * myReservedSeats={myReservedSeats}
47
+ * reservedSeats={otherReservedSeats}
48
+ * unavailableSeats={unavailableSeats}
49
+ * />
50
+ * );
51
+ * ```
52
+ */
53
+ export declare function useFirebaseSeatStates(options: UseFirebaseSeatStatesOptions): UseFirebaseSeatStatesResult;
@@ -0,0 +1,74 @@
1
+ import { SeatMapConfig } from '../types';
2
+ import { FirebaseSeatStates } from '@zonetrix/shared';
3
+ export interface UseRealtimeSeatMapOptions {
4
+ /** The seat map ID to load and subscribe to */
5
+ seatMapId: string | null;
6
+ /** Current user ID for user-aware state derivation */
7
+ userId?: string;
8
+ /** Whether the hook is enabled (default: true) */
9
+ enabled?: boolean;
10
+ /** Subscribe to design changes in real-time (default: false) */
11
+ subscribeToDesignChanges?: boolean;
12
+ /** Callback when config loads */
13
+ onConfigLoad?: (config: SeatMapConfig) => void;
14
+ /** Callback when seat states change */
15
+ onStateChange?: (states: FirebaseSeatStates) => void;
16
+ /** Callback on any error */
17
+ onError?: (error: Error) => void;
18
+ }
19
+ export interface UseRealtimeSeatMapResult {
20
+ /** The seat map configuration */
21
+ config: SeatMapConfig | null;
22
+ /** Whether initial loading is in progress */
23
+ loading: boolean;
24
+ /** Any error that occurred */
25
+ error: Error | null;
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 */
31
+ unavailableSeats: string[];
32
+ /** @deprecated Use otherReservedSeats instead */
33
+ reservedSeats: string[];
34
+ /** Raw seat states map */
35
+ seatStates: FirebaseSeatStates | null;
36
+ /** Timestamp of last state update */
37
+ lastUpdated: number | null;
38
+ /** Manually refetch the config */
39
+ refetch: () => Promise<void>;
40
+ }
41
+ /**
42
+ * Combined hook for loading config and subscribing to real-time seat states
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * import { useRealtimeSeatMap, SeatMapViewer } from '@zonetrix/viewer';
47
+ *
48
+ * function BookingPage({ seatMapId, userId }) {
49
+ * const {
50
+ * config,
51
+ * myReservedSeats,
52
+ * otherReservedSeats,
53
+ * unavailableSeats,
54
+ * loading,
55
+ * error
56
+ * } = useRealtimeSeatMap({ seatMapId, userId });
57
+ *
58
+ * if (loading) return <LoadingSpinner />;
59
+ * if (error) return <ErrorMessage error={error} />;
60
+ * if (!config) return null;
61
+ *
62
+ * return (
63
+ * <SeatMapViewer
64
+ * config={config}
65
+ * myReservedSeats={myReservedSeats}
66
+ * reservedSeats={otherReservedSeats}
67
+ * unavailableSeats={unavailableSeats}
68
+ * onSeatSelect={handleSeatSelect}
69
+ * />
70
+ * );
71
+ * }
72
+ * ```
73
+ */
74
+ export declare function useRealtimeSeatMap(options: UseRealtimeSeatMapOptions): UseRealtimeSeatMapResult;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),n=require("react"),T=require("react-konva"),O=require("@zonetrix/shared");function Ce(o){const[f,t]=n.useState(null),[a,w]=n.useState(!1),[b,g]=n.useState(null),y=n.useCallback(async()=>{if(o){w(!0),g(null);try{const p=await fetch(o);if(!p.ok)throw new Error(`Failed to fetch config: ${p.statusText}`);const l=await p.json();t(l)}catch(p){const l=p instanceof Error?p:new Error("Unknown error occurred");g(l),console.error("Failed to fetch seat map config:",l)}finally{w(!1)}}},[o]);return n.useEffect(()=>{y()},[y]),{config:f,loading:a,error:b,refetch:y}}function je(o){const[f,t]=n.useState({width:0,height:0});return n.useEffect(()=>{const a=o.current;if(!a)return;const{width:w,height:b}=a.getBoundingClientRect();w>0&&b>0&&t({width:w,height:b});const g=new ResizeObserver(y=>{const p=y[0];if(!p)return;const{width:l,height:x}=p.contentRect;l>0&&x>0&&t(m=>m.width===l&&m.height===x?m:{width:l,height:x})});return g.observe(a),()=>{g.disconnect()}},[o]),f}function ve(o,f){return Math.sqrt(Math.pow(f.x-o.x,2)+Math.pow(f.y-o.y,2))}function we(o,f){return{x:(o.x+f.x)/2,y:(o.y+f.y)/2}}function Me(o,f){const t=n.useRef(null),a=n.useRef(null),w=n.useRef(1),{enabled:b,minScale:g,maxScale:y,currentScale:p,currentPosition:l,onScaleChange:x}=f;n.useEffect(()=>{const m=o.current;if(!m||!b)return;const d=m.container(),k=S=>{if(S.touches.length===2){S.preventDefault();const P={x:S.touches[0].clientX,y:S.touches[0].clientY},E={x:S.touches[1].clientX,y:S.touches[1].clientY};t.current=ve(P,E),a.current=we(P,E),w.current=p}},v=S=>{if(S.touches.length!==2)return;S.preventDefault();const P={x:S.touches[0].clientX,y:S.touches[0].clientY},E={x:S.touches[1].clientX,y:S.touches[1].clientY},Y=ve(P,E),M=we(P,E);if(t.current!==null&&a.current!==null){const $=Y/t.current,z=Math.min(Math.max(p*$,g),y),_=d.getBoundingClientRect(),A=M.x-_.left,ee=M.y-_.top,te=p,ne={x:(A-l.x)/te,y:(ee-l.y)/te},ie=M.x-a.current.x,L=M.y-a.current.y,B={x:A-ne.x*z+ie,y:ee-ne.y*z+L};x(z,B),t.current=Y,a.current=M}},C=S=>{S.touches.length<2&&(t.current=null,a.current=null)};return d.addEventListener("touchstart",k,{passive:!1}),d.addEventListener("touchmove",v,{passive:!1}),d.addEventListener("touchend",C),()=>{d.removeEventListener("touchstart",k),d.removeEventListener("touchmove",v),d.removeEventListener("touchend",C)}},[o,b,g,y,p,l,x])}const ke={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Fe=n.memo(({seat:o,state:f,colors:t,onClick:a,onMouseEnter:w,onMouseLeave:b})=>{const g=(o.size||24)/2,p={available:t.seatAvailable,reserved:t.seatReserved,selected:t.seatSelected,unavailable:t.seatUnavailable,hidden:t.seatHidden}[f],l=f==="available"||f==="selected",x=n.useCallback(()=>{l&&a(o)},[o,a,l]),m=n.useCallback(v=>{w(o,v);const C=v.target.getStage();C&&l&&(C.container().style.cursor="pointer")},[o,w,l]),d=n.useCallback(v=>{b();const C=v.target.getStage();C&&(C.container().style.cursor="grab")},[b]),k={x:o.position.x,y:o.position.y,fill:p,stroke:"#ffffff",strokeWidth:1,onClick:x,onTap:x,onMouseEnter:m,onMouseLeave:d};return o.shape==="circle"?i.jsx(T.Circle,{...k,radius:g}):i.jsx(T.Rect,{...k,width:g*2,height:g*2,offsetX:g,offsetY:g,cornerRadius:o.shape==="square"?0:4})});Fe.displayName="ViewerSeat";const Re=n.memo(({stage:o,stageColor:f})=>{const t=o.config,a=t.shape||"rectangle",w=t.showLabel!==!1,b=t.color||f,g=t.width/t.height,y=g<.5,p=g>2;let l;y?l=t.width*.25:p?l=t.height*.35:l=Math.min(t.width,t.height)*.25;const x=t.label?.length||6,k=t.width*.85/x*1.5,v=Math.max(10,Math.min(24,Math.min(l,k))),C=4,S=Math.max(20,t.width-C*2),P=(t.width-S)/2,E={fill:b+"80",stroke:"#ffffff",strokeWidth:2,perfectDrawEnabled:!1,hitStrokeWidth:0},Y=()=>{switch(a){case"circle":{const M=Math.min(t.width,t.height)/2;return i.jsx(T.Circle,{x:t.width/2,y:t.height/2,radius:M,...E})}case"triangle":{const M=Math.min(t.width,t.height)/2;return i.jsx(T.RegularPolygon,{x:t.width/2,y:t.height/2,sides:3,radius:M,rotation:-90,...E})}case"arrow":{const M=t.width/24,$=t.height/24,z=`M${9*M},${18*$} v${-8*$} H${5*M} l${7*M},${-7*$} l${7*M},${7*$} h${-4*M} v${8*$} Z`;return i.jsx(T.Path,{data:z,...E})}default:return i.jsx(T.Rect,{width:t.width,height:t.height,cornerRadius:10,...E})}};return i.jsxs(T.Group,{x:o.position.x,y:o.position.y,rotation:t.rotation||0,children:[Y(),w&&i.jsx(T.Text,{text:t.label,x:P,y:C,width:S,height:t.height-C*2,fontSize:v,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle",wrap:"word",ellipsis:!0})]})});Re.displayName="ViewerStage";const Ie=n.memo(({text:o})=>i.jsx(T.Text,{x:o.position.x,y:o.position.y,text:o.config.text,fontSize:o.config.fontSize,fill:o.config.color,rotation:o.config.rotation||0,listening:!1}));Ie.displayName="ViewerText";const Ee=n.memo(({floors:o,currentFloorId:f,onFloorChange:t,showAllOption:a,allLabel:w,position:b,className:g})=>{const y=n.useMemo(()=>[...o].sort((d,k)=>d.order-k.order),[o]),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}}[b]},x={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"},m={...x,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return i.jsxs("div",{className:g,style:l,children:[a&&i.jsx("button",{type:"button",onClick:()=>t(null),style:f===null?m:x,children:w}),y.map(d=>i.jsx("button",{type:"button",onClick:()=>t(d.id),style:f===d.id?m:x,children:d.name},d.id))]})});Ee.displayName="FloorSelectorBar";const Te=n.memo(({scale:o,minScale:f,maxScale:t,fitScale:a,onZoomIn:w,onZoomOut:b,onFitToScreen:g,position:y,className:p})=>{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}}[y]},m={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"},d={...m,opacity:.4,cursor:"not-allowed"},k=o<t,v=o>f,C=Math.abs(o-a)<.01;return i.jsxs("div",{className:p,style:x,children:[i.jsx("button",{type:"button",onClick:w,disabled:!k,style:k?m:d,title:"Zoom In","aria-label":"Zoom In",children:"+"}),i.jsx("button",{type:"button",onClick:g,disabled:C,style:C?d:m,title:"Fit to Screen","aria-label":"Fit to Screen",children:"⤢"}),i.jsx("button",{type:"button",onClick:b,disabled:!v,style:v?m:d,title:"Zoom Out","aria-label":"Zoom Out",children:"−"})]})});Te.displayName="ZoomControls";const De=n.memo(({visible:o,x:f,y:t,seat:a,currency:w,state:b})=>{if(!o||!a)return null;const g=a.seatNumber||(a.rowLabel&&a.columnLabel?`${a.rowLabel}-${a.columnLabel}`:"N/A"),y={position:"fixed",left:`${f+15}px`,top:`${t+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"},x={fontWeight:600},m={color:"#4ade80",fontWeight:600},d={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return i.jsx("div",{style:y,children:i.jsxs("div",{style:p,children:[a.sectionName&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Section:"}),i.jsx("span",{style:{...x,color:"#3b82f6"},children:a.sectionName})]}),i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Seat:"}),i.jsx("span",{style:x,children:g})]}),a.price!==void 0&&a.price>0&&b==="available"&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Price:"}),i.jsxs("span",{style:m,children:[w," ",a.price.toFixed(2)]})]}),i.jsxs("div",{style:d,children:["Status: ",b]})]})})});De.displayName="SeatTooltip";const et=({config:o,configUrl:f,floorId:t,onFloorChange:a,reservedSeats:w=[],otherReservedSeats:b,unavailableSeats:g=[],selectedSeats:y,myReservedSeats:p=[],onSeatSelect:l,onSeatDeselect:x,onSelectionChange:m,colorOverrides:d,showTooltip:k=!0,zoomEnabled:v=!0,className:C="",onConfigLoad:S,onError:P,showFloorSelector:E,floorSelectorPosition:Y="top-left",floorSelectorClassName:M,showAllFloorsOption:$=!0,allFloorsLabel:z="All",fitToView:_=!0,fitPadding:A=40,showZoomControls:ee=!0,zoomControlsPosition:te="bottom-right",zoomControlsClassName:ne,minZoom:ie,maxZoom:L=3,zoomStep:B=.25,touchEnabled:Pe=!0})=>{const xe=b!==void 0?b:w,ue=n.useRef(null),be=n.useRef(null),j=je(be),[H,ye]=n.useState(new Set),[R,G]=n.useState(1),[D,V]=n.useState({x:0,y:0}),[Le,Ne]=n.useState(null),[me,We]=n.useState(1),oe=n.useRef({width:0,height:0}),[U,Se]=n.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:$e,loading:ze,error:K}=Ce(f),c=o||$e,he=t!==void 0,I=he?t||null:Le,se=y!==void 0,Xe=n.useCallback(e=>{he||Ne(e),a?.(e)},[he,a]),de=c?.floors||[],Oe=E!==void 0?E:de.length>1,re=n.useMemo(()=>c?{...c.colors,...d}:{...ke,...d},[c,d]),q=n.useMemo(()=>{if(!c)return[];let e=c.seats.filter(s=>s.state!=="hidden");return I&&(e=e.filter(s=>s.floorId===I||!s.floorId&&I==="floor_default")),e},[c,I]),ae=n.useMemo(()=>c?.stages?I?c.stages.filter(e=>e.floorId===I||!e.floorId&&I==="floor_default"):c.stages:[],[c,I]),ce=n.useMemo(()=>c?.texts?I?c.texts.filter(e=>e.floorId===I||!e.floorId&&I==="floor_default"):c.texts:[],[c,I]),N=n.useMemo(()=>{if(!c||q.length===0&&ae.length===0&&ce.length===0)return null;let e=1/0,s=1/0,u=-1/0,h=-1/0;return q.forEach(r=>{const F=(r.size||24)/2;e=Math.min(e,r.position.x-F),s=Math.min(s,r.position.y-F),u=Math.max(u,r.position.x+F),h=Math.max(h,r.position.y+F)}),ae.forEach(r=>{e=Math.min(e,r.position.x),s=Math.min(s,r.position.y),u=Math.max(u,r.position.x+(r.config?.width||200)),h=Math.max(h,r.position.y+(r.config?.height||100))}),ce.forEach(r=>{const F=r.config.text.length*r.config.fontSize*.6,W=r.config.fontSize;e=Math.min(e,r.position.x),s=Math.min(s,r.position.y),u=Math.max(u,r.position.x+F),h=Math.max(h,r.position.y+W)}),{minX:e,minY:s,maxX:u,maxY:h,width:u-e,height:h-s}},[c,q,ae,ce]),fe=n.useCallback(()=>{if(!c||!N||j.width===0||j.height===0)return;const e=j.width,s=j.height,u=e-A*2,h=s-A*2,r=u/N.width,F=h/N.height,W=Math.min(r,F,L),le=N.minX+N.width/2,pe=N.minY+N.height/2,Ue=e/2,Ke=s/2,Je=Ue-le*W,Qe=Ke-pe*W;G(W),V({x:Je,y:Qe}),We(W)},[c,N,j,A,L]);n.useEffect(()=>{if(!_||!c||!N||j.width===0||j.height===0)return;const e=Math.abs(j.width-oe.current.width),s=Math.abs(j.height-oe.current.height);!(oe.current.width===0)&&e<10&&s<10||(oe.current=j,fe())},[_,c,N,j,I,fe]);const X=n.useMemo(()=>{const e=new Set(xe),s=new Set(g),u=new Set(p);return{reserved:e,unavailable:s,myReserved:u}},[xe,g,p]),ge=n.useMemo(()=>y?new Set(y):null,[y]),J=n.useCallback(e=>{const s=e.id,u=e.seatNumber||"";return X.unavailable.has(s)||X.unavailable.has(u)?"unavailable":X.reserved.has(s)||X.reserved.has(u)?"reserved":X.myReserved.has(s)||X.myReserved.has(u)||H.has(s)?"selected":e.state},[X,H]);n.useEffect(()=>{c&&S&&S(c)},[c,S]),n.useEffect(()=>{K&&P&&P(K)},[K,P]),n.useEffect(()=>{se&&ge&&ye(ge)},[se,ge]);const Ye=n.useCallback(e=>{const s=J(e);if(s!=="available"&&s!=="selected")return;const u=H.has(e.id);se||ye(h=>{const r=new Set(h);return u?r.delete(e.id):r.add(e.id),r}),u?x?.(e):(l?.(e),l||console.log("Seat selected:",e))},[J,H,se,l,x]),Q=n.useMemo(()=>c?q.filter(e=>H.has(e.id)):[],[c,q,H]);n.useEffect(()=>{m?.(Q)},[Q,m]);const Z=ie!==void 0?ie:me*.5,Ae=n.useCallback(()=>{if(!v)return;const e=Math.min(R+B,L);if(e!==R){const s=j.width||c?.canvas.width||800,u=j.height||c?.canvas.height||600,h=s/2,r=u/2,F={x:(h-D.x)/R,y:(r-D.y)/R};G(e),V({x:h-F.x*e,y:r-F.y*e})}},[v,R,B,L,j,c,D]),Be=n.useCallback(()=>{if(!v)return;const e=Math.max(R-B,Z);if(e!==R){const s=j.width||c?.canvas.width||800,u=j.height||c?.canvas.height||600,h=s/2,r=u/2,F={x:(h-D.x)/R,y:(r-D.y)/R};G(e),V({x:h-F.x*e,y:r-F.y*e})}},[v,R,B,Z,j,c,D]),He=n.useCallback(e=>{V({x:e.target.x(),y:e.target.y()})},[]),Ve=n.useCallback(e=>{if(!v)return;e.evt.preventDefault();const s=ue.current;if(!s)return;const u=s.scaleX(),h=s.getPointerPosition();if(!h)return;const r=1.1,F=e.evt.deltaY>0?u/r:u*r,W=Math.min(Math.max(F,Z),L),le={x:(h.x-D.x)/u,y:(h.y-D.y)/u},pe={x:h.x-le.x*W,y:h.y-le.y*W};G(W),V(pe)},[v,D,Z,L]);Me(ue,{enabled:Pe&&v,minScale:Z,maxScale:L,currentScale:R,currentPosition:D,onScaleChange:(e,s)=>{G(e),V(s)}});const qe=n.useCallback((e,s)=>{if(!k)return;const u=s.target.getStage();if(!u)return;const h=u.getPointerPosition();if(!h)return;const r=u.container().getBoundingClientRect();Se({visible:!0,x:r.left+h.x,y:r.top+h.y,seat:e,state:J(e)})},[k,J]),Ze=n.useCallback(()=>{Se(e=>({...e,visible:!1}))},[]);if(ze)return i.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:i.jsx("p",{children:"Loading seat map..."})});if(K)return i.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:i.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",K.message]})});if(!c)return i.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:i.jsx("p",{children:"No configuration provided"})});const _e=j.width||c.canvas.width,Ge=j.height||c.canvas.height;return i.jsxs("div",{ref:be,className:`relative ${C}`,style:{width:"100%",height:"100%"},children:[Oe&&de.length>0&&i.jsx(Ee,{floors:de,currentFloorId:I,onFloorChange:Xe,showAllOption:$,allLabel:z,position:Y,className:M}),i.jsxs(T.Stage,{ref:ue,width:_e,height:Ge,scaleX:R,scaleY:R,x:D.x,y:D.y,draggable:!0,onDragEnd:He,onWheel:Ve,style:{backgroundColor:c.canvas.backgroundColor,cursor:"grab"},children:[i.jsx(T.Layer,{listening:!1,children:ae.map(e=>i.jsx(Re,{stage:e,stageColor:re.stageColor},e.id))}),i.jsx(T.Layer,{listening:!1,children:ce.map(e=>i.jsx(Ie,{text:e},e.id))}),i.jsx(T.Layer,{children:q.map(e=>i.jsx(Fe,{seat:e,state:J(e),colors:re,onClick:Ye,onMouseEnter:qe,onMouseLeave:Ze},e.id))})]}),k&&i.jsx(De,{visible:U.visible,x:U.x,y:U.y,seat:U.seat,currency:re.currency,state:U.state}),ee&&v&&i.jsx(Te,{scale:R,minScale:Z,maxScale:L,fitScale:me,onZoomIn:Ae,onZoomOut:Be,onFitToScreen:fe,position:te,className:ne}),Q.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 (",Q.length,")"]}),i.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Q.map(e=>i.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${re.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};Object.defineProperty(exports,"clearFirebaseInstance",{enumerable:!0,get:()=>O.clearFirebaseInstance});Object.defineProperty(exports,"getFirebaseDatabase",{enumerable:!0,get:()=>O.getFirebaseDatabase});Object.defineProperty(exports,"initializeFirebaseForViewer",{enumerable:!0,get:()=>O.initializeFirebaseForViewer});Object.defineProperty(exports,"isFirebaseInitialized",{enumerable:!0,get:()=>O.isFirebaseInitialized});Object.defineProperty(exports,"useFirebaseConfig",{enumerable:!0,get:()=>O.useFirebaseConfig});Object.defineProperty(exports,"useFirebaseSeatStates",{enumerable:!0,get:()=>O.useFirebaseSeatStates});Object.defineProperty(exports,"useRealtimeSeatMap",{enumerable:!0,get:()=>O.useRealtimeSeatMap});exports.DEFAULT_COLORS=ke;exports.SeatMapViewer=et;exports.useConfigFetcher=Ce;exports.useContainerSize=je;exports.useTouchGestures=Me;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),n=require("react"),T=require("react-konva"),z=require("@zonetrix/shared");function Ce(i){const[f,t]=n.useState(null),[a,w]=n.useState(!1),[b,g]=n.useState(null),y=n.useCallback(async()=>{if(i){w(!0),g(null);try{const p=await fetch(i);if(!p.ok)throw new Error(`Failed to fetch config: ${p.statusText}`);const l=await p.json();t(l)}catch(p){const l=p instanceof Error?p:new Error("Unknown error occurred");g(l),console.error("Failed to fetch seat map config:",l)}finally{w(!1)}}},[i]);return n.useEffect(()=>{y()},[y]),{config:f,loading:a,error:b,refetch:y}}function je(i){const[f,t]=n.useState({width:0,height:0});return n.useEffect(()=>{const a=i.current;if(!a)return;const{width:w,height:b}=a.getBoundingClientRect();w>0&&b>0&&t({width:w,height:b});const g=new ResizeObserver(y=>{const p=y[0];if(!p)return;const{width:l,height:x}=p.contentRect;l>0&&x>0&&t(m=>m.width===l&&m.height===x?m:{width:l,height:x})});return g.observe(a),()=>{g.disconnect()}},[i]),f}function ve(i,f){return Math.sqrt(Math.pow(f.x-i.x,2)+Math.pow(f.y-i.y,2))}function we(i,f){return{x:(i.x+f.x)/2,y:(i.y+f.y)/2}}function Me(i,f){const t=n.useRef(null),a=n.useRef(null),w=n.useRef(1),{enabled:b,minScale:g,maxScale:y,currentScale:p,currentPosition:l,onScaleChange:x}=f;n.useEffect(()=>{const m=i.current;if(!m||!b)return;const d=m.container(),k=S=>{if(S.touches.length===2){S.preventDefault();const P={x:S.touches[0].clientX,y:S.touches[0].clientY},E={x:S.touches[1].clientX,y:S.touches[1].clientY};t.current=ve(P,E),a.current=we(P,E),w.current=p}},v=S=>{if(S.touches.length!==2)return;S.preventDefault();const P={x:S.touches[0].clientX,y:S.touches[0].clientY},E={x:S.touches[1].clientX,y:S.touches[1].clientY},O=ve(P,E),M=we(P,E);if(t.current!==null&&a.current!==null){const X=O/t.current,Y=Math.min(Math.max(p*X,g),y),G=d.getBoundingClientRect(),A=M.x-G.left,ne=M.y-G.top,ie=p,se={x:(A-l.x)/ie,y:(ne-l.y)/ie},oe=M.x-a.current.x,L=M.y-a.current.y,B={x:A-se.x*Y+oe,y:ne-se.y*Y+L};x(Y,B),t.current=O,a.current=M}},C=S=>{S.touches.length<2&&(t.current=null,a.current=null)};return d.addEventListener("touchstart",k,{passive:!1}),d.addEventListener("touchmove",v,{passive:!1}),d.addEventListener("touchend",C),()=>{d.removeEventListener("touchstart",k),d.removeEventListener("touchmove",v),d.removeEventListener("touchend",C)}},[i,b,g,y,p,l,x])}const ke={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Fe=n.memo(({seat:i,state:f,colors:t,onClick:a,onMouseEnter:w,onMouseLeave:b})=>{const g=(i.size||24)/2,p={available:t.seatAvailable,reserved:t.seatReserved,selected:t.seatSelected,unavailable:t.seatUnavailable,hidden:t.seatHidden}[f],l=f==="available"||f==="selected",x=n.useCallback(()=>{l&&a(i)},[i,a,l]),m=n.useCallback(v=>{w(i,v);const C=v.target.getStage();C&&l&&(C.container().style.cursor="pointer")},[i,w,l]),d=n.useCallback(v=>{b();const C=v.target.getStage();C&&(C.container().style.cursor="grab")},[b]),k={x:i.position.x,y:i.position.y,fill:p,stroke:"#ffffff",strokeWidth:1,onClick:x,onTap:x,onMouseEnter:m,onMouseLeave:d};return i.shape==="circle"?s.jsx(T.Circle,{...k,radius:g}):s.jsx(T.Rect,{...k,width:g*2,height:g*2,offsetX:g,offsetY:g,cornerRadius:i.shape==="square"?0:4})});Fe.displayName="ViewerSeat";const Re=n.memo(({stage:i,stageColor:f})=>{const t=i.config,a=t.shape||"rectangle",w=t.showLabel!==!1,b=t.color||f,g=t.width/t.height,y=g<.5,p=g>2;let l;y?l=t.width*.25:p?l=t.height*.35:l=Math.min(t.width,t.height)*.25;const x=t.label?.length||6,k=t.width*.85/x*1.5,v=Math.max(10,Math.min(24,Math.min(l,k))),C=4,S=Math.max(20,t.width-C*2),P=(t.width-S)/2,E={fill:b+"80",stroke:"#ffffff",strokeWidth:2,perfectDrawEnabled:!1,hitStrokeWidth:0},O=()=>{switch(a){case"circle":{const M=Math.min(t.width,t.height)/2;return s.jsx(T.Circle,{x:t.width/2,y:t.height/2,radius:M,...E})}case"triangle":{const M=Math.min(t.width,t.height)/2;return s.jsx(T.RegularPolygon,{x:t.width/2,y:t.height/2,sides:3,radius:M,rotation:-90,...E})}case"arrow":{const M=t.width/24,X=t.height/24,Y=`M${9*M},${18*X} v${-8*X} H${5*M} l${7*M},${-7*X} l${7*M},${7*X} h${-4*M} v${8*X} Z`;return s.jsx(T.Path,{data:Y,...E})}default:return s.jsx(T.Rect,{width:t.width,height:t.height,cornerRadius:10,...E})}};return s.jsxs(T.Group,{x:i.position.x,y:i.position.y,rotation:t.rotation||0,children:[O(),w&&s.jsx(T.Text,{text:t.label,x:P,y:C,width:S,height:t.height-C*2,fontSize:v,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle",wrap:"word",ellipsis:!0})]})});Re.displayName="ViewerStage";const Ie=n.memo(({text:i})=>s.jsx(T.Text,{x:i.position.x,y:i.position.y,text:i.config.text,fontSize:i.config.fontSize,fill:i.config.color,rotation:i.config.rotation||0,scaleX:i.config.scaleX||1,scaleY:i.config.scaleY||1,listening:!1}));Ie.displayName="ViewerText";const Ee=n.memo(({floors:i,currentFloorId:f,onFloorChange:t,showAllOption:a,allLabel:w,position:b,className:g})=>{const y=n.useMemo(()=>[...i].sort((d,k)=>d.order-k.order),[i]),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}}[b]},x={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"},m={...x,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return s.jsxs("div",{className:g,style:l,children:[a&&s.jsx("button",{type:"button",onClick:()=>t(null),style:f===null?m:x,children:w}),y.map(d=>s.jsx("button",{type:"button",onClick:()=>t(d.id),style:f===d.id?m:x,children:d.name},d.id))]})});Ee.displayName="FloorSelectorBar";const Te=n.memo(({scale:i,minScale:f,maxScale:t,fitScale:a,onZoomIn:w,onZoomOut:b,onFitToScreen:g,position:y,className:p})=>{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}}[y]},m={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"},d={...m,opacity:.4,cursor:"not-allowed"},k=i<t,v=i>f,C=Math.abs(i-a)<.01;return s.jsxs("div",{className:p,style:x,children:[s.jsx("button",{type:"button",onClick:w,disabled:!k,style:k?m:d,title:"Zoom In","aria-label":"Zoom In",children:"+"}),s.jsx("button",{type:"button",onClick:g,disabled:C,style:C?d:m,title:"Fit to Screen","aria-label":"Fit to Screen",children:"⤢"}),s.jsx("button",{type:"button",onClick:b,disabled:!v,style:v?m:d,title:"Zoom Out","aria-label":"Zoom Out",children:"−"})]})});Te.displayName="ZoomControls";const De=n.memo(({visible:i,x:f,y:t,seat:a,currency:w,state:b})=>{if(!i||!a)return null;const g=a.seatNumber||(a.rowLabel&&a.columnLabel?`${a.rowLabel}-${a.columnLabel}`:"N/A"),y={position:"fixed",left:`${f+15}px`,top:`${t+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"},x={fontWeight:600},m={color:"#4ade80",fontWeight:600},d={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return s.jsx("div",{style:y,children:s.jsxs("div",{style:p,children:[a.sectionName&&s.jsxs("div",{style:{marginBottom:"4px"},children:[s.jsx("span",{style:l,children:"Section:"}),s.jsx("span",{style:{...x,color:"#3b82f6"},children:a.sectionName})]}),s.jsxs("div",{style:{marginBottom:"4px"},children:[s.jsx("span",{style:l,children:"Seat:"}),s.jsx("span",{style:x,children:g})]}),a.price!==void 0&&a.price>0&&b==="available"&&s.jsxs("div",{style:{marginBottom:"4px"},children:[s.jsx("span",{style:l,children:"Price:"}),s.jsxs("span",{style:m,children:[w," ",a.price.toFixed(2)]})]}),s.jsxs("div",{style:d,children:["Status: ",b]})]})})});De.displayName="SeatTooltip";const et=({config:i,configUrl:f,floorId:t,onFloorChange:a,reservedSeats:w=[],otherReservedSeats:b,unavailableSeats:g=[],selectedSeats:y,myReservedSeats:p=[],onSeatSelect:l,onSeatDeselect:x,onSelectionChange:m,colorOverrides:d,showTooltip:k=!0,zoomEnabled:v=!0,className:C="",onConfigLoad:S,onError:P,showFloorSelector:E,floorSelectorPosition:O="top-left",floorSelectorClassName:M,showAllFloorsOption:X=!0,allFloorsLabel:Y="All",fitToView:G=!0,fitPadding:A=40,showZoomControls:ne=!0,zoomControlsPosition:ie="bottom-right",zoomControlsClassName:se,minZoom:oe,maxZoom:L=3,zoomStep:B=.25,touchEnabled:Pe=!0})=>{const xe=b!==void 0?b:w,he=n.useRef(null),be=n.useRef(null),j=je(be),[H,ye]=n.useState(new Set),[R,U]=n.useState(1),[D,V]=n.useState({x:0,y:0}),[Le,Ne]=n.useState(null),[me,We]=n.useState(1),re=n.useRef({width:0,height:0}),[K,Se]=n.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Xe,loading:Ye,error:J}=Ce(f),c=i||Xe,de=t!==void 0,I=de?t||null:Le,ae=y!==void 0,$e=n.useCallback(e=>{de||Ne(e),a?.(e)},[de,a]),fe=c?.floors||[],ze=E!==void 0?E:fe.length>1,ce=n.useMemo(()=>c?{...c.colors,...d}:{...ke,...d},[c,d]),q=n.useMemo(()=>{if(!c)return[];let e=c.seats.filter(o=>o.state!=="hidden");return I&&(e=e.filter(o=>o.floorId===I||!o.floorId&&I==="floor_default")),e},[c,I]),le=n.useMemo(()=>c?.stages?I?c.stages.filter(e=>e.floorId===I||!e.floorId&&I==="floor_default"):c.stages:[],[c,I]),ue=n.useMemo(()=>c?.texts?I?c.texts.filter(e=>e.floorId===I||!e.floorId&&I==="floor_default"):c.texts:[],[c,I]),N=n.useMemo(()=>{if(!c||q.length===0&&le.length===0&&ue.length===0)return null;let e=1/0,o=1/0,u=-1/0,h=-1/0;return q.forEach(r=>{const F=(r.size||24)/2;e=Math.min(e,r.position.x-F),o=Math.min(o,r.position.y-F),u=Math.max(u,r.position.x+F),h=Math.max(h,r.position.y+F)}),le.forEach(r=>{e=Math.min(e,r.position.x),o=Math.min(o,r.position.y),u=Math.max(u,r.position.x+(r.config?.width||200)),h=Math.max(h,r.position.y+(r.config?.height||100))}),ue.forEach(r=>{const F=r.config.scaleX||1,W=r.config.scaleY||1,_=r.config.text.length*r.config.fontSize*.6*F,te=r.config.fontSize*W;e=Math.min(e,r.position.x),o=Math.min(o,r.position.y),u=Math.max(u,r.position.x+_),h=Math.max(h,r.position.y+te)}),{minX:e,minY:o,maxX:u,maxY:h,width:u-e,height:h-o}},[c,q,le,ue]),ge=n.useCallback(()=>{if(!c||!N||j.width===0||j.height===0)return;const e=j.width,o=j.height,u=e-A*2,h=o-A*2,r=u/N.width,F=h/N.height,W=Math.min(r,F,L),_=N.minX+N.width/2,te=N.minY+N.height/2,Ue=e/2,Ke=o/2,Je=Ue-_*W,Qe=Ke-te*W;U(W),V({x:Je,y:Qe}),We(W)},[c,N,j,A,L]);n.useEffect(()=>{if(!G||!c||!N||j.width===0||j.height===0)return;const e=Math.abs(j.width-re.current.width),o=Math.abs(j.height-re.current.height);!(re.current.width===0)&&e<10&&o<10||(re.current=j,ge())},[G,c,N,j,I,ge]);const $=n.useMemo(()=>{const e=new Set(xe),o=new Set(g),u=new Set(p);return{reserved:e,unavailable:o,myReserved:u}},[xe,g,p]),pe=n.useMemo(()=>y?new Set(y):null,[y]),Q=n.useCallback(e=>{const o=e.id,u=e.seatNumber||"";return $.unavailable.has(o)||$.unavailable.has(u)?"unavailable":$.reserved.has(o)||$.reserved.has(u)?"reserved":$.myReserved.has(o)||$.myReserved.has(u)||H.has(o)?"selected":e.state},[$,H]);n.useEffect(()=>{c&&S&&S(c)},[c,S]),n.useEffect(()=>{J&&P&&P(J)},[J,P]),n.useEffect(()=>{ae&&pe&&ye(pe)},[ae,pe]);const Oe=n.useCallback(e=>{const o=Q(e);if(o!=="available"&&o!=="selected")return;const u=H.has(e.id);ae||ye(h=>{const r=new Set(h);return u?r.delete(e.id):r.add(e.id),r}),u?x?.(e):(l?.(e),l||console.log("Seat selected:",e))},[Q,H,ae,l,x]),ee=n.useMemo(()=>c?q.filter(e=>H.has(e.id)):[],[c,q,H]);n.useEffect(()=>{m?.(ee)},[ee,m]);const Z=oe!==void 0?oe:me*.5,Ae=n.useCallback(()=>{if(!v)return;const e=Math.min(R+B,L);if(e!==R){const o=j.width||c?.canvas.width||800,u=j.height||c?.canvas.height||600,h=o/2,r=u/2,F={x:(h-D.x)/R,y:(r-D.y)/R};U(e),V({x:h-F.x*e,y:r-F.y*e})}},[v,R,B,L,j,c,D]),Be=n.useCallback(()=>{if(!v)return;const e=Math.max(R-B,Z);if(e!==R){const o=j.width||c?.canvas.width||800,u=j.height||c?.canvas.height||600,h=o/2,r=u/2,F={x:(h-D.x)/R,y:(r-D.y)/R};U(e),V({x:h-F.x*e,y:r-F.y*e})}},[v,R,B,Z,j,c,D]),He=n.useCallback(e=>{V({x:e.target.x(),y:e.target.y()})},[]),Ve=n.useCallback(e=>{if(!v)return;e.evt.preventDefault();const o=he.current;if(!o)return;const u=o.scaleX(),h=o.getPointerPosition();if(!h)return;const r=1.1,F=e.evt.deltaY>0?u/r:u*r,W=Math.min(Math.max(F,Z),L),_={x:(h.x-D.x)/u,y:(h.y-D.y)/u},te={x:h.x-_.x*W,y:h.y-_.y*W};U(W),V(te)},[v,D,Z,L]);Me(he,{enabled:Pe&&v,minScale:Z,maxScale:L,currentScale:R,currentPosition:D,onScaleChange:(e,o)=>{U(e),V(o)}});const qe=n.useCallback((e,o)=>{if(!k)return;const u=o.target.getStage();if(!u)return;const h=u.getPointerPosition();if(!h)return;const r=u.container().getBoundingClientRect();Se({visible:!0,x:r.left+h.x,y:r.top+h.y,seat:e,state:Q(e)})},[k,Q]),Ze=n.useCallback(()=>{Se(e=>({...e,visible:!1}))},[]);if(Ye)return s.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:s.jsx("p",{children:"Loading seat map..."})});if(J)return s.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:s.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",J.message]})});if(!c)return s.jsx("div",{className:`flex items-center justify-center h-full ${C}`,children:s.jsx("p",{children:"No configuration provided"})});const _e=j.width||c.canvas.width,Ge=j.height||c.canvas.height;return s.jsxs("div",{ref:be,className:`relative ${C}`,style:{width:"100%",height:"100%"},children:[ze&&fe.length>0&&s.jsx(Ee,{floors:fe,currentFloorId:I,onFloorChange:$e,showAllOption:X,allLabel:Y,position:O,className:M}),s.jsxs(T.Stage,{ref:he,width:_e,height:Ge,scaleX:R,scaleY:R,x:D.x,y:D.y,draggable:!0,onDragEnd:He,onWheel:Ve,style:{backgroundColor:c.canvas.backgroundColor,cursor:"grab"},children:[s.jsx(T.Layer,{listening:!1,children:le.map(e=>s.jsx(Re,{stage:e,stageColor:ce.stageColor},e.id))}),s.jsx(T.Layer,{listening:!1,children:ue.map(e=>s.jsx(Ie,{text:e},e.id))}),s.jsx(T.Layer,{children:q.map(e=>s.jsx(Fe,{seat:e,state:Q(e),colors:ce,onClick:Oe,onMouseEnter:qe,onMouseLeave:Ze},e.id))})]}),k&&s.jsx(De,{visible:K.visible,x:K.x,y:K.y,seat:K.seat,currency:ce.currency,state:K.state}),ne&&v&&s.jsx(Te,{scale:R,minScale:Z,maxScale:L,fitScale:me,onZoomIn:Ae,onZoomOut:Be,onFitToScreen:ge,position:ie,className:se}),ee.length>0&&s.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[s.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",ee.length,")"]}),s.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:ee.map(e=>s.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${ce.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};Object.defineProperty(exports,"clearFirebaseInstance",{enumerable:!0,get:()=>z.clearFirebaseInstance});Object.defineProperty(exports,"getFirebaseDatabase",{enumerable:!0,get:()=>z.getFirebaseDatabase});Object.defineProperty(exports,"initializeFirebaseForViewer",{enumerable:!0,get:()=>z.initializeFirebaseForViewer});Object.defineProperty(exports,"isFirebaseInitialized",{enumerable:!0,get:()=>z.isFirebaseInitialized});Object.defineProperty(exports,"useFirebaseConfig",{enumerable:!0,get:()=>z.useFirebaseConfig});Object.defineProperty(exports,"useFirebaseSeatStates",{enumerable:!0,get:()=>z.useFirebaseSeatStates});Object.defineProperty(exports,"useRealtimeSeatMap",{enumerable:!0,get:()=>z.useRealtimeSeatMap});exports.DEFAULT_COLORS=ke;exports.SeatMapViewer=et;exports.useConfigFetcher=Ce;exports.useContainerSize=je;exports.useTouchGestures=Me;
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { jsx as a, jsxs as k } from "react/jsx-runtime";
2
- import { useState as Y, useCallback as N, useEffect as B, useRef as U, useMemo as z, memo as K } from "react";
2
+ import { useState as E, useCallback as N, useEffect as B, useRef as K, useMemo as z, memo as J } from "react";
3
3
  import { Stage as oe, Layer as vt, Group as re, Text as Rt, Circle as Dt, Rect as Nt, Path as se, RegularPolygon as ae } from "react-konva";
4
4
  import { clearFirebaseInstance as be, getFirebaseDatabase as me, initializeFirebaseForViewer as ve, isFirebaseInitialized as Se, useFirebaseConfig as we, useFirebaseSeatStates as Ce, useRealtimeSeatMap as Me } from "@zonetrix/shared";
5
5
  function ce(n) {
6
- const [u, e] = Y(null), [r, S] = Y(!1), [y, f] = Y(null), x = N(async () => {
6
+ const [u, e] = E(null), [r, S] = E(!1), [y, f] = E(null), x = N(async () => {
7
7
  if (n) {
8
8
  S(!0), f(null);
9
9
  try {
@@ -30,7 +30,7 @@ function ce(n) {
30
30
  };
31
31
  }
32
32
  function le(n) {
33
- const [u, e] = Y({ width: 0, height: 0 });
33
+ const [u, e] = E({ width: 0, height: 0 });
34
34
  return B(() => {
35
35
  const r = n.current;
36
36
  if (!r) return;
@@ -57,7 +57,7 @@ function kt(n, u) {
57
57
  };
58
58
  }
59
59
  function he(n, u) {
60
- const e = U(null), r = U(null), S = U(1), {
60
+ const e = K(null), r = K(null), S = K(1), {
61
61
  enabled: y,
62
62
  minScale: f,
63
63
  maxScale: x,
@@ -71,23 +71,23 @@ function he(n, u) {
71
71
  const d = b.container(), I = (m) => {
72
72
  if (m.touches.length === 2) {
73
73
  m.preventDefault();
74
- const L = { x: m.touches[0].clientX, y: m.touches[0].clientY }, W = { x: m.touches[1].clientX, y: m.touches[1].clientY };
75
- e.current = Ft(L, W), r.current = kt(L, W), S.current = g;
74
+ const X = { x: m.touches[0].clientX, y: m.touches[0].clientY }, W = { x: m.touches[1].clientX, y: m.touches[1].clientY };
75
+ e.current = Ft(X, W), r.current = kt(X, W), S.current = g;
76
76
  }
77
77
  }, v = (m) => {
78
78
  if (m.touches.length !== 2) return;
79
79
  m.preventDefault();
80
- const L = { x: m.touches[0].clientX, y: m.touches[0].clientY }, W = { x: m.touches[1].clientX, y: m.touches[1].clientY }, O = Ft(L, W), M = kt(L, W);
80
+ const X = { x: m.touches[0].clientX, y: m.touches[0].clientY }, W = { x: m.touches[1].clientX, y: m.touches[1].clientY }, O = Ft(X, W), M = kt(X, W);
81
81
  if (e.current !== null && r.current !== null) {
82
82
  const P = O / e.current, A = Math.min(
83
83
  Math.max(g * P, f),
84
84
  x
85
- ), J = d.getBoundingClientRect(), j = M.x - J.left, ot = M.y - J.top, rt = g, st = {
86
- x: (j - c.x) / rt,
87
- y: (ot - c.y) / rt
88
- }, at = M.x - r.current.x, $ = M.y - r.current.y, V = {
89
- x: j - st.x * A + at,
90
- y: ot - st.y * A + $
85
+ ), Q = d.getBoundingClientRect(), j = M.x - Q.left, st = M.y - Q.top, at = g, ct = {
86
+ x: (j - c.x) / at,
87
+ y: (st - c.y) / at
88
+ }, lt = M.x - r.current.x, Y = M.y - r.current.y, V = {
89
+ x: j - ct.x * A + lt,
90
+ y: st - ct.y * A + Y
91
91
  };
92
92
  p(A, V), e.current = O, r.current = M;
93
93
  }
@@ -121,7 +121,7 @@ const de = {
121
121
  seatHidden: "#4a4a4a",
122
122
  gridLines: "#404040",
123
123
  currency: "KD"
124
- }, Wt = K(
124
+ }, Wt = J(
125
125
  ({ seat: n, state: u, colors: e, onClick: r, onMouseEnter: S, onMouseLeave: y }) => {
126
126
  const f = (n.size || 24) / 2, g = {
127
127
  available: e.seatAvailable,
@@ -171,14 +171,14 @@ const de = {
171
171
  }
172
172
  );
173
173
  Wt.displayName = "ViewerSeat";
174
- const Tt = K(({ stage: n, stageColor: u }) => {
174
+ const Tt = J(({ stage: n, stageColor: u }) => {
175
175
  const e = n.config, r = e.shape || "rectangle", S = e.showLabel !== !1, y = e.color || u, f = e.width / e.height, x = f < 0.5, g = f > 2;
176
176
  let c;
177
177
  x ? c = e.width * 0.25 : g ? c = e.height * 0.35 : c = Math.min(e.width, e.height) * 0.25;
178
178
  const p = e.label?.length || 6, I = e.width * 0.85 / p * 1.5, v = Math.max(
179
179
  10,
180
180
  Math.min(24, Math.min(c, I))
181
- ), w = 4, m = Math.max(20, e.width - w * 2), L = (e.width - m) / 2, W = {
181
+ ), w = 4, m = Math.max(20, e.width - w * 2), X = (e.width - m) / 2, W = {
182
182
  fill: y + "80",
183
183
  stroke: "#ffffff",
184
184
  strokeWidth: 2,
@@ -240,7 +240,7 @@ const Tt = K(({ stage: n, stageColor: u }) => {
240
240
  Rt,
241
241
  {
242
242
  text: e.label,
243
- x: L,
243
+ x: X,
244
244
  y: w,
245
245
  width: m,
246
246
  height: e.height - w * 2,
@@ -258,7 +258,7 @@ const Tt = K(({ stage: n, stageColor: u }) => {
258
258
  );
259
259
  });
260
260
  Tt.displayName = "ViewerStage";
261
- const Lt = K(({ text: n }) => /* @__PURE__ */ a(
261
+ const Xt = J(({ text: n }) => /* @__PURE__ */ a(
262
262
  Rt,
263
263
  {
264
264
  x: n.position.x,
@@ -267,11 +267,13 @@ const Lt = K(({ text: n }) => /* @__PURE__ */ a(
267
267
  fontSize: n.config.fontSize,
268
268
  fill: n.config.color,
269
269
  rotation: n.config.rotation || 0,
270
+ scaleX: n.config.scaleX || 1,
271
+ scaleY: n.config.scaleY || 1,
270
272
  listening: !1
271
273
  }
272
274
  ));
273
- Lt.displayName = "ViewerText";
274
- const $t = K(
275
+ Xt.displayName = "ViewerText";
276
+ const Yt = J(
275
277
  ({
276
278
  floors: n,
277
279
  currentFloorId: u,
@@ -340,8 +342,8 @@ const $t = K(
340
342
  ] });
341
343
  }
342
344
  );
343
- $t.displayName = "FloorSelectorBar";
344
- const Et = K(
345
+ Yt.displayName = "FloorSelectorBar";
346
+ const Lt = J(
345
347
  ({ scale: n, minScale: u, maxScale: e, fitScale: r, onZoomIn: S, onZoomOut: y, onFitToScreen: f, position: x, className: g }) => {
346
348
  const p = {
347
349
  position: "absolute",
@@ -421,8 +423,8 @@ const Et = K(
421
423
  ] });
422
424
  }
423
425
  );
424
- Et.displayName = "ZoomControls";
425
- const Xt = K(
426
+ Lt.displayName = "ZoomControls";
427
+ const $t = J(
426
428
  ({ visible: n, x: u, y: e, seat: r, currency: S, state: y }) => {
427
429
  if (!n || !r) return null;
428
430
  const f = r.seatNumber || (r.rowLabel && r.columnLabel ? `${r.rowLabel}-${r.columnLabel}` : "N/A"), x = {
@@ -478,7 +480,7 @@ const Xt = K(
478
480
  ] }) });
479
481
  }
480
482
  );
481
- Xt.displayName = "SeatTooltip";
483
+ $t.displayName = "SeatTooltip";
482
484
  const pe = ({
483
485
  config: n,
484
486
  configUrl: u,
@@ -498,33 +500,33 @@ const pe = ({
498
500
  zoomEnabled: v = !0,
499
501
  className: w = "",
500
502
  onConfigLoad: m,
501
- onError: L,
503
+ onError: X,
502
504
  // Floor selector props
503
505
  showFloorSelector: W,
504
506
  floorSelectorPosition: O = "top-left",
505
507
  floorSelectorClassName: M,
506
508
  showAllFloorsOption: P = !0,
507
509
  allFloorsLabel: A = "All",
508
- fitToView: J = !0,
510
+ fitToView: Q = !0,
509
511
  fitPadding: j = 40,
510
512
  // Zoom controls
511
- showZoomControls: ot = !0,
512
- zoomControlsPosition: rt = "bottom-right",
513
- zoomControlsClassName: st,
514
- minZoom: at,
515
- maxZoom: $ = 3,
513
+ showZoomControls: st = !0,
514
+ zoomControlsPosition: at = "bottom-right",
515
+ zoomControlsClassName: ct,
516
+ minZoom: lt,
517
+ maxZoom: Y = 3,
516
518
  zoomStep: V = 0.25,
517
519
  // Touch gestures
518
- touchEnabled: Yt = !0
520
+ touchEnabled: Et = !0
519
521
  }) => {
520
- const St = y !== void 0 ? y : S, gt = U(null), wt = U(null), C = le(wt), [Z, Ct] = Y(
522
+ const St = y !== void 0 ? y : S, pt = K(null), wt = K(null), C = le(wt), [Z, Ct] = E(
521
523
  /* @__PURE__ */ new Set()
522
- ), [R, Q] = Y(1), [T, _] = Y({ x: 0, y: 0 }), [Pt, zt] = Y(null), [Mt, Bt] = Y(1), ct = U({ width: 0, height: 0 }), [tt, It] = Y({ visible: !1, x: 0, y: 0, seat: null, state: "available" }), { config: At, loading: Ht, error: et } = ce(u), s = n || At, pt = e !== void 0, D = pt ? e || null : Pt, lt = x !== void 0, Ot = N(
524
+ ), [R, tt] = E(1), [T, _] = E({ x: 0, y: 0 }), [Pt, zt] = E(null), [Mt, Bt] = E(1), ht = K({ width: 0, height: 0 }), [et, It] = E({ visible: !1, x: 0, y: 0, seat: null, state: "available" }), { config: At, loading: Ht, error: nt } = ce(u), s = n || At, yt = e !== void 0, D = yt ? e || null : Pt, dt = x !== void 0, Ot = N(
523
525
  (t) => {
524
- pt || zt(t), r?.(t);
526
+ yt || zt(t), r?.(t);
525
527
  },
526
- [pt, r]
527
- ), yt = s?.floors || [], jt = W !== void 0 ? W : yt.length > 1, ht = z(
528
+ [yt, r]
529
+ ), xt = s?.floors || [], jt = W !== void 0 ? W : xt.length > 1, ut = z(
528
530
  () => s ? { ...s.colors, ...d } : { ...de, ...d },
529
531
  [s, d]
530
532
  ), q = z(() => {
@@ -533,41 +535,41 @@ const pe = ({
533
535
  return D && (t = t.filter(
534
536
  (i) => i.floorId === D || !i.floorId && D === "floor_default"
535
537
  )), t;
536
- }, [s, D]), dt = z(() => s?.stages ? D ? s.stages.filter(
538
+ }, [s, D]), ft = z(() => s?.stages ? D ? s.stages.filter(
537
539
  (t) => t.floorId === D || !t.floorId && D === "floor_default"
538
- ) : s.stages : [], [s, D]), ut = z(() => s?.texts ? D ? s.texts.filter(
540
+ ) : s.stages : [], [s, D]), gt = z(() => s?.texts ? D ? s.texts.filter(
539
541
  (t) => t.floorId === D || !t.floorId && D === "floor_default"
540
- ) : s.texts : [], [s, D]), E = z(() => {
541
- if (!s || q.length === 0 && dt.length === 0 && ut.length === 0)
542
+ ) : s.texts : [], [s, D]), L = z(() => {
543
+ if (!s || q.length === 0 && ft.length === 0 && gt.length === 0)
542
544
  return null;
543
545
  let t = 1 / 0, i = 1 / 0, l = -1 / 0, h = -1 / 0;
544
546
  return q.forEach((o) => {
545
547
  const F = (o.size || 24) / 2;
546
548
  t = Math.min(t, o.position.x - F), i = Math.min(i, o.position.y - F), l = Math.max(l, o.position.x + F), h = Math.max(h, o.position.y + F);
547
- }), dt.forEach((o) => {
549
+ }), ft.forEach((o) => {
548
550
  t = Math.min(t, o.position.x), i = Math.min(i, o.position.y), l = Math.max(l, o.position.x + (o.config?.width || 200)), h = Math.max(h, o.position.y + (o.config?.height || 100));
549
- }), ut.forEach((o) => {
550
- const F = o.config.text.length * o.config.fontSize * 0.6, X = o.config.fontSize;
551
- t = Math.min(t, o.position.x), i = Math.min(i, o.position.y), l = Math.max(l, o.position.x + F), h = Math.max(h, o.position.y + X);
551
+ }), gt.forEach((o) => {
552
+ const F = o.config.scaleX || 1, $ = o.config.scaleY || 1, U = o.config.text.length * o.config.fontSize * 0.6 * F, rt = o.config.fontSize * $;
553
+ t = Math.min(t, o.position.x), i = Math.min(i, o.position.y), l = Math.max(l, o.position.x + U), h = Math.max(h, o.position.y + rt);
552
554
  }), { minX: t, minY: i, maxX: l, maxY: h, width: l - t, height: h - i };
553
- }, [s, q, dt, ut]), xt = N(() => {
554
- if (!s || !E || C.width === 0 || C.height === 0) return;
555
- const t = C.width, i = C.height, l = t - j * 2, h = i - j * 2, o = l / E.width, F = h / E.height, X = Math.min(o, F, $), ft = E.minX + E.width / 2, mt = E.minY + E.height / 2, te = t / 2, ee = i / 2, ne = te - ft * X, ie = ee - mt * X;
556
- Q(X), _({ x: ne, y: ie }), Bt(X);
557
- }, [s, E, C, j, $]);
555
+ }, [s, q, ft, gt]), bt = N(() => {
556
+ if (!s || !L || C.width === 0 || C.height === 0) return;
557
+ const t = C.width, i = C.height, l = t - j * 2, h = i - j * 2, o = l / L.width, F = h / L.height, $ = Math.min(o, F, Y), U = L.minX + L.width / 2, rt = L.minY + L.height / 2, te = t / 2, ee = i / 2, ne = te - U * $, ie = ee - rt * $;
558
+ tt($), _({ x: ne, y: ie }), Bt($);
559
+ }, [s, L, C, j, Y]);
558
560
  B(() => {
559
- if (!J || !s || !E || C.width === 0 || C.height === 0) return;
561
+ if (!Q || !s || !L || C.width === 0 || C.height === 0) return;
560
562
  const t = Math.abs(
561
- C.width - ct.current.width
563
+ C.width - ht.current.width
562
564
  ), i = Math.abs(
563
- C.height - ct.current.height
565
+ C.height - ht.current.height
564
566
  );
565
- !(ct.current.width === 0) && t < 10 && i < 10 || (ct.current = C, xt());
566
- }, [J, s, E, C, D, xt]);
567
+ !(ht.current.width === 0) && t < 10 && i < 10 || (ht.current = C, bt());
568
+ }, [Q, s, L, C, D, bt]);
567
569
  const H = z(() => {
568
570
  const t = new Set(St), i = new Set(f), l = new Set(g);
569
571
  return { reserved: t, unavailable: i, myReserved: l };
570
- }, [St, f, g]), bt = z(() => x ? new Set(x) : null, [x]), nt = N(
572
+ }, [St, f, g]), mt = z(() => x ? new Set(x) : null, [x]), it = N(
571
573
  (t) => {
572
574
  const i = t.id, l = t.seatNumber || "";
573
575
  return H.unavailable.has(i) || H.unavailable.has(l) ? "unavailable" : H.reserved.has(i) || H.reserved.has(l) ? "reserved" : H.myReserved.has(i) || H.myReserved.has(l) || Z.has(i) ? "selected" : t.state;
@@ -577,41 +579,41 @@ const pe = ({
577
579
  B(() => {
578
580
  s && m && m(s);
579
581
  }, [s, m]), B(() => {
580
- et && L && L(et);
581
- }, [et, L]), B(() => {
582
- lt && bt && Ct(bt);
583
- }, [lt, bt]);
582
+ nt && X && X(nt);
583
+ }, [nt, X]), B(() => {
584
+ dt && mt && Ct(mt);
585
+ }, [dt, mt]);
584
586
  const Vt = N(
585
587
  (t) => {
586
- const i = nt(t);
588
+ const i = it(t);
587
589
  if (i !== "available" && i !== "selected")
588
590
  return;
589
591
  const l = Z.has(t.id);
590
- lt || Ct((h) => {
592
+ dt || Ct((h) => {
591
593
  const o = new Set(h);
592
594
  return l ? o.delete(t.id) : o.add(t.id), o;
593
595
  }), l ? p?.(t) : (c?.(t), c || console.log("Seat selected:", t));
594
596
  },
595
597
  [
596
- nt,
598
+ it,
597
599
  Z,
598
- lt,
600
+ dt,
599
601
  c,
600
602
  p
601
603
  ]
602
- ), it = z(() => s ? q.filter((t) => Z.has(t.id)) : [], [s, q, Z]);
604
+ ), ot = z(() => s ? q.filter((t) => Z.has(t.id)) : [], [s, q, Z]);
603
605
  B(() => {
604
- b?.(it);
605
- }, [it, b]);
606
- const G = at !== void 0 ? at : Mt * 0.5, Zt = N(() => {
606
+ b?.(ot);
607
+ }, [ot, b]);
608
+ const G = lt !== void 0 ? lt : Mt * 0.5, Zt = N(() => {
607
609
  if (!v) return;
608
- const t = Math.min(R + V, $);
610
+ const t = Math.min(R + V, Y);
609
611
  if (t !== R) {
610
612
  const i = C.width || s?.canvas.width || 800, l = C.height || s?.canvas.height || 600, h = i / 2, o = l / 2, F = {
611
613
  x: (h - T.x) / R,
612
614
  y: (o - T.y) / R
613
615
  };
614
- Q(t), _({
616
+ tt(t), _({
615
617
  x: h - F.x * t,
616
618
  y: o - F.y * t
617
619
  });
@@ -620,7 +622,7 @@ const pe = ({
620
622
  v,
621
623
  R,
622
624
  V,
623
- $,
625
+ Y,
624
626
  C,
625
627
  s,
626
628
  T
@@ -632,7 +634,7 @@ const pe = ({
632
634
  x: (h - T.x) / R,
633
635
  y: (o - T.y) / R
634
636
  };
635
- Q(t), _({
637
+ tt(t), _({
636
638
  x: h - F.x * t,
637
639
  y: o - F.y * t
638
640
  });
@@ -654,29 +656,29 @@ const pe = ({
654
656
  (t) => {
655
657
  if (!v) return;
656
658
  t.evt.preventDefault();
657
- const i = gt.current;
659
+ const i = pt.current;
658
660
  if (!i) return;
659
661
  const l = i.scaleX(), h = i.getPointerPosition();
660
662
  if (!h) return;
661
- const o = 1.1, F = t.evt.deltaY > 0 ? l / o : l * o, X = Math.min(Math.max(F, G), $), ft = {
663
+ const o = 1.1, F = t.evt.deltaY > 0 ? l / o : l * o, $ = Math.min(Math.max(F, G), Y), U = {
662
664
  x: (h.x - T.x) / l,
663
665
  y: (h.y - T.y) / l
664
- }, mt = {
665
- x: h.x - ft.x * X,
666
- y: h.y - ft.y * X
666
+ }, rt = {
667
+ x: h.x - U.x * $,
668
+ y: h.y - U.y * $
667
669
  };
668
- Q(X), _(mt);
670
+ tt($), _(rt);
669
671
  },
670
- [v, T, G, $]
672
+ [v, T, G, Y]
671
673
  );
672
- he(gt, {
673
- enabled: Yt && v,
674
+ he(pt, {
675
+ enabled: Et && v,
674
676
  minScale: G,
675
- maxScale: $,
677
+ maxScale: Y,
676
678
  currentScale: R,
677
679
  currentPosition: T,
678
680
  onScaleChange: (t, i) => {
679
- Q(t), _(i);
681
+ tt(t), _(i);
680
682
  }
681
683
  });
682
684
  const Ut = N(
@@ -692,19 +694,19 @@ const pe = ({
692
694
  x: o.left + h.x,
693
695
  y: o.top + h.y,
694
696
  seat: t,
695
- state: nt(t)
697
+ state: it(t)
696
698
  });
697
699
  },
698
- [I, nt]
700
+ [I, it]
699
701
  ), Kt = N(() => {
700
702
  It((t) => ({ ...t, visible: !1 }));
701
703
  }, []);
702
704
  if (Ht)
703
705
  return /* @__PURE__ */ a("div", { className: `flex items-center justify-center h-full ${w}`, children: /* @__PURE__ */ a("p", { children: "Loading seat map..." }) });
704
- if (et)
706
+ if (nt)
705
707
  return /* @__PURE__ */ a("div", { className: `flex items-center justify-center h-full ${w}`, children: /* @__PURE__ */ k("p", { className: "text-red-500", children: [
706
708
  "Error loading seat map: ",
707
- et.message
709
+ nt.message
708
710
  ] }) });
709
711
  if (!s)
710
712
  return /* @__PURE__ */ a("div", { className: `flex items-center justify-center h-full ${w}`, children: /* @__PURE__ */ a("p", { children: "No configuration provided" }) });
@@ -716,10 +718,10 @@ const pe = ({
716
718
  className: `relative ${w}`,
717
719
  style: { width: "100%", height: "100%" },
718
720
  children: [
719
- jt && yt.length > 0 && /* @__PURE__ */ a(
720
- $t,
721
+ jt && xt.length > 0 && /* @__PURE__ */ a(
722
+ Yt,
721
723
  {
722
- floors: yt,
724
+ floors: xt,
723
725
  currentFloorId: D,
724
726
  onFloorChange: Ot,
725
727
  showAllOption: P,
@@ -731,7 +733,7 @@ const pe = ({
731
733
  /* @__PURE__ */ k(
732
734
  oe,
733
735
  {
734
- ref: gt,
736
+ ref: pt,
735
737
  width: Jt,
736
738
  height: Qt,
737
739
  scaleX: R,
@@ -746,21 +748,21 @@ const pe = ({
746
748
  cursor: "grab"
747
749
  },
748
750
  children: [
749
- /* @__PURE__ */ a(vt, { listening: !1, children: dt.map((t) => /* @__PURE__ */ a(
751
+ /* @__PURE__ */ a(vt, { listening: !1, children: ft.map((t) => /* @__PURE__ */ a(
750
752
  Tt,
751
753
  {
752
754
  stage: t,
753
- stageColor: ht.stageColor
755
+ stageColor: ut.stageColor
754
756
  },
755
757
  t.id
756
758
  )) }),
757
- /* @__PURE__ */ a(vt, { listening: !1, children: ut.map((t) => /* @__PURE__ */ a(Lt, { text: t }, t.id)) }),
759
+ /* @__PURE__ */ a(vt, { listening: !1, children: gt.map((t) => /* @__PURE__ */ a(Xt, { text: t }, t.id)) }),
758
760
  /* @__PURE__ */ a(vt, { children: q.map((t) => /* @__PURE__ */ a(
759
761
  Wt,
760
762
  {
761
763
  seat: t,
762
- state: nt(t),
763
- colors: ht,
764
+ state: it(t),
765
+ colors: ut,
764
766
  onClick: Vt,
765
767
  onMouseEnter: Ut,
766
768
  onMouseLeave: Kt
@@ -771,39 +773,39 @@ const pe = ({
771
773
  }
772
774
  ),
773
775
  I && /* @__PURE__ */ a(
774
- Xt,
776
+ $t,
775
777
  {
776
- visible: tt.visible,
777
- x: tt.x,
778
- y: tt.y,
779
- seat: tt.seat,
780
- currency: ht.currency,
781
- state: tt.state
778
+ visible: et.visible,
779
+ x: et.x,
780
+ y: et.y,
781
+ seat: et.seat,
782
+ currency: ut.currency,
783
+ state: et.state
782
784
  }
783
785
  ),
784
- ot && v && /* @__PURE__ */ a(
785
- Et,
786
+ st && v && /* @__PURE__ */ a(
787
+ Lt,
786
788
  {
787
789
  scale: R,
788
790
  minScale: G,
789
- maxScale: $,
791
+ maxScale: Y,
790
792
  fitScale: Mt,
791
793
  onZoomIn: Zt,
792
794
  onZoomOut: _t,
793
- onFitToScreen: xt,
794
- position: rt,
795
- className: st
795
+ onFitToScreen: bt,
796
+ position: at,
797
+ className: ct
796
798
  }
797
799
  ),
798
- it.length > 0 && /* @__PURE__ */ k("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
800
+ ot.length > 0 && /* @__PURE__ */ k("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
799
801
  /* @__PURE__ */ k("h3", { className: "font-semibold mb-2", children: [
800
802
  "Selected Seats (",
801
- it.length,
803
+ ot.length,
802
804
  ")"
803
805
  ] }),
804
- /* @__PURE__ */ a("div", { className: "max-h-48 overflow-y-auto space-y-1", children: it.map((t) => /* @__PURE__ */ k("div", { className: "text-sm", children: [
806
+ /* @__PURE__ */ a("div", { className: "max-h-48 overflow-y-auto space-y-1", children: ot.map((t) => /* @__PURE__ */ k("div", { className: "text-sm", children: [
805
807
  t.seatNumber,
806
- t.price && ` - ${ht.currency} ${t.price.toFixed(2)}`
808
+ t.price && ` - ${ut.currency} ${t.price.toFixed(2)}`
807
809
  ] }, t.id)) })
808
810
  ] })
809
811
  ]
@@ -67,6 +67,8 @@ export interface TextConfig {
67
67
  fontSize: number;
68
68
  color: string;
69
69
  rotation?: number;
70
+ scaleX?: number;
71
+ scaleY?: number;
70
72
  }
71
73
  export interface SerializedText {
72
74
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonetrix/viewer",
3
- "version": "2.13.1",
3
+ "version": "2.13.2",
4
4
  "type": "module",
5
5
  "description": "Lightweight React component for rendering interactive seat maps",
6
6
  "main": "./dist/index.js",