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