@zonetrix/viewer 2.4.1 → 2.5.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 CHANGED
@@ -112,7 +112,7 @@ function BookingApp() {
112
112
  | `onSeatDeselect` | `(seat: SeatData) => void` | No | Callback when a seat is deselected |
113
113
  | `onSelectionChange` | `(seats: SeatData[]) => void` | No | Callback when selection changes |
114
114
  | `colorOverrides` | `Partial<ColorSettings>` | No | Custom colors for seat states |
115
- | `showTooltip` | `boolean` | No | Show tooltips on hover (default: true) |
115
+ | `showTooltip` | `boolean` | No | Show seat tooltips on hover with seat info, price, status (default: true) |
116
116
  | `zoomEnabled` | `boolean` | No | Enable/disable zoom functionality (default: true) |
117
117
  | `className` | `string` | No | Custom CSS class for the container |
118
118
  | `onConfigLoad` | `(config: SeatMapConfig) => void` | No | Callback when config is loaded |
@@ -28,5 +28,6 @@ export interface SeatMapViewerProps {
28
28
  zoomControlsClassName?: string;
29
29
  maxZoom?: number;
30
30
  zoomStep?: number;
31
+ touchEnabled?: boolean;
31
32
  }
32
33
  export declare const SeatMapViewer: React.FC<SeatMapViewerProps>;
@@ -0,0 +1,11 @@
1
+ import { RefObject } from 'react';
2
+ interface ContainerSize {
3
+ width: number;
4
+ height: number;
5
+ }
6
+ /**
7
+ * Hook to track the size of a container element using ResizeObserver.
8
+ * Returns { width: 0, height: 0 } until the container is mounted and measured.
9
+ */
10
+ export declare function useContainerSize(containerRef: RefObject<HTMLDivElement | null>): ContainerSize;
11
+ export {};
@@ -0,0 +1,25 @@
1
+ import { RefObject } from 'react';
2
+ import { default as Konva } from 'konva';
3
+ interface TouchGestureConfig {
4
+ enabled: boolean;
5
+ minScale: number;
6
+ maxScale: number;
7
+ currentScale: number;
8
+ currentPosition: {
9
+ x: number;
10
+ y: number;
11
+ };
12
+ onScaleChange: (scale: number, position: {
13
+ x: number;
14
+ y: number;
15
+ }) => void;
16
+ onPositionChange: (position: {
17
+ x: number;
18
+ y: number;
19
+ }) => void;
20
+ }
21
+ /**
22
+ * Hook to handle touch gestures (pinch-to-zoom and two-finger pan) on a Konva Stage.
23
+ */
24
+ export declare function useTouchGestures(stageRef: RefObject<Konva.Stage | null>, config: TouchGestureConfig): void;
25
+ export {};
package/dist/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export type { SeatMapViewerProps } from './components/SeatMapViewer';
3
3
  export type { SeatState, SeatShape, SeatData, SerializedSeat, SerializedSection, SerializedStage, ColorSettings, SeatMapConfig, FloorConfig, } from './types';
4
4
  export { DEFAULT_COLORS } from './types';
5
5
  export { useConfigFetcher } from './hooks/useConfigFetcher';
6
+ export { useContainerSize } from './hooks/useContainerSize';
7
+ export { useTouchGestures } from './hooks/useTouchGestures';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),n=require("react"),E=require("react-konva");function J(o){const[p,h]=n.useState(null),[a,y]=n.useState(!1),[m,S]=n.useState(null),j=async()=>{if(o){y(!0),S(null);try{const x=await fetch(o);if(!x.ok)throw new Error(`Failed to fetch config: ${x.statusText}`);const r=await x.json();h(r)}catch(x){const r=x instanceof Error?x:new Error("Unknown error occurred");S(r),console.error("Failed to fetch seat map config:",r)}finally{y(!1)}}};return n.useEffect(()=>{j()},[o]),{config:p,loading:a,error:m,refetch:j}}const Q={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},ee=n.memo(({seat:o,state:p,colors:h,onClick:a,onMouseEnter:y,onMouseLeave:m})=>{const x={available:h.seatAvailable,reserved:h.seatReserved,selected:h.seatSelected,unavailable:h.seatUnavailable,hidden:h.seatHidden}[p],r=p==="available"||p==="selected",g=n.useCallback(()=>{r&&a(o)},[o,a,r]),b=n.useCallback(k=>{y(o,k);const M=k.target.getStage();M&&r&&(M.container().style.cursor="pointer")},[o,y,r]),f=n.useCallback(k=>{m();const M=k.target.getStage();M&&(M.container().style.cursor="grab")},[m]),w={x:o.position.x,y:o.position.y,fill:x,stroke:"#ffffff",strokeWidth:1,onClick:g,onTap:g,onMouseEnter:b,onMouseLeave:f};return o.shape==="circle"?t.jsx(E.Circle,{...w,radius:12}):t.jsx(E.Rect,{...w,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:o.shape==="square"?0:4})});ee.displayName="ViewerSeat";const te=n.memo(({stage:o,stageColor:p})=>t.jsxs(E.Group,{x:o.position.x,y:o.position.y,children:[t.jsx(E.Rect,{width:o.config.width,height:o.config.height,fill:p+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),t.jsx(E.Text,{text:o.config.label,x:0,y:0,width:o.config.width,height:o.config.height,fontSize:24,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]}));te.displayName="ViewerStage";const ne=n.memo(({floors:o,currentFloorId:p,onFloorChange:h,showAllOption:a,allLabel:y,position:m,className:S})=>{const j=n.useMemo(()=>[...o].sort((f,w)=>f.order-w.order),[o]),r={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}}[m]},g={padding:"6px 14px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease"},b={...g,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return t.jsxs("div",{className:S,style:r,children:[a&&t.jsx("button",{type:"button",onClick:()=>h(null),style:p===null?b:g,children:y}),j.map(f=>t.jsx("button",{type:"button",onClick:()=>h(f.id),style:p===f.id?b:g,children:f.name},f.id))]})});ne.displayName="FloorSelectorBar";const se=n.memo(({scale:o,minScale:p,maxScale:h,onZoomIn:a,onZoomOut:y,position:m,className:S})=>{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}}[m]},r={width:"36px",height:"36px",fontSize:"20px",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"},g={...r,opacity:.4,cursor:"not-allowed"},b=o<h,f=o>p;return t.jsxs("div",{className:S,style:x,children:[t.jsx("button",{type:"button",onClick:a,disabled:!b,style:b?r:g,title:"Zoom In",children:"+"}),t.jsx("button",{type:"button",onClick:y,disabled:!f,style:f?r:g,title:"Zoom Out",children:"−"})]})});se.displayName="ZoomControls";const oe=n.memo(({visible:o,x:p,y:h,seat:a,currency:y,state:m})=>{if(!o||!a)return null;const S=a.seatNumber||(a.rowLabel&&a.columnLabel?`${a.rowLabel}-${a.columnLabel}`:"N/A"),j={position:"fixed",left:`${p+15}px`,top:`${h+15}px`,zIndex:1e3,pointerEvents:"none"},x={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},r={color:"#9ca3af",marginRight:"4px"},g={fontWeight:600},b={color:"#4ade80",fontWeight:600},f={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return t.jsx("div",{style:j,children:t.jsxs("div",{style:x,children:[a.sectionName&&t.jsxs("div",{style:{marginBottom:"4px"},children:[t.jsx("span",{style:r,children:"Section:"}),t.jsx("span",{style:{...g,color:"#3b82f6"},children:a.sectionName})]}),t.jsxs("div",{style:{marginBottom:"4px"},children:[t.jsx("span",{style:r,children:"Seat:"}),t.jsx("span",{style:g,children:S})]}),a.price!==void 0&&a.price>0&&t.jsxs("div",{style:{marginBottom:"4px"},children:[t.jsx("span",{style:r,children:"Price:"}),t.jsxs("span",{style:b,children:[y," ",a.price.toFixed(2)]})]}),t.jsxs("div",{style:f,children:["Status: ",m]})]})})});oe.displayName="SeatTooltip";const Be=({config:o,configUrl:p,floorId:h,onFloorChange:a,reservedSeats:y=[],unavailableSeats:m=[],onSeatSelect:S,onSeatDeselect:j,onSelectionChange:x,colorOverrides:r,showTooltip:g=!0,zoomEnabled:b=!0,className:f="",onConfigLoad:w,onError:k,showFloorSelector:M,floorSelectorPosition:ie="top-left",floorSelectorClassName:ae,showAllFloorsOption:re=!0,allFloorsLabel:le="All",fitToView:$=!0,fitPadding:P=40,showZoomControls:ce=!0,zoomControlsPosition:de="bottom-right",zoomControlsClassName:ue,maxZoom:L=3,zoomStep:D=.25})=>{const fe=n.useRef(null),[R,he]=n.useState(new Set),[v,Z]=n.useState(1),[I,T]=n.useState({x:0,y:0}),[pe,xe]=n.useState(null),[U,K]=n.useState(!1),[ge,be]=n.useState(1),[A,G]=n.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:ye,loading:me,error:B}=J(p),s=o||ye,V=h!==void 0,C=V?h||null:pe,Se=n.useCallback(e=>{V||xe(e),a?.(e)},[V,a]),q=s?.floors||[],ve=M!==void 0?M:q.length>1,z=n.useMemo(()=>s?{...s.colors,...r}:{...Q,...r},[s,r]),F=n.useMemo(()=>{if(!s)return[];let e=s.seats.filter(i=>i.state!=="hidden");return C&&(e=e.filter(i=>i.floorId===C||!i.floorId&&C==="floor_default")),e},[s,C]),O=n.useMemo(()=>s?.stages?C?s.stages.filter(e=>e.floorId===C||!e.floorId&&C==="floor_default"):s.stages:[],[s,C]),N=n.useMemo(()=>{if(!s||F.length===0&&O.length===0)return null;const e=12;let i=1/0,l=1/0,d=-1/0,c=-1/0;return F.forEach(u=>{i=Math.min(i,u.position.x-e),l=Math.min(l,u.position.y-e),d=Math.max(d,u.position.x+e),c=Math.max(c,u.position.y+e)}),O.forEach(u=>{i=Math.min(i,u.position.x),l=Math.min(l,u.position.y),d=Math.max(d,u.position.x+(u.config?.width||200)),c=Math.max(c,u.position.y+(u.config?.height||100))}),{minX:i,minY:l,maxX:d,maxY:c,width:d-i,height:c-l}},[s,F,O]);n.useEffect(()=>{if(!$||U||!s||!N)return;const e=s.canvas.width,i=s.canvas.height,l=e-P*2,d=i-P*2,c=l/N.width,u=d/N.height,H=Math.min(c,u,L),Ne=N.minX+N.width/2,Ee=N.minY+N.height/2,Re=e/2,Fe=i/2,Le=Re-Ne*H,Ae=Fe-Ee*H;Z(H),T({x:Le,y:Ae}),be(H),K(!0)},[$,U,s,N,P,L]),n.useEffect(()=>{$&&K(!1)},[C,$]);const W=n.useMemo(()=>{const e=new Set(y),i=new Set(m);return{reserved:e,unavailable:i}},[y,m]),X=n.useCallback(e=>{const i=e.id,l=e.seatNumber||"";return W.unavailable.has(i)||W.unavailable.has(l)?"unavailable":W.reserved.has(i)||W.reserved.has(l)?"reserved":R.has(i)?"selected":e.state},[W,R]);n.useEffect(()=>{s&&w&&w(s)},[s,w]),n.useEffect(()=>{B&&k&&k(B)},[B,k]);const je=n.useCallback(e=>{const i=X(e);if(i!=="available"&&i!=="selected")return;const l=R.has(e.id);he(d=>{const c=new Set(d);return l?c.delete(e.id):c.add(e.id),c}),l?j?.(e):(S?.(e),S||console.log("Seat selected:",e))},[X,R,S,j]),Y=n.useMemo(()=>s?F.filter(e=>R.has(e.id)):[],[F,R]);n.useEffect(()=>{x?.(Y)},[Y,x]);const _=ge,Ce=n.useCallback(()=>{if(!b)return;const e=Math.min(v+D,L);if(e!==v){const i=s?.canvas.width||800,l=s?.canvas.height||600,d=i/2,c=l/2,u={x:(d-I.x)/v,y:(c-I.y)/v};Z(e),T({x:d-u.x*e,y:c-u.y*e})}},[b,v,D,L,s,I]),we=n.useCallback(()=>{if(!b)return;const e=Math.max(v-D,_);if(e!==v){const i=s?.canvas.width||800,l=s?.canvas.height||600,d=i/2,c=l/2,u={x:(d-I.x)/v,y:(c-I.y)/v};Z(e),T({x:d-u.x*e,y:c-u.y*e})}},[b,v,D,_,s,I]),ke=n.useCallback(e=>{T({x:e.target.x(),y:e.target.y()})},[]),Me=n.useCallback((e,i)=>{if(!g)return;const l=i.target.getStage();if(!l)return;const d=l.getPointerPosition();if(!d)return;const c=l.container().getBoundingClientRect();G({visible:!0,x:c.left+d.x,y:c.top+d.y,seat:e,state:X(e)})},[g,X]),Ie=n.useCallback(()=>{G(e=>({...e,visible:!1}))},[]);return me?t.jsx("div",{className:`flex items-center justify-center h-full ${f}`,children:t.jsx("p",{children:"Loading seat map..."})}):B?t.jsx("div",{className:`flex items-center justify-center h-full ${f}`,children:t.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",B.message]})}):s?t.jsxs("div",{className:`relative ${f}`,children:[ve&&q.length>0&&t.jsx(ne,{floors:q,currentFloorId:C,onFloorChange:Se,showAllOption:re,allLabel:le,position:ie,className:ae}),t.jsxs(E.Stage,{ref:fe,width:s.canvas.width,height:s.canvas.height,scaleX:v,scaleY:v,x:I.x,y:I.y,draggable:!0,onDragEnd:ke,style:{backgroundColor:s.canvas.backgroundColor,cursor:"grab"},children:[t.jsx(E.Layer,{listening:!1,children:O.map(e=>t.jsx(te,{stage:e,stageColor:z.stageColor},e.id))}),t.jsx(E.Layer,{children:F.map(e=>t.jsx(ee,{seat:e,state:X(e),colors:z,onClick:je,onMouseEnter:Me,onMouseLeave:Ie},e.id))})]}),g&&t.jsx(oe,{visible:A.visible,x:A.x,y:A.y,seat:A.seat,currency:z.currency,state:A.state}),ce&&b&&t.jsx(se,{scale:v,minScale:_,maxScale:L,onZoomIn:Ce,onZoomOut:we,position:de,className:ue}),Y.length>0&&t.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[t.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",Y.length,")"]}),t.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:Y.map(e=>t.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${z.currency} ${e.price.toFixed(2)}`]},e.id))})]})]}):t.jsx("div",{className:`flex items-center justify-center h-full ${f}`,children:t.jsx("p",{children:"No configuration provided"})})};exports.DEFAULT_COLORS=Q;exports.SeatMapViewer=Be;exports.useConfigFetcher=J;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),e=require("react"),L=require("react-konva");function dt(n){const[i,d]=e.useState(null),[r,b]=e.useState(!1),[S,p]=e.useState(null),v=async()=>{if(n){b(!0),p(null);try{const y=await fetch(n);if(!y.ok)throw new Error(`Failed to fetch config: ${y.statusText}`);const a=await y.json();d(a)}catch(y){const a=y instanceof Error?y:new Error("Unknown error occurred");p(a),console.error("Failed to fetch seat map config:",a)}finally{b(!1)}}};return e.useEffect(()=>{v()},[n]),{config:i,loading:r,error:S,refetch:v}}function ft(n){const[i,d]=e.useState({width:0,height:0});return e.useEffect(()=>{const r=n.current;if(!r)return;const{width:b,height:S}=r.getBoundingClientRect();b>0&&S>0&&d({width:b,height:S});const p=new ResizeObserver(v=>{const y=v[0];if(!y)return;const{width:a,height:s}=y.contentRect;a>0&&s>0&&d(u=>u.width===a&&u.height===s?u:{width:a,height:s})});return p.observe(r),()=>{p.disconnect()}},[n]),i}function ut(n,i){return Math.sqrt(Math.pow(i.x-n.x,2)+Math.pow(i.y-n.y,2))}function ht(n,i){return{x:(n.x+i.x)/2,y:(n.y+i.y)/2}}function xt(n,i){const d=e.useRef(null),r=e.useRef(null),b=e.useRef(1);e.useEffect(()=>{const S=n.current;if(!S||!i.enabled)return;const p=S.container(),v=s=>{if(s.touches.length===2){s.preventDefault();const u={x:s.touches[0].clientX,y:s.touches[0].clientY},g={x:s.touches[1].clientX,y:s.touches[1].clientY};d.current=ut(u,g),r.current=ht(u,g),b.current=i.currentScale}},y=s=>{if(s.touches.length!==2)return;s.preventDefault();const u={x:s.touches[0].clientX,y:s.touches[0].clientY},g={x:s.touches[1].clientX,y:s.touches[1].clientY},k=ut(u,g),C=ht(u,g);if(d.current!==null&&r.current!==null){const R=k/d.current,P=Math.min(Math.max(i.currentScale*R,i.minScale),i.maxScale),V=p.getBoundingClientRect(),_=C.x-V.left,G=C.y-V.top,W=i.currentScale,T={x:(_-i.currentPosition.x)/W,y:(G-i.currentPosition.y)/W},et=C.x-r.current.x,nt=C.y-r.current.y,ot={x:_-T.x*P+et,y:G-T.y*P+nt};i.onScaleChange(P,ot),d.current=k,r.current=C}},a=s=>{s.touches.length<2&&(d.current=null,r.current=null)};return p.addEventListener("touchstart",v,{passive:!1}),p.addEventListener("touchmove",y,{passive:!1}),p.addEventListener("touchend",a),()=>{p.removeEventListener("touchstart",v),p.removeEventListener("touchmove",y),p.removeEventListener("touchend",a)}},[n,i])}const pt={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},gt=e.memo(({seat:n,state:i,colors:d,onClick:r,onMouseEnter:b,onMouseLeave:S})=>{const y={available:d.seatAvailable,reserved:d.seatReserved,selected:d.seatSelected,unavailable:d.seatUnavailable,hidden:d.seatHidden}[i],a=i==="available"||i==="selected",s=e.useCallback(()=>{a&&r(n)},[n,r,a]),u=e.useCallback(C=>{b(n,C);const R=C.target.getStage();R&&a&&(R.container().style.cursor="pointer")},[n,b,a]),g=e.useCallback(C=>{S();const R=C.target.getStage();R&&(R.container().style.cursor="grab")},[S]),k={x:n.position.x,y:n.position.y,fill:y,stroke:"#ffffff",strokeWidth:1,onClick:s,onTap:s,onMouseEnter:u,onMouseLeave:g};return n.shape==="circle"?o.jsx(L.Circle,{...k,radius:12}):o.jsx(L.Rect,{...k,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:n.shape==="square"?0:4})});gt.displayName="ViewerSeat";const yt=e.memo(({stage:n,stageColor:i})=>o.jsxs(L.Group,{x:n.position.x,y:n.position.y,children:[o.jsx(L.Rect,{width:n.config.width,height:n.config.height,fill:i+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),o.jsx(L.Text,{text:n.config.label,x:0,y:0,width:n.config.width,height:n.config.height,fontSize:24,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]}));yt.displayName="ViewerStage";const mt=e.memo(({floors:n,currentFloorId:i,onFloorChange:d,showAllOption:r,allLabel:b,position:S,className:p})=>{const v=e.useMemo(()=>[...n].sort((g,k)=>g.order-k.order),[n]),a={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[S]},s={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"},u={...s,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return o.jsxs("div",{className:p,style:a,children:[r&&o.jsx("button",{type:"button",onClick:()=>d(null),style:i===null?u:s,children:b}),v.map(g=>o.jsx("button",{type:"button",onClick:()=>d(g.id),style:i===g.id?u:s,children:g.name},g.id))]})});mt.displayName="FloorSelectorBar";const bt=e.memo(({scale:n,minScale:i,maxScale:d,onZoomIn:r,onZoomOut:b,position:S,className:p})=>{const y={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}}[S]},a={width:"44px",height:"44px",minWidth:"44px",minHeight:"44px",fontSize:"22px",fontWeight:"bold",border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.2s ease",touchAction:"manipulation"},s={...a,opacity:.4,cursor:"not-allowed"},u=n<d,g=n>i;return o.jsxs("div",{className:p,style:y,children:[o.jsx("button",{type:"button",onClick:r,disabled:!u,style:u?a:s,title:"Zoom In",children:"+"}),o.jsx("button",{type:"button",onClick:b,disabled:!g,style:g?a:s,title:"Zoom Out",children:"−"})]})});bt.displayName="ZoomControls";const St=e.memo(({visible:n,x:i,y:d,seat:r,currency:b,state:S})=>{if(!n||!r)return null;const p=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),v={position:"fixed",left:`${i+15}px`,top:`${d+15}px`,zIndex:1e3,pointerEvents:"none"},y={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},a={color:"#9ca3af",marginRight:"4px"},s={fontWeight:600},u={color:"#4ade80",fontWeight:600},g={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return o.jsx("div",{style:v,children:o.jsxs("div",{style:y,children:[r.sectionName&&o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:a,children:"Section:"}),o.jsx("span",{style:{...s,color:"#3b82f6"},children:r.sectionName})]}),o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:a,children:"Seat:"}),o.jsx("span",{style:s,children:p})]}),r.price!==void 0&&r.price>0&&o.jsxs("div",{style:{marginBottom:"4px"},children:[o.jsx("span",{style:a,children:"Price:"}),o.jsxs("span",{style:u,children:[b," ",r.price.toFixed(2)]})]}),o.jsxs("div",{style:g,children:["Status: ",S]})]})})});St.displayName="SeatTooltip";const Vt=({config:n,configUrl:i,floorId:d,onFloorChange:r,reservedSeats:b=[],unavailableSeats:S=[],onSeatSelect:p,onSeatDeselect:v,onSelectionChange:y,colorOverrides:a,showTooltip:s=!0,zoomEnabled:u=!0,className:g="",onConfigLoad:k,onError:C,showFloorSelector:R,floorSelectorPosition:P="top-left",floorSelectorClassName:V,showAllFloorsOption:_=!0,allFloorsLabel:G="All",fitToView:W=!0,fitPadding:T=40,showZoomControls:et=!0,zoomControlsPosition:nt="bottom-right",zoomControlsClassName:ot,maxZoom:I=3,zoomStep:U=.25,touchEnabled:vt=!0})=>{const st=e.useRef(null),at=e.useRef(null),w=ft(at),[X,wt]=e.useState(new Set),[j,A]=e.useState(1),[M,D]=e.useState({x:0,y:0}),[Ct,jt]=e.useState(null),[Mt,kt]=e.useState(1),Z=e.useRef({width:0,height:0}),[B,lt]=e.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:Rt,loading:Et,error:z}=dt(i),l=n||Rt,it=d!==void 0,E=it?d||null:Ct,It=e.useCallback(t=>{it||jt(t),r?.(t)},[it,r]),rt=l?.floors||[],Nt=R!==void 0?R:rt.length>1,K=e.useMemo(()=>l?{...l.colors,...a}:{...pt,...a},[l,a]),Y=e.useMemo(()=>{if(!l)return[];let t=l.seats.filter(c=>c.state!=="hidden");return E&&(t=t.filter(c=>c.floorId===E||!c.floorId&&E==="floor_default")),t},[l,E]),J=e.useMemo(()=>l?.stages?E?l.stages.filter(t=>t.floorId===E||!t.floorId&&E==="floor_default"):l.stages:[],[l,E]),N=e.useMemo(()=>{if(!l||Y.length===0&&J.length===0)return null;const t=12;let c=1/0,f=1/0,h=-1/0,x=-1/0;return Y.forEach(m=>{c=Math.min(c,m.position.x-t),f=Math.min(f,m.position.y-t),h=Math.max(h,m.position.x+t),x=Math.max(x,m.position.y+t)}),J.forEach(m=>{c=Math.min(c,m.position.x),f=Math.min(f,m.position.y),h=Math.max(h,m.position.x+(m.config?.width||200)),x=Math.max(x,m.position.y+(m.config?.height||100))}),{minX:c,minY:f,maxX:h,maxY:x,width:h-c,height:x-f}},[l,Y,J]);e.useEffect(()=>{if(!W||!l||!N||w.width===0||w.height===0)return;const t=Math.abs(w.width-Z.current.width),c=Math.abs(w.height-Z.current.height);if(!(Z.current.width===0)&&t<10&&c<10)return;Z.current=w;const h=w.width,x=w.height,m=h-T*2,q=x-T*2,Q=m/N.width,ct=q/N.height,tt=Math.min(Q,ct,I),Bt=N.minX+N.width/2,zt=N.minY+N.height/2,$t=h/2,Ht=x/2,Ot=$t-Bt*tt,qt=Ht-zt*tt;A(tt),D({x:Ot,y:qt}),kt(tt)},[W,l,N,T,I,w,E]);const $=e.useMemo(()=>{const t=new Set(b),c=new Set(S);return{reserved:t,unavailable:c}},[b,S]),H=e.useCallback(t=>{const c=t.id,f=t.seatNumber||"";return $.unavailable.has(c)||$.unavailable.has(f)?"unavailable":$.reserved.has(c)||$.reserved.has(f)?"reserved":X.has(c)?"selected":t.state},[$,X]);e.useEffect(()=>{l&&k&&k(l)},[l,k]),e.useEffect(()=>{z&&C&&C(z)},[z,C]);const Lt=e.useCallback(t=>{const c=H(t);if(c!=="available"&&c!=="selected")return;const f=X.has(t.id);wt(h=>{const x=new Set(h);return f?x.delete(t.id):x.add(t.id),x}),f?v?.(t):(p?.(t),p||console.log("Seat selected:",t))},[H,X,p,v]),O=e.useMemo(()=>l?Y.filter(t=>X.has(t.id)):[],[Y,X]);e.useEffect(()=>{y?.(O)},[O,y]);const F=Mt,Dt=e.useCallback(()=>{if(!u)return;const t=Math.min(j+U,I);if(t!==j){const c=w.width||l?.canvas.width||800,f=w.height||l?.canvas.height||600,h=c/2,x=f/2,m={x:(h-M.x)/j,y:(x-M.y)/j};A(t),D({x:h-m.x*t,y:x-m.y*t})}},[u,j,U,I,w,l,M]),Tt=e.useCallback(()=>{if(!u)return;const t=Math.max(j-U,F);if(t!==j){const c=w.width||l?.canvas.width||800,f=w.height||l?.canvas.height||600,h=c/2,x=f/2,m={x:(h-M.x)/j,y:(x-M.y)/j};A(t),D({x:h-m.x*t,y:x-m.y*t})}},[u,j,U,F,w,l,M]),Xt=e.useCallback(t=>{D({x:t.target.x(),y:t.target.y()})},[]),Yt=e.useCallback(t=>{if(!u)return;t.evt.preventDefault();const c=st.current;if(!c)return;const f=c.scaleX(),h=c.getPointerPosition();if(!h)return;const x=1.1,m=t.evt.deltaY>0?f/x:f*x,q=Math.min(Math.max(m,F),I),Q={x:(h.x-M.x)/f,y:(h.y-M.y)/f},ct={x:h.x-Q.x*q,y:h.y-Q.y*q};A(q),D(ct)},[u,M,F,I]);xt(st,{enabled:vt&&u,minScale:F,maxScale:I,currentScale:j,currentPosition:M,onScaleChange:(t,c)=>{A(t),D(c)},onPositionChange:t=>{D(t)}});const Ft=e.useCallback((t,c)=>{if(!s)return;const f=c.target.getStage();if(!f)return;const h=f.getPointerPosition();if(!h)return;const x=f.container().getBoundingClientRect();lt({visible:!0,x:x.left+h.x,y:x.top+h.y,seat:t,state:H(t)})},[s,H]),Pt=e.useCallback(()=>{lt(t=>({...t,visible:!1}))},[]);if(Et)return o.jsx("div",{className:`flex items-center justify-center h-full ${g}`,children:o.jsx("p",{children:"Loading seat map..."})});if(z)return o.jsx("div",{className:`flex items-center justify-center h-full ${g}`,children:o.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",z.message]})});if(!l)return o.jsx("div",{className:`flex items-center justify-center h-full ${g}`,children:o.jsx("p",{children:"No configuration provided"})});const Wt=w.width||l.canvas.width,At=w.height||l.canvas.height;return o.jsxs("div",{ref:at,className:`relative ${g}`,style:{width:"100%",height:"100%"},children:[Nt&&rt.length>0&&o.jsx(mt,{floors:rt,currentFloorId:E,onFloorChange:It,showAllOption:_,allLabel:G,position:P,className:V}),o.jsxs(L.Stage,{ref:st,width:Wt,height:At,scaleX:j,scaleY:j,x:M.x,y:M.y,draggable:!0,onDragEnd:Xt,onWheel:Yt,style:{backgroundColor:l.canvas.backgroundColor,cursor:"grab"},children:[o.jsx(L.Layer,{listening:!1,children:J.map(t=>o.jsx(yt,{stage:t,stageColor:K.stageColor},t.id))}),o.jsx(L.Layer,{children:Y.map(t=>o.jsx(gt,{seat:t,state:H(t),colors:K,onClick:Lt,onMouseEnter:Ft,onMouseLeave:Pt},t.id))})]}),s&&o.jsx(St,{visible:B.visible,x:B.x,y:B.y,seat:B.seat,currency:K.currency,state:B.state}),et&&u&&o.jsx(bt,{scale:j,minScale:F,maxScale:I,onZoomIn:Dt,onZoomOut:Tt,position:nt,className:ot}),O.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 (",O.length,")"]}),o.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:O.map(t=>o.jsxs("div",{className:"text-sm",children:[t.seatNumber,t.price&&` - ${K.currency} ${t.price.toFixed(2)}`]},t.id))})]})]})};exports.DEFAULT_COLORS=pt;exports.SeatMapViewer=Vt;exports.useConfigFetcher=dt;exports.useContainerSize=ft;exports.useTouchGestures=xt;
package/dist/index.mjs CHANGED
@@ -1,34 +1,97 @@
1
- import { jsx as i, jsxs as x } from "react/jsx-runtime";
2
- import { useState as I, useEffect as W, useRef as zt, useCallback as C, useMemo as L, memo as j } from "react";
3
- import { Stage as Dt, Layer as nt, Group as Tt, Rect as ot, Text as jt, Circle as Ht } from "react-konva";
4
- function Ot(n) {
5
- const [u, h] = I(null), [r, b] = I(!1), [m, v] = I(null), w = async () => {
6
- if (n) {
7
- b(!0), v(null);
1
+ import { jsx as h, jsxs as w } from "react/jsx-runtime";
2
+ import { useState as L, useEffect as W, useRef as z, useCallback as I, useMemo as T, memo as U } from "react";
3
+ import { Stage as Gt, Layer as gt, Group as Ut, Rect as mt, Text as Kt, Circle as Jt } from "react-konva";
4
+ function Qt(e) {
5
+ const [o, d] = L(null), [i, m] = L(!1), [b, p] = L(null), S = async () => {
6
+ if (e) {
7
+ m(!0), p(null);
8
8
  try {
9
- const p = await fetch(n);
10
- if (!p.ok)
11
- throw new Error(`Failed to fetch config: ${p.statusText}`);
12
- const s = await p.json();
13
- h(s);
14
- } catch (p) {
15
- const s = p instanceof Error ? p : new Error("Unknown error occurred");
16
- v(s), console.error("Failed to fetch seat map config:", s);
9
+ const y = await fetch(e);
10
+ if (!y.ok)
11
+ throw new Error(`Failed to fetch config: ${y.statusText}`);
12
+ const s = await y.json();
13
+ d(s);
14
+ } catch (y) {
15
+ const s = y instanceof Error ? y : new Error("Unknown error occurred");
16
+ p(s), console.error("Failed to fetch seat map config:", s);
17
17
  } finally {
18
- b(!1);
18
+ m(!1);
19
19
  }
20
20
  }
21
21
  };
22
22
  return W(() => {
23
- w();
24
- }, [n]), {
25
- config: u,
26
- loading: r,
27
- error: m,
28
- refetch: w
23
+ S();
24
+ }, [e]), {
25
+ config: o,
26
+ loading: i,
27
+ error: b,
28
+ refetch: S
29
29
  };
30
30
  }
31
- const Zt = {
31
+ function te(e) {
32
+ const [o, d] = L({ width: 0, height: 0 });
33
+ return W(() => {
34
+ const i = e.current;
35
+ if (!i) return;
36
+ const { width: m, height: b } = i.getBoundingClientRect();
37
+ m > 0 && b > 0 && d({ width: m, height: b });
38
+ const p = new ResizeObserver((S) => {
39
+ const y = S[0];
40
+ if (!y) return;
41
+ const { width: s, height: n } = y.contentRect;
42
+ s > 0 && n > 0 && d((a) => a.width === s && a.height === n ? a : { width: s, height: n });
43
+ });
44
+ return p.observe(i), () => {
45
+ p.disconnect();
46
+ };
47
+ }, [e]), o;
48
+ }
49
+ function yt(e, o) {
50
+ return Math.sqrt(Math.pow(o.x - e.x, 2) + Math.pow(o.y - e.y, 2));
51
+ }
52
+ function xt(e, o) {
53
+ return {
54
+ x: (e.x + o.x) / 2,
55
+ y: (e.y + o.y) / 2
56
+ };
57
+ }
58
+ function ee(e, o) {
59
+ const d = z(null), i = z(null), m = z(1);
60
+ W(() => {
61
+ const b = e.current;
62
+ if (!b || !o.enabled) return;
63
+ const p = b.container(), S = (n) => {
64
+ if (n.touches.length === 2) {
65
+ n.preventDefault();
66
+ const a = { x: n.touches[0].clientX, y: n.touches[0].clientY }, g = { x: n.touches[1].clientX, y: n.touches[1].clientY };
67
+ d.current = yt(a, g), i.current = xt(a, g), m.current = o.currentScale;
68
+ }
69
+ }, y = (n) => {
70
+ if (n.touches.length !== 2) return;
71
+ n.preventDefault();
72
+ const a = { x: n.touches[0].clientX, y: n.touches[0].clientY }, g = { x: n.touches[1].clientX, y: n.touches[1].clientY }, N = yt(a, g), C = xt(a, g);
73
+ if (d.current !== null && i.current !== null) {
74
+ const D = N / d.current, $ = Math.min(
75
+ Math.max(o.currentScale * D, o.minScale),
76
+ o.maxScale
77
+ ), K = p.getBoundingClientRect(), J = C.x - K.left, Q = C.y - K.top, H = o.currentScale, P = {
78
+ x: (J - o.currentPosition.x) / H,
79
+ y: (Q - o.currentPosition.y) / H
80
+ }, st = C.x - i.current.x, ct = C.y - i.current.y, at = {
81
+ x: J - P.x * $ + st,
82
+ y: Q - P.y * $ + ct
83
+ };
84
+ o.onScaleChange($, at), d.current = N, i.current = C;
85
+ }
86
+ }, s = (n) => {
87
+ n.touches.length < 2 && (d.current = null, i.current = null);
88
+ };
89
+ return p.addEventListener("touchstart", S, { passive: !1 }), p.addEventListener("touchmove", y, { passive: !1 }), p.addEventListener("touchend", s), () => {
90
+ p.removeEventListener("touchstart", S), p.removeEventListener("touchmove", y), p.removeEventListener("touchend", s);
91
+ };
92
+ }, [e, o]);
93
+ }
94
+ const ne = {
32
95
  canvasBackground: "#1a1a1a",
33
96
  stageColor: "#808080",
34
97
  seatAvailable: "#2C2B30",
@@ -38,74 +101,74 @@ const Zt = {
38
101
  seatHidden: "#4a4a4a",
39
102
  gridLines: "#404040",
40
103
  currency: "KD"
41
- }, it = j(({ seat: n, state: u, colors: h, onClick: r, onMouseEnter: b, onMouseLeave: m }) => {
42
- const p = {
43
- available: h.seatAvailable,
44
- reserved: h.seatReserved,
45
- selected: h.seatSelected,
46
- unavailable: h.seatUnavailable,
47
- hidden: h.seatHidden
104
+ }, bt = U(({ seat: e, state: o, colors: d, onClick: i, onMouseEnter: m, onMouseLeave: b }) => {
105
+ const y = {
106
+ available: d.seatAvailable,
107
+ reserved: d.seatReserved,
108
+ selected: d.seatSelected,
109
+ unavailable: d.seatUnavailable,
110
+ hidden: d.seatHidden
48
111
  // Hidden seats are filtered out, but included for type safety
49
- }[u], s = u === "available" || u === "selected", g = C(() => {
50
- s && r(n);
51
- }, [n, r, s]), y = C((M) => {
52
- b(n, M);
53
- const R = M.target.getStage();
54
- R && s && (R.container().style.cursor = "pointer");
55
- }, [n, b, s]), f = C((M) => {
56
- m();
57
- const R = M.target.getStage();
58
- R && (R.container().style.cursor = "grab");
59
- }, [m]), N = {
60
- x: n.position.x,
61
- y: n.position.y,
62
- fill: p,
112
+ }[o], s = o === "available" || o === "selected", n = I(() => {
113
+ s && i(e);
114
+ }, [e, i, s]), a = I((C) => {
115
+ m(e, C);
116
+ const D = C.target.getStage();
117
+ D && s && (D.container().style.cursor = "pointer");
118
+ }, [e, m, s]), g = I((C) => {
119
+ b();
120
+ const D = C.target.getStage();
121
+ D && (D.container().style.cursor = "grab");
122
+ }, [b]), N = {
123
+ x: e.position.x,
124
+ y: e.position.y,
125
+ fill: y,
63
126
  stroke: "#ffffff",
64
127
  strokeWidth: 1,
65
- onClick: g,
66
- onTap: g,
67
- onMouseEnter: y,
68
- onMouseLeave: f
128
+ onClick: n,
129
+ onTap: n,
130
+ onMouseEnter: a,
131
+ onMouseLeave: g
69
132
  };
70
- return n.shape === "circle" ? /* @__PURE__ */ i(
71
- Ht,
133
+ return e.shape === "circle" ? /* @__PURE__ */ h(
134
+ Jt,
72
135
  {
73
136
  ...N,
74
137
  radius: 12
75
138
  }
76
- ) : /* @__PURE__ */ i(
77
- ot,
139
+ ) : /* @__PURE__ */ h(
140
+ mt,
78
141
  {
79
142
  ...N,
80
143
  width: 24,
81
144
  height: 24,
82
145
  offsetX: 12,
83
146
  offsetY: 12,
84
- cornerRadius: n.shape === "square" ? 0 : 4
147
+ cornerRadius: e.shape === "square" ? 0 : 4
85
148
  }
86
149
  );
87
150
  });
88
- it.displayName = "ViewerSeat";
89
- const rt = j(({ stage: n, stageColor: u }) => /* @__PURE__ */ x(Tt, { x: n.position.x, y: n.position.y, children: [
90
- /* @__PURE__ */ i(
91
- ot,
151
+ bt.displayName = "ViewerSeat";
152
+ const St = U(({ stage: e, stageColor: o }) => /* @__PURE__ */ w(Ut, { x: e.position.x, y: e.position.y, children: [
153
+ /* @__PURE__ */ h(
154
+ mt,
92
155
  {
93
- width: n.config.width,
94
- height: n.config.height,
95
- fill: u + "80",
156
+ width: e.config.width,
157
+ height: e.config.height,
158
+ fill: o + "80",
96
159
  stroke: "#ffffff",
97
160
  strokeWidth: 2,
98
161
  cornerRadius: 10
99
162
  }
100
163
  ),
101
- /* @__PURE__ */ i(
102
- jt,
164
+ /* @__PURE__ */ h(
165
+ Kt,
103
166
  {
104
- text: n.config.label,
167
+ text: e.config.label,
105
168
  x: 0,
106
169
  y: 0,
107
- width: n.config.width,
108
- height: n.config.height,
170
+ width: e.config.width,
171
+ height: e.config.height,
109
172
  fontSize: 24,
110
173
  fontStyle: "bold",
111
174
  fill: "#ffffff",
@@ -114,19 +177,19 @@ const rt = j(({ stage: n, stageColor: u }) => /* @__PURE__ */ x(Tt, { x: n.posit
114
177
  }
115
178
  )
116
179
  ] }));
117
- rt.displayName = "ViewerStage";
118
- const st = j(({
119
- floors: n,
120
- currentFloorId: u,
121
- onFloorChange: h,
122
- showAllOption: r,
123
- allLabel: b,
124
- position: m,
125
- className: v
180
+ St.displayName = "ViewerStage";
181
+ const vt = U(({
182
+ floors: e,
183
+ currentFloorId: o,
184
+ onFloorChange: d,
185
+ showAllOption: i,
186
+ allLabel: m,
187
+ position: b,
188
+ className: p
126
189
  }) => {
127
- const w = L(
128
- () => [...n].sort((f, N) => f.order - N.order),
129
- [n]
190
+ const S = T(
191
+ () => [...e].sort((g, N) => g.order - N.order),
192
+ [e]
130
193
  ), s = {
131
194
  position: "absolute",
132
195
  display: "flex",
@@ -142,9 +205,9 @@ const st = j(({
142
205
  "top-right": { top: 0, right: 0 },
143
206
  "bottom-left": { bottom: 0, left: 0 },
144
207
  "bottom-right": { bottom: 0, right: 0 }
145
- }[m]
146
- }, g = {
147
- padding: "6px 14px",
208
+ }[b]
209
+ }, n = {
210
+ padding: "10px 16px",
148
211
  fontSize: "14px",
149
212
  fontWeight: 500,
150
213
  border: "1px solid #444",
@@ -152,45 +215,47 @@ const st = j(({
152
215
  backgroundColor: "transparent",
153
216
  color: "#fff",
154
217
  cursor: "pointer",
155
- transition: "all 0.2s ease"
156
- }, y = {
157
- ...g,
218
+ transition: "all 0.2s ease",
219
+ minHeight: "44px",
220
+ touchAction: "manipulation"
221
+ }, a = {
222
+ ...n,
158
223
  backgroundColor: "#3A7DE5",
159
224
  borderColor: "#3A7DE5"
160
225
  };
161
- return /* @__PURE__ */ x("div", { className: v, style: s, children: [
162
- r && /* @__PURE__ */ i(
226
+ return /* @__PURE__ */ w("div", { className: p, style: s, children: [
227
+ i && /* @__PURE__ */ h(
163
228
  "button",
164
229
  {
165
230
  type: "button",
166
- onClick: () => h(null),
167
- style: u === null ? y : g,
168
- children: b
231
+ onClick: () => d(null),
232
+ style: o === null ? a : n,
233
+ children: m
169
234
  }
170
235
  ),
171
- w.map((f) => /* @__PURE__ */ i(
236
+ S.map((g) => /* @__PURE__ */ h(
172
237
  "button",
173
238
  {
174
239
  type: "button",
175
- onClick: () => h(f.id),
176
- style: u === f.id ? y : g,
177
- children: f.name
240
+ onClick: () => d(g.id),
241
+ style: o === g.id ? a : n,
242
+ children: g.name
178
243
  },
179
- f.id
244
+ g.id
180
245
  ))
181
246
  ] });
182
247
  });
183
- st.displayName = "FloorSelectorBar";
184
- const at = j(({
185
- scale: n,
186
- minScale: u,
187
- maxScale: h,
188
- onZoomIn: r,
189
- onZoomOut: b,
190
- position: m,
191
- className: v
248
+ vt.displayName = "FloorSelectorBar";
249
+ const wt = U(({
250
+ scale: e,
251
+ minScale: o,
252
+ maxScale: d,
253
+ onZoomIn: i,
254
+ onZoomOut: m,
255
+ position: b,
256
+ className: p
192
257
  }) => {
193
- const p = {
258
+ const y = {
194
259
  position: "absolute",
195
260
  display: "flex",
196
261
  flexDirection: "column",
@@ -205,11 +270,13 @@ const at = j(({
205
270
  "top-right": { top: 0, right: 0 },
206
271
  "bottom-left": { bottom: 0, left: 0 },
207
272
  "bottom-right": { bottom: 0, right: 0 }
208
- }[m]
273
+ }[b]
209
274
  }, s = {
210
- width: "36px",
211
- height: "36px",
212
- fontSize: "20px",
275
+ width: "44px",
276
+ height: "44px",
277
+ minWidth: "44px",
278
+ minHeight: "44px",
279
+ fontSize: "22px",
213
280
  fontWeight: "bold",
214
281
  border: "1px solid #444",
215
282
  borderRadius: "6px",
@@ -219,54 +286,55 @@ const at = j(({
219
286
  display: "flex",
220
287
  alignItems: "center",
221
288
  justifyContent: "center",
222
- transition: "all 0.2s ease"
223
- }, g = {
289
+ transition: "all 0.2s ease",
290
+ touchAction: "manipulation"
291
+ }, n = {
224
292
  ...s,
225
293
  opacity: 0.4,
226
294
  cursor: "not-allowed"
227
- }, y = n < h, f = n > u;
228
- return /* @__PURE__ */ x("div", { className: v, style: p, children: [
229
- /* @__PURE__ */ i(
295
+ }, a = e < d, g = e > o;
296
+ return /* @__PURE__ */ w("div", { className: p, style: y, children: [
297
+ /* @__PURE__ */ h(
230
298
  "button",
231
299
  {
232
300
  type: "button",
233
- onClick: r,
234
- disabled: !y,
235
- style: y ? s : g,
301
+ onClick: i,
302
+ disabled: !a,
303
+ style: a ? s : n,
236
304
  title: "Zoom In",
237
305
  children: "+"
238
306
  }
239
307
  ),
240
- /* @__PURE__ */ i(
308
+ /* @__PURE__ */ h(
241
309
  "button",
242
310
  {
243
311
  type: "button",
244
- onClick: b,
245
- disabled: !f,
246
- style: f ? s : g,
312
+ onClick: m,
313
+ disabled: !g,
314
+ style: g ? s : n,
247
315
  title: "Zoom Out",
248
316
  children: "−"
249
317
  }
250
318
  )
251
319
  ] });
252
320
  });
253
- at.displayName = "ZoomControls";
254
- const lt = j(({
255
- visible: n,
256
- x: u,
257
- y: h,
258
- seat: r,
259
- currency: b,
260
- state: m
321
+ wt.displayName = "ZoomControls";
322
+ const Ct = U(({
323
+ visible: e,
324
+ x: o,
325
+ y: d,
326
+ seat: i,
327
+ currency: m,
328
+ state: b
261
329
  }) => {
262
- if (!n || !r) return null;
263
- const v = r.seatNumber || (r.rowLabel && r.columnLabel ? `${r.rowLabel}-${r.columnLabel}` : "N/A"), w = {
330
+ if (!e || !i) return null;
331
+ const p = i.seatNumber || (i.rowLabel && i.columnLabel ? `${i.rowLabel}-${i.columnLabel}` : "N/A"), S = {
264
332
  position: "fixed",
265
- left: `${u + 15}px`,
266
- top: `${h + 15}px`,
333
+ left: `${o + 15}px`,
334
+ top: `${d + 15}px`,
267
335
  zIndex: 1e3,
268
336
  pointerEvents: "none"
269
- }, p = {
337
+ }, y = {
270
338
  backgroundColor: "rgba(26, 26, 26, 0.95)",
271
339
  color: "#fff",
272
340
  border: "1px solid #444",
@@ -278,267 +346,317 @@ const lt = j(({
278
346
  }, s = {
279
347
  color: "#9ca3af",
280
348
  marginRight: "4px"
281
- }, g = {
349
+ }, n = {
282
350
  fontWeight: 600
283
- }, y = {
351
+ }, a = {
284
352
  color: "#4ade80",
285
353
  fontWeight: 600
286
- }, f = {
354
+ }, g = {
287
355
  fontSize: "11px",
288
356
  color: "#6b7280",
289
357
  textTransform: "capitalize",
290
358
  marginTop: "4px"
291
359
  };
292
- return /* @__PURE__ */ i("div", { style: w, children: /* @__PURE__ */ x("div", { style: p, children: [
293
- r.sectionName && /* @__PURE__ */ x("div", { style: { marginBottom: "4px" }, children: [
294
- /* @__PURE__ */ i("span", { style: s, children: "Section:" }),
295
- /* @__PURE__ */ i("span", { style: { ...g, color: "#3b82f6" }, children: r.sectionName })
360
+ return /* @__PURE__ */ h("div", { style: S, children: /* @__PURE__ */ w("div", { style: y, children: [
361
+ i.sectionName && /* @__PURE__ */ w("div", { style: { marginBottom: "4px" }, children: [
362
+ /* @__PURE__ */ h("span", { style: s, children: "Section:" }),
363
+ /* @__PURE__ */ h("span", { style: { ...n, color: "#3b82f6" }, children: i.sectionName })
296
364
  ] }),
297
- /* @__PURE__ */ x("div", { style: { marginBottom: "4px" }, children: [
298
- /* @__PURE__ */ i("span", { style: s, children: "Seat:" }),
299
- /* @__PURE__ */ i("span", { style: g, children: v })
365
+ /* @__PURE__ */ w("div", { style: { marginBottom: "4px" }, children: [
366
+ /* @__PURE__ */ h("span", { style: s, children: "Seat:" }),
367
+ /* @__PURE__ */ h("span", { style: n, children: p })
300
368
  ] }),
301
- r.price !== void 0 && r.price > 0 && /* @__PURE__ */ x("div", { style: { marginBottom: "4px" }, children: [
302
- /* @__PURE__ */ i("span", { style: s, children: "Price:" }),
303
- /* @__PURE__ */ x("span", { style: y, children: [
304
- b,
369
+ i.price !== void 0 && i.price > 0 && /* @__PURE__ */ w("div", { style: { marginBottom: "4px" }, children: [
370
+ /* @__PURE__ */ h("span", { style: s, children: "Price:" }),
371
+ /* @__PURE__ */ w("span", { style: a, children: [
372
+ m,
305
373
  " ",
306
- r.price.toFixed(2)
374
+ i.price.toFixed(2)
307
375
  ] })
308
376
  ] }),
309
- /* @__PURE__ */ x("div", { style: f, children: [
377
+ /* @__PURE__ */ w("div", { style: g, children: [
310
378
  "Status: ",
311
- m
379
+ b
312
380
  ] })
313
381
  ] }) });
314
382
  });
315
- lt.displayName = "SeatTooltip";
316
- const Ut = ({
317
- config: n,
318
- configUrl: u,
319
- floorId: h,
320
- onFloorChange: r,
321
- reservedSeats: b = [],
322
- unavailableSeats: m = [],
323
- onSeatSelect: v,
324
- onSeatDeselect: w,
325
- onSelectionChange: p,
383
+ Ct.displayName = "SeatTooltip";
384
+ const se = ({
385
+ config: e,
386
+ configUrl: o,
387
+ floorId: d,
388
+ onFloorChange: i,
389
+ reservedSeats: m = [],
390
+ unavailableSeats: b = [],
391
+ onSeatSelect: p,
392
+ onSeatDeselect: S,
393
+ onSelectionChange: y,
326
394
  colorOverrides: s,
327
- showTooltip: g = !0,
328
- zoomEnabled: y = !0,
329
- className: f = "",
395
+ showTooltip: n = !0,
396
+ zoomEnabled: a = !0,
397
+ className: g = "",
330
398
  onConfigLoad: N,
331
- onError: M,
399
+ onError: C,
332
400
  // Floor selector props
333
- showFloorSelector: R,
334
- floorSelectorPosition: ct = "top-left",
335
- floorSelectorClassName: dt,
336
- showAllFloorsOption: ft = !0,
337
- allFloorsLabel: ht = "All",
401
+ showFloorSelector: D,
402
+ floorSelectorPosition: $ = "top-left",
403
+ floorSelectorClassName: K,
404
+ showAllFloorsOption: J = !0,
405
+ allFloorsLabel: Q = "All",
338
406
  fitToView: H = !0,
339
- fitPadding: U = 40,
407
+ fitPadding: P = 40,
340
408
  // Zoom controls
341
- showZoomControls: ut = !0,
342
- zoomControlsPosition: pt = "bottom-right",
343
- zoomControlsClassName: gt,
409
+ showZoomControls: st = !0,
410
+ zoomControlsPosition: ct = "bottom-right",
411
+ zoomControlsClassName: at,
344
412
  maxZoom: X = 3,
345
- zoomStep: O = 0.25
413
+ zoomStep: tt = 0.25,
414
+ // Touch gestures
415
+ touchEnabled: Mt = !0
346
416
  }) => {
347
- const yt = zt(null), [A, xt] = I(/* @__PURE__ */ new Set()), [S, q] = I(1), [F, Z] = I({ x: 0, y: 0 }), [bt, mt] = I(null), [Q, tt] = I(!1), [vt, St] = I(1), [Y, et] = I({ visible: !1, x: 0, y: 0, seat: null, state: "available" }), { config: wt, loading: Ct, error: $ } = Ot(u), e = n || wt, G = h !== void 0, k = G ? h || null : bt, kt = C((t) => {
348
- G || mt(t), r?.(t);
349
- }, [G, r]), K = e?.floors || [], It = R !== void 0 ? R : K.length > 1, P = L(
350
- () => e ? { ...e.colors, ...s } : { ...Zt, ...s },
351
- [e, s]
352
- ), B = L(() => {
353
- if (!e) return [];
354
- let t = e.seats.filter((o) => o.state !== "hidden");
355
- return k && (t = t.filter(
356
- (o) => o.floorId === k || !o.floorId && k === "floor_default"
417
+ const lt = z(null), ft = z(null), v = te(ft), [B, kt] = L(/* @__PURE__ */ new Set()), [M, j] = L(1), [k, E] = L({ x: 0, y: 0 }), [It, Nt] = L(null), [Dt, Rt] = L(1), et = z({ width: 0, height: 0 }), [O, pt] = L({ visible: !1, x: 0, y: 0, seat: null, state: "available" }), { config: Lt, loading: Xt, error: V } = Qt(o), c = e || Lt, ht = d !== void 0, R = ht ? d || null : It, Yt = I((t) => {
418
+ ht || Nt(t), i?.(t);
419
+ }, [ht, i]), dt = c?.floors || [], Et = D !== void 0 ? D : dt.length > 1, nt = T(
420
+ () => c ? { ...c.colors, ...s } : { ...ne, ...s },
421
+ [c, s]
422
+ ), F = T(() => {
423
+ if (!c) return [];
424
+ let t = c.seats.filter((r) => r.state !== "hidden");
425
+ return R && (t = t.filter(
426
+ (r) => r.floorId === R || !r.floorId && R === "floor_default"
357
427
  )), t;
358
- }, [e, k]), V = L(() => e?.stages ? k ? e.stages.filter(
359
- (t) => t.floorId === k || !t.floorId && k === "floor_default"
360
- ) : e.stages : [], [e, k]), E = L(() => {
361
- if (!e || B.length === 0 && V.length === 0)
428
+ }, [c, R]), ot = T(() => c?.stages ? R ? c.stages.filter(
429
+ (t) => t.floorId === R || !t.floorId && R === "floor_default"
430
+ ) : c.stages : [], [c, R]), Y = T(() => {
431
+ if (!c || F.length === 0 && ot.length === 0)
362
432
  return null;
363
433
  const t = 12;
364
- let o = 1 / 0, a = 1 / 0, c = -1 / 0, l = -1 / 0;
365
- return B.forEach((d) => {
366
- o = Math.min(o, d.position.x - t), a = Math.min(a, d.position.y - t), c = Math.max(c, d.position.x + t), l = Math.max(l, d.position.y + t);
367
- }), V.forEach((d) => {
368
- o = Math.min(o, d.position.x), a = Math.min(a, d.position.y), c = Math.max(c, d.position.x + (d.config?.width || 200)), l = Math.max(l, d.position.y + (d.config?.height || 100));
369
- }), { minX: o, minY: a, maxX: c, maxY: l, width: c - o, height: l - a };
370
- }, [e, B, V]);
434
+ let r = 1 / 0, u = 1 / 0, l = -1 / 0, f = -1 / 0;
435
+ return F.forEach((x) => {
436
+ r = Math.min(r, x.position.x - t), u = Math.min(u, x.position.y - t), l = Math.max(l, x.position.x + t), f = Math.max(f, x.position.y + t);
437
+ }), ot.forEach((x) => {
438
+ r = Math.min(r, x.position.x), u = Math.min(u, x.position.y), l = Math.max(l, x.position.x + (x.config?.width || 200)), f = Math.max(f, x.position.y + (x.config?.height || 100));
439
+ }), { minX: r, minY: u, maxX: l, maxY: f, width: l - r, height: f - u };
440
+ }, [c, F, ot]);
371
441
  W(() => {
372
- if (!H || Q || !e || !E) return;
373
- const t = e.canvas.width, o = e.canvas.height, a = t - U * 2, c = o - U * 2, l = a / E.width, d = c / E.height, _ = Math.min(l, d, X), At = E.minX + E.width / 2, Bt = E.minY + E.height / 2, Wt = t / 2, Xt = o / 2, Yt = Wt - At * _, $t = Xt - Bt * _;
374
- q(_), Z({ x: Yt, y: $t }), St(_), tt(!0);
375
- }, [H, Q, e, E, U, X]), W(() => {
376
- H && tt(!1);
377
- }, [k, H]);
378
- const z = L(() => {
379
- const t = new Set(b), o = new Set(m);
380
- return { reserved: t, unavailable: o };
381
- }, [b, m]), D = C((t) => {
382
- const o = t.id, a = t.seatNumber || "";
383
- return z.unavailable.has(o) || z.unavailable.has(a) ? "unavailable" : z.reserved.has(o) || z.reserved.has(a) ? "reserved" : A.has(o) ? "selected" : t.state;
384
- }, [z, A]);
442
+ if (!H || !c || !Y || v.width === 0 || v.height === 0) return;
443
+ const t = Math.abs(v.width - et.current.width), r = Math.abs(v.height - et.current.height);
444
+ if (!(et.current.width === 0) && t < 10 && r < 10) return;
445
+ et.current = v;
446
+ const l = v.width, f = v.height, x = l - P * 2, G = f - P * 2, it = x / Y.width, ut = G / Y.height, rt = Math.min(it, ut, X), jt = Y.minX + Y.width / 2, Ot = Y.minY + Y.height / 2, Vt = l / 2, Zt = f / 2, _t = Vt - jt * rt, qt = Zt - Ot * rt;
447
+ j(rt), E({ x: _t, y: qt }), Rt(rt);
448
+ }, [H, c, Y, P, X, v, R]);
449
+ const Z = T(() => {
450
+ const t = new Set(m), r = new Set(b);
451
+ return { reserved: t, unavailable: r };
452
+ }, [m, b]), _ = I((t) => {
453
+ const r = t.id, u = t.seatNumber || "";
454
+ return Z.unavailable.has(r) || Z.unavailable.has(u) ? "unavailable" : Z.reserved.has(r) || Z.reserved.has(u) ? "reserved" : B.has(r) ? "selected" : t.state;
455
+ }, [Z, B]);
385
456
  W(() => {
386
- e && N && N(e);
387
- }, [e, N]), W(() => {
388
- $ && M && M($);
389
- }, [$, M]);
390
- const Nt = C((t) => {
391
- const o = D(t);
392
- if (o !== "available" && o !== "selected")
457
+ c && N && N(c);
458
+ }, [c, N]), W(() => {
459
+ V && C && C(V);
460
+ }, [V, C]);
461
+ const Tt = I((t) => {
462
+ const r = _(t);
463
+ if (r !== "available" && r !== "selected")
393
464
  return;
394
- const a = A.has(t.id);
395
- xt((c) => {
396
- const l = new Set(c);
397
- return a ? l.delete(t.id) : l.add(t.id), l;
398
- }), a ? w?.(t) : (v?.(t), v || console.log("Seat selected:", t));
399
- }, [D, A, v, w]), T = L(() => e ? B.filter((t) => A.has(t.id)) : [], [B, A]);
465
+ const u = B.has(t.id);
466
+ kt((l) => {
467
+ const f = new Set(l);
468
+ return u ? f.delete(t.id) : f.add(t.id), f;
469
+ }), u ? S?.(t) : (p?.(t), p || console.log("Seat selected:", t));
470
+ }, [_, B, p, S]), q = T(() => c ? F.filter((t) => B.has(t.id)) : [], [F, B]);
400
471
  W(() => {
401
- p?.(T);
402
- }, [T, p]);
403
- const J = vt, Mt = C(() => {
404
- if (!y) return;
405
- const t = Math.min(S + O, X);
406
- if (t !== S) {
407
- const o = e?.canvas.width || 800, a = e?.canvas.height || 600, c = o / 2, l = a / 2, d = {
408
- x: (c - F.x) / S,
409
- y: (l - F.y) / S
472
+ y?.(q);
473
+ }, [q, y]);
474
+ const A = Dt, Wt = I(() => {
475
+ if (!a) return;
476
+ const t = Math.min(M + tt, X);
477
+ if (t !== M) {
478
+ const r = v.width || c?.canvas.width || 800, u = v.height || c?.canvas.height || 600, l = r / 2, f = u / 2, x = {
479
+ x: (l - k.x) / M,
480
+ y: (f - k.y) / M
410
481
  };
411
- q(t), Z({
412
- x: c - d.x * t,
413
- y: l - d.y * t
482
+ j(t), E({
483
+ x: l - x.x * t,
484
+ y: f - x.y * t
414
485
  });
415
486
  }
416
- }, [y, S, O, X, e, F]), Rt = C(() => {
417
- if (!y) return;
418
- const t = Math.max(S - O, J);
419
- if (t !== S) {
420
- const o = e?.canvas.width || 800, a = e?.canvas.height || 600, c = o / 2, l = a / 2, d = {
421
- x: (c - F.x) / S,
422
- y: (l - F.y) / S
487
+ }, [a, M, tt, X, v, c, k]), Pt = I(() => {
488
+ if (!a) return;
489
+ const t = Math.max(M - tt, A);
490
+ if (t !== M) {
491
+ const r = v.width || c?.canvas.width || 800, u = v.height || c?.canvas.height || 600, l = r / 2, f = u / 2, x = {
492
+ x: (l - k.x) / M,
493
+ y: (f - k.y) / M
423
494
  };
424
- q(t), Z({
425
- x: c - d.x * t,
426
- y: l - d.y * t
495
+ j(t), E({
496
+ x: l - x.x * t,
497
+ y: f - x.y * t
427
498
  });
428
499
  }
429
- }, [y, S, O, J, e, F]), Ft = C((t) => {
430
- Z({
500
+ }, [a, M, tt, A, v, c, k]), Bt = I((t) => {
501
+ E({
431
502
  x: t.target.x(),
432
503
  y: t.target.y()
433
504
  });
434
- }, []), Et = C((t, o) => {
435
- if (!g) return;
436
- const a = o.target.getStage();
505
+ }, []), Ft = I((t) => {
437
506
  if (!a) return;
438
- const c = a.getPointerPosition();
439
- if (!c) return;
440
- const l = a.container().getBoundingClientRect();
441
- et({
507
+ t.evt.preventDefault();
508
+ const r = lt.current;
509
+ if (!r) return;
510
+ const u = r.scaleX(), l = r.getPointerPosition();
511
+ if (!l) return;
512
+ const f = 1.1, x = t.evt.deltaY > 0 ? u / f : u * f, G = Math.min(Math.max(x, A), X), it = {
513
+ x: (l.x - k.x) / u,
514
+ y: (l.y - k.y) / u
515
+ }, ut = {
516
+ x: l.x - it.x * G,
517
+ y: l.y - it.y * G
518
+ };
519
+ j(G), E(ut);
520
+ }, [a, k, A, X]);
521
+ ee(lt, {
522
+ enabled: Mt && a,
523
+ minScale: A,
524
+ maxScale: X,
525
+ currentScale: M,
526
+ currentPosition: k,
527
+ onScaleChange: (t, r) => {
528
+ j(t), E(r);
529
+ },
530
+ onPositionChange: (t) => {
531
+ E(t);
532
+ }
533
+ });
534
+ const At = I((t, r) => {
535
+ if (!n) return;
536
+ const u = r.target.getStage();
537
+ if (!u) return;
538
+ const l = u.getPointerPosition();
539
+ if (!l) return;
540
+ const f = u.container().getBoundingClientRect();
541
+ pt({
442
542
  visible: !0,
443
- x: l.left + c.x,
444
- y: l.top + c.y,
543
+ x: f.left + l.x,
544
+ y: f.top + l.y,
445
545
  seat: t,
446
- state: D(t)
546
+ state: _(t)
447
547
  });
448
- }, [g, D]), Lt = C(() => {
449
- et((t) => ({ ...t, visible: !1 }));
548
+ }, [n, _]), zt = I(() => {
549
+ pt((t) => ({ ...t, visible: !1 }));
450
550
  }, []);
451
- return Ct ? /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${f}`, children: /* @__PURE__ */ i("p", { children: "Loading seat map..." }) }) : $ ? /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${f}`, children: /* @__PURE__ */ x("p", { className: "text-red-500", children: [
452
- "Error loading seat map: ",
453
- $.message
454
- ] }) }) : e ? /* @__PURE__ */ x("div", { className: `relative ${f}`, children: [
455
- It && K.length > 0 && /* @__PURE__ */ i(
456
- st,
457
- {
458
- floors: K,
459
- currentFloorId: k,
460
- onFloorChange: kt,
461
- showAllOption: ft,
462
- allLabel: ht,
463
- position: ct,
464
- className: dt
465
- }
466
- ),
467
- /* @__PURE__ */ x(
468
- Dt,
469
- {
470
- ref: yt,
471
- width: e.canvas.width,
472
- height: e.canvas.height,
473
- scaleX: S,
474
- scaleY: S,
475
- x: F.x,
476
- y: F.y,
477
- draggable: !0,
478
- onDragEnd: Ft,
479
- style: { backgroundColor: e.canvas.backgroundColor, cursor: "grab" },
480
- children: [
481
- /* @__PURE__ */ i(nt, { listening: !1, children: V.map((t) => /* @__PURE__ */ i(
482
- rt,
483
- {
484
- stage: t,
485
- stageColor: P.stageColor
486
- },
487
- t.id
488
- )) }),
489
- /* @__PURE__ */ i(nt, { children: B.map((t) => /* @__PURE__ */ i(
490
- it,
491
- {
492
- seat: t,
493
- state: D(t),
494
- colors: P,
495
- onClick: Nt,
496
- onMouseEnter: Et,
497
- onMouseLeave: Lt
498
- },
499
- t.id
500
- )) })
501
- ]
502
- }
503
- ),
504
- g && /* @__PURE__ */ i(
505
- lt,
506
- {
507
- visible: Y.visible,
508
- x: Y.x,
509
- y: Y.y,
510
- seat: Y.seat,
511
- currency: P.currency,
512
- state: Y.state
513
- }
514
- ),
515
- ut && y && /* @__PURE__ */ i(
516
- at,
517
- {
518
- scale: S,
519
- minScale: J,
520
- maxScale: X,
521
- onZoomIn: Mt,
522
- onZoomOut: Rt,
523
- position: pt,
524
- className: gt
525
- }
526
- ),
527
- T.length > 0 && /* @__PURE__ */ x("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
528
- /* @__PURE__ */ x("h3", { className: "font-semibold mb-2", children: [
529
- "Selected Seats (",
530
- T.length,
531
- ")"
532
- ] }),
533
- /* @__PURE__ */ i("div", { className: "max-h-48 overflow-y-auto space-y-1", children: T.map((t) => /* @__PURE__ */ x("div", { className: "text-sm", children: [
534
- t.seatNumber,
535
- t.price && ` - ${P.currency} ${t.price.toFixed(2)}`
536
- ] }, t.id)) })
537
- ] })
538
- ] }) : /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${f}`, children: /* @__PURE__ */ i("p", { children: "No configuration provided" }) });
551
+ if (Xt)
552
+ return /* @__PURE__ */ h("div", { className: `flex items-center justify-center h-full ${g}`, children: /* @__PURE__ */ h("p", { children: "Loading seat map..." }) });
553
+ if (V)
554
+ return /* @__PURE__ */ h("div", { className: `flex items-center justify-center h-full ${g}`, children: /* @__PURE__ */ w("p", { className: "text-red-500", children: [
555
+ "Error loading seat map: ",
556
+ V.message
557
+ ] }) });
558
+ if (!c)
559
+ return /* @__PURE__ */ h("div", { className: `flex items-center justify-center h-full ${g}`, children: /* @__PURE__ */ h("p", { children: "No configuration provided" }) });
560
+ const $t = v.width || c.canvas.width, Ht = v.height || c.canvas.height;
561
+ return /* @__PURE__ */ w(
562
+ "div",
563
+ {
564
+ ref: ft,
565
+ className: `relative ${g}`,
566
+ style: { width: "100%", height: "100%" },
567
+ children: [
568
+ Et && dt.length > 0 && /* @__PURE__ */ h(
569
+ vt,
570
+ {
571
+ floors: dt,
572
+ currentFloorId: R,
573
+ onFloorChange: Yt,
574
+ showAllOption: J,
575
+ allLabel: Q,
576
+ position: $,
577
+ className: K
578
+ }
579
+ ),
580
+ /* @__PURE__ */ w(
581
+ Gt,
582
+ {
583
+ ref: lt,
584
+ width: $t,
585
+ height: Ht,
586
+ scaleX: M,
587
+ scaleY: M,
588
+ x: k.x,
589
+ y: k.y,
590
+ draggable: !0,
591
+ onDragEnd: Bt,
592
+ onWheel: Ft,
593
+ style: { backgroundColor: c.canvas.backgroundColor, cursor: "grab" },
594
+ children: [
595
+ /* @__PURE__ */ h(gt, { listening: !1, children: ot.map((t) => /* @__PURE__ */ h(
596
+ St,
597
+ {
598
+ stage: t,
599
+ stageColor: nt.stageColor
600
+ },
601
+ t.id
602
+ )) }),
603
+ /* @__PURE__ */ h(gt, { children: F.map((t) => /* @__PURE__ */ h(
604
+ bt,
605
+ {
606
+ seat: t,
607
+ state: _(t),
608
+ colors: nt,
609
+ onClick: Tt,
610
+ onMouseEnter: At,
611
+ onMouseLeave: zt
612
+ },
613
+ t.id
614
+ )) })
615
+ ]
616
+ }
617
+ ),
618
+ n && /* @__PURE__ */ h(
619
+ Ct,
620
+ {
621
+ visible: O.visible,
622
+ x: O.x,
623
+ y: O.y,
624
+ seat: O.seat,
625
+ currency: nt.currency,
626
+ state: O.state
627
+ }
628
+ ),
629
+ st && a && /* @__PURE__ */ h(
630
+ wt,
631
+ {
632
+ scale: M,
633
+ minScale: A,
634
+ maxScale: X,
635
+ onZoomIn: Wt,
636
+ onZoomOut: Pt,
637
+ position: ct,
638
+ className: at
639
+ }
640
+ ),
641
+ q.length > 0 && /* @__PURE__ */ w("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
642
+ /* @__PURE__ */ w("h3", { className: "font-semibold mb-2", children: [
643
+ "Selected Seats (",
644
+ q.length,
645
+ ")"
646
+ ] }),
647
+ /* @__PURE__ */ h("div", { className: "max-h-48 overflow-y-auto space-y-1", children: q.map((t) => /* @__PURE__ */ w("div", { className: "text-sm", children: [
648
+ t.seatNumber,
649
+ t.price && ` - ${nt.currency} ${t.price.toFixed(2)}`
650
+ ] }, t.id)) })
651
+ ] })
652
+ ]
653
+ }
654
+ );
539
655
  };
540
656
  export {
541
- Zt as DEFAULT_COLORS,
542
- Ut as SeatMapViewer,
543
- Ot as useConfigFetcher
657
+ ne as DEFAULT_COLORS,
658
+ se as SeatMapViewer,
659
+ Qt as useConfigFetcher,
660
+ te as useContainerSize,
661
+ ee as useTouchGestures
544
662
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonetrix/viewer",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "description": "Lightweight React component for rendering interactive seat maps",
6
6
  "main": "./dist/index.js",