@alisaitteke/seatmap-canvas 2.6.1 → 2.7.1

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
@@ -1,19 +1,22 @@
1
1
  # Seatmap Canvas
2
2
  Seatmap Canvas is an advanced, open-source library for interactive seat selection in various settings such as stadiums, theaters, and event spaces. Designed with d3.js, this code version is optimized for developers looking for a customizable and efficient solution to handle seat arrangements and user interactions.
3
3
 
4
- [![LIVE DEMO](assets/banner_ui.png)](https://alisaitteke.github.io/seatmap-canvas)
4
+ [![LIVE DEMO](assets/banner_ui.png)](https://seatmap.io/demo)
5
+
6
+ **[📖 Documentation](https://seatmap.io)** | **[🎯 Live Demo](https://seatmap.io/demo)**
5
7
 
6
8
  ## Features
7
9
 
8
10
  - **Framework Agnostic** - Core library works with vanilla JS, plus official React and Vue 3 wrappers
9
11
  - **Dynamic Seat Selection** - Interactive selection, categorization, and location of seats
12
+ - **Custom Background Images** - Global and per-block background images with positioning control
10
13
  - **Customizable Styles** - Extensive styling options for seats, blocks, and labels
11
14
  - **Interactive Seat Models** - Define properties like salability, notes, colors, and custom data
12
15
  - **Block Organization** - Organize seats into blocks with titles, colors, and labels
13
16
  - **Event System** - Simplified event listeners for seat interactions
14
17
 
15
18
  ## Screenshot
16
- [![LIVE DEMO](assets/screenshot_1.png)](https://alisaitteke.github.io/seatmap-canvas)
19
+ [![LIVE DEMO](assets/screenshot_1.png)](https://seatmap.io/demo)
17
20
 
18
21
  ## 🚀 Framework Plugins & Integrations
19
22
 
@@ -28,7 +31,9 @@ Seatmap Canvas is an advanced, open-source library for interactive seat selectio
28
31
  <img src="https://img.shields.io/badge/React-⚠️_Testing-orange?style=for-the-badge&logo=react&logoColor=white" alt="React"/>
29
32
  </a>
30
33
  &nbsp;&nbsp;
31
- <img src="https://img.shields.io/badge/Next.js-Coming_Soon-000000?style=for-the-badge&logo=next.js&logoColor=white&color=gray" alt="Next.js"/>
34
+ <a href="src/nextjs/README.md">
35
+ <img src="https://img.shields.io/badge/Next.js-⚠️_Testing-orange?style=for-the-badge&logo=next.js&logoColor=white" alt="Next.js"/>
36
+ </a>
32
37
  &nbsp;&nbsp;
33
38
  <img src="https://img.shields.io/badge/Svelte-Coming_Soon-FF3E00?style=for-the-badge&logo=svelte&logoColor=white&color=gray" alt="Svelte"/>
34
39
  &nbsp;&nbsp;
@@ -68,7 +73,7 @@ Seatmap Canvas is an advanced, open-source library for interactive seat selectio
68
73
  | **Vanilla JS** | ✅ Available | `@alisaitteke/seatmap-canvas` | [📖 Documentation](#vanilla-javascript) | [🎯 Example](examples/) |
69
74
  | **Vue.js 3** | ⚠️ Testing | `@alisaitteke/seatmap-canvas/vue` | [📖 Documentation](src/vue/README.md) | [🎯 Example](examples/vue/) |
70
75
  | **React** | ⚠️ Testing | `@alisaitteke/seatmap-canvas/react` | [📖 Documentation](src/react/README.md) | [🎯 Example](examples/react/) |
71
- | **Next.js** | 🔜 Coming Soon | - | - | - |
76
+ | **Next.js** | ⚠️ Testing | `@alisaitteke/seatmap-canvas/nextjs` | [📖 Documentation](src/nextjs/README.md) | [🎯 App Router](examples/nextjs-app/) • [Pages Router](examples/nextjs-pages/) |
72
77
  | **Svelte** | 🔜 Coming Soon | - | - | - |
73
78
  | **Angular** | 🔜 Coming Soon | - | - | - |
74
79
  | **Nuxt** | 🔜 Coming Soon | - | - | - |
@@ -94,7 +99,7 @@ Seatmap Canvas is an advanced, open-source library for interactive seat selectio
94
99
 
95
100
  ---
96
101
 
97
- [LIVE DEMO](https://alisaitteke.github.io/seatmap-canvas/)
102
+ [LIVE DEMO](https://seatmap.io/demo)
98
103
 
99
104
 
100
105
 
@@ -181,7 +186,7 @@ const onSeatClick = (seat) => {
181
186
  </table>
182
187
 
183
188
  <p align="center">
184
- <a href="src/vue/README.md"><img src="https://img.shields.io/badge/📖_Full_Documentation-4FC08D?style=for-the-badge&logoColor=white" alt="Documentation"/></a>
189
+ <a href="https://seatmap.io/frameworks/vue"><img src="https://img.shields.io/badge/📖_Full_Documentation-4FC08D?style=for-the-badge&logoColor=white" alt="Documentation"/></a>
185
190
  &nbsp;
186
191
  <a href="examples/vue/"><img src="https://img.shields.io/badge/🎯_Examples-35495E?style=for-the-badge&logoColor=white" alt="Examples"/></a>
187
192
  </p>
@@ -237,13 +242,95 @@ function App() {
237
242
  </table>
238
243
 
239
244
  <p align="center">
240
- <a href="src/react/README.md"><img src="https://img.shields.io/badge/📖_Full_Documentation-61DAFB?style=for-the-badge&logoColor=black" alt="Documentation"/></a>
245
+ <a href="https://seatmap.io/frameworks/react"><img src="https://img.shields.io/badge/📖_Full_Documentation-61DAFB?style=for-the-badge&logoColor=black" alt="Documentation"/></a>
241
246
  &nbsp;
242
247
  <a href="examples/react/"><img src="https://img.shields.io/badge/🎯_Examples-20232A?style=for-the-badge&logoColor=white" alt="Examples"/></a>
243
248
  </p>
244
249
 
245
250
  ---
246
251
 
252
+ <h3>
253
+ <img src="https://api.iconify.design/logos:nextjs-icon.svg" width="24" height="24" alt="Next.js" style="vertical-align: middle;" />
254
+ &nbsp;Next.js
255
+ </h3>
256
+
257
+ <table>
258
+ <tr>
259
+ <td width="50%">
260
+
261
+ **Installation**
262
+
263
+ ```bash
264
+ npm install @alisaitteke/seatmap-canvas next react react-dom
265
+ ```
266
+
267
+ **App Router (Client Component)**
268
+
269
+ ```tsx
270
+ 'use client';
271
+
272
+ import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs';
273
+ import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';
274
+
275
+ export default function VenuePage() {
276
+ const handleSeatClick = (seat) => {
277
+ seat.isSelected() ? seat.unSelect() : seat.select();
278
+ };
279
+
280
+ return (
281
+ <SeatmapCanvas
282
+ data={blocks}
283
+ options={{ legend: true }}
284
+ onSeatClick={handleSeatClick}
285
+ />
286
+ );
287
+ }
288
+ ```
289
+
290
+ </td>
291
+ <td width="50%">
292
+
293
+ **Server Component + Data Fetching**
294
+
295
+ ```tsx
296
+ import { SeatmapServerWrapper } from '@alisaitteke/seatmap-canvas/nextjs/app-router';
297
+ import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';
298
+
299
+ export default async function VenuePage({ params }) {
300
+ return (
301
+ <SeatmapServerWrapper
302
+ dataSource={`/api/venues/${params.id}/seatmap`}
303
+ options={{ legend: true }}
304
+ revalidate={3600}
305
+ />
306
+ );
307
+ }
308
+ ```
309
+
310
+ **Pages Router (Dynamic Import)**
311
+
312
+ ```tsx
313
+ import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs/pages-router';
314
+
315
+ export default function VenuePage({ data }) {
316
+ return <SeatmapCanvas data={data} />;
317
+ }
318
+ ```
319
+
320
+ </td>
321
+ </tr>
322
+ </table>
323
+
324
+ <p align="center">
325
+ <a href="https://seatmap.io/frameworks/nextjs"><img src="https://img.shields.io/badge/📖_Full_Documentation-000000?style=for-the-badge&logoColor=white" alt="Documentation"/></a>
326
+ &nbsp;
327
+ <a href="examples/nextjs-app/"><img src="https://img.shields.io/badge/🎯_App_Router-000000?style=for-the-badge&logoColor=white" alt="App Router"/></a>
328
+ &nbsp;
329
+ <a href="examples/nextjs-pages/"><img src="https://img.shields.io/badge/🎯_Pages_Router-000000?style=for-the-badge&logoColor=white" alt="Pages Router"/></a>
330
+ </p>
331
+
332
+ ---
333
+
247
334
  <h3>
248
335
  <img src="https://api.iconify.design/logos:javascript.svg" width="24" height="24" alt="JavaScript" style="vertical-align: middle;" />
249
336
  &nbsp;Vanilla JavaScript
@@ -330,104 +417,186 @@ const selected = seatmap.getSelectedSeats();
330
417
  #### Configuration Options
331
418
  ```js
332
419
  {
333
- click_enable_sold_seats: true // Enable clicking on unavailable seats (default: false)
420
+ click_enable_sold_seats: true, // Enable clicking on unavailable seats (default: false)
421
+
422
+ // Global Background Image
423
+ background_image: "assets/stadium.jpg", // Image URL (PNG, JPG, SVG, WebP, GIF)
424
+ background_opacity: 0.3, // 0-1 (default: 0.3)
425
+ background_fit: "cover", // "cover" | "contain" | "fill" | "none"
426
+ background_x: 0, // Manual X position (optional, auto-detect if null)
427
+ background_y: 0, // Manual Y position (optional)
428
+ background_width: 1500, // Manual width (optional)
429
+ background_height: 1000 // Manual height (optional)
334
430
  }
335
431
  ```
336
432
 
337
433
  </details>
338
434
 
339
435
  <details>
340
- <summary><strong>📝 Complete Example</strong></summary>
436
+ <summary><strong>🖼️ Custom Background Images</strong></summary>
437
+
438
+ #### Global Background
439
+
440
+ Add a background image to the entire stage:
441
+
341
442
  ```javascript
443
+ const seatmap = new SeatmapCanvas(".container", {
444
+ background_image: "assets/concert-hall.jpg",
445
+ background_opacity: 0.3,
446
+ background_fit: "cover"
447
+ });
448
+ ```
342
449
 
343
- var config = {
344
- "resizable": true,
345
- "seat_style": {
346
- "radius": 12,
347
- "color": "#6796ff",
348
- "hover": "#5671ff",
349
- "not_salable": "#424747",
350
- "selected": "#56aa45",
351
- "focus": "#435fa4",
352
- "focus_out": "#56aa45"
353
- },
354
- "block_style": {
355
- "fill": "#e2e2e2",
356
- "stroke": "#e2e2e2"
357
- },
358
- "label_style": {
359
- "color": "#000",
360
- "radius": 12,
361
- "font-size": "12px",
362
- "bg": "#ffffff"
363
- }
450
+ **With Manual Positioning:**
451
+ ```javascript
452
+ const seatmap = new SeatmapCanvas(".container", {
453
+ background_image: "assets/stadium.jpg",
454
+ background_x: -500, // Position X
455
+ background_y: -500, // Position Y
456
+ background_width: 3000, // Width
457
+ background_height: 2500, // Height
458
+ background_opacity: 0.4,
459
+ background_fit: "contain" // Preserve aspect ratio
460
+ });
461
+ ```
462
+
463
+ #### Block-Level Background
464
+
465
+ Add custom backgrounds to individual blocks:
466
+
467
+ ```javascript
468
+ {
469
+ blocks: [{
470
+ id: "vip-section",
471
+ title: "VIP Area",
472
+ background_image: "assets/vip-lounge.jpg",
473
+ background_opacity: 0.6,
474
+ background_fit: "cover",
475
+ seats: [...]
476
+ }, {
477
+ id: "general",
478
+ title: "General Admission",
479
+ background_image: "assets/general-area.jpg",
480
+ background_opacity: 0.5,
481
+ seats: [...]
482
+ }]
364
483
  }
484
+ ```
365
485
 
366
- var seatmap = new SeatmapCanvas(".seats_container",config);
367
- seatmap.addEventListener("seat_click", (seat) => {
368
- console.log(seat);
369
- if (seat.selected) {
370
- seatmap.seatUnselect(seat);
371
- } else {
372
- seatmap.seatSelect(seat);
373
- }
374
- });
375
- var data = {
376
- "blocks": [
377
- {
378
- "id": 1,
379
- "title": "Test Block 1",
380
- "color": "#2c2828",
381
- "labels": [
382
- {
383
- "title": "A",
384
- "x": -30,
385
- "y": 0
386
- },
387
- {
388
- "title": "B",
389
- "x": 120,
390
- "y": 30
391
- }
392
- ],
393
- "seats": [
394
- {
395
- "id": 1,
396
- "x": 0,
397
- "y": 0,
398
- "salable": true,
399
- "note": "note test",
400
- "title": "49"
401
- },
402
- {
403
- "id": 2,
404
- "x": 30,
405
- "y": 0,
406
- "salable": true,
407
- "note": "note test",
408
- "title": "47"
409
- }
410
- ]
411
- }
412
- ]
486
+ **With Manual Positioning:**
487
+ ```javascript
488
+ {
489
+ blocks: [{
490
+ id: "block-a",
491
+ background_image: "section-a.jpg",
492
+ background_x: 100, // Exact X coordinate
493
+ background_y: 200, // Exact Y coordinate
494
+ background_width: 500, // Exact width
495
+ background_height: 400, // Exact height
496
+ background_opacity: 0.7,
497
+ background_fit: "cover",
498
+ seats: [...]
499
+ }]
413
500
  }
501
+ ```
414
502
 
415
- // SET SEATS DATA
416
- seatmap.setData(data);
503
+ #### Fit Modes
504
+
505
+ - **`cover`** (default) - Image covers entire area, may crop
506
+ - **`contain`** - Image fits inside area, preserves aspect ratio
507
+ - **`fill`** - Image stretches to fill area
508
+ - **`none`** - Image keeps original size, centered
509
+
510
+ #### Features
511
+
512
+ - ✅ **Auto-Detection:** X, Y, Width, Height auto-calculated from bounds if not specified
513
+ - ✅ **Clip-Path Masking:** Block backgrounds clipped to exact block shape
514
+ - ✅ **Opacity Control:** Adjustable transparency (0-1)
515
+ - ✅ **Auto-Hide Bounds:** Block borders/fills hidden when background exists
516
+ - ✅ **Zoom Preserved:** Bounds calculations still work for zoom levels
517
+ - ✅ **Format Support:** PNG, JPG, SVG, WebP, GIF, all web-compatible formats
518
+ - ✅ **Performance:** Browser-native image loading and caching
519
+
520
+ #### Use Cases
521
+
522
+ **Stadium/Arena:**
523
+ ```javascript
524
+ // Stadium overview as background
525
+ background_image: "stadium-aerial.jpg"
526
+ ```
527
+
528
+ **Theater:**
529
+ ```javascript
530
+ // Stage photo per seating section
531
+ blocks: [
532
+ { id: "orchestra", background_image: "orchestra-view.jpg" },
533
+ { id: "balcony", background_image: "balcony-view.jpg" }
534
+ ]
535
+ ```
536
+
537
+ **Restaurant:**
538
+ ```javascript
539
+ // Floor plan as background
540
+ background_image: "floor-plan.png",
541
+ background_opacity: 0.5,
542
+ background_fit: "contain"
417
543
  ```
418
544
 
545
+ **Event Space:**
546
+ ```javascript
547
+ // Custom venue layout
548
+ background_image: "venue-layout.svg",
549
+ background_fit: "contain"
550
+ ```
551
+
552
+ #### Important Notes
553
+
554
+ - Background images don't affect zoom calculations (bounds preserved)
555
+ - Block borders/fills automatically hidden when background assigned
556
+ - CORS: Images must be same-origin or CORS-enabled
557
+ - Performance: Use optimized images (< 500KB recommended)
558
+
419
559
  </details>
420
560
 
421
561
  <p align="center">
422
- <a href="examples/"><img src="https://img.shields.io/badge/📖_Documentation-F7DF1E?style=for-the-badge&logoColor=black" alt="Documentation"/></a>
562
+ <a href="https://seatmap.io/frameworks/vanilla-js"><img src="https://img.shields.io/badge/📖_Full_Documentation-F7DF1E?style=for-the-badge&logoColor=black" alt="Documentation"/></a>
423
563
  &nbsp;
424
564
  <a href="examples/"><img src="https://img.shields.io/badge/🎯_Examples-333333?style=for-the-badge&logoColor=white" alt="Examples"/></a>
425
565
  </p>
426
566
 
427
567
  ---
428
568
 
569
+ ## Links
570
+
571
+ - 📖 [Full Documentation](https://seatmap.io)
572
+ - 🎯 [Live Demo](https://seatmap.io/demo)
573
+ - 📦 [NPM Package](https://www.npmjs.com/package/@alisaitteke/seatmap-canvas)
574
+ - 🐛 [Report Issues](https://github.com/alisaitteke/seatmap-canvas/issues)
575
+
576
+ ## Author
577
+
578
+ <div align="center">
579
+ <a href="https://github.com/alisaitteke">
580
+ <img src="https://github.com/alisaitteke.png" width="100" height="100" style="border-radius: 50%;" alt="Ali Sait Teke"/>
581
+ </a>
582
+
583
+ <h3>Ali Sait Teke</h3>
584
+
585
+ <p>
586
+ <a href="https://github.com/alisaitteke">
587
+ <img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub"/>
588
+ </a>
589
+ &nbsp;
590
+ <a href="https://www.linkedin.com/in/alisaitteke">
591
+ <img src="https://img.shields.io/badge/LinkedIn-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white" alt="LinkedIn"/>
592
+ </a>
593
+ &nbsp;
594
+ <a href="https://twitter.com/alisaitteke">
595
+ <img src="https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white" alt="Twitter"/>
596
+ </a>
597
+ </p>
598
+ </div>
599
+
429
600
  ## Contributors
430
601
 
431
- <a href="https://github.com/alisaitteke">
432
- <img src="https://img.shields.io/badge/Ali_Sait_Teke-Maintainer-blue?style=flat-square&logo=github" alt="Ali Sait Teke"/>
433
- </a>
602
+ Contributions are welcome! Feel free to submit issues and pull requests.