SeatLayerView is the low-level Flutter map. It remains source-compatible with
the original 0.2.x surface inside seatlayer: 0.7.2.
Choose it only when your app will own confirmation, cart, hold timing,
validation messages, test-mode disclosure, required attribution, recovery, and
checkout. If you want a different arrangement without reimplementing those
rules, use SeatLayerPickerScope instead.
Create and own the controller
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:seatlayer/seatlayer.dart';
class RawSeatMap extends StatefulWidget {
const RawSeatMap({super.key});
@override
State<RawSeatMap> createState() => _RawSeatMapState();
}
class _RawSeatMapState extends State<RawSeatMap> {
final controller = SeatLayerController();
StreamSubscription<void>? holdExpired;
@override
void initState() {
super.initState();
holdExpired = controller.onHoldExpired.listen((_) {
returnBuyerToSelection();
});
}
@override
void dispose() {
holdExpired?.cancel();
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SeatLayerView(
controller: controller,
configuration: SeatLayerConfiguration(
event: 'ev_your_event_key',
publicKey: 'pk_test_your_public_key',
currency: 'USD',
),
onReady: (info) => debugPrint('SeatLayer mode: ${info.mode.raw}'),
onLoadError: showLoadError,
);
}
}The controller and configuration are required. Keep one controller for the mounted view lifecycle, and give the map a definite height or full-screen parent.
For gated inventory, replace publicKey with the renewable provider:
final configuration = SeatLayerConfiguration(
event: 'ev_private',
buyerAccessTokenProvider: (request) =>
buyerBackend.mintSeatLayerAccess(request.reason),
);Your backend creates the native buyer-access session through buyer access sessions, returns only its short-lived token to the authenticated app, and treats SDK access details as opaque. It never exposes a SeatLayer secret.
Configuration map
| Concern | SeatLayerConfiguration fields |
|---|---|
| Identity and access | event, publicKey, buyerAccessToken, buyerAccessTokenProvider |
| Selection policy | maxSelection, selectedObjects, selectableObjects, numberOfPlacesToSelect, selectionValidators |
| Presentation | locale, messages, currency, colorblindSafe, initialView, showsWebSeatTooltip |
| Operations | commandTimeout, handshakeTimeout, hostInfo |
See the complete tagged constructor and field documentation for types, defaults, and validation.
Common command groups
This table is a task-oriented map, not a substitute for the complete tagged API.
| Group | SeatLayerController methods |
|---|---|
| Read | getSelection, getSelectionValidity, getCurrentHold, getGAAreas, getFloors, getViewMode |
| Select | selectObjects, deselectObjects, clearSelection, selectCategories, deselectCategories, setSelectableObjects, setMaxSelection, setSeatTier |
| Hold | hold, resumeHold, extendHold, release, releaseLabels, bestAvailable, holdGA |
| Access | refreshAccess |
| Map | setFloor, setColorblindSafe, setViewMode, zoomIn, zoomOut, zoomToFit |
| Session | destroy, dispose |
Use the
tagged SeatLayerController source
for exact parameters, return types, and every method in 0.7.2. Feature controls
should also respect reported capability state; a public method does not prove a
particular Event supports the operation.
Commands return Futures and throw SeatLayerError at the awaited call site.
try {
final hold = await controller.hold();
if (hold != null) {
await checkoutBackend.begin(holdId: hold.holdId);
}
} on SeatLayerError catch (error) {
showInventoryMessage(error.code, error.message);
}Typed streams
Important streams include onReady, onSelectionChanged,
onSelectionValidityChanged, onHold, onHoldRestored, onHoldExpired,
onBuyerAccessExpired, onBuyerAccessUnavailable,
onSelectedObjectsUnavailable, onGAClick, onSeatHover, onError, and
onUnknownEvent.
Subscribe once, retain each StreamSubscription, and cancel it from dispose.
Unknown future enum values and events remain inspectable rather than crashing an
older application.
| Stream | Payload and host responsibility |
|---|---|
onSelectionChanged |
Full current List<SelectedSeat>; replace local selection rather than appending |
onSelectionValidityChanged |
SelectionValidity; enable host confirmation only when the configured rules are satisfied |
onHold, onHoldRestored, onHoldExpired |
Authoritative hold changes; expiry carries no reusable local hold |
onBuyerAccessExpired, onBuyerAccessUnavailable |
Refresh outcome or access refusal; never silently widen private inventory |
onSelectedObjectsUnavailable |
Labels and reason for inventory that must be removed from host UI |
onError, onUnknownEvent |
Typed operational failure or forward-compatible raw event for diagnostics |
Raw-map responsibilities
The complete picker normally owns these behaviors. A raw integration must provide them explicitly:
- selection confirmation and validation feedback;
- general-admission quantity and tier selection;
- test-mode disclosure and required attribution;
- hold countdown, server-authoritative expiry, resume, and release;
- background/foreground reconciliation;
- unavailable-inventory recovery;
- gesture-safe overlays and accessible controls;
- back-navigation behavior; and
- secure checkout handoff.
Do not duplicate venue behavior by forwarding touch coordinates or placing the map inside another pan/zoom surface. Use typed commands and let the canvas own its gestures.
Security boundary
HoldResult contains a display-oriented view of a temporary hold. Send only
holdId plus your own order context to your backend. The backend inspects the
hold, calculates the authoritative price, takes payment, and reuses the same
bookingRef for retries.