@seatlayer/react 0.65.0 → 0.67.15
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 +226 -27
- package/package.json +15 -6
package/README.md
CHANGED
|
@@ -1,19 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SeatLayer React Seat Map SDK for Reserved Seating
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@seatlayer/react)
|
|
4
4
|
[](https://www.npmjs.com/package/@seatlayer/react)
|
|
5
5
|
[](https://react.dev/)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
6
7
|
[](../../LICENSE)
|
|
7
8
|
|
|
8
|
-
The official React components for SeatLayer reserved seating.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[
|
|
9
|
+
The official React components for SeatLayer reserved seating. Drop an
|
|
10
|
+
interactive seating chart or a complete seat picker into a ticketing app, show
|
|
11
|
+
live seat availability, and let buyers take temporary holds on the inventory
|
|
12
|
+
they choose.
|
|
13
|
+
|
|
14
|
+
Everything is a real React component with a typed imperative handle: the browser
|
|
15
|
+
selects and **holds**, and your trusted server **books** the hold.
|
|
16
|
+
|
|
17
|
+
[SeatLayer React SDK on npm](https://www.npmjs.com/package/@seatlayer/react) ·
|
|
18
|
+
[React seat-map documentation](https://docs.seatlayer.io/buyer-sdk/seat-picker/) ·
|
|
19
|
+
[SeatLayer reserved-seating platform](https://seatlayer.io/) ·
|
|
20
|
+
[Buyer seat-map demo](https://app.seatlayer.io/demo/play/grand-theatre) ·
|
|
21
|
+
[SeatLayer JavaScript seat map SDK](https://www.npmjs.com/package/@seatlayer/js) ·
|
|
22
|
+
[SeatLayer Vue seat map SDK](https://www.npmjs.com/package/@seatlayer/vue) ·
|
|
23
|
+
[SeatLayer Angular seat map SDK](https://www.npmjs.com/package/@seatlayer/angular) ·
|
|
24
|
+
[SeatLayer React Native SDK](https://github.com/seatlayer/seatlayer-react-native) ·
|
|
25
|
+
[SeatLayer AI Toolkit](https://github.com/seatlayer/seatlayer-ai-toolkit)
|
|
26
|
+
|
|
27
|
+
## What is included
|
|
28
|
+
|
|
29
|
+
- `SeatingChart` — the headless interactive chart, mounted into a plain `<div>`
|
|
30
|
+
your styles own.
|
|
31
|
+
- `SeatPicker` — the complete buyer experience: map, legend, tray, pricing, and
|
|
32
|
+
the checkout hand-off.
|
|
33
|
+
- `SeatManager` — the organizer control room, for dashboards that monitor and
|
|
34
|
+
block live inventory.
|
|
35
|
+
- `EmbeddedDesigner` — a hosted chart Designer inside your own application.
|
|
36
|
+
- `SeatPickerWidget` and `attachPickerFrame` — the framework-agnostic modal and
|
|
37
|
+
iframe helpers, re-exported so a React host depends on this package alone.
|
|
38
|
+
- TypeScript declarations for ESM (`dist/index.d.ts`) and CommonJS
|
|
39
|
+
(`dist/index.d.cts`), plus the `@seatlayer/react/manager` subpath.
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- React 17 or newer (declared as a peer dependency).
|
|
44
|
+
- A browser DOM. The chart is created inside an effect, and this package ships
|
|
45
|
+
no `'use client'` banner of its own — in the Next.js App Router, mark the
|
|
46
|
+
component that imports it.
|
|
17
47
|
|
|
18
48
|
## Install
|
|
19
49
|
|
|
@@ -21,7 +51,7 @@ browser, and complete the booking from your trusted server.
|
|
|
21
51
|
npm install @seatlayer/react
|
|
22
52
|
```
|
|
23
53
|
|
|
24
|
-
##
|
|
54
|
+
## Quick start
|
|
25
55
|
|
|
26
56
|
```tsx
|
|
27
57
|
import { useRef } from 'react';
|
|
@@ -52,6 +82,28 @@ await chart.current?.releaseLabels(['A-12']); // keep the remainder hel
|
|
|
52
82
|
await chart.current?.release(); // release the current hold
|
|
53
83
|
```
|
|
54
84
|
|
|
85
|
+
For the complete buyer experience — map, legend, priced tray, and the checkout
|
|
86
|
+
hand-off — render `SeatPicker` instead:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { SeatPicker } from '@seatlayer/react';
|
|
90
|
+
|
|
91
|
+
export function Tickets() {
|
|
92
|
+
return (
|
|
93
|
+
<SeatPicker
|
|
94
|
+
event="ev_9f3a"
|
|
95
|
+
style={{ width: '100%', height: 640 }}
|
|
96
|
+
selectionValidators={[
|
|
97
|
+
{ type: 'minimumSelectedPlaces', minimum: 2 },
|
|
98
|
+
{ type: 'consecutiveSeats' },
|
|
99
|
+
{ type: 'noOrphanSeats' },
|
|
100
|
+
]}
|
|
101
|
+
onCheckout={(hold, seats, handoff) => myServerTakesPayment(handoff)}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
55
107
|
### Full SeatPicker imperative contract
|
|
56
108
|
|
|
57
109
|
The full-experience `SeatPicker` exposes the canonical safe widget controls through
|
|
@@ -97,13 +149,34 @@ Changing a callback prop does **not** rebuild the canvas. `selectedObjects` and
|
|
|
97
149
|
`selectableObjects` are initial values; use the imperative methods for later
|
|
98
150
|
changes. Exact count and validator props rebuild the chart.
|
|
99
151
|
|
|
100
|
-
##
|
|
152
|
+
## Security boundary
|
|
153
|
+
|
|
154
|
+
The React app **selects and holds** inventory. Your trusted backend **inspects
|
|
155
|
+
and books** the hold after payment or order validation.
|
|
156
|
+
|
|
157
|
+
- Never ship a SeatLayer secret key in browser code or in a bundled environment
|
|
158
|
+
variable.
|
|
159
|
+
- Send only the `holdId` and your normal checkout context to your backend.
|
|
160
|
+
- Calculate the charge from server-inspected hold items, not from browser input.
|
|
161
|
+
- Reuse your stable order id as `bookingRef` so a retried booking is idempotent.
|
|
162
|
+
- Organizer surfaces take a short-lived, event-scoped `mse_` browser grant —
|
|
163
|
+
never a tenant `sk_` secret.
|
|
101
164
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
[how the integration works](https://docs.seatlayer.io/start/how-it-works/).
|
|
165
|
+
Read [how the integration works](https://docs.seatlayer.io/start/how-it-works/)
|
|
166
|
+
before connecting checkout.
|
|
105
167
|
|
|
106
|
-
|
|
168
|
+
## Architecture
|
|
169
|
+
|
|
170
|
+
These components are a thin React layer over
|
|
171
|
+
[`@seatlayer/js`](https://www.npmjs.com/package/@seatlayer/js), the
|
|
172
|
+
framework-agnostic browser runtime. The wrapper mounts a plain `<div>`, builds
|
|
173
|
+
the chart inside an effect, forwards every prop and callback, and exposes the
|
|
174
|
+
runtime's imperative handle through `ref`. Chart geometry, availability, and
|
|
175
|
+
holds all come from the SeatLayer API at runtime, so the same event renders
|
|
176
|
+
identically on web and on the mobile SDKs.
|
|
177
|
+
|
|
178
|
+
Callback props are read through a ref, so changing one never tears the chart
|
|
179
|
+
down. Only the identity props listed above rebuild it.
|
|
107
180
|
|
|
108
181
|
## Embed the live control room
|
|
109
182
|
|
|
@@ -246,17 +319,143 @@ export function VenueEditor({ chartId }: { chartId: string }) {
|
|
|
246
319
|
}
|
|
247
320
|
```
|
|
248
321
|
|
|
249
|
-
##
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
322
|
+
## SeatingChart imperative handle
|
|
323
|
+
|
|
324
|
+
Every method the runtime exposes to a wrapper, reachable through the `ref`:
|
|
325
|
+
|
|
326
|
+
`hold` · `resumeHold` · `getCurrentHold` · `getGAAreas` · `holdGA` ·
|
|
327
|
+
`bestAvailable` · `release` · `releaseLabels` · `getSelection` ·
|
|
328
|
+
`selectObjects` · `deselectObjects` · `clearSelection` · `selectCategories` ·
|
|
329
|
+
`deselectCategories` · `setSelectableObjects` · `setMaxSelection` ·
|
|
330
|
+
`getSelectionValidity` · `setSeatTier` · `getFloors` · `setFloor` ·
|
|
331
|
+
`setColorblindSafe` · `zoomIn` · `zoomOut` · `zoomToFit` · `refreshAccess`
|
|
332
|
+
|
|
333
|
+
Calling any of them before the chart exists returns an empty answer rather than
|
|
334
|
+
throwing, so a ref used one frame early is safe.
|
|
335
|
+
|
|
336
|
+
## Callback props
|
|
337
|
+
|
|
338
|
+
| Prop | Payload |
|
|
339
|
+
| --- | --- |
|
|
340
|
+
| `onSelectionChange` | `SelectedSeat[]` |
|
|
341
|
+
| `onSelectionValidityChange` | Rule state with typed `violations` |
|
|
342
|
+
| `onSelectionValid` / `onSelectionInvalid` | Rule-validity transition |
|
|
343
|
+
| `onSelectionLimit` | Active numeric cap |
|
|
344
|
+
| `onHold` | `HoldResult` |
|
|
345
|
+
| `onHoldRestored` | `HoldResult` |
|
|
346
|
+
| `onHoldExpired` | — |
|
|
347
|
+
| `onGAClick` | `GAAreaAvailability` |
|
|
348
|
+
| `onError` | `unknown` |
|
|
349
|
+
| `onDeckTap` | `string` (floor id) |
|
|
350
|
+
| `onHint` | `string \| null` — `null` clears the hint |
|
|
351
|
+
| `onSeatHover` | `SeatHoverDetails \| null` — `null` when the pointer leaves |
|
|
352
|
+
| `onAccessExpired` | `BuyerAccessExpiredEvent` |
|
|
353
|
+
| `onAccessUnavailable` | `BuyerAccessUnavailableEvent` |
|
|
354
|
+
| `onSelectedObjectUnavailable` | `SelectedObjectUnavailableEvent` |
|
|
355
|
+
|
|
356
|
+
## Frequently asked questions
|
|
357
|
+
|
|
358
|
+
### How do I add a seat map to a React app?
|
|
359
|
+
|
|
360
|
+
Install `@seatlayer/react`, render `<SeatingChart event="ev_…" />` inside a
|
|
361
|
+
container with a definite height, and read the buyer's choice from
|
|
362
|
+
`onSelectionChange`. That is a complete interactive seating chart with live
|
|
363
|
+
availability; the quick start above is the whole integration, and the
|
|
364
|
+
[seat-picker documentation](https://docs.seatlayer.io/buyer-sdk/seat-picker/)
|
|
365
|
+
covers props, events, holds, and checkout in depth.
|
|
366
|
+
|
|
367
|
+
### Is this a real React component or an iframe?
|
|
368
|
+
|
|
369
|
+
`SeatingChart`, `SeatPicker`, and `SeatManager` are real React components that
|
|
370
|
+
render a plain `<div>` into your own tree — no iframe, no portal, and no
|
|
371
|
+
stylesheet of their own to fight with. `EmbeddedDesigner` is the one exception:
|
|
372
|
+
the organizer Designer is deliberately hosted in a sandboxed iframe so no
|
|
373
|
+
Designer credential ever reaches your bundle. If you *want* an iframe for the
|
|
374
|
+
buyer picker, `attachPickerFrame` is exported for that.
|
|
375
|
+
|
|
376
|
+
### What is the difference between `SeatPicker` and `SeatingChart`?
|
|
377
|
+
|
|
378
|
+
`SeatingChart` is the chart alone: it draws the venue, manages selection, and
|
|
379
|
+
hands you the seats — you build the surrounding UI. `SeatPicker` is the complete
|
|
380
|
+
buyer experience with legend, priced tray, hold timer, and checkout hand-off
|
|
381
|
+
already built. Start with `SeatPicker` if you want a working ticket flow today,
|
|
382
|
+
and drop to `SeatingChart` when your design system owns the chrome.
|
|
383
|
+
|
|
384
|
+
### How do temporary seat holds work?
|
|
385
|
+
|
|
386
|
+
When a buyer commits to a selection, `hold()` reserves that inventory against
|
|
387
|
+
concurrent buyers for a limited checkout window and returns an opaque `holdId`.
|
|
388
|
+
The hold lapses on its own if checkout never completes — `onHoldExpired` tells
|
|
389
|
+
the app to return the buyer to the map — and `resumeHold()` restores it after a
|
|
390
|
+
same-tab checkout navigation or a reload. This is what prevents double-selling
|
|
391
|
+
without locking seats forever.
|
|
392
|
+
|
|
393
|
+
### Can I use my own payment provider?
|
|
394
|
+
|
|
395
|
+
Yes. Nothing in this package takes a payment. The browser hands you a `holdId`
|
|
396
|
+
and a self-contained `CheckoutHandoff` with the priced line items, your backend
|
|
397
|
+
charges through whatever provider you already use, and it then books the hold
|
|
398
|
+
through the
|
|
399
|
+
[server-side checkout flow](https://docs.seatlayer.io/buyer-sdk/holds-and-checkout/).
|
|
400
|
+
The opt-in `checkout: 'hosted'` mode exists for hosts with no backend at all;
|
|
401
|
+
without it, no payment code is downloaded.
|
|
402
|
+
|
|
403
|
+
### Can I evaluate it without a SeatLayer account?
|
|
404
|
+
|
|
405
|
+
You can explore a live seating chart in the browser at the
|
|
406
|
+
[buyer seat-map demo](https://app.seatlayer.io/demo/play/grand-theatre) with no
|
|
407
|
+
account. Rendering your own venue needs an event key, because the chart and its
|
|
408
|
+
availability are served by the SeatLayer API — create a free test event for
|
|
409
|
+
that, which books no real inventory.
|
|
410
|
+
|
|
411
|
+
### Does it work with Next.js and other React frameworks?
|
|
412
|
+
|
|
413
|
+
Yes, on the client. The chart is built inside an effect and touches the DOM only
|
|
414
|
+
there, so a server render emits the empty container. This package ships no
|
|
415
|
+
`'use client'` banner of its own, so in the App Router mark your own component
|
|
416
|
+
that imports it, or load it through `next/dynamic` with `ssr: false`.
|
|
417
|
+
|
|
418
|
+
## Continue your React integration
|
|
419
|
+
|
|
420
|
+
- [Follow the buyer SDK installation guide](https://docs.seatlayer.io/buyer-sdk/install/)
|
|
421
|
+
for the full browser integration, options, and events.
|
|
422
|
+
- [Connect seat holds to secure server-side checkout](https://docs.seatlayer.io/buyer-sdk/holds-and-checkout/)
|
|
423
|
+
without putting booking credentials in the browser.
|
|
424
|
+
- [Run the complete checkout example](https://docs.seatlayer.io/examples/complete-checkout/)
|
|
425
|
+
to connect a buyer hold id to payment and idempotent booking.
|
|
426
|
+
- [Compare SeatLayer's mobile seat map SDKs](https://docs.seatlayer.io/buyer-sdk/mobile/)
|
|
427
|
+
when the same event also has to render in native iOS, Android, Flutter, or
|
|
428
|
+
React Native apps.
|
|
429
|
+
- [Read the embedded Designer guide](https://docs.seatlayer.io/platform/embedded-designer/)
|
|
430
|
+
to let organizers draw their own venues inside your product.
|
|
431
|
+
- [Explore the 3D seating chart](https://seatlayer.io/3d-seat-map/) for the
|
|
432
|
+
interactive venue view buyers can switch to from the map.
|
|
433
|
+
- [Point AI coding agents at the SeatLayer docs index](https://docs.seatlayer.io/llms.txt)
|
|
434
|
+
(`llms.txt`) for an agent-readable map of the documentation.
|
|
435
|
+
|
|
436
|
+
## SeatLayer SDK ecosystem
|
|
437
|
+
|
|
438
|
+
| Surface | Package or source |
|
|
439
|
+
| --- | --- |
|
|
440
|
+
| JavaScript | [`@seatlayer/js`](https://www.npmjs.com/package/@seatlayer/js) |
|
|
441
|
+
| React | [`@seatlayer/react`](https://www.npmjs.com/package/@seatlayer/react) (this package) |
|
|
442
|
+
| Vue | [`@seatlayer/vue`](https://www.npmjs.com/package/@seatlayer/vue) |
|
|
443
|
+
| Angular | [`@seatlayer/angular`](https://www.npmjs.com/package/@seatlayer/angular) |
|
|
444
|
+
| React Native | [`@seatlayer/react-native`](https://www.npmjs.com/package/@seatlayer/react-native) |
|
|
445
|
+
| iOS | [`seatlayer-ios`](https://github.com/seatlayer/seatlayer-ios) |
|
|
446
|
+
| Flutter | [`seatlayer`](https://pub.dev/packages/seatlayer) |
|
|
447
|
+
| Android | [`seatlayer-android`](https://github.com/seatlayer/seatlayer-android) |
|
|
448
|
+
| Server SDKs | [Node.js, Python, PHP, Ruby, .NET, Java, and Go](https://docs.seatlayer.io/server-sdk/install/) |
|
|
449
|
+
|
|
450
|
+
## Development
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
pnpm install
|
|
454
|
+
pnpm verify
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Source, issues, and contribution guidance live in
|
|
458
|
+
[seatlayer/seatlayer-sdk](https://github.com/seatlayer/seatlayer-sdk).
|
|
260
459
|
|
|
261
460
|
## License
|
|
262
461
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seatlayer/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React
|
|
3
|
+
"version": "0.67.15",
|
|
4
|
+
"description": "SeatLayer's official React seating chart and seat map SDK — live availability, seat selection, temporary holds, and a typed TypeScript API for ticketing apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SeatLayer",
|
|
@@ -55,17 +55,26 @@
|
|
|
55
55
|
],
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"keywords": [
|
|
58
|
-
"
|
|
58
|
+
"seat map",
|
|
59
|
+
"seating chart",
|
|
59
60
|
"seat-map",
|
|
60
61
|
"seating-chart",
|
|
61
62
|
"seat-picker",
|
|
63
|
+
"seat-selection",
|
|
64
|
+
"seat-reservation",
|
|
65
|
+
"reserved-seating",
|
|
66
|
+
"seat-booking",
|
|
67
|
+
"event-ticketing",
|
|
68
|
+
"ticketing",
|
|
69
|
+
"live-inventory",
|
|
70
|
+
"seating",
|
|
62
71
|
"seatlayer",
|
|
63
72
|
"react",
|
|
64
|
-
"
|
|
73
|
+
"typescript"
|
|
65
74
|
],
|
|
66
75
|
"dependencies": {
|
|
67
|
-
"@seatlayer/core": "0.
|
|
68
|
-
"@seatlayer/js": "0.
|
|
76
|
+
"@seatlayer/core": "0.67.15",
|
|
77
|
+
"@seatlayer/js": "0.67.15"
|
|
69
78
|
},
|
|
70
79
|
"peerDependencies": {
|
|
71
80
|
"react": ">=17.0.0"
|