@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.
- package/dist/firebase/client.d.ts +30 -0
- package/dist/hooks/useFirebaseConfig.d.ts +41 -0
- package/dist/hooks/useFirebaseSeatStates.d.ts +53 -0
- package/dist/hooks/useRealtimeSeatMap.d.ts +74 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +116 -114
- package/dist/types/index.d.ts +2 -0
- package/package.json +1 -1
|
@@ -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
|
|
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] =
|
|
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] =
|
|
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 =
|
|
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
|
|
75
|
-
e.current = Ft(
|
|
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
|
|
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
|
-
),
|
|
86
|
-
x: (j - c.x) /
|
|
87
|
-
y: (
|
|
88
|
-
},
|
|
89
|
-
x: j -
|
|
90
|
-
y:
|
|
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 =
|
|
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 =
|
|
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),
|
|
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:
|
|
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
|
|
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
|
-
|
|
274
|
-
const
|
|
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
|
-
|
|
344
|
-
const
|
|
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
|
-
|
|
425
|
-
const
|
|
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
|
-
|
|
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:
|
|
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:
|
|
510
|
+
fitToView: Q = !0,
|
|
509
511
|
fitPadding: j = 40,
|
|
510
512
|
// Zoom controls
|
|
511
|
-
showZoomControls:
|
|
512
|
-
zoomControlsPosition:
|
|
513
|
-
zoomControlsClassName:
|
|
514
|
-
minZoom:
|
|
515
|
-
maxZoom:
|
|
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:
|
|
520
|
+
touchEnabled: Et = !0
|
|
519
521
|
}) => {
|
|
520
|
-
const St = y !== void 0 ? y : S,
|
|
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,
|
|
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
|
-
|
|
526
|
+
yt || zt(t), r?.(t);
|
|
525
527
|
},
|
|
526
|
-
[
|
|
527
|
-
),
|
|
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]),
|
|
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]),
|
|
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]),
|
|
541
|
-
if (!s || q.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
|
-
}),
|
|
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
|
-
}),
|
|
550
|
-
const F = o.config.text.length * o.config.fontSize * 0.6,
|
|
551
|
-
t = Math.min(t, o.position.x), i = Math.min(i, o.position.y), l = Math.max(l, o.position.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,
|
|
554
|
-
if (!s || !
|
|
555
|
-
const t = C.width, i = C.height, l = t - j * 2, h = i - j * 2, o = l /
|
|
556
|
-
|
|
557
|
-
}, [s,
|
|
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 (!
|
|
561
|
+
if (!Q || !s || !L || C.width === 0 || C.height === 0) return;
|
|
560
562
|
const t = Math.abs(
|
|
561
|
-
C.width -
|
|
563
|
+
C.width - ht.current.width
|
|
562
564
|
), i = Math.abs(
|
|
563
|
-
C.height -
|
|
565
|
+
C.height - ht.current.height
|
|
564
566
|
);
|
|
565
|
-
!(
|
|
566
|
-
}, [
|
|
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]),
|
|
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
|
-
|
|
581
|
-
}, [
|
|
582
|
-
|
|
583
|
-
}, [
|
|
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 =
|
|
588
|
+
const i = it(t);
|
|
587
589
|
if (i !== "available" && i !== "selected")
|
|
588
590
|
return;
|
|
589
591
|
const l = Z.has(t.id);
|
|
590
|
-
|
|
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
|
-
|
|
598
|
+
it,
|
|
597
599
|
Z,
|
|
598
|
-
|
|
600
|
+
dt,
|
|
599
601
|
c,
|
|
600
602
|
p
|
|
601
603
|
]
|
|
602
|
-
),
|
|
604
|
+
), ot = z(() => s ? q.filter((t) => Z.has(t.id)) : [], [s, q, Z]);
|
|
603
605
|
B(() => {
|
|
604
|
-
b?.(
|
|
605
|
-
}, [
|
|
606
|
-
const G =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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,
|
|
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
|
-
},
|
|
665
|
-
x: h.x -
|
|
666
|
-
y: h.y -
|
|
666
|
+
}, rt = {
|
|
667
|
+
x: h.x - U.x * $,
|
|
668
|
+
y: h.y - U.y * $
|
|
667
669
|
};
|
|
668
|
-
|
|
670
|
+
tt($), _(rt);
|
|
669
671
|
},
|
|
670
|
-
[v, T, G,
|
|
672
|
+
[v, T, G, Y]
|
|
671
673
|
);
|
|
672
|
-
he(
|
|
673
|
-
enabled:
|
|
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
|
-
|
|
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:
|
|
697
|
+
state: it(t)
|
|
696
698
|
});
|
|
697
699
|
},
|
|
698
|
-
[I,
|
|
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 (
|
|
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
|
-
|
|
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 &&
|
|
720
|
-
|
|
721
|
+
jt && xt.length > 0 && /* @__PURE__ */ a(
|
|
722
|
+
Yt,
|
|
721
723
|
{
|
|
722
|
-
floors:
|
|
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:
|
|
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:
|
|
751
|
+
/* @__PURE__ */ a(vt, { listening: !1, children: ft.map((t) => /* @__PURE__ */ a(
|
|
750
752
|
Tt,
|
|
751
753
|
{
|
|
752
754
|
stage: t,
|
|
753
|
-
stageColor:
|
|
755
|
+
stageColor: ut.stageColor
|
|
754
756
|
},
|
|
755
757
|
t.id
|
|
756
758
|
)) }),
|
|
757
|
-
/* @__PURE__ */ a(vt, { listening: !1, children:
|
|
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:
|
|
763
|
-
colors:
|
|
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
|
-
|
|
776
|
+
$t,
|
|
775
777
|
{
|
|
776
|
-
visible:
|
|
777
|
-
x:
|
|
778
|
-
y:
|
|
779
|
-
seat:
|
|
780
|
-
currency:
|
|
781
|
-
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
|
-
|
|
785
|
-
|
|
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:
|
|
794
|
-
position:
|
|
795
|
-
className:
|
|
795
|
+
onFitToScreen: bt,
|
|
796
|
+
position: at,
|
|
797
|
+
className: ct
|
|
796
798
|
}
|
|
797
799
|
),
|
|
798
|
-
|
|
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
|
-
|
|
803
|
+
ot.length,
|
|
802
804
|
")"
|
|
803
805
|
] }),
|
|
804
|
-
/* @__PURE__ */ a("div", { className: "max-h-48 overflow-y-auto space-y-1", 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 && ` - ${
|
|
808
|
+
t.price && ` - ${ut.currency} ${t.price.toFixed(2)}`
|
|
807
809
|
] }, t.id)) })
|
|
808
810
|
] })
|
|
809
811
|
]
|
package/dist/types/index.d.ts
CHANGED