SeatPicker is the complete buyer experience: live map, confirmation, tier/GA
controls, selection tray, hold countdown, best available, 2D/3D, view from seat,
mobile bottom sheet, sold-out/closed states, and checkout handoff.
import { SeatPicker } from "@seatlayer/js";
const picker = new SeatPicker({
container: "#picker",
event: "ev_9f3a",
onCheckout: (_hold, _seats, handoff) => {
startCheckout({ holdId: handoff.holdId });
},
});
await picker.render();Choose the surface
SeatPicker |
SeatingChart |
|
|---|---|---|
| Map canvas | Included | Included |
| Cart/tray, CTA, timer, states | Included | Host builds |
| Seat confirmation and 360 view | Included | Host builds |
| Modal helper | SeatPicker.open() |
No |
| Best for | Complete, styleable buyer flow | Fully custom cart and controls |
Constructor options
| Option | Type | Default/notes |
|---|---|---|
container |
string | HTMLElement |
Required inline; omit for open() |
event |
string |
Required event key |
apiBase |
string |
https://api.seatlayer.io |
transport |
PickerTransport |
Built-in public transport; useful for controlled adapters/tests |
publicKey |
string |
Reserved; not current browser authorization |
maxSelection |
number |
10 |
locale |
string |
Browser language → en; built-in en, es, de, fr |
messages |
Record<string,string> |
Per-message copy overrides |
currency |
string |
USD fallback; event/org data wins |
colorblindSafe |
boolean |
false |
initialView |
RendererViewMode |
Use flat; legacy perspective values are deprecated |
enable3D |
boolean |
true when WebGL2 is available |
onAnalytics |
(event, props) => void |
Optional Preview 3D journey sink |
hideBadge |
boolean |
Host preference; entitlement/chart theme also applies |
theme |
SeatPickerTheme |
Partial host overrides |
pricing |
SeatPickerPricing |
Buyer display overrides; not server ledger authority |
holdTtlMs |
number |
Sent to hold; server clamps |
initialHoldId |
string |
Verify/restore an existing event hold |
restoreHold |
boolean |
true; uses per-event session storage |
confirmSelection |
boolean |
true |
seatView |
boolean |
true |
Callbacks
| Callback | Signature | Meaning |
|---|---|---|
onCheckout |
(hold, seats, handoff) => void |
Hold succeeded and buyer chose checkout |
onBooked |
(handoff) => void |
Realtime state confirms this handed-off hold was booked |
onSelectionChange |
(seats) => void |
Selection changes |
onHoldChange |
(hold, seats, handoff) => void |
Hold created/restored/extended/partially released/released |
onHoldExpired |
() => void |
Current hold expired and widget reset |
onHoldRestored |
(hold, seats, handoff) => void |
Prior hold verified and restored |
onClose |
() => void |
Modal closes |
onError |
(error) => void |
Render/transport operation fails |
Use the third onCheckout argument for new integrations:
interface CheckoutHandoff {
holdId: string;
expiresAt: number;
currency: string;
lineItems: CheckoutLineItem[];
total: number;
}
interface CheckoutLineItem {
label: string;
displayLabel?: string;
displayType?: string;
objectId: string;
objectType: "seat" | "booth" | "ga" | "table";
categoryKey: string;
tierId: string | null;
unitPrice: number;
currency: string;
quantity: number;
}The browser handoff is excellent display context, but payment still uses a fresh server hold inspection.
Public methods
| Method | Result |
|---|---|
render() |
Promise<this> |
close() |
Close modal or destroy inline picker |
getSelection() |
Current PickerSeat[] |
isColorblindSafe() |
Current accessible palette state |
setColorblindSafe(on) |
Change accessible palette state |
setViewMode(mode) / getViewMode() |
Legacy 2D renderer mode compatibility |
getBuyerView() |
"map" | "venue3d" |
setBuyerView(view, { flyToSeatId? }) |
Switch buyer surface/programmatic 3D tour |
getCurrentHold() |
HoldResult | null |
resumeHold(holdId) |
Verify and restore a hold |
removeHeldTicket(label) |
Remove one held item and keep the rest |
bestAvailable(qty, categoryKey?, options?) |
Hold a server-selected group |
release() |
Release current hold and reset |
destroy() |
Remove DOM, socket, listeners, and timers |
Modal mode
const picker = await SeatPicker.open({
event: "ev_9f3a",
onCheckout: (_hold, _seats, handoff) => {
startCheckout({ holdId: handoff.holdId });
},
onClose: () => restoreHostUI(),
});
picker.close();The modal traps focus, closes through Escape/scrim/close button, restores scroll
and prior focus, and fires onClose.
Holds and restore
The picker persists the current hold id in sessionStorage by default. On a
return visit it verifies that hold against the same event before showing it as
owned.
Set restoreHold: false when your router/cart owns persistence, then supply
initialHoldId or call resumeHold(). Clear host cart state when
onHoldChange(null, …) fires.
The built-in countdown offers an extension in the final minute and resets on confirmed extension. Server limits and renewal caps remain authoritative.
Buyer 3D and analytics
enable3D controls whether the Map/3D affordance is offered. The 3D module is
lazy-loaded only after use and falls back to the complete 2D experience when
WebGL2 is unavailable.
Use setBuyerView("venue3d", { flyToSeatId }) for a guided tour and
onAnalytics to forward Preview journey events to your own system.
See 3D buyer view and buyer analytics.
Responsive behavior
Layout responds to the picker container, not only the viewport:
- wide containers show a side panel and docked details;
- narrow containers use a bottom sheet and touch-first map controls; and
- fullscreen uses the native API or a platform fallback.
Give the container a definite height. Test the actual embed width, mobile browser chrome, keyboard, reduced motion, and colorblind-safe mode.
Lifecycle checklist
- Construct once per mounted host view.
- Await
render()and expose failures throughonError. - Send only
holdIdto the booking server boundary. - Clear host state when the hold disappears.
- Use stable order ids for booking retries.
- Call
destroy()during application unmount. - Test inline/modal, narrow/wide, 2D/no-WebGL, expiry, and conflict paths.
Continue with holds and checkout, customization, or the SeatingChart reference.