@zonetrix/viewer 2.10.5 → 2.10.6
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/dist/index.js +1 -1
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),t=require("react"),X=require("react-konva"),W=require("firebase/database"),ot=require("@zonetrix/shared");function we(n){const[s,a]=t.useState(null),[r,h]=t.useState(!1),[u,o]=t.useState(null),w=async()=>{if(n){h(!0),o(null);try{const g=await fetch(n);if(!g.ok)throw new Error(`Failed to fetch config: ${g.statusText}`);const l=await g.json();a(l)}catch(g){const l=g instanceof Error?g:new Error("Unknown error occurred");o(l),console.error("Failed to fetch seat map config:",l)}finally{h(!1)}}};return t.useEffect(()=>{w()},[n]),{config:s,loading:r,error:u,refetch:w}}function Ce(n){const[s,a]=t.useState({width:0,height:0});return t.useEffect(()=>{const r=n.current;if(!r)return;const{width:h,height:u}=r.getBoundingClientRect();h>0&&u>0&&a({width:h,height:u});const o=new ResizeObserver(w=>{const g=w[0];if(!g)return;const{width:l,height:c}=g.contentRect;l>0&&c>0&&a(f=>f.width===l&&f.height===c?f:{width:l,height:c})});return o.observe(r),()=>{o.disconnect()}},[n]),s}function ve(n,s){return Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2))}function me(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function Re(n,s){const a=t.useRef(null),r=t.useRef(null),h=t.useRef(1);t.useEffect(()=>{const u=n.current;if(!u||!s.enabled)return;const o=u.container(),w=c=>{if(c.touches.length===2){c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},p={x:c.touches[1].clientX,y:c.touches[1].clientY};a.current=ve(f,p),r.current=me(f,p),h.current=s.currentScale}},g=c=>{if(c.touches.length!==2)return;c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},p={x:c.touches[1].clientX,y:c.touches[1].clientY},b=ve(f,p),v=me(f,p);if(a.current!==null&&r.current!==null){const R=b/a.current,E=Math.min(Math.max(s.currentScale*R,s.minScale),s.maxScale),F=o.getBoundingClientRect(),M=v.x-F.left,j=v.y-F.top,z=s.currentScale,L={x:(M-s.currentPosition.x)/z,y:(j-s.currentPosition.y)/z},D=v.x-r.current.x,N=v.y-r.current.y,Q={x:M-L.x*E+D,y:j-L.y*E+N};s.onScaleChange(E,Q),a.current=b,r.current=v}},l=c=>{c.touches.length<2&&(a.current=null,r.current=null)};return o.addEventListener("touchstart",w,{passive:!1}),o.addEventListener("touchmove",g,{passive:!1}),o.addEventListener("touchend",l),()=>{o.removeEventListener("touchstart",w),o.removeEventListener("touchmove",g),o.removeEventListener("touchend",l)}},[n,s])}const je={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Me=t.memo(({seat:n,state:s,colors:a,onClick:r,onMouseEnter:h,onMouseLeave:u})=>{const g={available:a.seatAvailable,reserved:a.seatReserved,selected:a.seatSelected,unavailable:a.seatUnavailable,hidden:a.seatHidden}[s],l=s==="available"||s==="selected",c=t.useCallback(()=>{l&&r(n)},[n,r,l]),f=t.useCallback(v=>{h(n,v);const R=v.target.getStage();R&&l&&(R.container().style.cursor="pointer")},[n,h,l]),p=t.useCallback(v=>{u();const R=v.target.getStage();R&&(R.container().style.cursor="grab")},[u]),b={x:n.position.x,y:n.position.y,fill:g,stroke:"#ffffff",strokeWidth:1,onClick:c,onTap:c,onMouseEnter:f,onMouseLeave:p};return n.shape==="circle"?i.jsx(X.Circle,{...b,radius:12}):i.jsx(X.Rect,{...b,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:n.shape==="square"?0:4})});Me.displayName="ViewerSeat";const Ee=t.memo(({stage:n,stageColor:s})=>{const a=u=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[u||"stage"]||"🎭",r=n.config.color||s,h=a(n.config.objectType);return i.jsxs(X.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[i.jsx(X.Rect,{width:n.config.width,height:n.config.height,fill:r+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),i.jsx(X.Text,{text:h,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),i.jsx(X.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"})]})});Ee.displayName="ViewerStage";const Fe=t.memo(({floors:n,currentFloorId:s,onFloorChange:a,showAllOption:r,allLabel:h,position:u,className:o})=>{const w=t.useMemo(()=>[...n].sort((p,b)=>p.order-b.order),[n]),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}}[u]},c={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"},f={...c,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return i.jsxs("div",{className:o,style:l,children:[r&&i.jsx("button",{type:"button",onClick:()=>a(null),style:s===null?f:c,children:h}),w.map(p=>i.jsx("button",{type:"button",onClick:()=>a(p.id),style:s===p.id?f:c,children:p.name},p.id))]})});Fe.displayName="FloorSelectorBar";const ke=t.memo(({scale:n,minScale:s,maxScale:a,onZoomIn:r,onZoomOut:h,position:u,className:o})=>{const g={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}}[u]},l={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"},c={...l,opacity:.4,cursor:"not-allowed"},f=n<a,p=n>s;return i.jsxs("div",{className:o,style:g,children:[i.jsx("button",{type:"button",onClick:r,disabled:!f,style:f?l:c,title:"Zoom In",children:"+"}),i.jsx("button",{type:"button",onClick:h,disabled:!p,style:p?l:c,title:"Zoom Out",children:"−"})]})});ke.displayName="ZoomControls";const Ie=t.memo(({visible:n,x:s,y:a,seat:r,currency:h,state:u})=>{if(!n||!r)return null;const o=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),w={position:"fixed",left:`${s+15}px`,top:`${a+15}px`,zIndex:1e3,pointerEvents:"none"},g={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},l={color:"#9ca3af",marginRight:"4px"},c={fontWeight:600},f={color:"#4ade80",fontWeight:600},p={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return i.jsx("div",{style:w,children:i.jsxs("div",{style:g,children:[r.sectionName&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Section:"}),i.jsx("span",{style:{...c,color:"#3b82f6"},children:r.sectionName})]}),i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Seat:"}),i.jsx("span",{style:c,children:o})]}),r.price!==void 0&&r.price>0&&u==="available"&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Price:"}),i.jsxs("span",{style:f,children:[h," ",r.price.toFixed(2)]})]}),i.jsxs("div",{style:p,children:["Status: ",u]})]})})});Ie.displayName="SeatTooltip";const it=({config:n,configUrl:s,floorId:a,onFloorChange:r,reservedSeats:h=[],unavailableSeats:u=[],selectedSeats:o,myReservedSeats:w=[],onSeatSelect:g,onSeatDeselect:l,onSelectionChange:c,colorOverrides:f,showTooltip:p=!0,zoomEnabled:b=!0,className:v="",onConfigLoad:R,onError:E,showFloorSelector:F,floorSelectorPosition:M="top-left",floorSelectorClassName:j,showAllFloorsOption:z=!0,allFloorsLabel:L="All",fitToView:D=!0,fitPadding:N=40,showZoomControls:Q=!0,zoomControlsPosition:De="bottom-right",zoomControlsClassName:ze,minZoom:be,maxZoom:Y=3,zoomStep:ee=.25,touchEnabled:Ne=!0})=>{const le=t.useRef(null),xe=t.useRef(null),k=Ce(xe),[U,Se]=t.useState(new Set),[I,H]=t.useState(1),[T,B]=t.useState({x:0,y:0}),[Ae,Xe]=t.useState(null),[Ye,Pe]=t.useState(1),te=t.useRef({width:0,height:0}),[q,ye]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:We,loading:Be,error:_}=we(s),x=n||We,ue=a!==void 0,A=ue?a||null:Ae,ne=o!==void 0,$e=t.useCallback(e=>{ue||Xe(e),r?.(e)},[ue,r]),de=x?.floors||[],Ue=F!==void 0?F:de.length>1,se=t.useMemo(()=>x?{...x.colors,...f}:{...je,...f},[x,f]),O=t.useMemo(()=>{if(!x)return[];let e=x.seats.filter(d=>d.state!=="hidden");return A&&(e=e.filter(d=>d.floorId===A||!d.floorId&&A==="floor_default")),e},[x,A]),re=t.useMemo(()=>x?.stages?A?x.stages.filter(e=>e.floorId===A||!e.floorId&&A==="floor_default"):x.stages:[],[x,A]),P=t.useMemo(()=>{if(!x||O.length===0&&re.length===0)return null;const e=12;let d=1/0,S=1/0,y=-1/0,m=-1/0;return O.forEach(C=>{d=Math.min(d,C.position.x-e),S=Math.min(S,C.position.y-e),y=Math.max(y,C.position.x+e),m=Math.max(m,C.position.y+e)}),re.forEach(C=>{d=Math.min(d,C.position.x),S=Math.min(S,C.position.y),y=Math.max(y,C.position.x+(C.config?.width||200)),m=Math.max(m,C.position.y+(C.config?.height||100))}),{minX:d,minY:S,maxX:y,maxY:m,width:y-d,height:m-S}},[x,O,re]);t.useEffect(()=>{if(!D||!x||!P||k.width===0||k.height===0)return;const e=Math.abs(k.width-te.current.width),d=Math.abs(k.height-te.current.height);if(!(te.current.width===0)&&e<10&&d<10)return;te.current=k;const y=k.width,m=k.height,C=y-N*2,Z=m-N*2,oe=C/P.width,fe=Z/P.height,ie=Math.min(oe,fe,Y),Qe=P.minX+P.width/2,et=P.minY+P.height/2,tt=y/2,nt=m/2,st=tt-Qe*ie,rt=nt-et*ie;H(ie),B({x:st,y:rt}),Pe(ie)},[D,x,P,N,Y,k,A]);const $=t.useMemo(()=>{const e=new Set(h),d=new Set(u),S=new Set(w);return{reserved:e,unavailable:d,myReserved:S}},[h,u,w]),he=t.useMemo(()=>o?new Set(o):null,[o]),G=t.useCallback(e=>{const d=e.id,S=e.seatNumber||"";return $.unavailable.has(d)||$.unavailable.has(S)?"unavailable":$.reserved.has(d)||$.reserved.has(S)?"reserved":$.myReserved.has(d)||$.myReserved.has(S)||U.has(d)?"selected":e.state},[$,U]);t.useEffect(()=>{x&&R&&R(x)},[x,R]),t.useEffect(()=>{_&&E&&E(_)},[_,E]),t.useEffect(()=>{ne&&he&&Se(he)},[ne,he]);const Oe=t.useCallback(e=>{const d=G(e);if(d!=="available"&&d!=="selected")return;const S=U.has(e.id);ne||Se(y=>{const m=new Set(y);return S?m.delete(e.id):m.add(e.id),m}),S?l?.(e):(g?.(e),g||console.log("Seat selected:",e))},[G,U,ne,g,l]),K=t.useMemo(()=>x?O.filter(e=>U.has(e.id)):[],[O,U]);t.useEffect(()=>{c?.(K)},[K,c]);const V=be!==void 0?be:Ye,Ve=t.useCallback(()=>{if(!b)return;const e=Math.min(I+ee,Y);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,y=d/2,m=S/2,C={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-C.x*e,y:m-C.y*e})}},[b,I,ee,Y,k,x,T]),He=t.useCallback(()=>{if(!b)return;const e=Math.max(I-ee,V);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,y=d/2,m=S/2,C={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-C.x*e,y:m-C.y*e})}},[b,I,ee,V,k,x,T]),qe=t.useCallback(e=>{B({x:e.target.x(),y:e.target.y()})},[]),_e=t.useCallback(e=>{if(!b)return;e.evt.preventDefault();const d=le.current;if(!d)return;const S=d.scaleX(),y=d.getPointerPosition();if(!y)return;const m=1.1,C=e.evt.deltaY>0?S/m:S*m,Z=Math.min(Math.max(C,V),Y),oe={x:(y.x-T.x)/S,y:(y.y-T.y)/S},fe={x:y.x-oe.x*Z,y:y.y-oe.y*Z};H(Z),B(fe)},[b,T,V,Y]);Re(le,{enabled:Ne&&b,minScale:V,maxScale:Y,currentScale:I,currentPosition:T,onScaleChange:(e,d)=>{H(e),B(d)},onPositionChange:e=>{B(e)}});const Ge=t.useCallback((e,d)=>{if(!p)return;const S=d.target.getStage();if(!S)return;const y=S.getPointerPosition();if(!y)return;const m=S.container().getBoundingClientRect();ye({visible:!0,x:m.left+y.x,y:m.top+y.y,seat:e,state:G(e)})},[p,G]),Ke=t.useCallback(()=>{ye(e=>({...e,visible:!1}))},[]);if(Be)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsx("p",{children:"Loading seat map..."})});if(_)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",_.message]})});if(!x)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsx("p",{children:"No configuration provided"})});const Ze=k.width||x.canvas.width,Je=k.height||x.canvas.height;return i.jsxs("div",{ref:xe,className:`relative ${v}`,style:{width:"100%",height:"100%"},children:[Ue&&de.length>0&&i.jsx(Fe,{floors:de,currentFloorId:A,onFloorChange:$e,showAllOption:z,allLabel:L,position:M,className:j}),i.jsxs(X.Stage,{ref:le,width:Ze,height:Je,scaleX:I,scaleY:I,x:T.x,y:T.y,draggable:!0,onDragEnd:qe,onWheel:_e,style:{backgroundColor:x.canvas.backgroundColor,cursor:"grab"},children:[i.jsx(X.Layer,{listening:!1,children:re.map(e=>i.jsx(Ee,{stage:e,stageColor:se.stageColor},e.id))}),i.jsx(X.Layer,{children:O.map(e=>i.jsx(Me,{seat:e,state:G(e),colors:se,onClick:Oe,onMouseEnter:Ge,onMouseLeave:Ke},e.id))})]}),p&&i.jsx(Ie,{visible:q.visible,x:q.x,y:q.y,seat:q.seat,currency:se.currency,state:q.state}),Q&&b&&i.jsx(ke,{scale:I,minScale:V,maxScale:Y,onZoomIn:Ve,onZoomOut:He,position:De,className:ze}),K.length>0&&i.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[i.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",K.length,")"]}),i.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:K.map(e=>i.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${se.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let J=null;function at(n){J=n}function pe(){if(!J)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return J}function ce(){return J!==null}function ct(){J=null}function ge(n,s){if(n.length!==s.length)return!1;const a=[...n].sort(),r=[...s].sort();return a.every((h,u)=>h===r[u])}function lt(n,s){const a=[],r=[],h=[];return Object.entries(n).forEach(([u,o])=>{o&&typeof o=="object"&&o.state&&(o.state==="unavailable"?h.push(u):o.state==="reserved"&&(s&&o.userId===s?a.push(u):r.push(u)))}),{myReserved:a.sort(),otherReserved:r.sort(),unavailable:h.sort()}}const ae={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function Le(n){const{seatMapId:s,currentUserId:a,enabled:r=!0,onStateChange:h,onError:u}=n,o=t.useRef({...ae}),w=t.useRef(h),g=t.useRef(u),l=t.useRef(a);w.current=h,g.current=u,l.current=a;const c=t.useCallback(v=>{if(!r||!s)return(o.current.loading!==!1||o.current.states!==null)&&(o.current={...ae,loading:!1},v()),()=>{};if(!ce()){const j="Firebase not initialized. Call initializeFirebaseForViewer first.";return o.current.error?.message!==j&&(o.current={...ae,loading:!1,error:new Error(j)},v()),()=>{}}const R=pe(),E=W.ref(R,`seatmaps/${s}/seat_states`),F=j=>{const L=j.val()||{},D=lt(L,l.current),N=o.current;(N.loading||!ge(N.myReservedSeats,D.myReserved)||!ge(N.otherReservedSeats,D.otherReserved)||!ge(N.unavailableSeats,D.unavailable))&&(o.current={states:L,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:D.myReserved,otherReservedSeats:D.otherReserved,unavailableSeats:D.unavailable},w.current?.(L),v())},M=j=>{o.current={...o.current,loading:!1,error:j},g.current?.(j),v()};return W.onValue(E,F,M),()=>{W.off(E)}},[s,r,a]),f=t.useCallback(()=>o.current,[]),p=t.useCallback(()=>ae,[]),b=t.useSyncExternalStore(c,f,p);return{states:b.states,loading:b.loading,error:b.error,lastUpdated:b.lastUpdated,myReservedSeats:b.myReservedSeats,otherReservedSeats:b.otherReservedSeats,unavailableSeats:b.unavailableSeats,reservedSeats:b.otherReservedSeats}}function Te(n){const{seatMapId:s,enabled:a=!0,subscribeToChanges:r=!1,onConfigLoad:h,onError:u}=n,[o,w]=t.useState(null),[g,l]=t.useState(!0),[c,f]=t.useState(null),p=t.useRef(h),b=t.useRef(u);p.current=h,b.current=u;const v=t.useCallback(async()=>{if(!s)return;if(!ce()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),l(!1);return}const R=pe(),E=W.ref(R,`seatmaps/${s}`);try{l(!0),f(null);const M=(await W.get(E)).val();if(M){const j=ot.fromFirebaseSeatMap(M);w(j),p.current?.(j)}else f(new Error(`Seat map ${s} not found in Firebase`))}catch(F){const M=F instanceof Error?F:new Error("Unknown error");f(M),b.current?.(M)}finally{l(!1)}},[s]);return t.useEffect(()=>{if(!a||!s){l(!1);return}if(v(),r&&ce()){const R=pe(),E=W.ref(R,`seatmaps/${s}/meta/updated_at`);let F=!0,M=null;const j=z=>{if(F){F=!1,M=z.val();return}const L=z.val();z.exists()&&L!==M&&(M=L,v())};return W.onValue(E,j),()=>{W.off(E)}}},[s,a,r]),{config:o,loading:g,error:c,refetch:v}}function ut(n){const{seatMapId:s,userId:a,enabled:r=!0,subscribeToDesignChanges:h=!1,onConfigLoad:u,onStateChange:o,onError:w}=n,{config:g,loading:l,error:c,refetch:f}=Te({seatMapId:s,enabled:r,subscribeToChanges:h,onConfigLoad:u,onError:w}),{states:p,loading:b,error:v,lastUpdated:R,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:M,reservedSeats:j}=Le({seatMapId:s,currentUserId:a,enabled:r,onStateChange:o,onError:w});return{config:g,loading:l||b,error:c||v,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:M,reservedSeats:j,seatStates:p,lastUpdated:R,refetch:f}}exports.DEFAULT_COLORS=je;exports.SeatMapViewer=it;exports.clearFirebaseInstance=ct;exports.initializeFirebaseForViewer=at;exports.isFirebaseInitialized=ce;exports.useConfigFetcher=we;exports.useContainerSize=Ce;exports.useFirebaseConfig=Te;exports.useFirebaseSeatStates=Le;exports.useRealtimeSeatMap=ut;exports.useTouchGestures=Re;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),t=require("react"),X=require("react-konva"),W=require("firebase/database"),ot=require("@zonetrix/shared");function we(n){const[s,a]=t.useState(null),[r,h]=t.useState(!1),[u,o]=t.useState(null),w=async()=>{if(n){h(!0),o(null);try{const g=await fetch(n);if(!g.ok)throw new Error(`Failed to fetch config: ${g.statusText}`);const l=await g.json();a(l)}catch(g){const l=g instanceof Error?g:new Error("Unknown error occurred");o(l),console.error("Failed to fetch seat map config:",l)}finally{h(!1)}}};return t.useEffect(()=>{w()},[n]),{config:s,loading:r,error:u,refetch:w}}function Ce(n){const[s,a]=t.useState({width:0,height:0});return t.useEffect(()=>{const r=n.current;if(!r)return;const{width:h,height:u}=r.getBoundingClientRect();h>0&&u>0&&a({width:h,height:u});const o=new ResizeObserver(w=>{const g=w[0];if(!g)return;const{width:l,height:c}=g.contentRect;l>0&&c>0&&a(f=>f.width===l&&f.height===c?f:{width:l,height:c})});return o.observe(r),()=>{o.disconnect()}},[n]),s}function ve(n,s){return Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2))}function me(n,s){return{x:(n.x+s.x)/2,y:(n.y+s.y)/2}}function Re(n,s){const a=t.useRef(null),r=t.useRef(null),h=t.useRef(1);t.useEffect(()=>{const u=n.current;if(!u||!s.enabled)return;const o=u.container(),w=c=>{if(c.touches.length===2){c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},p={x:c.touches[1].clientX,y:c.touches[1].clientY};a.current=ve(f,p),r.current=me(f,p),h.current=s.currentScale}},g=c=>{if(c.touches.length!==2)return;c.preventDefault();const f={x:c.touches[0].clientX,y:c.touches[0].clientY},p={x:c.touches[1].clientX,y:c.touches[1].clientY},b=ve(f,p),v=me(f,p);if(a.current!==null&&r.current!==null){const R=b/a.current,E=Math.min(Math.max(s.currentScale*R,s.minScale),s.maxScale),F=o.getBoundingClientRect(),M=v.x-F.left,j=v.y-F.top,z=s.currentScale,L={x:(M-s.currentPosition.x)/z,y:(j-s.currentPosition.y)/z},D=v.x-r.current.x,N=v.y-r.current.y,Q={x:M-L.x*E+D,y:j-L.y*E+N};s.onScaleChange(E,Q),a.current=b,r.current=v}},l=c=>{c.touches.length<2&&(a.current=null,r.current=null)};return o.addEventListener("touchstart",w,{passive:!1}),o.addEventListener("touchmove",g,{passive:!1}),o.addEventListener("touchend",l),()=>{o.removeEventListener("touchstart",w),o.removeEventListener("touchmove",g),o.removeEventListener("touchend",l)}},[n,s])}const je={canvasBackground:"#1a1a1a",stageColor:"#808080",seatAvailable:"#2C2B30",seatReserved:"#FCEA00",seatSelected:"#3A7DE5",seatUnavailable:"#6b7280",seatHidden:"#4a4a4a",gridLines:"#404040",currency:"KD"},Me=t.memo(({seat:n,state:s,colors:a,onClick:r,onMouseEnter:h,onMouseLeave:u})=>{const g={available:a.seatAvailable,reserved:a.seatReserved,selected:a.seatSelected,unavailable:a.seatUnavailable,hidden:a.seatHidden}[s],l=s==="available"||s==="selected",c=t.useCallback(()=>{l&&r(n)},[n,r,l]),f=t.useCallback(v=>{h(n,v);const R=v.target.getStage();R&&l&&(R.container().style.cursor="pointer")},[n,h,l]),p=t.useCallback(v=>{u();const R=v.target.getStage();R&&(R.container().style.cursor="grab")},[u]),b={x:n.position.x,y:n.position.y,fill:g,stroke:"#ffffff",strokeWidth:1,onClick:c,onTap:c,onMouseEnter:f,onMouseLeave:p};return n.shape==="circle"?i.jsx(X.Circle,{...b,radius:12}):i.jsx(X.Rect,{...b,width:24,height:24,offsetX:12,offsetY:12,cornerRadius:n.shape==="square"?0:4})});Me.displayName="ViewerSeat";const Ee=t.memo(({stage:n,stageColor:s})=>{const a=u=>({stage:"🎭",table:"⬜",wall:"▬",barrier:"🛡️","dj-booth":"🎵",bar:"🍷","entry-exit":"🚪",custom:"➕"})[u||"stage"]||"🎭",r=n.config.color||s,h=a(n.config.objectType);return i.jsxs(X.Group,{x:n.position.x,y:n.position.y,rotation:n.config.rotation||0,children:[i.jsx(X.Rect,{width:n.config.width,height:n.config.height,fill:r+"80",stroke:"#ffffff",strokeWidth:2,cornerRadius:10}),i.jsx(X.Text,{text:h,x:0,y:0,width:n.config.width,height:n.config.height*.4,fontSize:32,fill:"#ffffff",align:"center",verticalAlign:"middle"}),i.jsx(X.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"})]})});Ee.displayName="ViewerStage";const Fe=t.memo(({floors:n,currentFloorId:s,onFloorChange:a,showAllOption:r,allLabel:h,position:u,className:o})=>{const w=t.useMemo(()=>[...n].sort((p,b)=>p.order-b.order),[n]),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}}[u]},c={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"},f={...c,backgroundColor:"#3A7DE5",borderColor:"#3A7DE5"};return i.jsxs("div",{className:o,style:l,children:[r&&i.jsx("button",{type:"button",onClick:()=>a(null),style:s===null?f:c,children:h}),w.map(p=>i.jsx("button",{type:"button",onClick:()=>a(p.id),style:s===p.id?f:c,children:p.name},p.id))]})});Fe.displayName="FloorSelectorBar";const ke=t.memo(({scale:n,minScale:s,maxScale:a,onZoomIn:r,onZoomOut:h,position:u,className:o})=>{const g={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}}[u]},l={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"},c={...l,opacity:.4,cursor:"not-allowed"},f=n<a,p=n>s;return i.jsxs("div",{className:o,style:g,children:[i.jsx("button",{type:"button",onClick:r,disabled:!f,style:f?l:c,title:"Zoom In",children:"+"}),i.jsx("button",{type:"button",onClick:h,disabled:!p,style:p?l:c,title:"Zoom Out",children:"−"})]})});ke.displayName="ZoomControls";const Ie=t.memo(({visible:n,x:s,y:a,seat:r,currency:h,state:u})=>{if(!n||!r)return null;const o=r.seatNumber||(r.rowLabel&&r.columnLabel?`${r.rowLabel}-${r.columnLabel}`:"N/A"),w={position:"fixed",left:`${s+15}px`,top:`${a+15}px`,zIndex:1e3,pointerEvents:"none"},g={backgroundColor:"rgba(26, 26, 26, 0.95)",color:"#fff",border:"1px solid #444",borderRadius:"8px",padding:"8px 12px",fontSize:"13px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",minWidth:"140px"},l={color:"#9ca3af",marginRight:"4px"},c={fontWeight:600},f={color:"#4ade80",fontWeight:600},p={fontSize:"11px",color:"#6b7280",textTransform:"capitalize",marginTop:"4px"};return i.jsx("div",{style:w,children:i.jsxs("div",{style:g,children:[r.sectionName&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Section:"}),i.jsx("span",{style:{...c,color:"#3b82f6"},children:r.sectionName})]}),i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Seat:"}),i.jsx("span",{style:c,children:o})]}),r.price!==void 0&&r.price>0&&u==="available"&&i.jsxs("div",{style:{marginBottom:"4px"},children:[i.jsx("span",{style:l,children:"Price:"}),i.jsxs("span",{style:f,children:[h," ",r.price.toFixed(2)]})]}),i.jsxs("div",{style:p,children:["Status: ",u]})]})})});Ie.displayName="SeatTooltip";const it=({config:n,configUrl:s,floorId:a,onFloorChange:r,reservedSeats:h=[],unavailableSeats:u=[],selectedSeats:o,myReservedSeats:w=[],onSeatSelect:g,onSeatDeselect:l,onSelectionChange:c,colorOverrides:f,showTooltip:p=!0,zoomEnabled:b=!0,className:v="",onConfigLoad:R,onError:E,showFloorSelector:F,floorSelectorPosition:M="top-left",floorSelectorClassName:j,showAllFloorsOption:z=!0,allFloorsLabel:L="All",fitToView:D=!0,fitPadding:N=40,showZoomControls:Q=!0,zoomControlsPosition:De="bottom-right",zoomControlsClassName:ze,minZoom:be,maxZoom:Y=3,zoomStep:ee=.25,touchEnabled:Ne=!0})=>{const le=t.useRef(null),xe=t.useRef(null),k=Ce(xe),[U,Se]=t.useState(new Set),[I,H]=t.useState(1),[T,B]=t.useState({x:0,y:0}),[Ae,Xe]=t.useState(null),[Ye,Pe]=t.useState(1),te=t.useRef({width:0,height:0}),[q,ye]=t.useState({visible:!1,x:0,y:0,seat:null,state:"available"}),{config:We,loading:Be,error:_}=we(s),x=n||We,ue=a!==void 0,A=ue?a||null:Ae,ne=o!==void 0,$e=t.useCallback(e=>{ue||Xe(e),r?.(e)},[ue,r]),de=x?.floors||[],Ue=F!==void 0?F:de.length>1,se=t.useMemo(()=>x?{...x.colors,...f}:{...je,...f},[x,f]),O=t.useMemo(()=>{if(!x)return[];let e=x.seats.filter(d=>d.state!=="hidden");return A&&(e=e.filter(d=>d.floorId===A||!d.floorId&&A==="floor_default")),e},[x,A]),re=t.useMemo(()=>x?.stages?A?x.stages.filter(e=>e.floorId===A||!e.floorId&&A==="floor_default"):x.stages:[],[x,A]),P=t.useMemo(()=>{if(!x||O.length===0&&re.length===0)return null;const e=12;let d=1/0,S=1/0,y=-1/0,m=-1/0;return O.forEach(C=>{d=Math.min(d,C.position.x-e),S=Math.min(S,C.position.y-e),y=Math.max(y,C.position.x+e),m=Math.max(m,C.position.y+e)}),re.forEach(C=>{d=Math.min(d,C.position.x),S=Math.min(S,C.position.y),y=Math.max(y,C.position.x+(C.config?.width||200)),m=Math.max(m,C.position.y+(C.config?.height||100))}),{minX:d,minY:S,maxX:y,maxY:m,width:y-d,height:m-S}},[x,O,re]);t.useEffect(()=>{if(!D||!x||!P||k.width===0||k.height===0)return;const e=Math.abs(k.width-te.current.width),d=Math.abs(k.height-te.current.height);if(!(te.current.width===0)&&e<10&&d<10)return;te.current=k;const y=k.width,m=k.height,C=y-N*2,Z=m-N*2,oe=C/P.width,fe=Z/P.height,ie=Math.min(oe,fe,Y),Qe=P.minX+P.width/2,et=P.minY+P.height/2,tt=y/2,nt=m/2,st=tt-Qe*ie,rt=nt-et*ie;H(ie),B({x:st,y:rt}),Pe(ie)},[D,x,P,N,Y,k,A]);const $=t.useMemo(()=>{const e=new Set(h),d=new Set(u),S=new Set(w);return{reserved:e,unavailable:d,myReserved:S}},[h,u,w]),he=t.useMemo(()=>o?new Set(o):null,[o]),G=t.useCallback(e=>{const d=e.id,S=e.seatNumber||"";return $.unavailable.has(d)||$.unavailable.has(S)?"unavailable":$.reserved.has(d)||$.reserved.has(S)?"reserved":$.myReserved.has(d)||$.myReserved.has(S)||U.has(d)?"selected":e.state},[$,U]);t.useEffect(()=>{x&&R&&R(x)},[x,R]),t.useEffect(()=>{_&&E&&E(_)},[_,E]),t.useEffect(()=>{ne&&he&&Se(he)},[ne,he]);const Oe=t.useCallback(e=>{const d=G(e);if(d!=="available"&&d!=="selected")return;const S=U.has(e.id);ne||Se(y=>{const m=new Set(y);return S?m.delete(e.id):m.add(e.id),m}),S?l?.(e):(g?.(e),g||console.log("Seat selected:",e))},[G,U,ne,g,l]),K=t.useMemo(()=>x?O.filter(e=>U.has(e.id)):[],[O,U]);t.useEffect(()=>{c?.(K)},[K,c]);const V=be!==void 0?be:Ye,Ve=t.useCallback(()=>{if(!b)return;const e=Math.min(I+ee,Y);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,y=d/2,m=S/2,C={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-C.x*e,y:m-C.y*e})}},[b,I,ee,Y,k,x,T]),He=t.useCallback(()=>{if(!b)return;const e=Math.max(I-ee,V);if(e!==I){const d=k.width||x?.canvas.width||800,S=k.height||x?.canvas.height||600,y=d/2,m=S/2,C={x:(y-T.x)/I,y:(m-T.y)/I};H(e),B({x:y-C.x*e,y:m-C.y*e})}},[b,I,ee,V,k,x,T]),qe=t.useCallback(e=>{B({x:e.target.x(),y:e.target.y()})},[]),_e=t.useCallback(e=>{if(!b)return;e.evt.preventDefault();const d=le.current;if(!d)return;const S=d.scaleX(),y=d.getPointerPosition();if(!y)return;const m=1.1,C=e.evt.deltaY>0?S/m:S*m,Z=Math.min(Math.max(C,V),Y),oe={x:(y.x-T.x)/S,y:(y.y-T.y)/S},fe={x:y.x-oe.x*Z,y:y.y-oe.y*Z};H(Z),B(fe)},[b,T,V,Y]);Re(le,{enabled:Ne&&b,minScale:V,maxScale:Y,currentScale:I,currentPosition:T,onScaleChange:(e,d)=>{H(e),B(d)},onPositionChange:e=>{B(e)}});const Ge=t.useCallback((e,d)=>{if(!p)return;const S=d.target.getStage();if(!S)return;const y=S.getPointerPosition();if(!y)return;const m=S.container().getBoundingClientRect();ye({visible:!0,x:m.left+y.x,y:m.top+y.y,seat:e,state:G(e)})},[p,G]),Ke=t.useCallback(()=>{ye(e=>({...e,visible:!1}))},[]);if(Be)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsx("p",{children:"Loading seat map..."})});if(_)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsxs("p",{className:"text-red-500",children:["Error loading seat map: ",_.message]})});if(!x)return i.jsx("div",{className:`flex items-center justify-center h-full ${v}`,children:i.jsx("p",{children:"No configuration provided"})});const Ze=k.width||x.canvas.width,Je=k.height||x.canvas.height;return i.jsxs("div",{ref:xe,className:`relative ${v}`,style:{width:"100%",height:"100%"},children:[Ue&&de.length>0&&i.jsx(Fe,{floors:de,currentFloorId:A,onFloorChange:$e,showAllOption:z,allLabel:L,position:M,className:j}),i.jsxs(X.Stage,{ref:le,width:Ze,height:Je,scaleX:I,scaleY:I,x:T.x,y:T.y,draggable:!0,onDragEnd:qe,onWheel:_e,style:{backgroundColor:x.canvas.backgroundColor,cursor:"grab"},children:[i.jsx(X.Layer,{listening:!1,children:re.map(e=>i.jsx(Ee,{stage:e,stageColor:se.stageColor},e.id))}),i.jsx(X.Layer,{children:O.map(e=>i.jsx(Me,{seat:e,state:G(e),colors:se,onClick:Oe,onMouseEnter:Ge,onMouseLeave:Ke},e.id))})]}),p&&i.jsx(Ie,{visible:q.visible,x:q.x,y:q.y,seat:q.seat,currency:se.currency,state:q.state}),Q&&b&&i.jsx(ke,{scale:I,minScale:V,maxScale:Y,onZoomIn:Ve,onZoomOut:He,position:De,className:ze}),K.length>0&&i.jsxs("div",{className:"absolute top-4 right-4 bg-white dark:bg-gray-800 p-4 rounded shadow-lg",children:[i.jsxs("h3",{className:"font-semibold mb-2",children:["Selected Seats (",K.length,")"]}),i.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:K.map(e=>i.jsxs("div",{className:"text-sm",children:[e.seatNumber,e.price&&` - ${se.currency} ${e.price.toFixed(2)}`]},e.id))})]})]})};let J=null;function at(n){J=n}function pe(){if(!J)throw new Error("Firebase database not initialized. Call initializeFirebaseForViewer(db) first.");return J}function ce(){return J!==null}function ct(){J=null}function ge(n,s){if(n.length!==s.length)return!1;const a=[...n].sort(),r=[...s].sort();return a.every((h,u)=>h===r[u])}function lt(n,s){const a=[],r=[],h=[];return Object.entries(n).forEach(([u,o])=>{o&&typeof o=="object"&&o.state&&(o.state==="unavailable"?h.push(u):o.state==="reserved"&&(s&&o.userId===s?a.push(u):r.push(u)))}),{myReserved:a.sort(),otherReserved:r.sort(),unavailable:h.sort()}}const ae={states:null,loading:!0,error:null,lastUpdated:null,myReservedSeats:[],otherReservedSeats:[],unavailableSeats:[]};function Le(n){const{seatMapId:s,currentUserId:a,enabled:r=!0,onStateChange:h,onError:u}=n,o=t.useRef({...ae}),w=t.useRef(h),g=t.useRef(u),l=t.useRef(a);w.current=h,g.current=u,l.current=a;const c=t.useCallback(v=>{if(!r||!s)return(o.current.loading!==!1||o.current.states!==null)&&(o.current={...ae,loading:!1},v()),()=>{};if(!ce()){const j="Firebase not initialized. Call initializeFirebaseForViewer first.";return o.current.error?.message!==j&&(o.current={...ae,loading:!1,error:new Error(j)},v()),()=>{}}const R=pe(),E=W.ref(R,`seatmaps/${s}/seat_states`),F=j=>{const L=j.val()||{},D=lt(L,l.current),N=o.current;(N.loading||!ge(N.myReservedSeats,D.myReserved)||!ge(N.otherReservedSeats,D.otherReserved)||!ge(N.unavailableSeats,D.unavailable))&&(o.current={states:L,loading:!1,error:null,lastUpdated:Date.now(),myReservedSeats:D.myReserved,otherReservedSeats:D.otherReserved,unavailableSeats:D.unavailable},w.current?.(L),v())},M=j=>{o.current={...o.current,loading:!1,error:j},g.current?.(j),v()};return W.onValue(E,F,M),()=>{W.off(E)}},[s,r]),f=t.useCallback(()=>o.current,[]),p=t.useCallback(()=>ae,[]),b=t.useSyncExternalStore(c,f,p);return{states:b.states,loading:b.loading,error:b.error,lastUpdated:b.lastUpdated,myReservedSeats:b.myReservedSeats,otherReservedSeats:b.otherReservedSeats,unavailableSeats:b.unavailableSeats,reservedSeats:b.otherReservedSeats}}function Te(n){const{seatMapId:s,enabled:a=!0,subscribeToChanges:r=!1,onConfigLoad:h,onError:u}=n,[o,w]=t.useState(null),[g,l]=t.useState(!0),[c,f]=t.useState(null),p=t.useRef(h),b=t.useRef(u);p.current=h,b.current=u;const v=t.useCallback(async()=>{if(!s)return;if(!ce()){f(new Error("Firebase not initialized. Call initializeFirebaseForViewer first.")),l(!1);return}const R=pe(),E=W.ref(R,`seatmaps/${s}`);try{l(!0),f(null);const M=(await W.get(E)).val();if(M){const j=ot.fromFirebaseSeatMap(M);w(j),p.current?.(j)}else f(new Error(`Seat map ${s} not found in Firebase`))}catch(F){const M=F instanceof Error?F:new Error("Unknown error");f(M),b.current?.(M)}finally{l(!1)}},[s]);return t.useEffect(()=>{if(!a||!s){l(!1);return}if(v(),r&&ce()){const R=pe(),E=W.ref(R,`seatmaps/${s}/meta/updated_at`);let F=!0,M=null;const j=z=>{if(F){F=!1,M=z.val();return}const L=z.val();z.exists()&&L!==M&&(M=L,v())};return W.onValue(E,j),()=>{W.off(E)}}},[s,a,r]),{config:o,loading:g,error:c,refetch:v}}function ut(n){const{seatMapId:s,userId:a,enabled:r=!0,subscribeToDesignChanges:h=!1,onConfigLoad:u,onStateChange:o,onError:w}=n,{config:g,loading:l,error:c,refetch:f}=Te({seatMapId:s,enabled:r,subscribeToChanges:h,onConfigLoad:u,onError:w}),{states:p,loading:b,error:v,lastUpdated:R,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:M,reservedSeats:j}=Le({seatMapId:s,currentUserId:a,enabled:r,onStateChange:o,onError:w});return{config:g,loading:l||b,error:c||v,myReservedSeats:E,otherReservedSeats:F,unavailableSeats:M,reservedSeats:j,seatStates:p,lastUpdated:R,refetch:f}}exports.DEFAULT_COLORS=je;exports.SeatMapViewer=it;exports.clearFirebaseInstance=ct;exports.initializeFirebaseForViewer=at;exports.isFirebaseInitialized=ce;exports.useConfigFetcher=we;exports.useContainerSize=Ce;exports.useFirebaseConfig=Te;exports.useFirebaseSeatStates=Le;exports.useRealtimeSeatMap=ut;exports.useTouchGestures=Re;
|
package/dist/index.mjs
CHANGED
|
@@ -766,8 +766,8 @@ function St(t) {
|
|
|
766
766
|
Ne(M);
|
|
767
767
|
};
|
|
768
768
|
},
|
|
769
|
-
[n, r
|
|
770
|
-
//
|
|
769
|
+
[n, r]
|
|
770
|
+
// Don't include currentUserId - we use currentUserIdRef.current which is always up-to-date
|
|
771
771
|
), u = F(() => o.current, []), f = F(() => ue, []), g = lt(s, u, f);
|
|
772
772
|
return {
|
|
773
773
|
states: g.states,
|