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