@zonetrix/viewer 2.3.0 → 2.4.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
@@ -113,7 +113,7 @@ function BookingApp() {
113
113
  | `onSelectionChange` | `(seats: SeatData[]) => void` | No | Callback when selection changes |
114
114
  | `colorOverrides` | `Partial<ColorSettings>` | No | Custom colors for seat states |
115
115
  | `showTooltip` | `boolean` | No | Show tooltips on hover (default: true) |
116
- | `zoomEnabled` | `boolean` | No | Enable/disable mouse wheel zoom (default: true) |
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 |
119
119
  | `onError` | `(error: Error) => void` | No | Callback when an error occurs |
@@ -122,6 +122,13 @@ function BookingApp() {
122
122
  | `floorSelectorClassName` | `string` | No | Custom CSS class for floor selector |
123
123
  | `showAllFloorsOption` | `boolean` | No | Show "All" button in floor selector (default: true) |
124
124
  | `allFloorsLabel` | `string` | No | Custom label for "All" button (default: 'All') |
125
+ | `fitToView` | `boolean` | No | Auto-fit content on load (default: true) |
126
+ | `fitPadding` | `number` | No | Padding around content when fitting (default: 40) |
127
+ | `showZoomControls` | `boolean` | No | Show zoom +/- buttons (default: true) |
128
+ | `zoomControlsPosition` | `string` | No | Position: 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' (default: 'bottom-right') |
129
+ | `zoomControlsClassName` | `string` | No | Custom CSS class for zoom controls |
130
+ | `maxZoom` | `number` | No | Maximum zoom level (default: 3) |
131
+ | `zoomStep` | `number` | No | Zoom increment per click (default: 0.25) |
125
132
 
126
133
  *Note: Either `config` or `configUrl` must be provided.
127
134
 
@@ -245,22 +252,33 @@ function SelectionTracker() {
245
252
  }
246
253
  ```
247
254
 
248
- ### 5. Disable Zoom for Mobile
255
+ ### 5. Customize Zoom Controls
249
256
 
250
257
  ```tsx
251
258
  import { SeatMapViewer } from '@zonetrix/viewer';
252
259
 
253
- function MobileOptimized() {
254
- const isMobile = window.innerWidth < 768;
255
-
260
+ function CustomZoom() {
256
261
  return (
257
262
  <SeatMapViewer
258
263
  config={venueConfig}
259
- zoomEnabled={!isMobile}
264
+ // Zoom controls appear in bottom-right by default
265
+ zoomControlsPosition="bottom-left"
266
+ maxZoom={5} // Allow up to 5x zoom
267
+ zoomStep={0.5} // Larger zoom increments
260
268
  onSeatSelect={(seat) => handleSelection(seat)}
261
269
  />
262
270
  );
263
271
  }
272
+
273
+ // Hide zoom controls entirely
274
+ function NoZoomControls() {
275
+ return (
276
+ <SeatMapViewer
277
+ config={venueConfig}
278
+ showZoomControls={false}
279
+ />
280
+ );
281
+ }
264
282
  ```
265
283
 
266
284
  ### 6. Multi-floor Venue (Built-in Floor Selector)
@@ -23,5 +23,10 @@ export interface SeatMapViewerProps {
23
23
  allFloorsLabel?: string;
24
24
  fitToView?: boolean;
25
25
  fitPadding?: number;
26
+ showZoomControls?: boolean;
27
+ zoomControlsPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
28
+ zoomControlsClassName?: string;
29
+ maxZoom?: number;
30
+ zoomStep?: number;
26
31
  }
27
32
  export declare const SeatMapViewer: React.FC<SeatMapViewerProps>;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),t=require("react"),v=require("react-konva");function K(i){const[h,d]=t.useState(null),[S,y]=t.useState(!1),[w,x]=t.useState(null),g=async()=>{if(i){y(!0),x(null);try{const f=await fetch(i);if(!f.ok)throw new Error(`Failed to fetch config: ${f.statusText}`);const u=await f.json();d(u)}catch(f){const u=f instanceof Error?f:new Error("Unknown error occurred");x(u),console.error("Failed to fetch seat map config:",u)}finally{y(!1)}}};return t.useEffect(()=>{g()},[i]),{config:h,loading:S,error:w,refetch:g}}const G={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},J=t.memo(({seat:i,state:h,colors:d,onClick:S})=>{const x={available:d.seatAvailable,reserved:d.seatReserved,selected:d.seatSelected,unavailable:d.seatUnavailable,hidden:d.seatHidden}[h],g=h==="available"||h==="selected",f=t.useCallback(()=>{g&&S(i)},[i,S,g]),u={x:i.position.x,y:i.position.y,fill:x,stroke:"#ffffff",strokeWidth:1,onClick:f,onTap:f};return i.shape==="circle"?o.jsx(v.Circle,{...u,radius:12}):o.jsx(v.Rect,{...u,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:i.shape==="square"?0:4})});J.displayName="ViewerSeat";const Q=t.memo(({stage:i,stageColor:h})=>o.jsxs(v.Group,{x:i.position.x,y:i.position.y,children:[o.jsx(v.Rect,{width:i.config.width,height:i.config.height,fill:h+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),o.jsx(v.Text,{text:i.config.label,x:0,y:0,width:i.config.width,height:i.config.height,fontSize:24,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]}));Q.displayName="ViewerStage";const Z=t.memo(({floors:i,currentFloorId:h,onFloorChange:d,showAllOption:S,allLabel:y,position:w,className:x})=>{const g=t.useMemo(()=>[...i].sort((p,I)=>p.order-I.order),[i]),u={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}}[w]},Y={padding:"6px 14px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease"},E={...Y,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return o.jsxs("div",{className:x,style:u,children:[S&&o.jsx("button",{type:"button",onClick:()=>d(null),style:h===null?E:Y,children:y}),g.map(p=>o.jsx("button",{type:"button",onClick:()=>d(p.id),style:h===p.id?E:Y,children:p.name},p.id))]})});Z.displayName="FloorSelectorBar";const Se=({config:i,configUrl:h,floorId:d,onFloorChange:S,reservedSeats:y=[],unavailableSeats:w=[],onSeatSelect:x,onSeatDeselect:g,onSelectionChange:f,colorOverrides:u,showTooltip:Y=!0,zoomEnabled:E=!0,className:p="",onConfigLoad:I,onError:T,showFloorSelector:O,floorSelectorPosition:ee="top-left",floorSelectorClassName:te,showAllFloorsOption:ne=!0,allFloorsLabel:se="All",fitToView:z=!0,fitPadding:W=40})=>{const P=t.useRef(null),[j,oe]=t.useState(new Set),[X,V]=t.useState(1),[F,_]=t.useState({x:0,y:0}),[ie,re]=t.useState(null),[q,U]=t.useState(!1),{config:ae,loading:le,error:N}=K(h),s=i||ae,$=d!==void 0,m=$?d||null:ie,ce=t.useCallback(e=>{$||re(e),S?.(e)},[$,S]),B=s?.floors||[],de=O!==void 0?O:B.length>1,D=t.useMemo(()=>s?{...s.colors,...u}:{...G,...u},[s,u]),k=t.useMemo(()=>{if(!s)return[];let e=s.seats.filter(n=>n.state!=="hidden");return m&&(e=e.filter(n=>n.floorId===m||!n.floorId&&m==="floor_default")),e},[s,m]),L=t.useMemo(()=>s?.stages?m?s.stages.filter(e=>e.floorId===m||!e.floorId&&m==="floor_default"):s.stages:[],[s,m]),b=t.useMemo(()=>{if(!s||k.length===0&&L.length===0)return null;const e=12;let n=1/0,r=1/0,a=-1/0,l=-1/0;return k.forEach(c=>{n=Math.min(n,c.position.x-e),r=Math.min(r,c.position.y-e),a=Math.max(a,c.position.x+e),l=Math.max(l,c.position.y+e)}),L.forEach(c=>{n=Math.min(n,c.position.x),r=Math.min(r,c.position.y),a=Math.max(a,c.position.x+(c.config?.width||200)),l=Math.max(l,c.position.y+(c.config?.height||100))}),{minX:n,minY:r,maxX:a,maxY:l,width:a-n,height:l-r}},[s,k,L]);t.useEffect(()=>{if(!z||q||!s||!b)return;const e=s.canvas.width,n=s.canvas.height,r=e-W*2,a=n-W*2,l=r/b.width,c=a/b.height,M=Math.min(l,c,2),C=b.minX+b.width/2,he=b.minY+b.height/2,pe=e/2,xe=n/2,ge=pe-C*M,me=xe-he*M;V(M),_({x:ge,y:me}),U(!0)},[z,q,s,b,W]),t.useEffect(()=>{z&&U(!1)},[m,z]);const R=t.useMemo(()=>{const e=new Set(y),n=new Set(w);return{reserved:e,unavailable:n}},[y,w]),H=t.useCallback(e=>{const n=e.id,r=e.seatNumber||"";return R.unavailable.has(n)||R.unavailable.has(r)?"unavailable":R.reserved.has(n)||R.reserved.has(r)?"reserved":j.has(n)?"selected":e.state},[R,j]);t.useEffect(()=>{s&&I&&I(s)},[s,I]),t.useEffect(()=>{N&&T&&T(N)},[N,T]);const fe=t.useCallback(e=>{const n=H(e);if(n!=="available"&&n!=="selected")return;const r=j.has(e.id);oe(a=>{const l=new Set(a);return r?l.delete(e.id):l.add(e.id),l}),r?g?.(e):(x?.(e),x||console.log("Seat selected:",e))},[H,j,x,g]),A=t.useMemo(()=>s?k.filter(e=>j.has(e.id)):[],[k,j]);t.useEffect(()=>{f?.(A)},[A,f]);const ue=t.useCallback(e=>{if(!E)return;e.evt.preventDefault();const n=P.current;if(!n)return;const r=X,a=n.getPointerPosition();if(!a)return;const l={x:(a.x-F.x)/r,y:(a.y-F.y)/r},c=e.evt.deltaY>0?-1:1,M=1.05;let C=c>0?r*M:r/M;C=Math.max(.5,Math.min(5,C)),V(C),_({x:a.x-l.x*C,y:a.y-l.y*C})},[E,X,F]);return le?o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsx("p",{children:"Loading seat map..."})}):N?o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",N.message]})}):s?o.jsxs("div",{className:`relative ${p}`,children:[de&&B.length>0&&o.jsx(Z,{floors:B,currentFloorId:m,onFloorChange:ce,showAllOption:ne,allLabel:se,position:ee,className:te}),o.jsxs(v.Stage,{ref:P,width:s.canvas.width,height:s.canvas.height,scaleX:X,scaleY:X,x:F.x,y:F.y,onWheel:ue,style:{backgroundColor:s.canvas.backgroundColor},children:[o.jsx(v.Layer,{listening:!1,children:L.map(e=>o.jsx(Q,{stage:e,stageColor:D.stageColor},e.id))}),o.jsx(v.Layer,{children:k.map(e=>o.jsx(J,{seat:e,state:H(e),colors:D,onClick:fe},e.id))})]}),A.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 (",A.length,")"]}),o.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:A.map(e=>o.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${D.currency} ${e.price.toFixed(2)}`]},e.id))})]})]}):o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsx("p",{children:"No configuration provided"})})};exports.DEFAULT_COLORS=G;exports.SeatMapViewer=Se;exports.useConfigFetcher=K;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),t=require("react"),k=require("react-konva");function P(i){const[h,u]=t.useState(null),[m,S]=t.useState(!1),[C,x]=t.useState(null),b=async()=>{if(i){S(!0),x(null);try{const f=await fetch(i);if(!f.ok)throw new Error(`Failed to fetch config: ${f.statusText}`);const c=await f.json();u(c)}catch(f){const c=f instanceof Error?f:new Error("Unknown error occurred");x(c),console.error("Failed to fetch seat map config:",c)}finally{S(!1)}}};return t.useEffect(()=>{b()},[i]),{config:h,loading:m,error:C,refetch:b}}const G={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},J=t.memo(({seat:i,state:h,colors:u,onClick:m})=>{const x={available:u.seatAvailable,reserved:u.seatReserved,selected:u.seatSelected,unavailable:u.seatUnavailable,hidden:u.seatHidden}[h],b=h==="available"||h==="selected",f=t.useCallback(()=>{b&&m(i)},[i,m,b]),c={x:i.position.x,y:i.position.y,fill:x,stroke:"#ffffff",strokeWidth:1,onClick:f,onTap:f};return i.shape==="circle"?o.jsx(k.Circle,{...c,radius:12}):o.jsx(k.Rect,{...c,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:i.shape==="square"?0:4})});J.displayName="ViewerSeat";const Q=t.memo(({stage:i,stageColor:h})=>o.jsxs(k.Group,{x:i.position.x,y:i.position.y,children:[o.jsx(k.Rect,{width:i.config.width,height:i.config.height,fill:h+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),o.jsx(k.Text,{text:i.config.label,x:0,y:0,width:i.config.width,height:i.config.height,fontSize:24,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]}));Q.displayName="ViewerStage";const ee=t.memo(({floors:i,currentFloorId:h,onFloorChange:u,showAllOption:m,allLabel:S,position:C,className:x})=>{const b=t.useMemo(()=>[...i].sort((p,E)=>p.order-E.order),[i]),c={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[C]},M={padding:"6px 14px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease"},y={...M,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return o.jsxs("div",{className:x,style:c,children:[m&&o.jsx("button",{type:"button",onClick:()=>u(null),style:h===null?y:M,children:S}),b.map(p=>o.jsx("button",{type:"button",onClick:()=>u(p.id),style:h===p.id?y:M,children:p.name},p.id))]})});ee.displayName="FloorSelectorBar";const te=t.memo(({scale:i,minScale:h,maxScale:u,onZoomIn:m,onZoomOut:S,position:C,className:x})=>{const f={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}}[C]},c={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"},M={...c,opacity:.4,cursor:"not-allowed"},y=i<u,p=i>h;return o.jsxs("div",{className:x,style:f,children:[o.jsx("button",{type:"button",onClick:m,disabled:!y,style:y?c:M,title:"Zoom In",children:"+"}),o.jsx("button",{type:"button",onClick:S,disabled:!p,style:p?c:M,title:"Zoom Out",children:"−"})]})});te.displayName="ZoomControls";const Ee=({config:i,configUrl:h,floorId:u,onFloorChange:m,reservedSeats:S=[],unavailableSeats:C=[],onSeatSelect:x,onSeatDeselect:b,onSelectionChange:f,colorOverrides:c,showTooltip:M=!0,zoomEnabled:y=!0,className:p="",onConfigLoad:E,onError:W,showFloorSelector:q,floorSelectorPosition:ne="top-left",floorSelectorClassName:oe,showAllFloorsOption:se=!0,allFloorsLabel:ie="All",fitToView:Y=!0,fitPadding:B=40,showZoomControls:ae=!0,zoomControlsPosition:re="bottom-right",zoomControlsClassName:le,maxZoom:F=3,zoomStep:O=.25})=>{const ce=t.useRef(null),[I,de]=t.useState(new Set),[g,H]=t.useState(1),[w,T]=t.useState({x:0,y:0}),[ue,fe]=t.useState(null),[U,K]=t.useState(!1),[he,pe]=t.useState(1),{config:ge,loading:xe,error:R}=P(h),n=i||ge,$=u!==void 0,v=$?u||null:ue,me=t.useCallback(e=>{$||fe(e),m?.(e)},[$,m]),Z=n?.floors||[],be=q!==void 0?q:Z.length>1,z=t.useMemo(()=>n?{...n.colors,...c}:{...G,...c},[n,c]),N=t.useMemo(()=>{if(!n)return[];let e=n.seats.filter(s=>s.state!=="hidden");return v&&(e=e.filter(s=>s.floorId===v||!s.floorId&&v==="floor_default")),e},[n,v]),D=t.useMemo(()=>n?.stages?v?n.stages.filter(e=>e.floorId===v||!e.floorId&&v==="floor_default"):n.stages:[],[n,v]),j=t.useMemo(()=>{if(!n||N.length===0&&D.length===0)return null;const e=12;let s=1/0,r=1/0,d=-1/0,l=-1/0;return N.forEach(a=>{s=Math.min(s,a.position.x-e),r=Math.min(r,a.position.y-e),d=Math.max(d,a.position.x+e),l=Math.max(l,a.position.y+e)}),D.forEach(a=>{s=Math.min(s,a.position.x),r=Math.min(r,a.position.y),d=Math.max(d,a.position.x+(a.config?.width||200)),l=Math.max(l,a.position.y+(a.config?.height||100))}),{minX:s,minY:r,maxX:d,maxY:l,width:d-s,height:l-r}},[n,N,D]);t.useEffect(()=>{if(!Y||U||!n||!j)return;const e=n.canvas.width,s=n.canvas.height,r=e-B*2,d=s-B*2,l=r/j.width,a=d/j.height,L=Math.min(l,a,F),we=j.minX+j.width/2,je=j.minY+j.height/2,ke=e/2,Me=s/2,Ie=ke-we*L,Ne=Me-je*L;H(L),T({x:Ie,y:Ne}),pe(L),K(!0)},[Y,U,n,j,B,F]),t.useEffect(()=>{Y&&K(!1)},[v,Y]);const A=t.useMemo(()=>{const e=new Set(S),s=new Set(C);return{reserved:e,unavailable:s}},[S,C]),V=t.useCallback(e=>{const s=e.id,r=e.seatNumber||"";return A.unavailable.has(s)||A.unavailable.has(r)?"unavailable":A.reserved.has(s)||A.reserved.has(r)?"reserved":I.has(s)?"selected":e.state},[A,I]);t.useEffect(()=>{n&&E&&E(n)},[n,E]),t.useEffect(()=>{R&&W&&W(R)},[R,W]);const ye=t.useCallback(e=>{const s=V(e);if(s!=="available"&&s!=="selected")return;const r=I.has(e.id);de(d=>{const l=new Set(d);return r?l.delete(e.id):l.add(e.id),l}),r?b?.(e):(x?.(e),x||console.log("Seat selected:",e))},[V,I,x,b]),X=t.useMemo(()=>n?N.filter(e=>I.has(e.id)):[],[N,I]);t.useEffect(()=>{f?.(X)},[X,f]);const _=he,Se=t.useCallback(()=>{if(!y)return;const e=Math.min(g+O,F);if(e!==g){const s=n?.canvas.width||800,r=n?.canvas.height||600,d=s/2,l=r/2,a={x:(d-w.x)/g,y:(l-w.y)/g};H(e),T({x:d-a.x*e,y:l-a.y*e})}},[y,g,O,F,n,w]),ve=t.useCallback(()=>{if(!y)return;const e=Math.max(g-O,_);if(e!==g){const s=n?.canvas.width||800,r=n?.canvas.height||600,d=s/2,l=r/2,a={x:(d-w.x)/g,y:(l-w.y)/g};H(e),T({x:d-a.x*e,y:l-a.y*e})}},[y,g,O,_,n,w]),Ce=t.useCallback(e=>{T({x:e.target.x(),y:e.target.y()})},[]);return xe?o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsx("p",{children:"Loading seat map..."})}):R?o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",R.message]})}):n?o.jsxs("div",{className:`relative ${p}`,children:[be&&Z.length>0&&o.jsx(ee,{floors:Z,currentFloorId:v,onFloorChange:me,showAllOption:se,allLabel:ie,position:ne,className:oe}),o.jsxs(k.Stage,{ref:ce,width:n.canvas.width,height:n.canvas.height,scaleX:g,scaleY:g,x:w.x,y:w.y,draggable:!0,onDragEnd:Ce,style:{backgroundColor:n.canvas.backgroundColor,cursor:"grab"},children:[o.jsx(k.Layer,{listening:!1,children:D.map(e=>o.jsx(Q,{stage:e,stageColor:z.stageColor},e.id))}),o.jsx(k.Layer,{children:N.map(e=>o.jsx(J,{seat:e,state:V(e),colors:z,onClick:ye},e.id))})]}),ae&&y&&o.jsx(te,{scale:g,minScale:_,maxScale:F,onZoomIn:Se,onZoomOut:ve,position:re,className:le}),X.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 (",X.length,")"]}),o.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:X.map(e=>o.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${z.currency} ${e.price.toFixed(2)}`]},e.id))})]})]}):o.jsx("div",{className:`flex items-center justify-center h-full ${p}`,children:o.jsx("p",{children:"No configuration provided"})})};exports.DEFAULT_COLORS=G;exports.SeatMapViewer=Ee;exports.useConfigFetcher=P;
package/dist/index.mjs CHANGED
@@ -1,34 +1,34 @@
1
- import { jsx as r, jsxs as v } from "react/jsx-runtime";
2
- import { useState as S, useEffect as F, useRef as we, useCallback as W, useMemo as k, memo as O } from "react";
3
- import { Stage as Ce, Layer as Z, Group as ke, Rect as ee, Text as Ie, Circle as Me } from "react-konva";
4
- function Ne(i) {
5
- const [h, c] = S(null), [y, x] = S(!1), [w, p] = S(null), g = async () => {
6
- if (i) {
7
- x(!0), p(null);
1
+ import { jsx as i, jsxs as w } from "react/jsx-runtime";
2
+ import { useState as C, useEffect as Y, useRef as Et, useCallback as M, useMemo as F, memo as Z } from "react";
3
+ import { Stage as Wt, Layer as tt, Group as jt, Rect as et, Text as Bt, Circle as Dt } from "react-konva";
4
+ function Ht(o) {
5
+ const [f, d] = C(null), [m, x] = C(!1), [S, g] = C(null), y = async () => {
6
+ if (o) {
7
+ x(!0), g(null);
8
8
  try {
9
- const d = await fetch(i);
10
- if (!d.ok)
11
- throw new Error(`Failed to fetch config: ${d.statusText}`);
12
- const f = await d.json();
13
- c(f);
14
- } catch (d) {
15
- const f = d instanceof Error ? d : new Error("Unknown error occurred");
16
- p(f), console.error("Failed to fetch seat map config:", f);
9
+ const h = await fetch(o);
10
+ if (!h.ok)
11
+ throw new Error(`Failed to fetch config: ${h.statusText}`);
12
+ const l = await h.json();
13
+ d(l);
14
+ } catch (h) {
15
+ const l = h instanceof Error ? h : new Error("Unknown error occurred");
16
+ g(l), console.error("Failed to fetch seat map config:", l);
17
17
  } finally {
18
18
  x(!1);
19
19
  }
20
20
  }
21
21
  };
22
- return F(() => {
23
- g();
24
- }, [i]), {
25
- config: h,
26
- loading: y,
27
- error: w,
28
- refetch: g
22
+ return Y(() => {
23
+ y();
24
+ }, [o]), {
25
+ config: f,
26
+ loading: m,
27
+ error: S,
28
+ refetch: y
29
29
  };
30
30
  }
31
- const Fe = {
31
+ const Tt = {
32
32
  canvasBackground: "#1a1a1a",
33
33
  stageColor: "#808080",
34
34
  seatAvailable: "#2C2B30",
@@ -38,64 +38,64 @@ const Fe = {
38
38
  seatHidden: "#4a4a4a",
39
39
  gridLines: "#404040",
40
40
  currency: "KD"
41
- }, te = O(({ seat: i, state: h, colors: c, onClick: y }) => {
42
- const p = {
43
- available: c.seatAvailable,
44
- reserved: c.seatReserved,
45
- selected: c.seatSelected,
46
- unavailable: c.seatUnavailable,
47
- hidden: c.seatHidden
41
+ }, nt = Z(({ seat: o, state: f, colors: d, onClick: m }) => {
42
+ const g = {
43
+ available: d.seatAvailable,
44
+ reserved: d.seatReserved,
45
+ selected: d.seatSelected,
46
+ unavailable: d.seatUnavailable,
47
+ hidden: d.seatHidden
48
48
  // Hidden seats are filtered out, but included for type safety
49
- }[h], g = h === "available" || h === "selected", d = W(() => {
50
- g && y(i);
51
- }, [i, y, g]), f = {
52
- x: i.position.x,
53
- y: i.position.y,
54
- fill: p,
49
+ }[f], y = f === "available" || f === "selected", h = M(() => {
50
+ y && m(o);
51
+ }, [o, m, y]), l = {
52
+ x: o.position.x,
53
+ y: o.position.y,
54
+ fill: g,
55
55
  stroke: "#ffffff",
56
56
  strokeWidth: 1,
57
- onClick: d,
58
- onTap: d
57
+ onClick: h,
58
+ onTap: h
59
59
  };
60
- return i.shape === "circle" ? /* @__PURE__ */ r(
61
- Me,
60
+ return o.shape === "circle" ? /* @__PURE__ */ i(
61
+ Dt,
62
62
  {
63
- ...f,
63
+ ...l,
64
64
  radius: 12
65
65
  }
66
- ) : /* @__PURE__ */ r(
67
- ee,
66
+ ) : /* @__PURE__ */ i(
67
+ et,
68
68
  {
69
- ...f,
69
+ ...l,
70
70
  width: 24,
71
71
  height: 24,
72
72
  offsetX: 12,
73
73
  offsetY: 12,
74
- cornerRadius: i.shape === "square" ? 0 : 4
74
+ cornerRadius: o.shape === "square" ? 0 : 4
75
75
  }
76
76
  );
77
77
  });
78
- te.displayName = "ViewerSeat";
79
- const ne = O(({ stage: i, stageColor: h }) => /* @__PURE__ */ v(ke, { x: i.position.x, y: i.position.y, children: [
80
- /* @__PURE__ */ r(
81
- ee,
78
+ nt.displayName = "ViewerSeat";
79
+ const ot = Z(({ stage: o, stageColor: f }) => /* @__PURE__ */ w(jt, { x: o.position.x, y: o.position.y, children: [
80
+ /* @__PURE__ */ i(
81
+ et,
82
82
  {
83
- width: i.config.width,
84
- height: i.config.height,
85
- fill: h + "80",
83
+ width: o.config.width,
84
+ height: o.config.height,
85
+ fill: f + "80",
86
86
  stroke: "#ffffff",
87
87
  strokeWidth: 2,
88
88
  cornerRadius: 10
89
89
  }
90
90
  ),
91
- /* @__PURE__ */ r(
92
- Ie,
91
+ /* @__PURE__ */ i(
92
+ Bt,
93
93
  {
94
- text: i.config.label,
94
+ text: o.config.label,
95
95
  x: 0,
96
96
  y: 0,
97
- width: i.config.width,
98
- height: i.config.height,
97
+ width: o.config.width,
98
+ height: o.config.height,
99
99
  fontSize: 24,
100
100
  fontStyle: "bold",
101
101
  fill: "#ffffff",
@@ -104,20 +104,20 @@ const ne = O(({ stage: i, stageColor: h }) => /* @__PURE__ */ v(ke, { x: i.posit
104
104
  }
105
105
  )
106
106
  ] }));
107
- ne.displayName = "ViewerStage";
108
- const ie = O(({
109
- floors: i,
110
- currentFloorId: h,
111
- onFloorChange: c,
112
- showAllOption: y,
107
+ ot.displayName = "ViewerStage";
108
+ const it = Z(({
109
+ floors: o,
110
+ currentFloorId: f,
111
+ onFloorChange: d,
112
+ showAllOption: m,
113
113
  allLabel: x,
114
- position: w,
115
- className: p
114
+ position: S,
115
+ className: g
116
116
  }) => {
117
- const g = k(
118
- () => [...i].sort((u, E) => u.order - E.order),
119
- [i]
120
- ), f = {
117
+ const y = F(
118
+ () => [...o].sort((u, A) => u.order - A.order),
119
+ [o]
120
+ ), l = {
121
121
  position: "absolute",
122
122
  display: "flex",
123
123
  alignItems: "center",
@@ -132,8 +132,8 @@ const ie = O(({
132
132
  "top-right": { top: 0, right: 0 },
133
133
  "bottom-left": { bottom: 0, left: 0 },
134
134
  "bottom-right": { bottom: 0, right: 0 }
135
- }[w]
136
- }, $ = {
135
+ }[S]
136
+ }, N = {
137
137
  padding: "6px 14px",
138
138
  fontSize: "14px",
139
139
  fontWeight: 500,
@@ -143,197 +143,301 @@ const ie = O(({
143
143
  color: "#fff",
144
144
  cursor: "pointer",
145
145
  transition: "all 0.2s ease"
146
- }, A = {
147
- ...$,
146
+ }, b = {
147
+ ...N,
148
148
  backgroundColor: "#3A7DE5",
149
149
  borderColor: "#3A7DE5"
150
150
  };
151
- return /* @__PURE__ */ v("div", { className: p, style: f, children: [
152
- y && /* @__PURE__ */ r(
151
+ return /* @__PURE__ */ w("div", { className: g, style: l, children: [
152
+ m && /* @__PURE__ */ i(
153
153
  "button",
154
154
  {
155
155
  type: "button",
156
- onClick: () => c(null),
157
- style: h === null ? A : $,
156
+ onClick: () => d(null),
157
+ style: f === null ? b : N,
158
158
  children: x
159
159
  }
160
160
  ),
161
- g.map((u) => /* @__PURE__ */ r(
161
+ y.map((u) => /* @__PURE__ */ i(
162
162
  "button",
163
163
  {
164
164
  type: "button",
165
- onClick: () => c(u.id),
166
- style: h === u.id ? A : $,
165
+ onClick: () => d(u.id),
166
+ style: f === u.id ? b : N,
167
167
  children: u.name
168
168
  },
169
169
  u.id
170
170
  ))
171
171
  ] });
172
172
  });
173
- ie.displayName = "FloorSelectorBar";
174
- const Ye = ({
175
- config: i,
176
- configUrl: h,
177
- floorId: c,
178
- onFloorChange: y,
173
+ it.displayName = "FloorSelectorBar";
174
+ const st = Z(({
175
+ scale: o,
176
+ minScale: f,
177
+ maxScale: d,
178
+ onZoomIn: m,
179
+ onZoomOut: x,
180
+ position: S,
181
+ className: g
182
+ }) => {
183
+ const h = {
184
+ position: "absolute",
185
+ display: "flex",
186
+ flexDirection: "column",
187
+ gap: "4px",
188
+ padding: "8px",
189
+ backgroundColor: "rgba(26, 26, 26, 0.95)",
190
+ borderRadius: "8px",
191
+ margin: "12px",
192
+ zIndex: 10,
193
+ ...{
194
+ "top-left": { top: 0, left: 0 },
195
+ "top-right": { top: 0, right: 0 },
196
+ "bottom-left": { bottom: 0, left: 0 },
197
+ "bottom-right": { bottom: 0, right: 0 }
198
+ }[S]
199
+ }, l = {
200
+ width: "36px",
201
+ height: "36px",
202
+ fontSize: "20px",
203
+ fontWeight: "bold",
204
+ border: "1px solid #444",
205
+ borderRadius: "6px",
206
+ backgroundColor: "transparent",
207
+ color: "#fff",
208
+ cursor: "pointer",
209
+ display: "flex",
210
+ alignItems: "center",
211
+ justifyContent: "center",
212
+ transition: "all 0.2s ease"
213
+ }, N = {
214
+ ...l,
215
+ opacity: 0.4,
216
+ cursor: "not-allowed"
217
+ }, b = o < d, u = o > f;
218
+ return /* @__PURE__ */ w("div", { className: g, style: h, children: [
219
+ /* @__PURE__ */ i(
220
+ "button",
221
+ {
222
+ type: "button",
223
+ onClick: m,
224
+ disabled: !b,
225
+ style: b ? l : N,
226
+ title: "Zoom In",
227
+ children: "+"
228
+ }
229
+ ),
230
+ /* @__PURE__ */ i(
231
+ "button",
232
+ {
233
+ type: "button",
234
+ onClick: x,
235
+ disabled: !u,
236
+ style: u ? l : N,
237
+ title: "Zoom Out",
238
+ children: "−"
239
+ }
240
+ )
241
+ ] });
242
+ });
243
+ st.displayName = "ZoomControls";
244
+ const zt = ({
245
+ config: o,
246
+ configUrl: f,
247
+ floorId: d,
248
+ onFloorChange: m,
179
249
  reservedSeats: x = [],
180
- unavailableSeats: w = [],
181
- onSeatSelect: p,
182
- onSeatDeselect: g,
183
- onSelectionChange: d,
184
- colorOverrides: f,
185
- showTooltip: $ = !0,
186
- zoomEnabled: A = !0,
250
+ unavailableSeats: S = [],
251
+ onSeatSelect: g,
252
+ onSeatDeselect: y,
253
+ onSelectionChange: h,
254
+ colorOverrides: l,
255
+ showTooltip: N = !0,
256
+ zoomEnabled: b = !0,
187
257
  className: u = "",
188
- onConfigLoad: E,
189
- onError: D,
258
+ onConfigLoad: A,
259
+ onError: z,
190
260
  // Floor selector props
191
- showFloorSelector: U,
192
- floorSelectorPosition: oe = "top-left",
193
- floorSelectorClassName: re,
194
- showAllFloorsOption: se = !0,
195
- allFloorsLabel: ae = "All",
196
- fitToView: j = !0,
197
- fitPadding: H = 40
261
+ showFloorSelector: P,
262
+ floorSelectorPosition: rt = "top-left",
263
+ floorSelectorClassName: at,
264
+ showAllFloorsOption: lt = !0,
265
+ allFloorsLabel: ct = "All",
266
+ fitToView: D = !0,
267
+ fitPadding: L = 40,
268
+ // Zoom controls
269
+ showZoomControls: dt = !0,
270
+ zoomControlsPosition: ht = "bottom-right",
271
+ zoomControlsClassName: ft,
272
+ maxZoom: E = 3,
273
+ zoomStep: H = 0.25
198
274
  }) => {
199
- const q = we(null), [I, le] = S(/* @__PURE__ */ new Set()), [B, G] = S(1), [R, K] = S({ x: 0, y: 0 }), [ce, de] = S(null), [J, Q] = S(!1), { config: fe, loading: he, error: Y } = Ne(h), n = i || fe, L = c !== void 0, m = L ? c || null : ce, ue = W((e) => {
200
- L || de(e), y?.(e);
201
- }, [L, y]), P = n?.floors || [], pe = U !== void 0 ? U : P.length > 1, V = k(
202
- () => n ? { ...n.colors, ...f } : { ...Fe, ...f },
203
- [n, f]
204
- ), M = k(() => {
205
- if (!n) return [];
206
- let e = n.seats.filter((t) => t.state !== "hidden");
207
- return m && (e = e.filter(
208
- (t) => t.floorId === m || !t.floorId && m === "floor_default"
209
- )), e;
210
- }, [n, m]), T = k(() => n?.stages ? m ? n.stages.filter(
211
- (e) => e.floorId === m || !e.floorId && m === "floor_default"
212
- ) : n.stages : [], [n, m]), b = k(() => {
213
- if (!n || M.length === 0 && T.length === 0)
275
+ const ut = Et(null), [R, pt] = C(/* @__PURE__ */ new Set()), [p, V] = C(1), [k, T] = C({ x: 0, y: 0 }), [gt, mt] = C(null), [J, Q] = C(!1), [yt, bt] = C(1), { config: xt, loading: vt, error: W } = Ht(f), e = o || xt, _ = d !== void 0, v = _ ? d || null : gt, St = M((t) => {
276
+ _ || mt(t), m?.(t);
277
+ }, [_, m]), U = e?.floors || [], wt = P !== void 0 ? P : U.length > 1, q = F(
278
+ () => e ? { ...e.colors, ...l } : { ...Tt, ...l },
279
+ [e, l]
280
+ ), X = F(() => {
281
+ if (!e) return [];
282
+ let t = e.seats.filter((n) => n.state !== "hidden");
283
+ return v && (t = t.filter(
284
+ (n) => n.floorId === v || !n.floorId && v === "floor_default"
285
+ )), t;
286
+ }, [e, v]), $ = F(() => e?.stages ? v ? e.stages.filter(
287
+ (t) => t.floorId === v || !t.floorId && v === "floor_default"
288
+ ) : e.stages : [], [e, v]), I = F(() => {
289
+ if (!e || X.length === 0 && $.length === 0)
214
290
  return null;
215
- const e = 12;
216
- let t = 1 / 0, o = 1 / 0, s = -1 / 0, a = -1 / 0;
217
- return M.forEach((l) => {
218
- t = Math.min(t, l.position.x - e), o = Math.min(o, l.position.y - e), s = Math.max(s, l.position.x + e), a = Math.max(a, l.position.y + e);
219
- }), T.forEach((l) => {
220
- t = Math.min(t, l.position.x), o = Math.min(o, l.position.y), s = Math.max(s, l.position.x + (l.config?.width || 200)), a = Math.max(a, l.position.y + (l.config?.height || 100));
221
- }), { minX: t, minY: o, maxX: s, maxY: a, width: s - t, height: a - o };
222
- }, [n, M, T]);
223
- F(() => {
224
- if (!j || J || !n || !b) return;
225
- const e = n.canvas.width, t = n.canvas.height, o = e - H * 2, s = t - H * 2, a = o / b.width, l = s / b.height, N = Math.min(a, l, 2), C = b.minX + b.width / 2, ye = b.minY + b.height / 2, xe = e / 2, be = t / 2, ve = xe - C * N, Se = be - ye * N;
226
- G(N), K({ x: ve, y: Se }), Q(!0);
227
- }, [j, J, n, b, H]), F(() => {
228
- j && Q(!1);
229
- }, [m, j]);
230
- const z = k(() => {
231
- const e = new Set(x), t = new Set(w);
232
- return { reserved: e, unavailable: t };
233
- }, [x, w]), _ = W((e) => {
234
- const t = e.id, o = e.seatNumber || "";
235
- return z.unavailable.has(t) || z.unavailable.has(o) ? "unavailable" : z.reserved.has(t) || z.reserved.has(o) ? "reserved" : I.has(t) ? "selected" : e.state;
236
- }, [z, I]);
237
- F(() => {
238
- n && E && E(n);
239
- }, [n, E]), F(() => {
240
- Y && D && D(Y);
241
- }, [Y, D]);
242
- const ge = W((e) => {
243
- const t = _(e);
244
- if (t !== "available" && t !== "selected")
291
+ const t = 12;
292
+ let n = 1 / 0, r = 1 / 0, c = -1 / 0, a = -1 / 0;
293
+ return X.forEach((s) => {
294
+ n = Math.min(n, s.position.x - t), r = Math.min(r, s.position.y - t), c = Math.max(c, s.position.x + t), a = Math.max(a, s.position.y + t);
295
+ }), $.forEach((s) => {
296
+ n = Math.min(n, s.position.x), r = Math.min(r, s.position.y), c = Math.max(c, s.position.x + (s.config?.width || 200)), a = Math.max(a, s.position.y + (s.config?.height || 100));
297
+ }), { minX: n, minY: r, maxX: c, maxY: a, width: c - n, height: a - r };
298
+ }, [e, X, $]);
299
+ Y(() => {
300
+ if (!D || J || !e || !I) return;
301
+ const t = e.canvas.width, n = e.canvas.height, r = t - L * 2, c = n - L * 2, a = r / I.width, s = c / I.height, O = Math.min(a, s, E), Mt = I.minX + I.width / 2, Ft = I.minY + I.height / 2, Rt = t / 2, Xt = n / 2, Yt = Rt - Mt * O, At = Xt - Ft * O;
302
+ V(O), T({ x: Yt, y: At }), bt(O), Q(!0);
303
+ }, [D, J, e, I, L, E]), Y(() => {
304
+ D && Q(!1);
305
+ }, [v, D]);
306
+ const j = F(() => {
307
+ const t = new Set(x), n = new Set(S);
308
+ return { reserved: t, unavailable: n };
309
+ }, [x, S]), G = M((t) => {
310
+ const n = t.id, r = t.seatNumber || "";
311
+ return j.unavailable.has(n) || j.unavailable.has(r) ? "unavailable" : j.reserved.has(n) || j.reserved.has(r) ? "reserved" : R.has(n) ? "selected" : t.state;
312
+ }, [j, R]);
313
+ Y(() => {
314
+ e && A && A(e);
315
+ }, [e, A]), Y(() => {
316
+ W && z && z(W);
317
+ }, [W, z]);
318
+ const Ct = M((t) => {
319
+ const n = G(t);
320
+ if (n !== "available" && n !== "selected")
245
321
  return;
246
- const o = I.has(e.id);
247
- le((s) => {
248
- const a = new Set(s);
249
- return o ? a.delete(e.id) : a.add(e.id), a;
250
- }), o ? g?.(e) : (p?.(e), p || console.log("Seat selected:", e));
251
- }, [_, I, p, g]), X = k(() => n ? M.filter((e) => I.has(e.id)) : [], [M, I]);
252
- F(() => {
253
- d?.(X);
254
- }, [X, d]);
255
- const me = W((e) => {
256
- if (!A) return;
257
- e.evt.preventDefault();
258
- const t = q.current;
259
- if (!t) return;
260
- const o = B, s = t.getPointerPosition();
261
- if (!s) return;
262
- const a = {
263
- x: (s.x - R.x) / o,
264
- y: (s.y - R.y) / o
265
- }, l = e.evt.deltaY > 0 ? -1 : 1, N = 1.05;
266
- let C = l > 0 ? o * N : o / N;
267
- C = Math.max(0.5, Math.min(5, C)), G(C), K({
268
- x: s.x - a.x * C,
269
- y: s.y - a.y * C
322
+ const r = R.has(t.id);
323
+ pt((c) => {
324
+ const a = new Set(c);
325
+ return r ? a.delete(t.id) : a.add(t.id), a;
326
+ }), r ? y?.(t) : (g?.(t), g || console.log("Seat selected:", t));
327
+ }, [G, R, g, y]), B = F(() => e ? X.filter((t) => R.has(t.id)) : [], [X, R]);
328
+ Y(() => {
329
+ h?.(B);
330
+ }, [B, h]);
331
+ const K = yt, kt = M(() => {
332
+ if (!b) return;
333
+ const t = Math.min(p + H, E);
334
+ if (t !== p) {
335
+ const n = e?.canvas.width || 800, r = e?.canvas.height || 600, c = n / 2, a = r / 2, s = {
336
+ x: (c - k.x) / p,
337
+ y: (a - k.y) / p
338
+ };
339
+ V(t), T({
340
+ x: c - s.x * t,
341
+ y: a - s.y * t
342
+ });
343
+ }
344
+ }, [b, p, H, E, e, k]), It = M(() => {
345
+ if (!b) return;
346
+ const t = Math.max(p - H, K);
347
+ if (t !== p) {
348
+ const n = e?.canvas.width || 800, r = e?.canvas.height || 600, c = n / 2, a = r / 2, s = {
349
+ x: (c - k.x) / p,
350
+ y: (a - k.y) / p
351
+ };
352
+ V(t), T({
353
+ x: c - s.x * t,
354
+ y: a - s.y * t
355
+ });
356
+ }
357
+ }, [b, p, H, K, e, k]), Nt = M((t) => {
358
+ T({
359
+ x: t.target.x(),
360
+ y: t.target.y()
270
361
  });
271
- }, [A, B, R]);
272
- return he ? /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ r("p", { children: "Loading seat map..." }) }) : Y ? /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ v("p", { className: "text-red-500", children: [
362
+ }, []);
363
+ return vt ? /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ i("p", { children: "Loading seat map..." }) }) : W ? /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ w("p", { className: "text-red-500", children: [
273
364
  "Error loading seat map: ",
274
- Y.message
275
- ] }) }) : n ? /* @__PURE__ */ v("div", { className: `relative ${u}`, children: [
276
- pe && P.length > 0 && /* @__PURE__ */ r(
277
- ie,
365
+ W.message
366
+ ] }) }) : e ? /* @__PURE__ */ w("div", { className: `relative ${u}`, children: [
367
+ wt && U.length > 0 && /* @__PURE__ */ i(
368
+ it,
278
369
  {
279
- floors: P,
280
- currentFloorId: m,
281
- onFloorChange: ue,
282
- showAllOption: se,
283
- allLabel: ae,
284
- position: oe,
285
- className: re
370
+ floors: U,
371
+ currentFloorId: v,
372
+ onFloorChange: St,
373
+ showAllOption: lt,
374
+ allLabel: ct,
375
+ position: rt,
376
+ className: at
286
377
  }
287
378
  ),
288
- /* @__PURE__ */ v(
289
- Ce,
379
+ /* @__PURE__ */ w(
380
+ Wt,
290
381
  {
291
- ref: q,
292
- width: n.canvas.width,
293
- height: n.canvas.height,
294
- scaleX: B,
295
- scaleY: B,
296
- x: R.x,
297
- y: R.y,
298
- onWheel: me,
299
- style: { backgroundColor: n.canvas.backgroundColor },
382
+ ref: ut,
383
+ width: e.canvas.width,
384
+ height: e.canvas.height,
385
+ scaleX: p,
386
+ scaleY: p,
387
+ x: k.x,
388
+ y: k.y,
389
+ draggable: !0,
390
+ onDragEnd: Nt,
391
+ style: { backgroundColor: e.canvas.backgroundColor, cursor: "grab" },
300
392
  children: [
301
- /* @__PURE__ */ r(Z, { listening: !1, children: T.map((e) => /* @__PURE__ */ r(
302
- ne,
393
+ /* @__PURE__ */ i(tt, { listening: !1, children: $.map((t) => /* @__PURE__ */ i(
394
+ ot,
303
395
  {
304
- stage: e,
305
- stageColor: V.stageColor
396
+ stage: t,
397
+ stageColor: q.stageColor
306
398
  },
307
- e.id
399
+ t.id
308
400
  )) }),
309
- /* @__PURE__ */ r(Z, { children: M.map((e) => /* @__PURE__ */ r(
310
- te,
401
+ /* @__PURE__ */ i(tt, { children: X.map((t) => /* @__PURE__ */ i(
402
+ nt,
311
403
  {
312
- seat: e,
313
- state: _(e),
314
- colors: V,
315
- onClick: ge
404
+ seat: t,
405
+ state: G(t),
406
+ colors: q,
407
+ onClick: Ct
316
408
  },
317
- e.id
409
+ t.id
318
410
  )) })
319
411
  ]
320
412
  }
321
413
  ),
322
- X.length > 0 && /* @__PURE__ */ v("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
323
- /* @__PURE__ */ v("h3", { className: "font-semibold mb-2", children: [
414
+ dt && b && /* @__PURE__ */ i(
415
+ st,
416
+ {
417
+ scale: p,
418
+ minScale: K,
419
+ maxScale: E,
420
+ onZoomIn: kt,
421
+ onZoomOut: It,
422
+ position: ht,
423
+ className: ft
424
+ }
425
+ ),
426
+ B.length > 0 && /* @__PURE__ */ w("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
427
+ /* @__PURE__ */ w("h3", { className: "font-semibold mb-2", children: [
324
428
  "Selected Seats (",
325
- X.length,
429
+ B.length,
326
430
  ")"
327
431
  ] }),
328
- /* @__PURE__ */ r("div", { className: "max-h-48 overflow-y-auto space-y-1", children: X.map((e) => /* @__PURE__ */ v("div", { className: "text-sm", children: [
329
- e.seatNumber,
330
- e.price && ` - ${V.currency} ${e.price.toFixed(2)}`
331
- ] }, e.id)) })
432
+ /* @__PURE__ */ i("div", { className: "max-h-48 overflow-y-auto space-y-1", children: B.map((t) => /* @__PURE__ */ w("div", { className: "text-sm", children: [
433
+ t.seatNumber,
434
+ t.price && ` - ${q.currency} ${t.price.toFixed(2)}`
435
+ ] }, t.id)) })
332
436
  ] })
333
- ] }) : /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ r("p", { children: "No configuration provided" }) });
437
+ ] }) : /* @__PURE__ */ i("div", { className: `flex items-center justify-center h-full ${u}`, children: /* @__PURE__ */ i("p", { children: "No configuration provided" }) });
334
438
  };
335
439
  export {
336
- Fe as DEFAULT_COLORS,
337
- Ye as SeatMapViewer,
338
- Ne as useConfigFetcher
440
+ Tt as DEFAULT_COLORS,
441
+ zt as SeatMapViewer,
442
+ Ht as useConfigFetcher
339
443
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonetrix/viewer",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "description": "Lightweight React component for rendering interactive seat maps",
6
6
  "main": "./dist/index.js",