@seatlayer/js 0.93.0 → 0.95.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.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { PickerSeat, PickerGAArea, PickerMapTheme, PickerTransport, PickerSelectionValidator, RendererViewMode, PickerSelectionValidity, ChartTheme, AccessibilityType, FloorLabelStyle, LodRung, SectionSummary, PickerAccessNeed, SeatHoverDetails, AccessibleSectionStep, AvailabilityRefreshOutcome, PickerController, ExpandedSeat, TableSelectionDetails, PickerSalesState } from '@seatlayer/core';
1
+ import { PickerSeat, PickerGAArea, PickerMapTheme, PickerTransport, PickerSelectionValidator, RendererViewMode, PickerSelectionValidity, ChartTheme, AccessibilityType, FloorLabelStyle, LodRung, SectionSummary, PickerAccessNeed, SeatHoverDetails, AccessibleSectionStep, AvailabilityRefreshOutcome, RendererMinimapSnapshot, ISeatmapRenderer, PickerController, ExpandedSeat, TableSelectionDetails, PickerSalesState } from '@seatlayer/core';
2
2
  export { ExpandedSeat, PickerMapTheme, PickerSelectionValidator, PickerSelectionValidity, PickerSelectionViolation, RendererViewMode, SeatHoverDetails } from '@seatlayer/core';
3
- import { T as ThemeMode } from './channelsMode-B41tbE29.cjs';
4
- export { A as AccessIntentForbidsDetails, a as AccessLinkRecord, b as AccessLinkReveal, c as AccessLinkState, d as AccessLinkStatus, e as AccessLinkStatusRecord, f as ArchiveBlockedDetails, g as AssignmentBuckets, h as AssignmentDropDetails, i as AssignmentResult, B as BucketRow, C as ChannelAccessIntent, j as ChannelAccessSummary, k as ChannelAllocationPage, l as ChannelAttribution, m as ChannelAuditEntry, n as ChannelAuditPage, o as ChannelCounts, p as ChannelListResult, q as ChannelPreviewProjection, r as ChannelRecord, s as ChannelReport, t as ChannelReportLinkRecord, u as ChannelReportLinkReveal, v as ChannelReportResult, w as ChannelReportRow, x as ChannelSeatStatus, y as ChannelState, z as ChannelsCapabilities, D as ChannelsClient, E as ChannelsMode, F as ChannelsModeHost, G as ChannelsRowView, H as ChannelsSeatView, I as ControlRoomActivityEntry, J as ControlRoomSectionMetric, K as ControlRoomSnapshot, L as EventCategoryAssignmentResult, M as EventScopedManageToken, N as EventTableBookingMode, O as EventTableBookingResult, P as IntentSwitchBlockedDetails, Q as InventoryBooking, R as InventoryBookingActivity, S as InventoryBookingDetail, U as InventoryBookingObject, V as InventoryBookingState, W as InventoryBookingsPage, X as InventoryBookingsQuery, Y as LogEntry, Z as LogPage, _ as ManageApi, $ as ManageApiError, a0 as ReportByStatus, a1 as ReportCategoryMeta, a2 as ReportCategoryRow, a3 as ReportResult, a4 as SeatManager, a5 as SeatManagerActionResult, a6 as SeatManagerActivity, a7 as SeatManagerCapability, a8 as SeatManagerConnection, a9 as SeatManagerFilteredSection, aa as SeatManagerMode, ab as SeatManagerOptions, ac as SeatManagerSelectionValidity, ad as SeatManagerTallies, ae as SelectionSourceRow } from './channelsMode-B41tbE29.cjs';
3
+ import { T as ThemeMode } from './channelsMode-7x0h8OuH.cjs';
4
+ export { A as AccessIntentForbidsDetails, a as AccessLinkRecord, b as AccessLinkReveal, c as AccessLinkState, d as AccessLinkStatus, e as AccessLinkStatusRecord, f as ArchiveBlockedDetails, g as AssignmentBuckets, h as AssignmentDropDetails, i as AssignmentResult, B as BucketRow, C as ChannelAccessIntent, j as ChannelAccessSummary, k as ChannelAllocationPage, l as ChannelAttribution, m as ChannelAuditEntry, n as ChannelAuditPage, o as ChannelCounts, p as ChannelListResult, q as ChannelPreviewProjection, r as ChannelRecord, s as ChannelReport, t as ChannelReportLinkRecord, u as ChannelReportLinkReveal, v as ChannelReportResult, w as ChannelReportRow, x as ChannelSeatStatus, y as ChannelState, z as ChannelsCapabilities, D as ChannelsClient, E as ChannelsMode, F as ChannelsModeHost, G as ChannelsRowView, H as ChannelsSeatView, I as ControlRoomActivityEntry, J as ControlRoomSectionMetric, K as ControlRoomSnapshot, L as EventCategoryAssignmentResult, M as EventScopedManageToken, N as EventTableBookingMode, O as EventTableBookingResult, P as IntentSwitchBlockedDetails, Q as InventoryBooking, R as InventoryBookingActivity, S as InventoryBookingDetail, U as InventoryBookingObject, V as InventoryBookingState, W as InventoryBookingsPage, X as InventoryBookingsQuery, Y as LogEntry, Z as LogPage, _ as ManageApi, $ as ManageApiError, a0 as ReportByStatus, a1 as ReportCategoryMeta, a2 as ReportCategoryRow, a3 as ReportResult, a4 as SeatManager, a5 as SeatManagerActionResult, a6 as SeatManagerActivity, a7 as SeatManagerArea, a8 as SeatManagerCapability, a9 as SeatManagerConnection, aa as SeatManagerFilteredSection, ab as SeatManagerMode, ac as SeatManagerOptions, ad as SeatManagerSelectionValidity, ae as SeatManagerTallies, af as SelectionSourceRow } from './channelsMode-7x0h8OuH.cjs';
5
5
  import * as _seatlayer_core_core_seatConfidence from '@seatlayer/core/core/seatConfidence';
