@zonetrix/viewer 1.0.0 → 1.1.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.
Files changed (2) hide show
  1. package/README.md +364 -78
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,15 +1,22 @@
1
1
  # @zonetrix/viewer
2
2
 
3
- Lightweight React component for rendering interactive seat maps. Perfect for booking systems, event ticketing, and venue management.
3
+ Lightweight React component for rendering interactive seat maps in your booking applications, event ticketing systems, and venue management platforms.
4
+
5
+ ## Overview
6
+
7
+ `@zonetrix/viewer` is a production-ready React component that renders beautiful, interactive seat maps with support for selection, zooming, and real-time state updates. Perfect for theaters, stadiums, cinemas, and event venues.
4
8
 
5
9
  ## Features
6
10
 
7
- - 🎯 **Read-only rendering** - Display seat maps without editing capabilities
8
- - 🔄 **Interactive selection** - Click seats to select/deselect
9
- - 🌐 **API integration** - Load configs from JSON file or API endpoint
10
- - 🎨 **Customizable** - Override colors and styles
11
- - 📱 **Responsive** - Works on all screen sizes
12
- - **Lightweight** - Minimal dependencies, small bundle size
11
+ - 🎯 **Read-only Display** - Optimized for end-user viewing and selection
12
+ - 🖱️ **Interactive Selection** - Click seats to select/deselect with visual feedback
13
+ - 🔄 **Real-time Updates** - Support for dynamic seat state changes
14
+ - 🌐 **Flexible Config Loading** - Load from JSON files or API endpoints
15
+ - 🔍 **Mouse Wheel Zoom** - Smooth zoom with configurable limits
16
+ - 🎨 **Customizable Colors** - Override default colors to match your brand
17
+ - 📱 **Responsive** - Works seamlessly across all screen sizes
18
+ - ⚡ **Lightweight** - Minimal dependencies (~95KB gzipped)
19
+ - 🔒 **Type-safe** - Full TypeScript support
13
20
 
14
21
  ## Installation
15
22
 
@@ -21,18 +28,24 @@ yarn add @zonetrix/viewer
21
28
  pnpm add @zonetrix/viewer
22
29
  ```
23
30
 
24
- ## Usage
31
+ ### Peer Dependencies
32
+
33
+ ```bash
34
+ npm install react react-dom
35
+ ```
36
+
37
+ ## Quick Start
25
38
 
26
- ### Basic Example (with JSON file)
39
+ ### Basic Usage with JSON Config
27
40
 
28
41
  ```tsx
29
42
  import { SeatMapViewer } from '@zonetrix/viewer';
30
- import config from './my-venue-config.json';
43
+ import venueConfig from './venue-config.json';
31
44
 
