@zonetrix/viewer 2.1.1 → 2.2.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.
@@ -16,5 +16,10 @@ export interface SeatMapViewerProps {
16
16
  className?: string;
17
17
  onConfigLoad?: (config: SeatMapConfig) => void;
18
18
  onError?: (error: Error) => void;
19
+ showFloorSelector?: boolean;
20
+ floorSelectorPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
21
+ floorSelectorClassName?: string;
22
+ showAllFloorsOption?: boolean;
23
+ allFloorsLabel?: string;
19
24
  }
20
25
  export declare const SeatMapViewer: React.FC<SeatMapViewerProps>;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { SeatMapViewer } from './components/SeatMapViewer';
2
2
  export type { SeatMapViewerProps } from './components/SeatMapViewer';
3
- export type { SeatState, SeatShape, SeatData, SerializedSeat, SerializedSection, SerializedStage, ColorSettings, SeatMapConfig, } from './types';
3
+ export type { SeatState, SeatShape, SeatData, SerializedSeat, SerializedSection, SerializedStage, ColorSettings, SeatMapConfig, FloorConfig, } from './types';
4
4
  export { DEFAULT_COLORS } from './types';
5
5
  export { useConfigFetcher } from './hooks/useConfigFetcher';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),t=require("react"),h=require("react-konva");function $(i){const[f,n]=t.useState(null),[v,x]=t.useState(!1),[p,d]=t.useState(null),u=async()=>{if(i){x(!0),d(null);try{const o=await fetch(i);if(!o.ok)throw new Error(`Failed to fetch config: ${o.statusText}`);const c=await o.json();n(c)}catch(o){const c=o instanceof Error?o:new Error("Unknown error occurred");d(c),console.error("Failed to fetch seat map config:",c)}finally{x(!1)}}};return t.useEffect(()=>{u()},[i]),{config:f,loading:v,error:p,refetch:u}}const z={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},V=t.memo(({seat:i,state:f,colors:n,onClick:v})=>{const d={available:n.seatAvailable,reserved:n.seatReserved,selected:n.seatSelected,unavailable:n.seatUnavailable,hidden:n.seatHidden}[f],u=f==="available"||f==="selected",o=t.useCallback(()=>{u&&v(i)},[i,v,u]),c={x:i.position.x,y:i.position.y,fill:d,stroke:"#ffffff",strokeWidth:1,onClick:o,onTap:o};return i.shape==="circle"?s.jsx(h.Circle,{...c,radius:12}):s.jsx(h.Rect,{...c,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:i.shape==="square"?0:4})});V.displayName="ViewerSeat";const _=t.memo(({stage:i,stageColor:f})=>s.jsxs(h.Group,{x:i.position.x,y:i.position.y,children:[s.jsx(h.Rect,{width:i.config.width,height:i.config.height,fill:f+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),s.jsx(h.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"})]}));_.displayName="ViewerStage";const X=({config:i,configUrl:f,floorId:n,onFloorChange:v,reservedSeats:x=[],unavailableSeats:p=[],onSeatSelect:d,onSeatDeselect:u,onSelectionChange:o,colorOverrides:c,showTooltip:G=!0,zoomEnabled:A=!0,className:k="",onConfigLoad:N,onError:R})=>{const L=t.useRef(null),[S,q]=t.useState(new Set),[M,D]=t.useState(1),[y,O]=t.useState({x:0,y:0}),{config:W,loading:U,error:b}=$(f),r=i||W,E=t.useMemo(()=>r?{...r.colors,...c}:{...z,...c},[r,c]),F=t.useMemo(()=>{if(!r)return[];let e=r.seats.filter(a=>a.state!=="hidden");return n&&(e=e.filter(a=>a.floorId===n||!a.floorId&&n==="floor_default")),e},[r,n]),Y=t.useMemo(()=>r?.stages?n?r.stages.filter(e=>e.floorId===n||!e.floorId&&n==="floor_default"):r.stages:[],[r,n]),w=t.useMemo(()=>{const e=new Set(x),a=new Set(p);return{reserved:e,unavailable:a}},[x,p]),T=t.useCallback(e=>{const a=e.id,l=e.seatNumber||"";return w.unavailable.has(a)||w.unavailable.has(l)?"unavailable":w.reserved.has(a)||w.reserved.has(l)?"reserved":S.has(a)?"selected":e.state},[w,S]);t.useEffect(()=>{r&&N&&N(r)},[r,N]),t.useEffect(()=>{b&&R&&R(b)},[b,R]);const B=t.useCallback(e=>{const a=T(e);if(a!=="available"&&a!=="selected")return;const l=S.has(e.id);q(g=>{const m=new Set(g);return l?m.delete(e.id):m.add(e.id),m}),l?u?.(e):(d?.(e),d||console.log("Seat selected:",e))},[T,S,d,u]),j=t.useMemo(()=>r?F.filter(e=>S.has(e.id)):[],[F,S]);t.useEffect(()=>{o?.(j)},[j,o]);const H=t.useCallback(e=>{if(!A)return;e.evt.preventDefault();const a=L.current;if(!a)return;const l=M,g=a.getPointerPosition();if(!g)return;const m={x:(g.x-y.x)/l,y:(g.y-y.y)/l},K=e.evt.deltaY>0?-1:1,P=1.05;let C=K>0?l*P:l/P;C=Math.max(.5,Math.min(5,C)),D(C),O({x:g.x-m.x*C,y:g.y-m.y*C})},[A,M,y]);return U?s.jsx("div",{className:`flex items-center justify-center h-full ${k}`,children:s.jsx("p",{children:"Loading seat map..."})}):b?s.jsx("div",{className:`flex items-center justify-center h-full ${k}`,children:s.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",b.message]})}):r?s.jsxs("div",{className:`relative ${k}`,children:[s.jsxs(h.Stage,{ref:L,width:r.canvas.width,height:r.canvas.height,scaleX:M,scaleY:M,x:y.x,y:y.y,onWheel:H,style:{backgroundColor:r.canvas.backgroundColor},children:[s.jsx(h.Layer,{listening:!1,children:Y.map(e=>s.jsx(_,{stage:e,stageColor:E.stageColor},e.id))}),s.jsx(h.Layer,{children:F.map(e=>s.jsx(V,{seat:e,state:T(e),colors:E,onClick:B},e.id))})]}),j.length>0&&s.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[s.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",j.length,")"]}),s.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:j.map(e=>s.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${E.currency} ${e.price.toFixed(2)}`]},e.id))})]})]}):s.jsx("div",{className:`flex items-center justify-center h-full ${k}`,children:s.jsx("p",{children:"No configuration provided"})})};exports.DEFAULT_COLORS=z;exports.SeatMapViewer=X;exports.useConfigFetcher=$;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),t=require("react"),S=require("react-konva");function B(o){const[c,i]=t.useState(null),[g,x]=t.useState(!1),[m,f]=t.useState(null),u=async()=>{if(o){x(!0),f(null);try{const a=await fetch(o);if(!a.ok)throw new Error(`Failed to fetch config: ${a.statusText}`);const l=await a.json();i(l)}catch(a){const l=a instanceof Error?a:new Error("Unknown error occurred");f(l),console.error("Failed to fetch seat map config:",l)}finally{x(!1)}}};return t.useEffect(()=>{u()},[o]),{config:c,loading:g,error:m,refetch:u}}const O={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},W=t.memo(({seat:o,state:c,colors:i,onClick:g})=>{const f={available:i.seatAvailable,reserved:i.seatReserved,selected:i.seatSelected,unavailable:i.seatUnavailable,hidden:i.seatHidden}[c],u=c==="available"||c==="selected",a=t.useCallback(()=>{u&&g(o)},[o,g,u]),l={x:o.position.x,y:o.position.y,fill:f,stroke:"#ffffff",strokeWidth:1,onClick:a,onTap:a};return o.shape==="circle"?s.jsx(S.Circle,{...l,radius:12}):s.jsx(S.Rect,{...l,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:o.shape==="square"?0:4})});W.displayName="ViewerSeat";const _=t.memo(({stage:o,stageColor:c})=>s.jsxs(S.Group,{x:o.position.x,y:o.position.y,children:[s.jsx(S.Rect,{width:o.config.width,height:o.config.height,fill:c+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),s.jsx(S.Text,{text:o.config.label,x:0,y:0,width:o.config.width,height:o.config.height,fontSize:24,fontStyle:"bold",fill:"#ffffff",align:"center",verticalAlign:"middle"})]}));_.displayName="ViewerStage";const q=t.memo(({floors:o,currentFloorId:c,onFloorChange:i,showAllOption:g,allLabel:x,position:m,className:f})=>{const u=t.useMemo(()=>[...o].sort((d,w)=>d.order-w.order),[o]),l={position:"absolute",display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",backgroundColor:"rgba(26, 26, 26, 0.95)",borderRadius:"8px",margin:"12px",zIndex:10,...{"top-left":{top:0,left:0},"top-right":{top:0,right:0},"bottom-left":{bottom:0,left:0},"bottom-right":{bottom:0,right:0}}[m]},E={padding:"6px 14px",fontSize:"14px",fontWeight:500,border:"1px solid #444",borderRadius:"6px",backgroundColor:"transparent",color:"#fff",cursor:"pointer",transition:"all 0.2s ease"},j={...E,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return s.jsxs("div",{className:f,style:l,children:[g&&s.jsx("button",{type:"button",onClick:()=>i(null),style:c===null?j:E,children:x}),u.map(d=>s.jsx("button",{type:"button",onClick:()=>i(d.id),style:c===d.id?j:E,children:d.name},d.id))]})});q.displayName="FloorSelectorBar";const le=({config:o,configUrl:c,floorId:i,onFloorChange:g,reservedSeats:x=[],unavailableSeats:m=[],onSeatSelect:f,onSeatDeselect:u,onSelectionChange:a,colorOverrides:l,showTooltip:E=!0,zoomEnabled:j=!0,className:d="",onConfigLoad:w,onError:A,showFloorSelector:$,floorSelectorPosition:U="top-left",floorSelectorClassName:Y,showAllFloorsOption:H=!0,allFloorsLabel:K="All"})=>{const D=t.useRef(null),[y,X]=t.useState(new Set),[F,G]=t.useState(1),[C,J]=t.useState({x:0,y:0}),[Q,Z]=t.useState(null),{config:ee,loading:te,error:k}=B(c),r=o||ee,I=i!==void 0,p=I?i||null:Q,se=t.useCallback(e=>{I||Z(e),g?.(e)},[I,g]),T=r?.floors||[],oe=$!==void 0?$:T.length>1,z=t.useMemo(()=>r?{...r.colors,...l}:{...O,...l},[r,l]),L=t.useMemo(()=>{if(!r)return[];let e=r.seats.filter(n=>n.state!=="hidden");return p&&(e=e.filter(n=>n.floorId===p||!n.floorId&&p==="floor_default")),e},[r,p]),re=t.useMemo(()=>r?.stages?p?r.stages.filter(e=>e.floorId===p||!e.floorId&&p==="floor_default"):r.stages:[],[r,p]),N=t.useMemo(()=>{const e=new Set(x),n=new Set(m);return{reserved:e,unavailable:n}},[x,m]),P=t.useCallback(e=>{const n=e.id,h=e.seatNumber||"";return N.unavailable.has(n)||N.unavailable.has(h)?"unavailable":N.reserved.has(n)||N.reserved.has(h)?"reserved":y.has(n)?"selected":e.state},[N,y]);t.useEffect(()=>{r&&w&&w(r)},[r,w]),t.useEffect(()=>{k&&A&&A(k)},[k,A]);const ne=t.useCallback(e=>{const n=P(e);if(n!=="available"&&n!=="selected")return;const h=y.has(e.id);X(b=>{const v=new Set(b);return h?v.delete(e.id):v.add(e.id),v}),h?u?.(e):(f?.(e),f||console.log("Seat selected:",e))},[P,y,f,u]),M=t.useMemo(()=>r?L.filter(e=>y.has(e.id)):[],[L,y]);t.useEffect(()=>{a?.(M)},[M,a]);const ie=t.useCallback(e=>{if(!j)return;e.evt.preventDefault();const n=D.current;if(!n)return;const h=F,b=n.getPointerPosition();if(!b)return;const v={x:(b.x-C.x)/h,y:(b.y-C.y)/h},ae=e.evt.deltaY>0?-1:1,V=1.05;let R=ae>0?h*V:h/V;R=Math.max(.5,Math.min(5,R)),G(R),J({x:b.x-v.x*R,y:b.y-v.y*R})},[j,F,C]);return te?s.jsx("div",{className:`flex items-center justify-center h-full ${d}`,children:s.jsx("p",{children:"Loading seat map..."})}):k?s.jsx("div",{className:`flex items-center justify-center h-full ${d}`,children:s.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",k.message]})}):r?s.jsxs("div",{className:`relative ${d}`,children:[oe&&T.length>0&&s.jsx(q,{floors:T,currentFloorId:p,onFloorChange:se,showAllOption:H,allLabel:K,position:U,className:Y}),s.jsxs(S.Stage,{ref:D,width:r.canvas.width,height:r.canvas.height,scaleX:F,scaleY:F,x:C.x,y:C.y,onWheel:ie,style:{backgroundColor:r.canvas.backgroundColor},children:[s.jsx(S.Layer,{listening:!1,children:re.map(e=>s.jsx(_,{stage:e,stageColor:z.stageColor},e.id))}),s.jsx(S.Layer,{children:L.map(e=>s.jsx(W,{seat:e,state:P(e),colors:z,onClick:ne},e.id))})]}),M.length>0&&s.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[s.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",M.length,")"]}),s.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:M.map(e=>s.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${z.currency} ${e.price.toFixed(2)}`]},e.id))})]})]}):s.jsx("div",{className:`flex items-center justify-center h-full ${d}`,children:s.jsx("p",{children:"No configuration provided"})})};exports.DEFAULT_COLORS=O;exports.SeatMapViewer=le;exports.useConfigFetcher=B;
package/dist/index.mjs CHANGED
@@ -1,34 +1,34 @@
1
- import { jsx as s, jsxs as u } from "react/jsx-runtime";
2
- import { useState as v, useEffect as T, useRef as Q, useMemo as N, useCallback as $, memo as W } from "react";
3
- import { Stage as Z, Layer as L, Group as ee, Rect as D, Text as te, Circle as ie } from "react-konva";
4
- function re(t) {
5
- const [c, r] = v(null), [S, g] = v(!1), [y, d] = v(null), f = async () => {
1
+ import { jsx as r, jsxs as m } from "react/jsx-runtime";
2
+ import { useState as y, useEffect as $, useRef as ue, useCallback as z, useMemo as w, memo as V } from "react";
3
+ import { Stage as he, Layer as H, Group as pe, Rect as O, Text as ge, Circle as me } from "react-konva";
4
+ function be(t) {
5
+ const [a, i] = y(null), [h, g] = y(!1), [b, d] = y(null), f = async () => {
6
6
  if (t) {
7
7
  g(!0), d(null);
8
8
  try {
9
- const a = await fetch(t);
10
- if (!a.ok)
11
- throw new Error(`Failed to fetch config: ${a.statusText}`);
12
- const o = await a.json();
13
- r(o);
14
- } catch (a) {
15
- const o = a instanceof Error ? a : new Error("Unknown error occurred");
16
- d(o), console.error("Failed to fetch seat map config:", o);
9
+ const s = await fetch(t);
10
+ if (!s.ok)
11
+ throw new Error(`Failed to fetch config: ${s.statusText}`);
12
+ const l = await s.json();
13
+ i(l);
14
+ } catch (s) {
15
+ const l = s instanceof Error ? s : new Error("Unknown error occurred");
16
+ d(l), console.error("Failed to fetch seat map config:", l);
17
17
  } finally {
18
18
  g(!1);
19
19
  }
20
20
  }
21
21
  };
22
- return T(() => {
22
+ return $(() => {
23
23
  f();
24
24
  }, [t]), {
25
- config: c,
26
- loading: S,
27
- error: y,
25
+ config: a,
26
+ loading: h,
27
+ error: b,
28
28
  refetch: f
29
29
  };
30
30
  }
31
- const ne = {
31
+ const Se = {
32
32
  canvasBackground: "#1a1a1a",
33
33
  stageColor: "#808080",
34
34
  seatAvailable: "#2C2B30",
@@ -38,35 +38,35 @@ const ne = {
38
38
  seatHidden: "#4a4a4a",
39
39
  gridLines: "#404040",
40
40
  currency: "KD"
41
- }, Y = W(({ seat: t, state: c, colors: r, onClick: S }) => {
41
+ }, U = V(({ seat: t, state: a, colors: i, onClick: h }) => {
42
42
  const d = {
43
- available: r.seatAvailable,
44
- reserved: r.seatReserved,
45
- selected: r.seatSelected,
46
- unavailable: r.seatUnavailable,
47
- hidden: r.seatHidden
43
+ available: i.seatAvailable,
44
+ reserved: i.seatReserved,
45
+ selected: i.seatSelected,
46
+ unavailable: i.seatUnavailable,
47
+ hidden: i.seatHidden
48
48
  // Hidden seats are filtered out, but included for type safety
49
- }[c], f = c === "available" || c === "selected", a = $(() => {
50
- f && S(t);
51
- }, [t, S, f]), o = {
49
+ }[a], f = a === "available" || a === "selected", s = z(() => {
50
+ f && h(t);
51
+ }, [t, h, f]), l = {
52
52
  x: t.position.x,
53
53
  y: t.position.y,
54
54
  fill: d,
55
55
  stroke: "#ffffff",
56
56
  strokeWidth: 1,
57
- onClick: a,
58
- onTap: a
57
+ onClick: s,
58
+ onTap: s
59
59
  };
60
- return t.shape === "circle" ? /* @__PURE__ */ s(
61
- ie,
60
+ return t.shape === "circle" ? /* @__PURE__ */ r(
61
+ me,
62
62
  {
63
- ...o,
63
+ ...l,
64
64
  radius: 12
65
65
  }
66
- ) : /* @__PURE__ */ s(
67
- D,
66
+ ) : /* @__PURE__ */ r(
67
+ O,
68
68
  {
69
- ...o,
69
+ ...l,
70
70
  width: 24,
71
71
  height: 24,
72
72
  offsetX: 12,
@@ -75,21 +75,21 @@ const ne = {
75
75
  }
76
76
  );
77
77
  });
78
- Y.displayName = "ViewerSeat";
79
- const B = W(({ stage: t, stageColor: c }) => /* @__PURE__ */ u(ee, { x: t.position.x, y: t.position.y, children: [
80
- /* @__PURE__ */ s(
81
- D,
78
+ U.displayName = "ViewerSeat";
79
+ const X = V(({ stage: t, stageColor: a }) => /* @__PURE__ */ m(pe, { x: t.position.x, y: t.position.y, children: [
80
+ /* @__PURE__ */ r(
81
+ O,
82
82
  {
83
83
  width: t.config.width,
84
84
  height: t.config.height,
85
- fill: c + "80",
85
+ fill: a + "80",
86
86
  stroke: "#ffffff",
87
87
  strokeWidth: 2,
88
88
  cornerRadius: 10
89
89
  }
90
90
  ),
91
- /* @__PURE__ */ s(
92
- te,
91
+ /* @__PURE__ */ r(
92
+ ge,
93
93
  {
94
94
  text: t.config.label,
95
95
  x: 0,
@@ -104,130 +104,216 @@ const B = W(({ stage: t, stageColor: c }) => /* @__PURE__ */ u(ee, { x: t.positi
104
104
  }
105
105
  )
106
106
  ] }));
107
- B.displayName = "ViewerStage";
108
- const ce = ({
107
+ X.displayName = "ViewerStage";
108
+ const q = V(({
109
+ floors: t,
110
+ currentFloorId: a,
111
+ onFloorChange: i,
112
+ showAllOption: h,
113
+ allLabel: g,
114
+ position: b,
115
+ className: d
116
+ }) => {
117
+ const f = w(
118
+ () => [...t].sort((c, k) => c.order - k.order),
119
+ [t]
120
+ ), l = {
121
+ position: "absolute",
122
+ display: "flex",
123
+ alignItems: "center",
124
+ gap: "8px",
125
+ padding: "8px 12px",
126
+ backgroundColor: "rgba(26, 26, 26, 0.95)",
127
+ borderRadius: "8px",
128
+ margin: "12px",
129
+ zIndex: 10,
130
+ ...{
131
+ "top-left": { top: 0, left: 0 },
132
+ "top-right": { top: 0, right: 0 },
133
+ "bottom-left": { bottom: 0, left: 0 },
134
+ "bottom-right": { bottom: 0, right: 0 }
135
+ }[b]
136
+ }, E = {
137
+ padding: "6px 14px",
138
+ fontSize: "14px",
139
+ fontWeight: 500,
140
+ border: "1px solid #444",
141
+ borderRadius: "6px",
142
+ backgroundColor: "transparent",
143
+ color: "#fff",
144
+ cursor: "pointer",
145
+ transition: "all 0.2s ease"
146
+ }, C = {
147
+ ...E,
148
+ backgroundColor: "#3A7DE5",
149
+ borderColor: "#3A7DE5"
150
+ };
151
+ return /* @__PURE__ */ m("div", { className: d, style: l, children: [
152
+ h && /* @__PURE__ */ r(
153
+ "button",
154
+ {
155
+ type: "button",
156
+ onClick: () => i(null),
157
+ style: a === null ? C : E,
158
+ children: g
159
+ }
160
+ ),
161
+ f.map((c) => /* @__PURE__ */ r(
162
+ "button",
163
+ {
164
+ type: "button",
165
+ onClick: () => i(c.id),
166
+ style: a === c.id ? C : E,
167
+ children: c.name
168
+ },
169
+ c.id
170
+ ))
171
+ ] });
172
+ });
173
+ q.displayName = "FloorSelectorBar";
174
+ const we = ({
109
175
  config: t,
110
- configUrl: c,
111
- floorId: r,
112
- onFloorChange: S,
176
+ configUrl: a,
177
+ floorId: i,
178
+ onFloorChange: h,
113
179
  reservedSeats: g = [],
114
- unavailableSeats: y = [],
180
+ unavailableSeats: b = [],
115
181
  onSeatSelect: d,
116
182
  onSeatDeselect: f,
117
- onSelectionChange: a,
118
- colorOverrides: o,
119
- showTooltip: se = !0,
120
- zoomEnabled: P = !0,
121
- className: F = "",
122
- onConfigLoad: j,
123
- onError: z
183
+ onSelectionChange: s,
184
+ colorOverrides: l,
185
+ showTooltip: E = !0,
186
+ zoomEnabled: C = !0,
187
+ className: c = "",
188
+ onConfigLoad: k,
189
+ onError: j,
190
+ // Floor selector props
191
+ showFloorSelector: W,
192
+ floorSelectorPosition: G = "top-left",
193
+ floorSelectorClassName: K,
194
+ showAllFloorsOption: J = !0,
195
+ allFloorsLabel: Q = "All"
124
196
  }) => {
125
- const V = Q(null), [m, H] = v(/* @__PURE__ */ new Set()), [R, U] = v(1), [w, X] = v({ x: 0, y: 0 }), { config: q, loading: G, error: x } = re(c), i = t || q, A = N(
126
- () => i ? { ...i.colors, ...o } : { ...ne, ...o },
127
- [i, o]
128
- ), E = N(() => {
129
- if (!i) return [];
130
- let e = i.seats.filter((n) => n.state !== "hidden");
131
- return r && (e = e.filter(
132
- (n) => n.floorId === r || !n.floorId && r === "floor_default"
197
+ const _ = ue(null), [v, Z] = y(/* @__PURE__ */ new Set()), [T, ee] = y(1), [N, te] = y({ x: 0, y: 0 }), [oe, re] = y(null), { config: ne, loading: ie, error: I } = be(a), o = t || ne, M = i !== void 0, p = M ? i || null : oe, se = z((e) => {
198
+ M || re(e), h?.(e);
199
+ }, [M, h]), P = o?.floors || [], le = W !== void 0 ? W : P.length > 1, B = w(
200
+ () => o ? { ...o.colors, ...l } : { ...Se, ...l },
201
+ [o, l]
202
+ ), D = w(() => {
203
+ if (!o) return [];
204
+ let e = o.seats.filter((n) => n.state !== "hidden");
205
+ return p && (e = e.filter(
206
+ (n) => n.floorId === p || !n.floorId && p === "floor_default"
133
207
  )), e;
134
- }, [i, r]), K = N(() => i?.stages ? r ? i.stages.filter(
135
- (e) => e.floorId === r || !e.floorId && r === "floor_default"
136
- ) : i.stages : [], [i, r]), b = N(() => {
137
- const e = new Set(g), n = new Set(y);
208
+ }, [o, p]), ae = w(() => o?.stages ? p ? o.stages.filter(
209
+ (e) => e.floorId === p || !e.floorId && p === "floor_default"
210
+ ) : o.stages : [], [o, p]), A = w(() => {
211
+ const e = new Set(g), n = new Set(b);
138
212
  return { reserved: e, unavailable: n };
139
- }, [g, y]), M = $((e) => {
140
- const n = e.id, l = e.seatNumber || "";
141
- return b.unavailable.has(n) || b.unavailable.has(l) ? "unavailable" : b.reserved.has(n) || b.reserved.has(l) ? "reserved" : m.has(n) ? "selected" : e.state;
142
- }, [b, m]);
143
- T(() => {
144
- i && j && j(i);
145
- }, [i, j]), T(() => {
146
- x && z && z(x);
147
- }, [x, z]);
148
- const O = $((e) => {
149
- const n = M(e);
213
+ }, [g, b]), L = z((e) => {
214
+ const n = e.id, u = e.seatNumber || "";
215
+ return A.unavailable.has(n) || A.unavailable.has(u) ? "unavailable" : A.reserved.has(n) || A.reserved.has(u) ? "reserved" : v.has(n) ? "selected" : e.state;
216
+ }, [A, v]);
217
+ $(() => {
218
+ o && k && k(o);
219
+ }, [o, k]), $(() => {
220
+ I && j && j(I);
221
+ }, [I, j]);
222
+ const ce = z((e) => {
223
+ const n = L(e);
150
224
  if (n !== "available" && n !== "selected")
151
225
  return;
152
- const l = m.has(e.id);
153
- H((h) => {
154
- const p = new Set(h);
155
- return l ? p.delete(e.id) : p.add(e.id), p;
156
- }), l ? f?.(e) : (d?.(e), d || console.log("Seat selected:", e));
157
- }, [M, m, d, f]), C = N(() => i ? E.filter((e) => m.has(e.id)) : [], [E, m]);
158
- T(() => {
159
- a?.(C);
160
- }, [C, a]);
161
- const I = $((e) => {
162
- if (!P) return;
226
+ const u = v.has(e.id);
227
+ Z((S) => {
228
+ const x = new Set(S);
229
+ return u ? x.delete(e.id) : x.add(e.id), x;
230
+ }), u ? f?.(e) : (d?.(e), d || console.log("Seat selected:", e));
231
+ }, [L, v, d, f]), F = w(() => o ? D.filter((e) => v.has(e.id)) : [], [D, v]);
232
+ $(() => {
233
+ s?.(F);
234
+ }, [F, s]);
235
+ const de = z((e) => {
236
+ if (!C) return;
163
237
  e.evt.preventDefault();
164
- const n = V.current;
238
+ const n = _.current;
165
239
  if (!n) return;
166
- const l = R, h = n.getPointerPosition();
167
- if (!h) return;
168
- const p = {
169
- x: (h.x - w.x) / l,
170
- y: (h.y - w.y) / l
171
- }, J = e.evt.deltaY > 0 ? -1 : 1, _ = 1.05;
172
- let k = J > 0 ? l * _ : l / _;
173
- k = Math.max(0.5, Math.min(5, k)), U(k), X({
174
- x: h.x - p.x * k,
175
- y: h.y - p.y * k
240
+ const u = T, S = n.getPointerPosition();
241
+ if (!S) return;
242
+ const x = {
243
+ x: (S.x - N.x) / u,
244
+ y: (S.y - N.y) / u
245
+ }, fe = e.evt.deltaY > 0 ? -1 : 1, Y = 1.05;
246
+ let R = fe > 0 ? u * Y : u / Y;
247
+ R = Math.max(0.5, Math.min(5, R)), ee(R), te({
248
+ x: S.x - x.x * R,
249
+ y: S.y - x.y * R
176
250
  });
177
- }, [P, R, w]);
178
- return G ? /* @__PURE__ */ s("div", { className: `flex items-center justify-center h-full ${F}`, children: /* @__PURE__ */ s("p", { children: "Loading seat map..." }) }) : x ? /* @__PURE__ */ s("div", { className: `flex items-center justify-center h-full ${F}`, children: /* @__PURE__ */ u("p", { className: "text-red-500", children: [
251
+ }, [C, T, N]);
252
+ return ie ? /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${c}`, children: /* @__PURE__ */ r("p", { children: "Loading seat map..." }) }) : I ? /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${c}`, children: /* @__PURE__ */ m("p", { className: "text-red-500", children: [
179
253
  "Error loading seat map: ",
180
- x.message
181
- ] }) }) : i ? /* @__PURE__ */ u("div", { className: `relative ${F}`, children: [
182
- /* @__PURE__ */ u(
183
- Z,
254
+ I.message
255
+ ] }) }) : o ? /* @__PURE__ */ m("div", { className: `relative ${c}`, children: [
256
+ le && P.length > 0 && /* @__PURE__ */ r(
257
+ q,
258
+ {
259
+ floors: P,
260
+ currentFloorId: p,
261
+ onFloorChange: se,
262
+ showAllOption: J,
263
+ allLabel: Q,
264
+ position: G,
265
+ className: K
266
+ }
267
+ ),
268
+ /* @__PURE__ */ m(
269
+ he,
184
270
  {
185
- ref: V,
186
- width: i.canvas.width,
187
- height: i.canvas.height,
188
- scaleX: R,
189
- scaleY: R,
190
- x: w.x,
191
- y: w.y,
192
- onWheel: I,
193
- style: { backgroundColor: i.canvas.backgroundColor },
271
+ ref: _,
272
+ width: o.canvas.width,
273
+ height: o.canvas.height,
274
+ scaleX: T,
275
+ scaleY: T,
276
+ x: N.x,
277
+ y: N.y,
278
+ onWheel: de,
279
+ style: { backgroundColor: o.canvas.backgroundColor },
194
280
  children: [
195
- /* @__PURE__ */ s(L, { listening: !1, children: K.map((e) => /* @__PURE__ */ s(
196
- B,
281
+ /* @__PURE__ */ r(H, { listening: !1, children: ae.map((e) => /* @__PURE__ */ r(
282
+ X,
197
283
  {
198
284
  stage: e,
199
- stageColor: A.stageColor
285
+ stageColor: B.stageColor
200
286
  },
201
287
  e.id
202
288
  )) }),
203
- /* @__PURE__ */ s(L, { children: E.map((e) => /* @__PURE__ */ s(
204
- Y,
289
+ /* @__PURE__ */ r(H, { children: D.map((e) => /* @__PURE__ */ r(
290
+ U,
205
291
  {
206
292
  seat: e,
207
- state: M(e),
208
- colors: A,
209
- onClick: O
293
+ state: L(e),
294
+ colors: B,
295
+ onClick: ce
210
296
  },
211
297
  e.id
212
298
  )) })
213
299
  ]
214
300
  }
215
301
  ),
216
- C.length > 0 && /* @__PURE__ */ u("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
217
- /* @__PURE__ */ u("h3", { className: "font-semibold mb-2", children: [
302
+ F.length > 0 && /* @__PURE__ */ m("div", { className: "absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg", children: [
303
+ /* @__PURE__ */ m("h3", { className: "font-semibold mb-2", children: [
218
304
  "Selected Seats (",
219
- C.length,
305
+ F.length,
220
306
  ")"
221
307
  ] }),
222
- /* @__PURE__ */ s("div", { className: "max-h-48 overflow-y-auto space-y-1", children: C.map((e) => /* @__PURE__ */ u("div", { className: "text-sm", children: [
308
+ /* @__PURE__ */ r("div", { className: "max-h-48 overflow-y-auto space-y-1", children: F.map((e) => /* @__PURE__ */ m("div", { className: "text-sm", children: [
223
309
  e.seatNumber,
224
- e.price && ` - ${A.currency} ${e.price.toFixed(2)}`
310
+ e.price && ` - ${B.currency} ${e.price.toFixed(2)}`
225
311
  ] }, e.id)) })
226
312
  ] })
227
- ] }) : /* @__PURE__ */ s("div", { className: `flex items-center justify-center h-full ${F}`, children: /* @__PURE__ */ s("p", { children: "No configuration provided" }) });
313
+ ] }) : /* @__PURE__ */ r("div", { className: `flex items-center justify-center h-full ${c}`, children: /* @__PURE__ */ r("p", { children: "No configuration provided" }) });
228
314
  };
229
315
  export {
230
- ne as DEFAULT_COLORS,
231
- ce as SeatMapViewer,
232
- re as useConfigFetcher
316
+ Se as DEFAULT_COLORS,
317
+ we as SeatMapViewer,
318
+ be as useConfigFetcher
233
319
  };
@@ -44,6 +44,12 @@ export interface SerializedStage {
44
44
  config: any;
45
45
  floorId?: string;
46
46
  }
47
+ export interface FloorConfig {
48
+ id: string;
49
+ name: string;
50
+ order: number;
51
+ color?: string;
52
+ }
47
53
  export interface ColorSettings {
48
54
  canvasBackground: string;
49
55
  stageColor: string;
@@ -74,5 +80,6 @@ export interface SeatMapConfig {
74
80
  seats: SerializedSeat[];
75
81
  sections?: SerializedSection[];
76
82
  stages?: SerializedStage[];
83
+ floors?: FloorConfig[];
77
84
  }
78
85
  export declare const DEFAULT_COLORS: ColorSettings;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonetrix/viewer",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "description": "Lightweight React component for rendering interactive seat maps",
6
6
  "main": "./dist/index.js",