@zonetrix/viewer 2.12.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/dist/components/SeatMapViewer.d.ts +4 -4
- package/dist/index.d.ts +3 -7
- package/dist/index.js +1 -1
- package/dist/index.mjs +499 -719
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ function BookingApp() {
|
|
|
129
129
|
| `showZoomControls` | `boolean` | No | Show zoom +/- buttons (default: true) |
|
|
130
130
|
| `zoomControlsPosition` | `string` | No | Position: 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' (default: 'bottom-right') |
|
|
131
131
|
| `zoomControlsClassName` | `string` | No | Custom CSS class for zoom controls |
|
|
132
|
-
| `minZoom` | `number` | No | Minimum zoom level. If not set,
|
|
132
|
+
| `minZoom` | `number` | No | Minimum zoom level. If not set, defaults to 50% of fit-to-view scale for comfortable breathing room (default: undefined) |
|
|
133
133
|
| `maxZoom` | `number` | No | Maximum zoom level (default: 3) |
|
|
134
134
|
| `zoomStep` | `number` | No | Zoom increment per click (default: 0.25) |
|
|
135
135
|
|
|
@@ -597,7 +597,7 @@ function RobustViewer() {
|
|
|
597
597
|
|
|
598
598
|
### 9. Custom Minimum Zoom
|
|
599
599
|
|
|
600
|
-
By default, users
|
|
600
|
+
By default, users can zoom out to 50% of the "fit to screen" level, providing comfortable breathing room around all content. To customize this behavior:
|
|
601
601
|
|
|
602
602
|
```tsx
|
|
603
603
|
import { SeatMapViewer } from '@zonetrix/viewer';
|
|
@@ -624,6 +624,17 @@ function BirdEyeView() {
|
|
|
624
624
|
/>
|
|
625
625
|
);
|
|
626
626
|
}
|
|
627
|
+
|
|
628
|
+
// Restrict zoom out to fit-to-screen scale (legacy behavior)
|
|
629
|
+
function RestrictedZoom() {
|
|
630
|
+
return (
|
|
631
|
+
<SeatMapViewer
|
|
632
|
+
config={venueConfig}
|
|
633
|
+
minZoom={1.0} // Set explicitly to match fit scale
|
|
634
|
+
onSeatSelect={(seat) => handleSelection(seat)}
|
|
635
|
+
/>
|
|
636
|
+
);
|
|
637
|
+
}
|
|
627
638
|
```
|
|
628
639
|
|
|
629
640
|
**Note**: Very low minZoom values (< 0.1) may impact rendering performance with large seat maps.
|
|
@@ -33,12 +33,12 @@ export interface SeatMapViewerProps {
|
|
|
33
33
|
/**
|
|
34
34
|
* Minimum zoom level.
|
|
35
35
|
*
|
|
36
|
-
* When undefined (default), users
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* When undefined (default), users can zoom out to 50% of the "fit to screen"
|
|
37
|
+
* scale, providing comfortable breathing room around all content. When set,
|
|
38
|
+
* this value becomes the absolute minimum zoom level.
|
|
39
39
|
*
|
|
40
40
|
* Examples:
|
|
41
|
-
* - undefined: Default behavior, minimum is fit-to-screen scale
|
|
41
|
+
* - undefined: Default behavior, minimum is 50% of fit-to-screen scale
|
|
42
42
|
* - 0.1: Allow zooming out to 10% of original size
|
|
43
43
|
* - 0.25: Allow zooming out to 25% of original size
|
|
44
44
|
* - 1.0: Prevent zooming out below 100% (actual size)
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,6 @@ export { DEFAULT_COLORS } from './types';
|
|
|
5
5
|
export { useConfigFetcher } from './hooks/useConfigFetcher';
|
|
6
6
|
export { useContainerSize } from './hooks/useContainerSize';
|
|
7
7
|
export { useTouchGestures } from './hooks/useTouchGestures';
|
|
8
|
-
export { useFirebaseSeatStates } from '
|
|
9
|
-
export type { UseFirebaseSeatStatesOptions, UseFirebaseSeatStatesResult, } from '
|
|
10
|
-
export {
|
|
11
|
-
export type { UseFirebaseConfigOptions, UseFirebaseConfigResult, } from './hooks/useFirebaseConfig';
|
|
12
|
-
export { useRealtimeSeatMap } from './hooks/useRealtimeSeatMap';
|
|
13
|
-
export type { UseRealtimeSeatMapOptions, UseRealtimeSeatMapResult, } from './hooks/useRealtimeSeatMap';
|
|
14
|
-
export { initializeFirebaseForViewer, isFirebaseInitialized, clearFirebaseInstance, } from './firebase/client';
|
|
8
|
+
export { useFirebaseSeatStates, useFirebaseConfig, useRealtimeSeatMap, } from '@zonetrix/shared';
|
|
9
|
+
export type { UseFirebaseSeatStatesOptions, UseFirebaseSeatStatesResult, UseFirebaseConfigOptions, UseFirebaseConfigResult, UseRealtimeSeatMapOptions, UseRealtimeSeatMapResult, } from '@zonetrix/shared';
|
|
10
|
+
export { initializeFirebaseForViewer, getFirebaseDatabase, isFirebaseInitialized, clearFirebaseInstance, } from '@zonetrix/shared';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),n=require("react"),N=require("react-konva"),Y=require("firebase/database"),at=require("@zonetrix/shared");function Fe(s){const[i,t]=n.useState(null),[r,f]=n.useState(!1),[d,a]=n.useState(null),y=n.useCallback(async()=>{if(s){f(!0),a(null);try{const b=await fetch(s);if(!b.ok)throw new Error(`Failed to fetch config: ${b.statusText}`);const c=await b.json();t(c)}catch(b){const c=b instanceof Error?b:new Error("Unknown error occurred");a(c),console.error("Failed to fetch seat map config:",c)}finally{f(!1)}}},[s]);return n.useEffect(()=>{y()},[y]),{config:i,loading:r,error:d,refetch:y}}function Ee(s){const[i,t]=n.useState({width:0,height:0});return n.useEffect(()=>{const r=s.current;if(!r)return;const{width:f,height:d}=r.getBoundingClientRect();f>0&&d>0&&t({width:f,height:d});const a=new ResizeObserver(y=>{const b=y[0];if(!b)return;const{width:c,height:x}=b.contentRect;c>0&&x>0&&t(v=>v.width===c&&v.height===x?v:{width:c,height:x})});return a.observe(r),()=>{a.disconnect()}},[s]),i}function Me(s,i){return Math.sqrt(Math.pow(i.x-s.x,2)+Math.pow(i.y-s.y,2))}function je(s,i){return{x:(s.x+i.x)/2,y:(s.y+i.y)/2}}function ke(s,i){const t=n.useRef(null),r=n.useRef(null),f=n.useRef(1),{enabled:d,minScale:a,maxScale:y,currentScale:b,currentPosition:c,onScaleChange:x}=i;n.useEffect(()=>{const v=s.current;if(!v||!d)return;const g=v.container(),w=S=>{if(S.touches.length===2){S.preventDefault();const F={x:S.touches[0].clientX,y:S.touches[0].clientY},R={x:S.touches[1].clientX,y:S.touches[1].clientY};t.current=Me(F,R),r.current=je(F,R),f.current=b}},m=S=>{if(S.touches.length!==2)return;S.preventDefault();const F={x:S.touches[0].clientX,y:S.touches[0].clientY},R={x:S.touches[1].clientX,y:S.touches[1].clientY},E=Me(F,R),j=je(F,R);if(t.current!==null&&r.current!==null){const I=E/t.current,L=Math.min(Math.max(b*I,a),y),W=g.getBoundingClientRect(),B=j.x-W.left,te=j.y-W.top,ne=b,se={x:(B-c.x)/ne,y:(te-c.y)/ne},re=j.x-r.current.x,P=j.y-r.current.y,O={x:B-se.x*L+re,y:te-se.y*L+P};x(L,O),t.current=E,r.current=j}},M=S=>{S.touches.length<2&&(t.current=null,r.current=null)};return g.addEventListener("touchstart",w,{passive:!1}),g.addEventListener("touchmove",m,{passive:!1}),g.addEventListener("touchend",M),()=>{g.removeEventListener("touchstart",w),g.removeEventListener("touchmove",m),g.removeEventListener("touchend",M)}},[s,d,a,y,b,c,x])}const Ie={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Te=n.memo(({seat:s,state:i,colors:t,onClick:r,onMouseEnter:f,onMouseLeave:d})=>{const a=(s.size||24)/2,b={available:t.seatAvailable,reserved:t.seatReserved,selected:t.seatSelected,unavailable:t.seatUnavailable,hidden:t.seatHidden}[i],c=i==="available"||i==="selected",x=n.useCallback(()=>{c&&r(s)},[s,r,c]),v=n.useCallback(m=>{f(s,m);const M=m.target.getStage();M&&c&&(M.container().style.cursor="pointer")},[s,f,c]),g=n.useCallback(m=>{d();const M=m.target.getStage();M&&(M.container().style.cursor="grab")},[d]),w={x:s.position.x,y:s.position.y,fill:b,stroke:"#ffffff",strokeWidth:1,onClick:x,onTap:x,onMouseEnter:v,onMouseLeave:g};return s.shape==="circle"?o.jsx(N.Circle,{...w,radius:a}):o.jsx(N.Rect,{...w,width:a*2,height:a*2,offsetX:a,offsetY:a,cornerRadius:s.shape==="square"?0:4})});Te.displayName="ViewerSeat";const Le=n.memo(({stage:s,stageColor:i})=>{const t=s.config,r=t.shape||"rectangle",f=t.showLabel!==!1,d=t.color||i,a=t.width/t.height,y=a<.5,b=a>2;let c;y?c=t.width*.25:b?c=t.height*.35:c=Math.min(t.width,t.height)*.25;const x=t.label?.length||6,w=t.width*.85/x*1.5,m=Math.max(10,Math.min(24,Math.min(c,w))),M=4,S=Math.max(20,t.width-M*2),F=(t.width-S)/2,R={fill:d+"80",stroke:"#ffffff",strokeWidth:2,perfectDrawEnabled:!1,hitStrokeWidth:0},E=()=>{switch(r){case"circle":{const j=Math.min(t.width,t.height)/2;return o.jsx(N.Circle,{x:t.width/2,y:t.height/2,radius:j,...R})}case"triangle":{const j=Math.min(t.width,t.height)/2;return o.jsx(N.RegularPolygon,{x:t.width/2,y:t.height/2,sides:3,radius:j,rotation:-90,...R})}case"arrow":{const j=t.width/24,I=t.height/24,L=`M${9*j},${18*I} v${-8*I} H${5*j} l${7*j},${-7*I} l${7*j},${7*I} h${-4*j} v${8*I} Z`;return o.jsx(N.Path,{data:L,...R})}default:return o.jsx(N.Rect,{width:t.width,height:t.height,cornerRadius:10,...R})}};return o.jsxs(N.Group,{x:s.position.x,y:s.position.y,rotation:t.rotation||0,children:[E(),f&&o.jsx(N.Text,{text:t.label,x:F,y:M,width:S,height:t.height-M*2,fontSize:m,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle",wrap:"word",ellipsis:!0})]})});Le.displayName="ViewerStage";const De=n.memo(({text:s})=>o.jsx(N.Text,{x:s.position.x,y:s.position.y,text:s.config.text,fontSize:s.config.fontSize,fill:s.config.color,rotation:s.config.rotation||0,listening:!1}));De.displayName="ViewerText";const ze=n.memo(({floors:s,currentFloorId:i,onFloorChange:t,showAllOption:r,allLabel:f,position:d,className:a})=>{const y=n.useMemo(()=>[...s].sort((g,w)=>g.order-w.order),[s]),c={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[d]},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"},v={...x,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return o.jsxs("div",{className:a,style:c,children:[r&&o.jsx("button",{type:"button",onClick:()=>t(null),style:i===null?v:x,children:f}),y.map(g=>o.jsx("button",{type:"button",onClick:()=>t(g.id),style:i===g.id?v:x,children:g.name},g.id))]})});ze.displayName="FloorSelectorBar";const Ne=n.memo(({scale:s,minScale:i,maxScale:t,onZoomIn:r,onZoomOut:f,onFitToScreen:d,position:a,className:y})=>{const c={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}}[a]},x={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"},v={...x,opacity:.4,cursor:"not-allowed"},g=s<t,w=s>i,m=Math.abs(s-i)<.01;return o.jsxs("div",{className:y,style:c,children:[o.jsx("button",{type:"button",onClick:r,disabled:!g,style:g?x:v,title:"Zoom In","aria-label":"Zoom In",children:"+"}),o.jsx("button",{type:"button",onClick:d,disabled:m,style:m?v:x,title:"Fit to Screen","aria-label":"Fit to Screen",children:"⤢"}),o.jsx("button",{type:"button",onClick:f,disabled:!w,style:w?x:v,title:"Zoom Out","aria-label":"Zoom Out",children:"−"})]})});Ne.displayName="ZoomControls";const $e=n.memo(({visible:s,x:i,y:t,seat:r,currency:f,state:d})=>{if(!s||!r)return null;const a=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),y={position:"fixed",left:`${i+15}px`,top:`${t+15}px`,zIndex:1e3,pointerEvents:"none"},b={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},c={color:"#9ca3af",marginRight:"4px"},x={fontWeight:600},v={color:"#4ade80",fontWeight:600},g={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return o.jsx("div",{style:y,children:o.jsxs("div",{style:b,children:[r.sectionName&&o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:c,children:"Section:"}),o.jsx("span",{style:{...x,color:"#3b82f6"},children:r.sectionName})]}),o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:c,children:"Seat:"}),o.jsx("span",{style:x,children:a})]}),r.price!==void 0&&r.price>0&&d==="available"&&o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:c,children:"Price:"}),o.jsxs("span",{style:v,children:[f," ",r.price.toFixed(2)]})]}),o.jsxs("div",{style:g,children:["Status: ",d]})]})})});$e.displayName="SeatTooltip";const ct=({config:s,configUrl:i,floorId:t,onFloorChange:r,reservedSeats:f=[],otherReservedSeats:d,unavailableSeats:a=[],selectedSeats:y,myReservedSeats:b=[],onSeatSelect:c,onSeatDeselect:x,onSelectionChange:v,colorOverrides:g,showTooltip:w=!0,zoomEnabled:m=!0,className:M="",onConfigLoad:S,onError:F,showFloorSelector:R,floorSelectorPosition:E="top-left",floorSelectorClassName:j,showAllFloorsOption:I=!0,allFloorsLabel:L="All",fitToView:W=!0,fitPadding:B=40,showZoomControls:te=!0,zoomControlsPosition:ne="bottom-right",zoomControlsClassName:se,minZoom:re,maxZoom:P=3,zoomStep:O=.25,touchEnabled:Xe=!0})=>{const ve=d!==void 0?d:f,fe=n.useRef(null),we=n.useRef(null),k=Ee(we),[U,Ce]=n.useState(new Set),[D,Z]=n.useState(1),[$,H]=n.useState({x:0,y:0}),[Ae,Ye]=n.useState(null),[Be,Ve]=n.useState(1),oe=n.useRef({width:0,height:0}),[G,Re]=n.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Oe,loading:Ue,error:K}=Fe(i),h=s||Oe,ge=t!==void 0,z=ge?t||null:Ae,ie=y!==void 0,He=n.useCallback(e=>{ge||Ye(e),r?.(e)},[ge,r]),pe=h?.floors||[],qe=R!==void 0?R:pe.length>1,ae=n.useMemo(()=>h?{...h.colors,...g}:{...Ie,...g},[h,g]),q=n.useMemo(()=>{if(!h)return[];let e=h.seats.filter(l=>l.state!=="hidden");return z&&(e=e.filter(l=>l.floorId===z||!l.floorId&&z==="floor_default")),e},[h,z]),ce=n.useMemo(()=>h?.stages?z?h.stages.filter(e=>e.floorId===z||!e.floorId&&z==="floor_default"):h.stages:[],[h,z]),le=n.useMemo(()=>h?.texts?z?h.texts.filter(e=>e.floorId===z||!e.floorId&&z==="floor_default"):h.texts:[],[h,z]),X=n.useMemo(()=>{if(!h||q.length===0&&ce.length===0&&le.length===0)return null;let e=1/0,l=1/0,p=-1/0,C=-1/0;return q.forEach(u=>{const T=(u.size||24)/2;e=Math.min(e,u.position.x-T),l=Math.min(l,u.position.y-T),p=Math.max(p,u.position.x+T),C=Math.max(C,u.position.y+T)}),ce.forEach(u=>{e=Math.min(e,u.position.x),l=Math.min(l,u.position.y),p=Math.max(p,u.position.x+(u.config?.width||200)),C=Math.max(C,u.position.y+(u.config?.height||100))}),le.forEach(u=>{const T=u.config.text.length*u.config.fontSize*.6,A=u.config.fontSize;e=Math.min(e,u.position.x),l=Math.min(l,u.position.y),p=Math.max(p,u.position.x+T),C=Math.max(C,u.position.y+A)}),{minX:e,minY:l,maxX:p,maxY:C,width:p-e,height:C-l}},[h,q,ce,le]),be=n.useCallback(()=>{if(!h||!X||k.width===0||k.height===0)return;const e=k.width,l=k.height,p=e-B*2,C=l-B*2,u=p/X.width,T=C/X.height,A=Math.min(u,T,P),ue=X.minX+X.width/2,me=X.minY+X.height/2,st=e/2,rt=l/2,ot=st-ue*A,it=rt-me*A;Z(A),H({x:ot,y:it}),Ve(A)},[h,X,k,B,P]);n.useEffect(()=>{if(!W||!h||!X||k.width===0||k.height===0)return;const e=Math.abs(k.width-oe.current.width),l=Math.abs(k.height-oe.current.height);!(oe.current.width===0)&&e<10&&l<10||(oe.current=k,be())},[W,h,X,k,z,be]);const V=n.useMemo(()=>{const e=new Set(ve),l=new Set(a),p=new Set(b);return{reserved:e,unavailable:l,myReserved:p}},[ve,a,b]),xe=n.useMemo(()=>y?new Set(y):null,[y]),J=n.useCallback(e=>{const l=e.id,p=e.seatNumber||"";return V.unavailable.has(l)||V.unavailable.has(p)?"unavailable":V.reserved.has(l)||V.reserved.has(p)?"reserved":V.myReserved.has(l)||V.myReserved.has(p)||U.has(l)?"selected":e.state},[V,U]);n.useEffect(()=>{h&&S&&S(h)},[h,S]),n.useEffect(()=>{K&&F&&F(K)},[K,F]),n.useEffect(()=>{ie&&xe&&Ce(xe)},[ie,xe]);const _e=n.useCallback(e=>{const l=J(e);if(l!=="available"&&l!=="selected")return;const p=U.has(e.id);ie||Ce(C=>{const u=new Set(C);return p?u.delete(e.id):u.add(e.id),u}),p?x?.(e):(c?.(e),c||console.log("Seat selected:",e))},[J,U,ie,c,x]),Q=n.useMemo(()=>h?q.filter(e=>U.has(e.id)):[],[h,q,U]);n.useEffect(()=>{v?.(Q)},[Q,v]);const _=re!==void 0?re:Be,Ze=n.useCallback(()=>{if(!m)return;const e=Math.min(D+O,P);if(e!==D){const l=k.width||h?.canvas.width||800,p=k.height||h?.canvas.height||600,C=l/2,u=p/2,T={x:(C-$.x)/D,y:(u-$.y)/D};Z(e),H({x:C-T.x*e,y:u-T.y*e})}},[m,D,O,P,k,h,$]),Ge=n.useCallback(()=>{if(!m)return;const e=Math.max(D-O,_);if(e!==D){const l=k.width||h?.canvas.width||800,p=k.height||h?.canvas.height||600,C=l/2,u=p/2,T={x:(C-$.x)/D,y:(u-$.y)/D};Z(e),H({x:C-T.x*e,y:u-T.y*e})}},[m,D,O,_,k,h,$]),Ke=n.useCallback(e=>{H({x:e.target.x(),y:e.target.y()})},[]),Je=n.useCallback(e=>{if(!m)return;e.evt.preventDefault();const l=fe.current;if(!l)return;const p=l.scaleX(),C=l.getPointerPosition();if(!C)return;const u=1.1,T=e.evt.deltaY>0?p/u:p*u,A=Math.min(Math.max(T,_),P),ue={x:(C.x-$.x)/p,y:(C.y-$.y)/p},me={x:C.x-ue.x*A,y:C.y-ue.y*A};Z(A),H(me)},[m,$,_,P]);ke(fe,{enabled:Xe&&m,minScale:_,maxScale:P,currentScale:D,currentPosition:$,onScaleChange:(e,l)=>{Z(e),H(l)}});const Qe=n.useCallback((e,l)=>{if(!w)return;const p=l.target.getStage();if(!p)return;const C=p.getPointerPosition();if(!C)return;const u=p.container().getBoundingClientRect();Re({visible:!0,x:u.left+C.x,y:u.top+C.y,seat:e,state:J(e)})},[w,J]),et=n.useCallback(()=>{Re(e=>({...e,visible:!1}))},[]);if(Ue)return o.jsx("div",{className:`flex items-center justify-center h-full ${M}`,children:o.jsx("p",{children:"Loading seat map..."})});if(K)return o.jsx("div",{className:`flex items-center justify-center h-full ${M}`,children:o.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",K.message]})});if(!h)return o.jsx("div",{className:`flex items-center justify-center h-full ${M}`,children:o.jsx("p",{children:"No configuration provided"})});const tt=k.width||h.canvas.width,nt=k.height||h.canvas.height;return o.jsxs("div",{ref:we,className:`relative ${M}`,style:{width:"100%",height:"100%"},children:[qe&&pe.length>0&&o.jsx(ze,{floors:pe,currentFloorId:z,onFloorChange:He,showAllOption:I,allLabel:L,position:E,className:j}),o.jsxs(N.Stage,{ref:fe,width:tt,height:nt,scaleX:D,scaleY:D,x:$.x,y:$.y,draggable:!0,onDragEnd:Ke,onWheel:Je,style:{backgroundColor:h.canvas.backgroundColor,cursor:"grab"},children:[o.jsx(N.Layer,{listening:!1,children:ce.map(e=>o.jsx(Le,{stage:e,stageColor:ae.stageColor},e.id))}),o.jsx(N.Layer,{listening:!1,children:le.map(e=>o.jsx(De,{text:e},e.id))}),o.jsx(N.Layer,{children:q.map(e=>o.jsx(Te,{seat:e,state:J(e),colors:ae,onClick:_e,onMouseEnter:Qe,onMouseLeave:et},e.id))})]}),w&&o.jsx($e,{visible:G.visible,x:G.x,y:G.y,seat:G.seat,currency:ae.currency,state:G.state}),te&&m&&o.jsx(Ne,{scale:D,minScale:_,maxScale:P,onZoomIn:Ze,onZoomOut:Ge,onFitToScreen:be,position:ne,className:se}),Q.length>0&&o.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[o.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",Q.length,")"]}),o.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Q.map(e=>o.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${ae.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let ee=null;function lt(s){ee=s}function ye(){if(!ee)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return ee}function he(){return ee!==null}function ut(){ee=null}function Se(s,i){if(s.length!==i.length)return!1;const t=[...s].sort(),r=[...i].sort();return t.every((f,d)=>f===r[d])}function dt(s,i){const t=[],r=[],f=[];return Object.entries(s).forEach(([d,a])=>{a&&typeof a=="object"&&a.state&&(a.state==="unavailable"?f.push(d):a.state==="reserved"&&(i&&a.userId===i?t.push(d):r.push(d)))}),{myReserved:t.sort(),otherReserved:r.sort(),unavailable:f.sort()}}const de={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function We(s){const{seatMapId:i,currentUserId:t,enabled:r=!0,onStateChange:f,onError:d}=s,a=n.useRef({...de}),y=n.useRef(f),b=n.useRef(d),c=n.useRef(t);y.current=f,b.current=d,c.current=t;const x=n.useCallback(m=>{if(!r||!i)return(a.current.loading!==!1||a.current.states!==null)&&(a.current={...de,loading:!1},m()),()=>{};if(!he()){const E="Firebase not initialized. Call initializeFirebaseForViewer first.";return a.current.error?.message!==E&&(a.current={...de,loading:!1,error:new Error(E)},m()),()=>{}}const M=ye(),S=Y.ref(M,`seatmaps/${i}/seat_states`),F=E=>{const I=E.val()||{},L=dt(I,c.current),W=a.current;(W.loading||!Se(W.myReservedSeats,L.myReserved)||!Se(W.otherReservedSeats,L.otherReserved)||!Se(W.unavailableSeats,L.unavailable))&&(a.current={states:I,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:L.myReserved,otherReservedSeats:L.otherReserved,unavailableSeats:L.unavailable},y.current?.(I),m())},R=E=>{a.current={...a.current,loading:!1,error:E},b.current?.(E),m()};return Y.onValue(S,F,R),()=>{Y.off(S)}},[i,r]),v=n.useCallback(()=>a.current,[]),g=n.useCallback(()=>de,[]),w=n.useSyncExternalStore(x,v,g);return{states:w.states,loading:w.loading,error:w.error,lastUpdated:w.lastUpdated,myReservedSeats:w.myReservedSeats,otherReservedSeats:w.otherReservedSeats,unavailableSeats:w.unavailableSeats,reservedSeats:w.otherReservedSeats}}function Pe(s){const{seatMapId:i,enabled:t=!0,subscribeToChanges:r=!1,onConfigLoad:f,onError:d}=s,[a,y]=n.useState(null),[b,c]=n.useState(!0),[x,v]=n.useState(null),g=n.useRef(f),w=n.useRef(d);g.current=f,w.current=d;const m=n.useCallback(async()=>{if(!i)return;if(!he()){v(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),c(!1);return}const M=ye(),S=Y.ref(M,`seatmaps/${i}`);try{c(!0),v(null);const R=(await Y.get(S)).val();if(R){const E=at.fromFirebaseSeatMap(R);y(E),g.current?.(E)}else v(new Error(`Seat map ${i} not found in Firebase`))}catch(F){const R=F instanceof Error?F:new Error("Unknown error");v(R),w.current?.(R)}finally{c(!1)}},[i]);return n.useEffect(()=>{if(!t||!i){c(!1);return}if(m(),r&&he()){const M=ye(),S=Y.ref(M,`seatmaps/${i}/meta/updated_at`);let F=!0,R=null;const E=j=>{if(F){F=!1,R=j.val();return}const I=j.val();j.exists()&&I!==R&&(R=I,m())};return Y.onValue(S,E),()=>{Y.off(S)}}},[i,t,r]),{config:a,loading:b,error:x,refetch:m}}function ht(s){const{seatMapId:i,userId:t,enabled:r=!0,subscribeToDesignChanges:f=!1,onConfigLoad:d,onStateChange:a,onError:y}=s,{config:b,loading:c,error:x,refetch:v}=Pe({seatMapId:i,enabled:r,subscribeToChanges:f,onConfigLoad:d,onError:y}),{states:g,loading:w,error:m,lastUpdated:M,myReservedSeats:S,otherReservedSeats:F,unavailableSeats:R,reservedSeats:E}=We({seatMapId:i,currentUserId:t,enabled:r,onStateChange:a,onError:y});return{config:b,loading:c||w,error:x||m,myReservedSeats:S,otherReservedSeats:F,unavailableSeats:R,reservedSeats:E,seatStates:g,lastUpdated:M,refetch:v}}exports.DEFAULT_COLORS=Ie;exports.SeatMapViewer=ct;exports.clearFirebaseInstance=ut;exports.initializeFirebaseForViewer=lt;exports.isFirebaseInitialized=he;exports.useConfigFetcher=Fe;exports.useContainerSize=Ee;exports.useFirebaseConfig=Pe;exports.useFirebaseSeatStates=We;exports.useRealtimeSeatMap=ht;exports.useTouchGestures=ke;
|
|
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;
|