32
- function App() {
45
+ function BookingApp() {
33
46
  return (
34
47
  <SeatMapViewer
35
- config={config}
48
+ config={venueConfig}
36
49
  onSeatSelect={(seat) => console.log('Selected:', seat)}
37
50
  onSeatDeselect={(seat) => console.log('Deselected:', seat)}
38
51
  />
@@ -40,90 +53,237 @@ function App() {
40
53
  }
41
54
  ```
42
55
 
43
- ### With API URL
56
+ ### Load Config from API
57
+
58
+ ```tsx
59
+ import { SeatMapViewer } from '@zonetrix/viewer';
60
+
61
+ function BookingApp() {
62
+ return (
63
+ <SeatMapViewer
64
+ configUrl="https://api.example.com/venues/123/config"
65
+ onSeatSelect={(seat) => addToCart(seat)}
66
+ onSeatDeselect={(seat) => removeFromCart(seat)}
67
+ />
68
+ );
69
+ }
70
+ ```
71
+
72
+ ## Props API
73
+
74
+ ### SeatMapViewerProps
75
+
76
+ | Prop | Type | Required | Description |
77
+ |------|------|----------|-------------|
78
+ | `config` | `SeatMapConfig` | No* | Seat map configuration object |
79
+ | `configUrl` | `string` | No* | URL to fetch configuration from |
80
+ | `reservedSeats` | `string[]` | No | Array of seat IDs/numbers to mark as reserved |
81
+ | `unavailableSeats` | `string[]` | No | Array of seat IDs/numbers to mark as unavailable |
82
+ | `onSeatSelect` | `(seat: SeatData) => void` | No | Callback when a seat is selected |
83
+ | `onSeatDeselect` | `(seat: SeatData) => void` | No | Callback when a seat is deselected |
84
+ | `onSelectionChange` | `(seats: SeatData[]) => void` | No | Callback when selection changes |
85
+ | `colorOverrides` | `Partial<ColorSettings>` | No | Custom colors for seat states |
86
+ | `zoomEnabled` | `boolean` | No | Enable/disable mouse wheel zoom (default: true) |
87
+ | `showSelectedCount` | `boolean` | No | Show selected seats counter (default: true) |
88
+
89
+ *Note: Either `config` or `configUrl` must be provided.
90
+
91
+ ## Usage Examples
92
+
93
+ ### 1. Booking System with Cart
94
+
95
+ ```tsx
96
+ import { useState } from 'react';
97
+ import { SeatMapViewer } from '@zonetrix/viewer';
98
+ import type { SeatData } from '@zonetrix/viewer';
99
+
100
+ function TheaterBooking() {
101
+ const [cart, setCart] = useState<SeatData[]>([]);
102
+
103
+ const handleSeatSelect = (seat: SeatData) => {
104
+ setCart((prev) => [...prev, seat]);
105
+ };
106
+
107
+ const handleSeatDeselect = (seat: SeatData) => {
108
+ setCart((prev) => prev.filter((s) => s.seatNumber !== seat.seatNumber));
109
+ };
110
+
111
+ const totalPrice = cart.reduce((sum, seat) => sum + (seat.price || 0), 0);
112
+
113
+ return (
114
+ <div>
115
+ <SeatMapViewer
116
+ configUrl="https://api.theater.com/venues/main-hall/config"
117
+ reservedSeats={['A-1', 'A-2', 'B-5']}
118
+ onSeatSelect={handleSeatSelect}
119
+ onSeatDeselect={handleSeatDeselect}
120
+ />
121
+
122
+ <div className="cart">
123
+ <h3>Your Selection</h3>
124
+ <p>Seats: {cart.map(s => s.seatNumber).join(', ')}</p>
125
+ <p>Total: ${totalPrice.toFixed(2)}</p>
126
+ <button onClick={() => checkout(cart)}>Proceed to Checkout</button>
127
+ </div>
128
+ </div>
129
+ );
130
+ }
131
+ ```
132
+
133
+ ### 2. Custom Colors (Brand Matching)
44
134
 
45
135
  ```tsx
46
136
  import { SeatMapViewer } from '@zonetrix/viewer';
47
137
 
48
- function App() {
138
+ function BrandedVenue() {
139
+ const customColors = {
140
+ seatAvailable: '#10b981', // Green
141
+ seatReserved: '#ef4444', // Red
142
+ seatSelected: '#3b82f6', // Blue
143
+ canvasBackground: '#ffffff', // White
144
+ };
145
+
49
146
  return (
50
147
  <SeatMapViewer
51
- configUrl="https://api.example.com/venue/123/config"
148
+ config={venueConfig}
149
+ colorOverrides={customColors}
52
150
  onSeatSelect={(seat) => console.log('Selected:', seat)}
53
151
  />
54
152
  );
55
153
  }
56
154
  ```
57
155
 
58
- ### With Seat State Overrides
156
+ ### 3. Real-time Updates from API
59
157
 
60
158
  ```tsx
61
- import { SeatMapViewer } from '@seat-map-studio/viewer';
159
+ import { useState, useEffect } from 'react';
160
+ import { SeatMapViewer } from '@zonetrix/viewer';
161
+
162
+ function LiveEventSeating() {
163
+ const [reservedSeats, setReservedSeats] = useState<string[]>([]);
164
+
165
+ // Poll API every 5 seconds for reserved seats
166
+ useEffect(() => {
167
+ const interval = setInterval(async () => {
168
+ const response = await fetch('/api/venue/123/reserved-seats');
169
+ const data = await response.json();
170
+ setReservedSeats(data.reserved);
171
+ }, 5000);
62
172
 
63
- function App() {
64
- const [reservedSeats, setReservedSeats] = useState(['A-1', 'A-2', 'B-5']);
65
- const [unavailableSeats] = useState(['C-1']);
173
+ return () => clearInterval(interval);
174
+ }, []);
66
175
 
67
176
  return (
68
177
  <SeatMapViewer
69
- config={config}
178
+ config={venueConfig}
70
179
  reservedSeats={reservedSeats}
71
- unavailableSeats={unavailableSeats}
72
- onSeatSelect={(seat) => {
73
- // Handle seat selection
74
- }}
180
+ onSeatSelect={(seat) => bookSeat(seat)}
75
181
  />
76
182
  );
77
183
  }
78
184
  ```
79
185
 
80
- ### Custom Colors
186
+ ### 4. Tracking Selection Changes
81
187
 
82
188
  ```tsx
83
- import { SeatMapViewer } from '@seat-map-studio/viewer';
189
+ import { SeatMapViewer } from '@zonetrix/viewer';
190
+
191
+ function SelectionTracker() {
192
+ const handleSelectionChange = (selectedSeats) => {
193
+ console.log('Current selection:', selectedSeats);
194
+
195
+ // Update analytics
196
+ analytics.track('Seats Selected', {
197
+ count: selectedSeats.length,
198
+ seats: selectedSeats.map(s => s.seatNumber),
199
+ });
200
+ };
84
201
 
85
- function App() {
86
202
  return (
87
203
  <SeatMapViewer
88
- config={config}
89
- colorOverrides={{
90
- seatAvailable: '#00ff00',
91
- seatSelected: '#0000ff',
92
- seatReserved: '#ffff00',
93
- seatUnavailable: '#ff0000',
94
- }}
204
+ config={venueConfig}
205
+ onSelectionChange={handleSelectionChange}
95
206
  />
96
207
  );
97
208
  }
98
209
  ```
99
210
 
100
- ## API Reference
211
+ ### 5. Disable Zoom for Mobile
101
212
 
102
- ### Props
213
+ ```tsx
214
+ import { SeatMapViewer } from '@zonetrix/viewer';
103
215
 
104
- | Prop | Type | Default | Description |
105
- |------|------|---------|-------------|
106
- | `config` | `SeatMapConfig` | - | Seat map configuration object |
107
- | `configUrl` | `string` | - | URL to fetch configuration from |
108
- | `reservedSeats` | `string[]` | `[]` | Array of seat IDs/numbers to mark as reserved |
109
- | `unavailableSeats` | `string[]` | `[]` | Array of seat IDs/numbers to mark as unavailable |
110
- | `onSeatSelect` | `(seat: SeatData) => void` | - | Called when a seat is selected |
111
- | `onSeatDeselect` | `(seat: SeatData) => void` | - | Called when a seat is deselected |
112
- | `onSelectionChange` | `(seats: SeatData[]) => void` | - | Called when selection changes |
113
- | `colorOverrides` | `Partial<ColorSettings>` | - | Custom color overrides |
114
- | `showTooltip` | `boolean` | `true` | Show tooltip on hover |
115
- | `zoomEnabled` | `boolean` | `true` | Enable mouse wheel zoom |
116
- | `className` | `string` | `''` | Additional CSS classes |
117
- | `onConfigLoad` | `(config: SeatMapConfig) => void` | - | Called when config is loaded |
118
- | `onError` | `(error: Error) => void` | - | Called on error |
216
+ function MobileOptimized() {
217
+ const isMobile = window.innerWidth < 768;
218
+
219
+ return (
220
+ <SeatMapViewer
221
+ config={venueConfig}
222
+ zoomEnabled={!isMobile}
223
+ onSeatSelect={(seat) => handleSelection(seat)}
224
+ />
225
+ );
226
+ }
227
+ ```
228
+
229
+ ## Configuration Format
230
+
231
+ The viewer accepts a `SeatMapConfig` object. You can create these configurations using our creator studio or build them programmatically.
232
+
233
+ ### Example Configuration
234
+
235
+ ```json
236
+ {
237
+ "version": "1.0.0",
238
+ "metadata": {
239
+ "name": "Main Auditorium",
240
+ "venue": "Grand Theater",
241
+ "capacity": 500,
242
+ "createdAt": "2025-01-01T00:00:00Z",
243
+ "updatedAt": "2025-01-01T00:00:00Z"
244
+ },
245
+ "canvas": {
246
+ "width": 1200,
247
+ "height": 800,
248
+ "backgroundColor": "#1a1a1a"
249
+ },
250
+ "colors": {
251
+ "canvasBackground": "#1a1a1a",
252
+ "stageColor": "#808080",
253
+ "seatAvailable": "#2C2B30",
254
+ "seatReserved": "#FCEA00",
255
+ "seatSelected": "#3A7DE5",
256
+ "seatUnavailable": "#6b7280",
257
+ "gridLines": "#404040",
258
+ "currency": "USD"
259
+ },
260
+ "seats": [
261
+ {
262
+ "id": "seat_001",
263
+ "position": { "x": 100, "y": 100 },
264
+ "shape": "rounded-square",
265
+ "state": "available",
266
+ "sectionName": "Orchestra",
267
+ "rowLabel": "A",
268
+ "columnLabel": "1",
269
+ "seatNumber": "A-1",
270
+ "price": 50.00
271
+ }
272
+ ],
273
+ "sections": [],
274
+ "stages": []
275
+ }
276
+ ```
119
277
 
120
- ### Types
278
+ ## TypeScript Types
279
+
280
+ ### SeatData
121
281
 
122
- #### SeatData
123
282
  ```typescript
124
283
  interface SeatData {
125
- seatState: 'available' | 'reserved' | 'selected' | 'unavailable';
126
- shape?: 'circle' | 'square' | 'rounded-square';
284
+ id: string;
285
+ state: SeatState;
286
+ shape?: SeatShape;
127
287
  sectionName?: string;
128
288
  rowLabel?: string;
129
289
  columnLabel?: string;
@@ -132,34 +292,160 @@ interface SeatData {
132
292
  }
133
293
  ```
134
294
 
135
- #### SeatMapConfig
295
+ ### SeatState
296
+
136
297
  ```typescript
137
- interface SeatMapConfig {
138
- version: string;
139
- metadata: {
140
- name: string;
141
- description?: string;
142
- createdAt: string;
143
- updatedAt: string;
144
- venue?: string;
145
- capacity?: number;
146
- };
147
- canvas: {
148
- width: number;
149
- height: number;
150
- backgroundColor: string;
151
- };
152
- colors: ColorSettings;
153
- seats: SerializedSeat[];
154
- sections?: SerializedSection[];
155
- stages?: SerializedStage[];
298
+ type SeatState = 'available' | 'reserved' | 'selected' | 'unavailable';
299
+ ```
300
+
301
+ ### SeatShape
302
+
303
+ ```typescript
304
+ type SeatShape = 'circle' | 'square' | 'rounded-square';
305
+ ```
306
+
307
+ ### ColorSettings
308
+
309
+ ```typescript
310
+ interface ColorSettings {
311
+ canvasBackground: string;
312
+ stageColor: string;
313
+ seatAvailable: string;
314
+ seatReserved: string;
315
+ seatSelected: string;
316
+ seatUnavailable: string;
317
+ gridLines: string;
318
+ currency: string;
156
319
  }
157
320
  ```
158
321
 
159
- ## Creating Seat Map Configs
322
+ ## Seat States Explained
160
323
 
161
- Use [@seat-map-studio/creator](../creator) to visually design and export seat map configurations.
324
+ | State | Description | User Can Select? | Visual |
325
+ |-------|-------------|------------------|--------|
326
+ | `available` | Seat is free and can be selected | ✅ Yes | Default color |
327
+ | `reserved` | Seat is booked by another user | ❌ No | Yellow/Warning color |
328
+ | `selected` | Seat is selected by current user | ✅ Yes (to deselect) | Primary/Blue color |
329
+ | `unavailable` | Seat is blocked (maintenance, etc.) | ❌ No | Gray color |
330
+
331
+ ## Events & Callbacks
332
+
333
+ ### onSeatSelect
334
+
335
+ Called when a user selects an available seat.
336
+
337
+ ```typescript
338
+ const handleSelect = (seat: SeatData) => {
339
+ console.log('Seat selected:', seat.seatNumber);
340
+ console.log('Price:', seat.price);
341
+ console.log('Section:', seat.sectionName);
342
+ };
343
+ ```
344
+
345
+ ### onSeatDeselect
346
+
347
+ Called when a user deselects a previously selected seat.
348
+
349
+ ```typescript
350
+ const handleDeselect = (seat: SeatData) => {
351
+ console.log('Seat deselected:', seat.seatNumber);
352
+ };
353
+ ```
354
+
355
+ ### onSelectionChange
356
+
357
+ Called whenever the selection changes (includes all selected seats).
358
+
359
+ ```typescript
360
+ const handleSelectionChange = (selectedSeats: SeatData[]) => {
361
+ console.log('Total selected:', selectedSeats.length);
362
+ const total = selectedSeats.reduce((sum, s) => sum + (s.price || 0), 0);
363
+ console.log('Total price:', total);
364
+ };
365
+ ```
366
+
367
+ ## Styling
368
+
369
+ The component uses inline styles generated from the configuration. To customize the container, wrap it in a styled div:
370
+
371
+ ```tsx
372
+ <div style={{ width: '100%', height: '600px', border: '1px solid #ccc' }}>
373
+ <SeatMapViewer config={venueConfig} />
374
+ </div>
375
+ ```
376
+
377
+ ## Performance Tips
378
+
379
+ 1. **Large Venues** (500+ seats): Consider splitting into sections
380
+ 2. **API Loading**: Show a loading spinner while `configUrl` is being fetched
381
+ 3. **Mobile**: Disable zoom on mobile devices for better UX
382
+ 4. **Memoization**: Wrap callbacks with `useCallback` to prevent unnecessary re-renders
383
+
384
+ ## Browser Support
385
+
386
+ - Chrome (latest)
387
+ - Firefox (latest)
388
+ - Safari (latest)
389
+ - Edge (latest)
390
+
391
+ ## Common Issues
392
+
393
+ ### Configuration not loading from API
394
+
395
+ Ensure your API returns valid JSON and has proper CORS headers:
396
+
397
+ ```javascript
398
+ // Server-side (Express example)
399
+ res.setHeader('Access-Control-Allow-Origin', '*');
400
+ res.json(seatMapConfig);
401
+ ```
402
+
403
+ ### Seats not responding to clicks
404
+
405
+ Make sure seat states are correctly set. Only `available` and `selected` seats can be clicked.
406
+
407
+ ### Canvas size issues
408
+
409
+ The canvas size is determined by the `canvas.width` and `canvas.height` in your configuration. Adjust these values or wrap the component in a responsive container.
410
+
411
+ ## Related Packages
412
+
413
+ - **[@zonetrix/shared](https://www.npmjs.com/package/@zonetrix/shared)** - Shared types and utilities
414
+
415
+ ## Examples Repository
416
+
417
+ Check out our [examples repository](https://github.com/fahadkhan1740/seat-map-studio/tree/main/examples) for more use cases:
418
+
419
+ - Booking system integration
420
+ - API polling for real-time updates
421
+ - Custom theming
422
+ - Mobile-optimized layouts
423
+
424
+ ## Contributing
425
+
426
+ Contributions are welcome! Please read our contributing guidelines before submitting PRs.
162
427
 
163
428
  ## License
164
429
 
165
430
  MIT
431
+
432
+ ## Author
433
+
434
+ Fahad Khan ([@fahadkhan1740](https://github.com/fahadkhan1740))
435
+
436
+ ## Links
437
+
438
+ - [npm Package](https://www.npmjs.com/package/@zonetrix/viewer)
439
+ - [GitHub Repository](https://github.com/fahadkhan1740/seat-map-studio)
440
+ - [Documentation](https://github.com/fahadkhan1740/seat-map-studio#readme)
441
+ - [Issue Tracker](https://github.com/fahadkhan1740/seat-map-studio/issues)
442
+
443
+ ## Support
444
+
445
+ For questions and support:
446
+ - Open an [issue on GitHub](https://github.com/fahadkhan1740/seat-map-studio/issues)
447
+ - Email: fahadkhan1740@outlook.com
448
+
449
+ ---
450
+
451
+ **Made with ❤️ by Fahad Khan**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonetrix/viewer",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Lightweight React component for rendering interactive seat maps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",