@seatlayer/js 0.73.0 → 0.75.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/dist/index.d.ts CHANGED
@@ -249,7 +249,8 @@ declare function createBuyerAccessContext(options: {
249
249
  * - compact `{default, exceptions}` snapshot reconstruction;
250
250
  * - `sv.<n>` resume, handling BOTH outcomes (a `resumed` delta or a full
251
251
  * snapshot) on every reconnect;
252
- * - close code 4401 as a typed access-revoked state, never a reconnect loop;
252
+ * - close code 4401 distinguishes an expired session (refresh/reconnect) from
253
+ * a genuinely revoked one (typed terminal state, never a reconnect loop);
253
254
  * - liveness by ping/pong only. Silence is normal and carries no information
254
255
  * (protocol doc §5) — a quiet socket is never treated as a dead one.
255
256
  */
@@ -306,7 +307,7 @@ interface BuyerRealtimeOptions {
306
307
  /** Mint a one-use ticket for THIS connection attempt. Returns null for the
307
308
  * anonymous public case (no ticket needed). Throwing stops the client. */
308
309
  mintTicket?: () => Promise<SubscribeTicket | null>;
309
- /** Typed access states. 4401 arrives here as `revoked`. */
310
+ /** Typed terminal access states. A 4401 `access_expired` close reconnects. */
310
311
  onAccessUnavailable?: (event: BuyerAccessUnavailableEvent) => void;
311
312
  /** Test seam. Defaults to the global WebSocket. */
312
313
  socketFactory?: (url: string, protocols: string[]) => WebSocket;
@@ -1095,7 +1096,10 @@ interface SeatPickerOptions {
1095
1096
  * same live fact. The picker remains fully functional when it is omitted.
1096
1097
  */
1097
1098
  onOfferAvailabilityChange?: (availability: TicketOfferAvailability | null) => void;
1098
- /** Hold TTL in ms passed to hold(); server clamps to its own limits. */
1099
+ /**
1100
+ * Fallback hold TTL in ms. An explicit event-dashboard duration takes
1101
+ * priority; otherwise the server uses this request, then its 15-minute default.
1102
+ */
1099
1103
  holdTtlMs?: number;
1100
1104
  /**
1101
1105
  * An opaque hold id supplied by the host to restore after navigation. It is
@@ -1339,7 +1343,22 @@ interface SeatingChartPickerState {
1339
1343
  label: string;
1340
1344
  color: string;
1341
1345
  price: number;
1346
+ /** Remaining count, ZERO when the answer is not known yet. Kept for the
1347
+ * hosts that already read it; `free` below is the honest form. */
1342
1348
  available: number;
1349
+ /**
1350
+ * Remaining seats in this category — the number the confirm card's band
1351
+ * prints as "N left", from the same `categoryAvailability()` the legend
1352
+ * reads. `capability: category-availability-v1`.
1353
+ *
1354
+ * PRESENT-ONLY, and that is the whole reason it exists beside
1355
+ * `available`. Availability lands after first paint, so `available: 0`
1356
+ * cannot be told apart from "sold out" by a host that arrived early —
1357
+ * and a shell that renders "0 left" on a category the buyer can still
1358
+ * book has lied about the event. An absent `free` means "not known
1359
+ * yet"; a `free: 0` means gone.
1360
+ */
1361
+ free?: number;
1343
1362
  tiers: Array<{
1344
1363
  id: string;
1345
1364
  name: string;
@@ -1416,7 +1435,11 @@ interface SeatingChartPickerState {
1416
1435
  accessNeeds: PickerAccessNeed[];
1417
1436
  };
1418
1437
  selection: {
1419
- seats: SelectedSeat[];
1438
+ /**
1439
+ * The selected seats, each carrying where it currently IS on screen when
1440
+ * the renderer can say — see {@link SeatScreenPoint}.
1441
+ */
1442
+ seats: Array<SelectedSeat & SeatScreenPoint>;
1420
1443
  validity: PickerSelectionValidity | null;
1421
1444
  maxSelection: number;
1422
1445
  };
@@ -1426,6 +1449,26 @@ interface SeatingChartPickerState {
1426
1449
  reason?: string;
1427
1450
  };
1428
1451
  }
1452
+ /**
1453
+ * Where a seat is on screen, for a shell drawing its OWN card over the map.
1454
+ *
1455
+ * `capability: seat-screen-point-v1`. The point is the seat's position in the
1456
+ * map container's CSS pixels — the same value `reanchorConfirm` anchors the
1457
+ * web confirm card to, read from the same `worldToScreen`, so a native card
1458
+ * and the web one cannot disagree about where the seat is. Origin is the map
1459
+ * container's top-left, not the page's.
1460
+ *
1461
+ * OPTIONAL, and a host must treat it that way: it exists only once a renderer
1462
+ * is attached and only for a seat whose geometry the chart actually carries.
1463
+ * A snapshot taken before first paint has none, and a shell that assumed it
1464
+ * would place its card at (0, 0).
1465
+ */
1466
+ interface SeatScreenPoint {
1467
+ screenPoint?: {
1468
+ x: number;
1469
+ y: number;
1470
+ };
1471
+ }
1429
1472
 
1430
1473
  /**
1431
1474
  * SeatingChart — the embeddable buyer picker.
@@ -1685,6 +1728,16 @@ declare class SeatingChart {
1685
1728
  private interactionEnabled_;
1686
1729
  /** The organizer's language for this event, learned when the chart resolves. */
1687
1730
  private eventLocale;
1731
+ /**
1732
+ * Fences competing dictionary loads. Several can be in flight at once — the
1733
+ * boot fetch, the event's own language arriving with the chart, a buyer using
1734
+ * the switcher — and they resolve in whatever order the network chooses.
1735
+ * Without the fence the LAST to ARRIVE wins rather than the last to be ASKED
1736
+ * for, which is how someone who picks French ends up reading German.
1737
+ */
1738
+ private localeGeneration;
1739
+ /** The switcher, kept in step with a language change made from anywhere else. */
1740
+ private languageSelect;
1688
1741
  private rendered;
1689
1742
  private mode_;
1690
1743
  private eventInfo;
@@ -1768,6 +1821,18 @@ declare class SeatingChart {
1768
1821
  * it does at first render.
1769
1822
  */
1770
1823
  setLocale(next: string | null | undefined): Promise<string>;
1824
+ /**
1825
+ * Re-say everything already on screen in the now-active locale.
1826
+ *
1827
+ * Split out of {@link setLocale} because two paths reach it: an explicit
1828
+ * language change, and the boot dictionary landing after first paint — the
1829
+ * second being the reason `render()` no longer waits for a locale fetch.
1830
+ *
1831
+ * `generation` fences out a stale winner; see {@link localeGeneration}.
1832
+ * `refreshMapCopy` is a no-op before the renderer is mounted, so a dictionary
1833
+ * that lands mid-chart-fetch costs nothing and the map is built translated.
1834
+ */
1835
+ private applyActiveLocale;
1771
1836
  getMode(): 'live' | 'test' | null;
1772
1837
  /** Atomic, token-free display state for native-owned picker chrome. */
1773
1838
  getPickerState(): SeatingChartPickerState;
@@ -1845,8 +1910,9 @@ declare class SeatingChart {
1845
1910
  }): Promise<HoldResult | null>;
1846
1911
  /**
1847
1912
  * Ask the server for the `qty` best free seats and hold them atomically.
1848
- * `options.ttlMs` sets the checkout window exactly like {@link hold}; omit it
1849
- * and the server falls back to the event setting, then its own default.
1913
+ * `options.ttlMs` requests the fallback hold window exactly like {@link hold}.
1914
+ * An event-dashboard duration wins; otherwise the server uses this value,
1915
+ * then its own default.
1850
1916
  */
1851
1917
  bestAvailable(qty: number, categoryKey?: string, options?: {
1852
1918
  zoneId?: string;
@@ -2639,6 +2705,18 @@ declare class SeatPicker implements GaPromptPicker {
2639
2705
  private handedOff;
2640
2706
  /** Guards single onBooked + single success overlay per hold. */
2641
2707
  private bookedShown;
2708
+ /**
2709
+ * The last hold attempt lost its seats.
2710
+ *
2711
+ * THE INTERLOCK. "Seat A12 was just taken by another buyer" and "You're all
2712
+ * set — 1 ticket confirmed" were rendering together, because `detectBooked`
2713
+ * reads a cleared controller hold as a completed booking — and a hold that
2714
+ * was TAKEN clears exactly the same way one that was PAID clears. This flag
2715
+ * is the difference the controller cannot express: set when an attempt
2716
+ * conflicts, cleared the moment a hold succeeds, and checked before anything
2717
+ * is allowed to congratulate the buyer.
2718
+ */
2719
+ private holdConflicted;
2642
2720
  /**
2643
2721
  * `'hosted'` only when the host asked for it AND the widget owns its own
2644
2722
  * transport. Resolved once in the constructor so every later read is a field
@@ -2739,6 +2817,20 @@ declare class SeatPicker implements GaPromptPicker {
2739
2817
  /** Supersedes an older authored-view byte request when another seat is opened. */
2740
2818
  private seatViewGen;
2741
2819
  private allSeatsCache;
2820
+ /** The 3D "Back to map"/"Back to venue" control while 3D is on. It lives in
2821
+ * the top-left chrome region rather than in the 3D overlay, so it outlives
2822
+ * the overlay's own teardown and must be removed explicitly. */
2823
+ private view3dBack;
2824
+ /** The levels/areas rail while 3D is on. Region chrome for the same reason
2825
+ * the back control is (it shared twelve pixels with the ♿ menu), so like
2826
+ * the back control it outlives the overlay and is removed by hand. */
2827
+ private view3dNav;
2828
+ /** Which chips the price rail last drew, so a repaint that changes them can
2829
+ * send the scroller back to the start without stealing a buyer's own scroll. */
2830
+ private lastRailSignature;
2831
+ /** The panel's price-band <select>, so the rail's reset chip can keep it in
2832
+ * step. Null when the chart has fewer than two bands and none was built. */
2833
+ private priceSelect;
2742
2834
  private minimap;
2743
2835
  private pickerLayoutSize;
2744
2836
  private priceBandKeys;
@@ -2990,7 +3082,27 @@ declare class SeatPicker implements GaPromptPicker {
2990
3082
  /** Held tickets and standing quantities consume the same order-wide cap. */
2991
3083
  private updateSelectionCapacity;
2992
3084
  private syncCta;
3085
+ /**
3086
+ * Narrate the money path.
3087
+ *
3088
+ * THE PHASE BELONGS TO THE PROMISE, NOT TO A CLOCK. `checkout` used to clear
3089
+ * itself after a fixed 1,100ms whatever the unawaited hold or handoff was
3090
+ * doing — so the button re-armed while the request was still in flight, and a
3091
+ * buyer could press it again into a hold that had already failed. The phase
3092
+ * now ends where the work ends: `runCheckoutHandoff` returns it to idle when
3093
+ * the handoff settles, and `handleCta`'s catch returns it on failure.
3094
+ */
2993
3095
  private setCtaPhase;
3096
+ /**
3097
+ * Hand the buyer to checkout and hold the "Opening secure checkout…" state
3098
+ * for exactly as long as that takes.
3099
+ *
3100
+ * The default `onCheckout` is usually synchronous and usually navigates; the
3101
+ * hosted path is a real promise. Awaiting both means the one visible signal
3102
+ * that money is moving cannot expire early, and cannot outlive the work
3103
+ * either.
3104
+ */
3105
+ private runCheckoutHandoff;
2994
3106
  /** Session-scoped capability key: isolated by API origin and event. */
2995
3107
  private holdStorageKey;
2996
3108
  private rememberedHoldId;
@@ -3000,8 +3112,22 @@ declare class SeatPicker implements GaPromptPicker {
3000
3112
  private restoreRememberedHold;
3001
3113
  /** Section-bearing objects on the active floor (single-floor → doc.objects). */
3002
3114
  private activeFloorObjects;
3003
- /** Attach the F3 overview minimap into the bottom-left chrome region. */
3115
+ /**
3116
+ * Attach the F3 overview minimap into the bottom-left chrome region — on a
3117
+ * layout that has room for it.
3118
+ *
3119
+ * A PHONE NEVER GETS ONE (owner call 2026-09-02). At 375px the overview was
3120
+ * a 114×89 thumbnail of a venue behind a toggle, sitting on top of the map
3121
+ * it was meant to explain, and the drag-the-viewport gesture it exists for
3122
+ * competes with the pan gesture directly underneath it. It is not hidden —
3123
+ * it is not built, so it costs no canvas, no redraw on every pan, and no
3124
+ * button in the tab order. `syncMinimapForLayout` builds and disposes it
3125
+ * across a rotation, and every call site was already optional-chained.
3126
+ */
3004
3127
  private buildMinimap;
3128
+ /** Bring the overview into line with the current breakpoint after a resize
3129
+ * or a rotation. Wide gains one if it has none; narrow loses the one it has. */
3130
+ private syncMinimapForLayout;
3005
3131
  /** Effective category summary price. Object-specific channel prices are added to the range below. */
3006
3132
  /** @internal */ catPrice(c: PricedCategory): number | undefined;
3007
3133
  /** @internal */ catPriceRange(c: PricedCategory): {
@@ -3011,6 +3137,15 @@ declare class SeatPicker implements GaPromptPicker {
3011
3137
  /** Build the compact price selector in the panel header. Choosing a band both
3012
3138
  * filters availability and smoothly frames the matching seats on the map. */
3013
3139
  private buildPriceFilter;
3140
+ /**
3141
+ * Narrow the map to a price band, or clear it.
3142
+ *
3143
+ * Extracted from the select's change handler because the phone rail's
3144
+ * leading "All prices" chip has to perform the SAME reset. Two copies of
3145
+ * this would be two ways for the map, the legend, the floors and the 3D
3146
+ * snapshot to end up disagreeing about what is filtered.
3147
+ */
3148
+ private applyPriceBand;
3014
3149
  /** Build projection, rung and floor controls for arena-scale charts. */
3015
3150
  private buildArenaChrome;
3016
3151
  /** Reflect the engine's current LOD rung onto the pill group. */
@@ -3060,8 +3195,55 @@ declare class SeatPicker implements GaPromptPicker {
3060
3195
  private cancelTableDialog;
3061
3196
  private dismissTableDialog;
3062
3197
  /** @internal */ showConfirm(seat: ExpandedSeat): void;
3198
+ /**
3199
+ * Ask for the press, once, until someone answers.
3200
+ *
3201
+ * The confirm card arrives with two buttons and nothing saying which one
3202
+ * carries the decision. So the commit button shimmers shortly after the card
3203
+ * lands and then breathes — and stops at the first sign of a person touching
3204
+ * the card at all, not after a fixed count. An invitation that keeps being
3205
+ * made after it has been received is nagging, which is why the stop is bound
3206
+ * to three different first-contacts rather than to a timer.
3207
+ *
3208
+ * Nothing here runs under reduced motion: the class is never added, so the
3209
+ * button is simply a button. (pickerMotion also stands the class down, for a
3210
+ * caller that is not this one.)
3211
+ */
3212
+ private inviteCommit;
3213
+ /**
3214
+ * What the confirm card's commit button says.
3215
+ *
3216
+ * "Select" named the mechanism, not the act — on a card already showing Row,
3217
+ * Seat and a price, the one control that decides the purchase was the least
3218
+ * specific thing on it. It names the act instead.
3219
+ *
3220
+ * NO PRICE ON THE BUTTON (owner call 2026-09-02). "Add seat · $180" was tried
3221
+ * and wrapped the button to two lines beside a one-line Cancel on a 310px
3222
+ * phone card. The amount is already the largest thing in the band directly
3223
+ * above, so putting it on the button bought a second copy of a fact the
3224
+ * buyer is looking at and cost the row its shape.
3225
+ *
3226
+ * A seat only. A booth, a table or a general-admission line keeps the
3227
+ * existing wording rather than being told it is adding a "seat" — those
3228
+ * surfaces have their own nouns (the table dialog says "Select whole table"),
3229
+ * and a wrong noun is worse than a general verb.
3230
+ */
3231
+ private addSeatLabel;
3063
3232
  private reanchorConfirm;
3064
3233
  private dismissConfirm;
3234
+ /**
3235
+ * Commit the candidate — and let the press be seen.
3236
+ *
3237
+ * STATE FIRST, ALWAYS. The cart, the totals and the 3D snapshot update on the
3238
+ * same tick as the click; nothing below defers a fact. What IS sequenced is
3239
+ * the card's departure: the button sweeps its accent left to right while the
3240
+ * tick draws and the label turns to "Added", and only then does the card
3241
+ * leave and the seat fly to the tray. Dismissing on the click cut that sweep
3242
+ * off after about one frame — the widget was animating a moment nobody could
3243
+ * see, which is worse than not animating it.
3244
+ *
3245
+ * Reduced motion takes the old path exactly: no sweep, no wait.
3246
+ */
3065
3247
  private commitConfirm;
3066
3248
  private cancelConfirm;
3067
3249
  private closeConfirm;
@@ -3160,7 +3342,18 @@ declare class SeatPicker implements GaPromptPicker {
3160
3342
  * on a different path, which nulls this.hold first).
3161
3343
  */
3162
3344
  private detectBooked;
3345
+ /**
3346
+ * Say that the seats were lost, and make sure nothing says otherwise.
3347
+ *
3348
+ * Every conflict path funnels through here rather than calling `toast`
3349
+ * directly, so the flag and the message can never disagree — and so a
3350
+ * success overlay that somehow got up is taken down with the same gesture
3351
+ * that reports the failure.
3352
+ */
3353
+ private raiseHoldConflict;
3163
3354
  private showBooked;
3355
+ /** Take the confirmation down and give the map back. The booking stands. */
3356
+ private dismissBooked;
3164
3357
  /**
3165
3358
  * A Performance Group hold settled, told to us by the WRAPPER rather than by
3166
3359
  * a socket (§8: this surface has no realtime feed). `detectBooked` waits for
@@ -3210,6 +3403,24 @@ declare class SeatPicker implements GaPromptPicker {
3210
3403
  label: string;
3211
3404
  onClick: () => void;
3212
3405
  }): void;
3406
+ /**
3407
+ * Keep the toast off the confirm card's buttons.
3408
+ *
3409
+ * Both live at the bottom of the map, so a message raised while a card is
3410
+ * open painted straight over Cancel/Add for its full 4.2 seconds — measured
3411
+ * with the toast at [94,677,187,71] across a card at [32,536,310,212]. The
3412
+ * buyer was told a seat had gone by something sitting on the two controls
3413
+ * they needed to answer with.
3414
+ *
3415
+ * The toast rides ABOVE the card's own top edge instead, and only while a
3416
+ * card is up: with no card it belongs where it has always been, at the
3417
+ * bottom of the map. It is the whole bottom-center region that moves,
3418
+ * because the "need more time?" prompt shares it and would collide the same
3419
+ * way.
3420
+ */
3421
+ private liftToastOverConfirm;
3422
+ /** Re-run the lift once the browser has laid the card out. */
3423
+ private liftToastOverConfirmSoon;
3213
3424
  /** Loading silhouette → real venue. The sequence lives in pickerBootReveal. */
3214
3425
  private dismissSkeleton;
3215
3426
  private placeTooltip;
@@ -3481,6 +3692,19 @@ declare class SeatPicker implements GaPromptPicker {
3481
3692
  private openView3dComparison;
3482
3693
  private closeView3dComparison;
3483
3694
  private enter3d;
3695
+ /**
3696
+ * Publish how much room the picker's own top-left chrome takes, as
3697
+ * `--sl-3d-top-inset` on the widget root.
3698
+ *
3699
+ * The 3D layer draws its "Live seat-eye view · …" caption in the same twelve
3700
+ * pixels. That caption is engine surface with its position written inline, so
3701
+ * the widget cannot move it; publishing the measurement is the seam the
3702
+ * engine needs to read one day, and it costs nothing until it does. The
3703
+ * widget's own rules already use it, which is why it is measured rather than
3704
+ * assumed: the region wraps, and a chart with an accessibility flag beside
3705
+ * the back button is two rows tall.
3706
+ */
3707
+ private publish3dTopInset;
3484
3708
  private exit3d;
3485
3709
  /** Current active/restored hold reflected in the tray. */
3486
3710
  getCurrentHold(): HoldResult | null;