6
6
  import { SeatConfidenceDisclosure } from '@seatlayer/core/core/seatConfidence';
7
7
  import { SeatViewStopName, Venue3DHandle, SeatState3D, SeatView } from '@seatlayer/core/view3d';
@@ -338,14 +338,26 @@ interface SubscribeTicket {
338
338
  protocols?: string[];
339
339
  }
340
340
  interface BuyerRealtimeOptions {
341
- /** The subscribe URL. Must never carry a credential — asserted below. */
342
- url: string;
341
+ /** The subscribe URL. Must never carry a credential — asserted below. A
342
+ * function is read on every connection attempt, so a reconnect can carry
343
+ * a rotated viewer id (see `onIdleExpired`). */
344
+ url: string | (() => string);
343
345
  sink: RealtimeSink;
344
346
  /** Mint a one-use ticket for THIS connection attempt. Returns null for the
345
347
  * anonymous public case (no ticket needed). Throwing stops the client. */
346
348
  mintTicket?: () => Promise<SubscribeTicket | null>;
347
349
  /** Typed terminal access states. A 4401 `access_expired` close reconnects. */
348
350
  onAccessUnavailable?: (event: BuyerAccessUnavailableEvent) => void;
351
+ /**
352
+ * The server's idle backstop closed the socket: 4401 `idle_expired`, sent
353
+ * once a public socket has stood for EVENT_SOCKET_IDLE_MINUTES. The client
354
+ * stops — the same socket would only be refused again — and the widget
355
+ * decides: raise its paused card, or, when the buyer is plainly still here
356
+ * (a live hold, recent input), `restart()` at once behind a rotated viewer
357
+ * id. Absent, the close is reported through `onAccessUnavailable` as the
358
+ * terminal revoked state, exactly as the runtimes before 0.94 read it.
359
+ */
360
+ onIdleExpired?: () => void;
349
361
  /** Test seam. Defaults to the global WebSocket. */
350
362
  socketFactory?: (url: string, protocols: string[]) => WebSocket;
351
363
  /** Test seam for the keepalive/backoff timers. */
@@ -407,6 +419,9 @@ declare class BuyerRealtimeClient {
407
419
  * Workflow step that has to replay deterministically.
408
420
  */
409
421
  private scheduleReconnect;
422
+ /** Socket reconnects this client has made in its lifetime — for the telemetry beacon. */
423
+ private reconnectCount;
424
+ get reconnects(): number;
410
425
  private clearPongTimer;
411
426
  private clearTimers;
412
427
  }
@@ -2079,6 +2094,8 @@ interface SeatingChartOptions {
2079
2094
  declare class SeatingChart {
2080
2095
  private readonly opts;
2081
2096
  private readonly controller;
2097
+ private readonly chartFetch?;
2098
+ private renderErrorEmitted;
2082
2099
  /** Publishable key used only by the public-only direct bootstrap path. */
2083
2100
  readonly publicKey?: string;
2084
2101
  private mount;
@@ -3159,28 +3176,56 @@ interface PerformanceGroupPickerInternal {
3159
3176
  type ConfirmCardMode = 'add' | 'remove';
3160
3177
 
3161
3178
  /**
3162
- * pickerMinimap — the F3 venue-overview minimap: build, layout, static paint,
3163
- * viewport rectangle, and the pointer/keyboard interactions that pan or focus
3164
- * from it.
3165
- *
3166
- * Lifted out of SeatPicker.ts with the method bodies verbatim — statement for
3167
- * statement, including canvas call order, which matters here because a 2D
3168
- * context is a state machine and jsdom cannot exercise it. The ONLY edits are
3169
- * the indirections through {@link MinimapHost}: `this.controller` →
3170
- * `this.host.controller`, `this.cssVar` → `this.host.cssVar`, `this.tf` →
3171
- * the module-level `tfStatic` it always delegated to, and the widget root and
3172
- * focused-section label behind accessors (SeatPicker replaces both across a
3173
- * re-mount, so they must be read late, not captured).
3179
+ * MapCamera — what a map-chrome component (minimap, zoom pills, crumb) needs
3180
+ * from the surface that owns the renderer (plan item 7, slice A).
3174
3181
  *
3175
- * `build()` also takes its mount element as an argument rather than reading
3176
- * SeatPicker's region map. Everything else — the two-canvas base/blit split,
3177
- * the drag-capture bookkeeping, the click suppression after a drag — is
3178
- * unchanged.
3182
+ * Named so the chrome can be shared: the buyer picker's `PickerController`
3183
+ * satisfies it by type, and the control room's manager satisfies it over its
3184
+ * own renderer. Nothing here is picker-specific — it is the camera, the
3185
+ * floors, the focus, and the overview snapshot the renderer already keeps.
3179
3186
  */
3180
3187
 
3181
- /** What the minimap needs from the widget around it. */
3188
+ interface MapRect {
3189
+ x: number;
3190
+ y: number;
3191
+ width: number;
3192
+ height: number;
3193
+ }
3194
+ interface MapCamera {
3195
+ /** World-space rect currently visible + full chart bounds; null before a chart. */
3196
+ getViewport(): {
3197
+ visible: MapRect;
3198
+ bounds: MapRect;
3199
+ } | null;
3200
+ getMinimapSnapshot(): RendererMinimapSnapshot;
3201
+ /** Pan without changing zoom so `point` becomes the viewport centre. */
3202
+ panToWorld(point: {
3203
+ x: number;
3204
+ y: number;
3205
+ }): void;
3206
+ /** Leave section-focus dimming without changing the current zoom. */
3207
+ clearSectionFocus(): void;
3208
+ /** Glide in on a section (the host surfaces whatever it surfaces on a tap). */
3209
+ focusSection(id: string, anchor?: {
3210
+ x: number;
3211
+ y: number;
3212
+ }): void;
3213
+ /** The whole venue again: focus off, fit the chart. */
3214
+ overview(): void;
3215
+ getFloors(): {
3216
+ id: string;
3217
+ name: string;
3218
+ }[];
3219
+ getActiveFloorId(): string;
3220
+ isFloorOverview(): boolean;
3221
+ /** Optional: the renderer itself, for hosts that still reach past the camera. */
3222
+ getRenderer?(): ISeatmapRenderer | null;
3223
+ }
3224
+
3225
+ /** What the minimap needs from the surface around it. */
3182
3226
  interface MinimapHost {
3183
- readonly controller: PickerController;
3227
+ /** The camera it reads and moves — a picker controller or a manager's map. */
3228
+ readonly controller: MapCamera;
3184
3229
  /** The widget root — it carries `data-minimap-open`. A function, not a
3185
3230
  * field: SeatPicker rebuilds its root, and a captured one goes stale. */
3186
3231
  root(): HTMLElement | null;
@@ -3189,8 +3234,15 @@ interface MinimapHost {
3189
3234
  /** Label of the last surfaced section card. Backs the minimap caption when
3190
3235
  * the renderer snapshot reports no active section. */
3191
3236
  focusedSectionLabel(): string | undefined;
3237
+ /**
3238
+ * The display colour of a category, for the seat-dot thumbnail of a chart
3239
+ * with no sections. ASKED OF THE HOST so a colourblind-safe remap reaches
3240
+ * the map, the legend and this thumbnail from one place. Undefined = the
3241
+ * flat availability colour.
3242
+ */
3243
+ tint?(categoryKey: string): string | undefined;
3192
3244
  }
3193
- declare class PickerMinimap {
3245
+ declare class MapMinimap {
3194
3246
  private readonly host;
3195
3247
  private miniCanvas;
3196
3248
  private miniBase;
@@ -3511,6 +3563,8 @@ declare class SeatPicker implements GaPromptPicker {
3511
3563
  /** @internal Read by pickerGaPrompt for the `onGAPrompt` host hook. */
3512
3564
  readonly opts: SeatPickerOptions;
3513
3565
  /** @internal */ readonly api: PickerTransport;
3566
+ private readonly chartFetch;
3567
+ private renderErrorEmitted;
3514
3568
  /** Authenticated view media, cached only for this picker lifetime. */
3515
3569
  /** @internal */ readonly buyerAssetUrls: BuyerAssetObjectUrls;
3516
3570
  /** Our own public client, or null when the host injected a transport. */
@@ -3519,6 +3573,8 @@ declare class SeatPicker implements GaPromptPicker {
3519
3573
  private readonly access;
3520
3574
  private realtime;
3521
3575
  private accessEl;
3576
+ /** The buyer's idle clock (0.94, #78; pickerIdle.ts). Null until mounted or when turned off. */
3577
+ private idleClock;
3522
3578
  /** @internal */ readonly apiBase: string;
3523
3579
  /** @internal */ controller: PickerController;
3524
3580
  /** @internal */ maxTickets: number;
@@ -3687,6 +3743,14 @@ declare class SeatPicker implements GaPromptPicker {
3687
3743
  /** "★ Best seats" premium quick-pick toggle — biases best-available to premium seats. */
3688
3744
  private baPremium;
3689
3745
  private bestAvailableConfirm;
3746
+ /**
3747
+ * Categories with nothing free, as the tray last drew them. Availability
3748
+ * deltas repaint the legend, not the tray, so `syncSoldout` compares against
3749
+ * this and repaints the tray only when a category sells out or comes back.
3750
+ */
3751
+ private baSoldOutSig;
3752
+ /** Every category is sold out, so there is no best-seats form to open. */
3753
+ /** @internal */ bestAvailableSoldOut: boolean;
3690
3754
  /** Event sales window is closed (read-only load state / live close). */
3691
3755
  /** @internal */ salesClosed: boolean;
3692
3756
  /**
@@ -3746,7 +3810,7 @@ declare class SeatPicker implements GaPromptPicker {
3746
3810
  /** The panel's price-band <select>, so the rail's reset chip can keep it in
3747
3811
  * step. Null when the chart has fewer than two bands and none was built. */
3748
3812
  /** @internal */ priceSelect: HTMLSelectElement | null;
3749
- /** @internal */ minimap: PickerMinimap | null;
3813
+ /** @internal */ minimap: MapMinimap | null;
3750
3814
  private pickerLayoutSize;
3751
3815
  private fullscreenAffordanceSize;
3752
3816
  /** @internal */ priceBandKeys: Set<string> | null;
@@ -4879,6 +4943,10 @@ declare class SeatPicker implements GaPromptPicker {
4879
4943
  */
4880
4944
  private recoverAccess;
4881
4945
  private dismissAccessPanel;
4946
+ /** The idle clock and the paused card — see pickerIdlePause.ts. */
4947
+ private get idlePauseHost();
4948
+ private startIdleClock;
4949
+ private resumeFromIdle;
4882
4950
  /**
4883
4951
  * The hold ran out under the buyer's feet — say so, and block.
4884
4952
  *
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { PickerSeat, PickerGAArea, PickerMapTheme, PickerTransport, PickerSelectionValidator, RendererViewMode, PickerSelectionValidity, ChartTheme, AccessibilityType, FloorLabelStyle, LodRung, SectionSummary, PickerAccessNeed, SeatHoverDetails, AccessibleSectionStep, AvailabilityRefreshOutcome, PickerController, ExpandedSeat, TableSelectionDetails, PickerSalesState } from '@seatlayer/core';
1
+ import { PickerSeat, PickerGAArea, PickerMapTheme, PickerTransport, PickerSelectionValidator, RendererViewMode, PickerSelectionValidity, ChartTheme, AccessibilityType, FloorLabelStyle, LodRung, SectionSummary, PickerAccessNeed, SeatHoverDetails, AccessibleSectionStep, AvailabilityRefreshOutcome, RendererMinimapSnapshot, ISeatmapRenderer, PickerController, ExpandedSeat, TableSelectionDetails, PickerSalesState } from '@seatlayer/core';
2
2
  export { ExpandedSeat, PickerMapTheme, PickerSelectionValidator, PickerSelectionValidity, PickerSelectionViolation, RendererViewMode, SeatHoverDetails } from '@seatlayer/core';
3
- import { T as ThemeMode } from './channelsMode-B41tbE29.js';
4
- export { A as AccessIntentForbidsDetails, a as AccessLinkRecord, b as AccessLinkReveal, c as AccessLinkState, d as AccessLinkStatus, e as AccessLinkStatusRecord, f as ArchiveBlockedDetails, g as AssignmentBuckets, h as AssignmentDropDetails, i as AssignmentResult, B as BucketRow, C as ChannelAccessIntent, j as ChannelAccessSummary, k as ChannelAllocationPage, l as ChannelAttribution, m as ChannelAuditEntry, n as ChannelAuditPage, o as ChannelCounts, p as ChannelListResult, q as ChannelPreviewProjection, r as ChannelRecord, s as ChannelReport, t as ChannelReportLinkRecord, u as ChannelReportLinkReveal, v as ChannelReportResult, w as ChannelReportRow, x as ChannelSeatStatus, y as ChannelState, z as ChannelsCapabilities, D as ChannelsClient, E as ChannelsMode, F as ChannelsModeHost, G as ChannelsRowView, H as ChannelsSeatView, I as ControlRoomActivityEntry, J as ControlRoomSectionMetric, K as ControlRoomSnapshot, L as EventCategoryAssignmentResult, M as EventScopedManageToken, N as EventTableBookingMode, O as EventTableBookingResult, P as IntentSwitchBlockedDetails, Q as InventoryBooking, R as InventoryBookingActivity, S as InventoryBookingDetail, U as InventoryBookingObject, V as InventoryBookingState, W as InventoryBookingsPage, X as InventoryBookingsQuery, Y as LogEntry, Z as LogPage, _ as ManageApi, $ as ManageApiError, a0 as ReportByStatus, a1 as ReportCategoryMeta, a2 as ReportCategoryRow, a3 as ReportResult, a4 as SeatManager, a5 as SeatManagerActionResult, a6 as SeatManagerActivity, a7 as SeatManagerCapability, a8 as SeatManagerConnection, a9 as SeatManagerFilteredSection, aa as SeatManagerMode, ab as SeatManagerOptions, ac as SeatManagerSelectionValidity, ad as SeatManagerTallies, ae as SelectionSourceRow } from './channelsMode-B41tbE29.js';
3
+ import { T as ThemeMode } from './channelsMode-7x0h8OuH.js';
4
+ export { A as AccessIntentForbidsDetails, a as AccessLinkRecord, b as AccessLinkReveal, c as AccessLinkState, d as AccessLinkStatus, e as AccessLinkStatusRecord, f as ArchiveBlockedDetails, g as AssignmentBuckets, h as AssignmentDropDetails, i as AssignmentResult, B as BucketRow, C as ChannelAccessIntent, j as ChannelAccessSummary, k as ChannelAllocationPage, l as ChannelAttribution, m as ChannelAuditEntry, n as ChannelAuditPage, o as ChannelCounts, p as ChannelListResult, q as ChannelPreviewProjection, r as ChannelRecord, s as ChannelReport, t as ChannelReportLinkRecord, u as ChannelReportLinkReveal, v as ChannelReportResult, w as ChannelReportRow, x as ChannelSeatStatus, y as ChannelState, z as ChannelsCapabilities, D as ChannelsClient, E as ChannelsMode, F as ChannelsModeHost, G as ChannelsRowView, H as ChannelsSeatView, I as ControlRoomActivityEntry, J as ControlRoomSectionMetric, K as ControlRoomSnapshot, L as EventCategoryAssignmentResult, M as EventScopedManageToken, N as EventTableBookingMode, O as EventTableBookingResult, P as IntentSwitchBlockedDetails, Q as InventoryBooking, R as InventoryBookingActivity, S as InventoryBookingDetail, U as InventoryBookingObject, V as InventoryBookingState, W as InventoryBookingsPage, X as InventoryBookingsQuery, Y as LogEntry, Z as LogPage, _ as ManageApi, $ as ManageApiError, a0 as ReportByStatus, a1 as ReportCategoryMeta, a2 as ReportCategoryRow, a3 as ReportResult, a4 as SeatManager, a5 as SeatManagerActionResult, a6 as SeatManagerActivity, a7 as SeatManagerArea, a8 as SeatManagerCapability, a9 as SeatManagerConnection, aa as SeatManagerFilteredSection, ab as SeatManagerMode, ac as SeatManagerOptions, ad as SeatManagerSelectionValidity, ae as SeatManagerTallies, af as SelectionSourceRow } from './channelsMode-7x0h8OuH.js';
5
5
  import * as _seatlayer_core_core_seatConfidence from '@seatlayer/core/core/seatConfidence';
6
6
  import { SeatConfidenceDisclosure } from '@seatlayer/core/core/seatConfidence';
7
7
  import { SeatViewStopName, Venue3DHandle, SeatState3D, SeatView } from '@seatlayer/core/view3d';
@@ -338,14 +338,26 @@ interface SubscribeTicket {
338
338
  protocols?: string[];
339
339
  }
340
340
  interface BuyerRealtimeOptions {
341
- /** The subscribe URL. Must never carry a credential — asserted below. */
342
- url: string;
341
+ /** The subscribe URL. Must never carry a credential — asserted below. A
342
+ * function is read on every connection attempt, so a reconnect can carry
343
+ * a rotated viewer id (see `onIdleExpired`). */
344
+ url: string | (() => string);
343
345
  sink: RealtimeSink;
344
346
  /** Mint a one-use ticket for THIS connection attempt. Returns null for the
345
347
  * anonymous public case (no ticket needed). Throwing stops the client. */
346
348
  mintTicket?: () => Promise<SubscribeTicket | null>;
347
349
  /** Typed terminal access states. A 4401 `access_expired` close reconnects. */
348
350
  onAccessUnavailable?: (event: BuyerAccessUnavailableEvent) => void;
351
+ /**
352
+ * The server's idle backstop closed the socket: 4401 `idle_expired`, sent
353
+ * once a public socket has stood for EVENT_SOCKET_IDLE_MINUTES. The client
354
+ * stops — the same socket would only be refused again — and the widget
355
+ * decides: raise its paused card, or, when the buyer is plainly still here
356
+ * (a live hold, recent input), `restart()` at once behind a rotated viewer
357
+ * id. Absent, the close is reported through `onAccessUnavailable` as the
358
+ * terminal revoked state, exactly as the runtimes before 0.94 read it.
359
+ */
360
+ onIdleExpired?: () => void;
349
361
  /** Test seam. Defaults to the global WebSocket. */
350
362
  socketFactory?: (url: string, protocols: string[]) => WebSocket;
351
363
  /** Test seam for the keepalive/backoff timers. */
@@ -407,6 +419,9 @@ declare class BuyerRealtimeClient {
407
419
  * Workflow step that has to replay deterministically.
408
420
  */
409
421
  private scheduleReconnect;
422
+ /** Socket reconnects this client has made in its lifetime — for the telemetry beacon. */
423
+ private reconnectCount;
424
+ get reconnects(): number;
410
425
  private clearPongTimer;
411
426
  private clearTimers;
412
427
  }
@@ -2079,6 +2094,8 @@ interface SeatingChartOptions {
2079
2094
  declare class SeatingChart {
2080
2095
  private readonly opts;
2081
2096
  private readonly controller;
2097
+ private readonly chartFetch?;
2098
+ private renderErrorEmitted;
2082
2099
  /** Publishable key used only by the public-only direct bootstrap path. */
2083
2100
  readonly publicKey?: string;
2084
2101
  private mount;
@@ -3159,28 +3176,56 @@ interface PerformanceGroupPickerInternal {
3159
3176
  type ConfirmCardMode = 'add' | 'remove';
3160
3177
 
3161
3178
  /**
3162
- * pickerMinimap — the F3 venue-overview minimap: build, layout, static paint,
3163
- * viewport rectangle, and the pointer/keyboard interactions that pan or focus
3164
- * from it.
3165
- *
3166
- * Lifted out of SeatPicker.ts with the method bodies verbatim — statement for
3167
- * statement, including canvas call order, which matters here because a 2D
3168
- * context is a state machine and jsdom cannot exercise it. The ONLY edits are
3169
- * the indirections through {@link MinimapHost}: `this.controller` →
3170
- * `this.host.controller`, `this.cssVar` → `this.host.cssVar`, `this.tf` →
3171
- * the module-level `tfStatic` it always delegated to, and the widget root and
3172
- * focused-section label behind accessors (SeatPicker replaces both across a
3173
- * re-mount, so they must be read late, not captured).
3179
+ * MapCamera — what a map-chrome component (minimap, zoom pills, crumb) needs
3180
+ * from the surface that owns the renderer (plan item 7, slice A).
3174
3181
  *
3175
- * `build()` also takes its mount element as an argument rather than reading
3176
- * SeatPicker's region map. Everything else — the two-canvas base/blit split,
3177
- * the drag-capture bookkeeping, the click suppression after a drag — is
3178
- * unchanged.
3182
+ * Named so the chrome can be shared: the buyer picker's `PickerController`
3183
+ * satisfies it by type, and the control room's manager satisfies it over its
3184
+ * own renderer. Nothing here is picker-specific — it is the camera, the
3185
+ * floors, the focus, and the overview snapshot the renderer already keeps.
3179
3186
  */
3180
3187
 
3181
- /** What the minimap needs from the widget around it. */
3188
+ interface MapRect {
3189
+ x: number;
3190
+ y: number;
3191
+ width: number;
3192
+ height: number;
3193
+ }
3194
+ interface MapCamera {
3195
+ /** World-space rect currently visible + full chart bounds; null before a chart. */
3196
+ getViewport(): {
3197
+ visible: MapRect;
3198
+ bounds: MapRect;
3199
+ } | null;
3200
+ getMinimapSnapshot(): RendererMinimapSnapshot;
3201
+ /** Pan without changing zoom so `point` becomes the viewport centre. */
3202
+ panToWorld(point: {
3203
+ x: number;
3204
+ y: number;
3205
+ }): void;
3206
+ /** Leave section-focus dimming without changing the current zoom. */
3207
+ clearSectionFocus(): void;
3208
+ /** Glide in on a section (the host surfaces whatever it surfaces on a tap). */
3209
+ focusSection(id: string, anchor?: {
3210
+ x: number;
3211
+ y: number;
3212
+ }): void;
3213
+ /** The whole venue again: focus off, fit the chart. */
3214
+ overview(): void;
3215
+ getFloors(): {
3216
+ id: string;
3217
+ name: string;
3218
+ }[];
3219
+ getActiveFloorId(): string;
3220
+ isFloorOverview(): boolean;
3221
+ /** Optional: the renderer itself, for hosts that still reach past the camera. */
3222
+ getRenderer?(): ISeatmapRenderer | null;
3223
+ }
3224
+
3225
+ /** What the minimap needs from the surface around it. */
3182
3226
  interface MinimapHost {
3183
- readonly controller: PickerController;
3227
+ /** The camera it reads and moves — a picker controller or a manager's map. */
3228
+ readonly controller: MapCamera;
3184
3229
  /** The widget root — it carries `data-minimap-open`. A function, not a
3185
3230
  * field: SeatPicker rebuilds its root, and a captured one goes stale. */
3186
3231
  root(): HTMLElement | null;
@@ -3189,8 +3234,15 @@ interface MinimapHost {
3189
3234
  /** Label of the last surfaced section card. Backs the minimap caption when
3190
3235
  * the renderer snapshot reports no active section. */
3191
3236
  focusedSectionLabel(): string | undefined;
3237
+ /**
3238
+ * The display colour of a category, for the seat-dot thumbnail of a chart
3239
+ * with no sections. ASKED OF THE HOST so a colourblind-safe remap reaches
3240
+ * the map, the legend and this thumbnail from one place. Undefined = the
3241
+ * flat availability colour.
3242
+ */
3243
+ tint?(categoryKey: string): string | undefined;
3192
3244
  }
3193
- declare class PickerMinimap {
3245
+ declare class MapMinimap {
3194
3246
  private readonly host;
3195
3247
  private miniCanvas;
3196
3248
  private miniBase;
@@ -3511,6 +3563,8 @@ declare class SeatPicker implements GaPromptPicker {
3511
3563
  /** @internal Read by pickerGaPrompt for the `onGAPrompt` host hook. */
3512
3564
  readonly opts: SeatPickerOptions;
3513
3565
  /** @internal */ readonly api: PickerTransport;
3566
+ private readonly chartFetch;
3567
+ private renderErrorEmitted;
3514
3568
  /** Authenticated view media, cached only for this picker lifetime. */
3515
3569
  /** @internal */ readonly buyerAssetUrls: BuyerAssetObjectUrls;
3516
3570
  /** Our own public client, or null when the host injected a transport. */
@@ -3519,6 +3573,8 @@ declare class SeatPicker implements GaPromptPicker {
3519
3573
  private readonly access;
3520
3574
  private realtime;
3521
3575
  private accessEl;
3576
+ /** The buyer's idle clock (0.94, #78; pickerIdle.ts). Null until mounted or when turned off. */
3577
+ private idleClock;
3522
3578
  /** @internal */ readonly apiBase: string;
3523
3579
  /** @internal */ controller: PickerController;
3524
3580
  /** @internal */ maxTickets: number;
@@ -3687,6 +3743,14 @@ declare class SeatPicker implements GaPromptPicker {
3687
3743
  /** "★ Best seats" premium quick-pick toggle — biases best-available to premium seats. */
3688
3744
  private baPremium;
3689
3745
  private bestAvailableConfirm;
3746
+ /**
3747
+ * Categories with nothing free, as the tray last drew them. Availability
3748
+ * deltas repaint the legend, not the tray, so `syncSoldout` compares against
3749
+ * this and repaints the tray only when a category sells out or comes back.
3750
+ */
3751
+ private baSoldOutSig;
3752
+ /** Every category is sold out, so there is no best-seats form to open. */
3753
+ /** @internal */ bestAvailableSoldOut: boolean;
3690
3754
  /** Event sales window is closed (read-only load state / live close). */
3691
3755
  /** @internal */ salesClosed: boolean;
3692
3756
  /**
@@ -3746,7 +3810,7 @@ declare class SeatPicker implements GaPromptPicker {
3746
3810
  /** The panel's price-band <select>, so the rail's reset chip can keep it in
3747
3811
  * step. Null when the chart has fewer than two bands and none was built. */
3748
3812
  /** @internal */ priceSelect: HTMLSelectElement | null;
3749
- /** @internal */ minimap: PickerMinimap | null;
3813
+ /** @internal */ minimap: MapMinimap | null;
3750
3814
  private pickerLayoutSize;
3751
3815
  private fullscreenAffordanceSize;
3752
3816
  /** @internal */ priceBandKeys: Set<string> | null;
@@ -4879,6 +4943,10 @@ declare class SeatPicker implements GaPromptPicker {
4879
4943
  */
4880
4944
  private recoverAccess;
4881
4945
  private dismissAccessPanel;
4946
+ /** The idle clock and the paused card — see pickerIdlePause.ts. */
4947
+ private get idlePauseHost();
4948
+ private startIdleClock;
4949
+ private resumeFromIdle;
4882
4950
  /**
4883
4951
  * The hold ran out under the buyer's feet — say so, and block.
4884
4952
  *