@seatlayer/js 0.8.0 → 0.10.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
@@ -271,6 +271,40 @@ declare class EmbeddedDesigner {
271
271
  * so plain host CSS can restyle too.
272
272
  */
273
273
 
274
+ /**
275
+ * Stable checkout-handoff contract (P4). Passed as the THIRD argument to
276
+ * `onCheckout(hold, seats, handoff)` — additive, so the legacy `(hold, seats)`
277
+ * shape used by DesiPass web-v2 (SDK 0.7.3+) is untouched. This is the object to
278
+ * build your order against: it is self-contained (holdId, expiry, currency, and
279
+ * per-line tier + price) and never changes shape across minor releases.
280
+ */
281
+ interface CheckoutLineItem {
282
+ /** Seat label (or GA synthetic-unit label). */
283
+ label: string;
284
+ /** Chart object id (row/booth/GA area) the unit belongs to. */
285
+ objectId: string;
286
+ objectType: 'seat' | 'booth' | 'ga';
287
+ categoryKey: string;
288
+ /** Chosen ticket tier id (Adult/Child/…), or null when the category has no tiers. */
289
+ tierId: string | null;
290
+ /** Unit price in MAJOR currency units (e.g. 45 = 45.00). Server-authoritative. */
291
+ unitPrice: number;
292
+ /** ISO-4217, resolved server-side (per-event override → org → USD). */
293
+ currency: string;
294
+ quantity: number;
295
+ }
296
+ interface CheckoutHandoff {
297
+ /** Server hold id — pass this to YOUR book call. */
298
+ holdId: string;
299
+ /** Epoch ms the hold expires (after any extensions). */
300
+ expiresAt: number;
301
+ /** ISO-4217 currency for the whole order. */
302
+ currency: string;
303
+ /** Priced line items (tier + unit price + currency), server-authoritative. */
304
+ lineItems: CheckoutLineItem[];
305
+ /** Convenience total in major units (Σ unitPrice × quantity). */
306
+ total: number;
307
+ }
274
308
  /** Host theme overrides — any subset; unset keys fall back to the org's chart theme, then defaults. */
275
309
  interface SeatPickerTheme {
276
310
  /** Brand accent (CTA, active chips, hold pill). */
@@ -332,9 +366,18 @@ interface SeatPickerOptions {
332
366
  seatView?: boolean;
333
367
  /**
334
368
  * Buyer pressed the CTA and the hold succeeded — hand off to YOUR checkout.
335
- * The hold carries holdId, expiresAt, seat labels and priced line items.
369
+ * `hold` and `seats` are the legacy args (unchanged since 0.6). `handoff` (P4)
370
+ * is the stable, self-contained {@link CheckoutHandoff} to build your order
371
+ * against — holdId, expiry, currency and priced line items. Prefer it.
372
+ */
373
+ onCheckout?: (hold: HoldResult, seats: PickerSeat[], handoff: CheckoutHandoff) => void;
374
+ /**
375
+ * The held seats were BOOKED (P4) — your server completed payment and the
376
+ * booking landed over the realtime channel while the widget was still open.
377
+ * The widget shows a success state; use this to advance your own UI (receipt,
378
+ * redirect). Fires once per hold.
336
379
  */
337
- onCheckout?: (hold: HoldResult, seats: PickerSeat[]) => void;
380
+ onBooked?: (handoff: CheckoutHandoff) => void;
338
381
  /** Selection changed (tap or best-available). */
339
382
  onSelectionChange?: (seats: PickerSeat[]) => void;
340
383
  /** The open hold expired server-side (widget already reset itself). */
@@ -351,11 +394,21 @@ declare class SeatPicker {
351
394
  private rendered;
352
395
  private destroyed;
353
396
  private els;
397
+ /** Feature 6 anchor regions — positioned flex containers over the map. */
398
+ private regions;
354
399
  private ro;
355
400
  private holdTimer;
356
401
  private toastTimer;
357
402
  private currency;
358
403
  private hold;
404
+ /** Latest server expiry for the open hold (moves on extend). */
405
+ private holdExpiresAt;
406
+ /** True once we handed off to checkout — arms booked-confirmation detection. */
407
+ private handedOff;
408
+ /** Guards single onBooked + single success overlay per hold. */
409
+ private bookedShown;
410
+ private extendEl;
411
+ private bookedEl;
359
412
  private gaQty;
360
413
  private tipEl;
361
414
  private tipPos;
@@ -371,6 +424,22 @@ declare class SeatPicker {
371
424
  private viewEl;
372
425
  private viewCleanup;
373
426
  private allSeatsCache;
427
+ private miniEl;
428
+ private miniCanvas;
429
+ private miniBase;
430
+ private miniTf;
431
+ private priceBandKeys;
432
+ private priceFilterEl;
433
+ /** Last surfaced section summary (re-rendered when the price band changes). */
434
+ private lastSection;
435
+ /** Section card collapsed to its slim pill (seat-picking has begun). */
436
+ private secCardCollapsed;
437
+ /** When the card was (re)shown — the focus glide's own view change must not collapse it. */
438
+ private secCardShownAt;
439
+ /** Previous tray ticket count — first 0→n transition auto-expands the mobile sheet. */
440
+ private lastTrayCount;
441
+ private a11yChipsEl;
442
+ private cbEl;
374
443
  private modalScrim;
375
444
  private prevFocus;
376
445
  private escHandler;
@@ -386,6 +455,54 @@ declare class SeatPicker {
386
455
  static open(options: Omit<SeatPickerOptions, 'container'>): Promise<SeatPicker>;
387
456
  constructor(options: SeatPickerOptions);
388
457
  render(): Promise<this>;
458
+ /**
459
+ * Move layout-dependent chrome between its wide dock (map regions / zoom
460
+ * column) and its narrow dock (the sheet's consolidated Filters row), and
461
+ * re-render the section card in the form the layout wants (docked card/pill
462
+ * on wide, sheet strip on narrow). Runs on every layout flip + once post-render.
463
+ */
464
+ private dockLayoutChrome;
465
+ /** The "Need more time?" prompt shown in the hold's final EXTEND_PROMPT_MS. */
466
+ private buildExtendPrompt;
467
+ /** Success overlay + onBooked fire when the held seats settle to booked. */
468
+ private buildBookedOverlay;
469
+ /**
470
+ * Create the positioned flex containers that own every persistent map overlay.
471
+ * Appended once after controller.render(); each chrome piece is then appended
472
+ * INTO its region and flows within it, so nothing free-floats over anything
473
+ * else. Regions carve the map into non-overlapping zones (top strip split into
474
+ * left/center/right, left rail, and the three used corners).
475
+ */
476
+ private buildRegions;
477
+ /** Read a resolved --sl-* token value (canvas needs a real color, not var()). */
478
+ private cssVar;
479
+ /** Section-bearing objects on the active floor (single-floor → doc.objects). */
480
+ private activeFloorObjects;
481
+ /**
482
+ * Build the overview minimap: a static venue thumbnail (section outlines, or
483
+ * seat dots when the chart has no sections) with the live viewport rectangle
484
+ * drawn on top. The rect tracks pan/zoom via the constructor's onViewChange.
485
+ */
486
+ private buildMinimap;
487
+ /** Repaint the static overview + rect (floor switch, live open/close). */
488
+ private refreshMinimap;
489
+ /** Paint the venue overview into the offscreen base canvas. */
490
+ private drawMinimapStatic;
491
+ /** Blit the base overview, then stroke the current viewport rectangle on top. */
492
+ private drawMinimapRect;
493
+ /** Minimap click → focus the section under the point (or overview on a miss). */
494
+ private minimapJump;
495
+ /** Effective price of a category (first tier when tiered, else base price). */
496
+ private catPrice;
497
+ /** Derive price bands: one chip per distinct price (≤5), else quantile ranges. */
498
+ private priceBands;
499
+ /**
500
+ * Build the price-band chip row in the side panel, directly under the "Prices"
501
+ * header and above the legend it dims. Living in the panel (not a map overlay)
502
+ * keeps it clear of the top-center rung pills and top-left a11y chips, and it
503
+ * rides the bottom sheet on narrow layouts. Skipped when there's <2 bands.
504
+ */
505
+ private buildPriceFilter;
389
506
  /** Build the rung pills (charts with sections) and floor switcher (>1 floor). */
390
507
  private buildArenaChrome;
391
508
  /** Reflect the engine's current LOD rung onto the pill group. */
@@ -394,6 +511,22 @@ declare class SeatPicker {
394
511
  private syncFloors;
395
512
  /** Show (or clear, on null) the tapped-section summary card. */
396
513
  private showSectionCard;
514
+ /**
515
+ * Render the section card in the form the layout + state want: expanded card
516
+ * or slim pill in the top-center anchor region (wide), or a compact strip in
517
+ * the sheet head (narrow). Never floats over the seats at the tap point.
518
+ */
519
+ private renderSectionCard;
520
+ /** Collapse the expanded card to its slim pill (seat-picking started). */
521
+ private collapseSectionCard;
522
+ /**
523
+ * onViewChange hook for the card. The focus glide's own settle (within the
524
+ * grace window) enforces the ~25% coverage rule with the FINAL viewport; any
525
+ * later pan/zoom means seat-picking has begun → collapse to the pill.
526
+ */
527
+ private sectionCardOnView;
528
+ /** Fraction of the focused section's on-screen bbox covered by the card. */
529
+ private sectionCardCoverage;
397
530
  /** aria-live readout when keyboard focus lands on a seat. */
398
531
  private announceSeat;
399
532
  private showConfirm;
@@ -418,6 +551,21 @@ declare class SeatPicker {
418
551
  private handleCta;
419
552
  private startHoldTimer;
420
553
  private stopHoldTimer;
554
+ /** Show/refresh (or hide) the "Need more time?" prompt with the live seconds left. */
555
+ private setExtendPrompt;
556
+ private handleExtend;
557
+ /**
558
+ * Fire the booked-confirmation state once the buyer's held seats settle to
559
+ * booked. The controller clears its own hold the moment every held label reads
560
+ * 'booked' over the realtime channel (clearBookedHoldIfSettled), and this runs
561
+ * on the same onStatusChange — so `currentHold() === null` while we still hold
562
+ * a checkout handoff means "sold", not expired (expiry clears via onHoldExpired
563
+ * on a different path, which nulls this.hold first).
564
+ */
565
+ private detectBooked;
566
+ private showBooked;
567
+ /** Assemble the stable {@link CheckoutHandoff} from a hold's server line items. */
568
+ private buildHandoff;
421
569
  private toast;
422
570
  private placeTooltip;
423
571
  private updateTooltip;
@@ -427,4 +575,4 @@ declare class SeatPicker {
427
575
  destroy(): void;
428
576
  }
429
577
 
430
- export { ApiError, type BestAvailableResult, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };
578
+ export { ApiError, type BestAvailableResult, type CheckoutHandoff, type CheckoutLineItem, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };
package/dist/index.d.ts CHANGED
@@ -271,6 +271,40 @@ declare class EmbeddedDesigner {
271
271
  * so plain host CSS can restyle too.
272
272
  */
273
273
 
274
+ /**
275
+ * Stable checkout-handoff contract (P4). Passed as the THIRD argument to
276
+ * `onCheckout(hold, seats, handoff)` — additive, so the legacy `(hold, seats)`
277
+ * shape used by DesiPass web-v2 (SDK 0.7.3+) is untouched. This is the object to
278
+ * build your order against: it is self-contained (holdId, expiry, currency, and
279
+ * per-line tier + price) and never changes shape across minor releases.
280
+ */
281
+ interface CheckoutLineItem {
282
+ /** Seat label (or GA synthetic-unit label). */
283
+ label: string;
284
+ /** Chart object id (row/booth/GA area) the unit belongs to. */
285
+ objectId: string;
286
+ objectType: 'seat' | 'booth' | 'ga';
287
+ categoryKey: string;
288
+ /** Chosen ticket tier id (Adult/Child/…), or null when the category has no tiers. */
289
+ tierId: string | null;
290
+ /** Unit price in MAJOR currency units (e.g. 45 = 45.00). Server-authoritative. */
291
+ unitPrice: number;
292
+ /** ISO-4217, resolved server-side (per-event override → org → USD). */
293
+ currency: string;
294
+ quantity: number;
295
+ }
296
+ interface CheckoutHandoff {
297
+ /** Server hold id — pass this to YOUR book call. */
298
+ holdId: string;
299
+ /** Epoch ms the hold expires (after any extensions). */
300
+ expiresAt: number;
301
+ /** ISO-4217 currency for the whole order. */
302
+ currency: string;
303
+ /** Priced line items (tier + unit price + currency), server-authoritative. */
304
+ lineItems: CheckoutLineItem[];
305
+ /** Convenience total in major units (Σ unitPrice × quantity). */
306
+ total: number;
307
+ }
274
308
  /** Host theme overrides — any subset; unset keys fall back to the org's chart theme, then defaults. */
275
309
  interface SeatPickerTheme {
276
310
  /** Brand accent (CTA, active chips, hold pill). */
@@ -332,9 +366,18 @@ interface SeatPickerOptions {
332
366
  seatView?: boolean;
333
367
  /**
334
368
  * Buyer pressed the CTA and the hold succeeded — hand off to YOUR checkout.
335
- * The hold carries holdId, expiresAt, seat labels and priced line items.
369
+ * `hold` and `seats` are the legacy args (unchanged since 0.6). `handoff` (P4)
370
+ * is the stable, self-contained {@link CheckoutHandoff} to build your order
371
+ * against — holdId, expiry, currency and priced line items. Prefer it.
372
+ */
373
+ onCheckout?: (hold: HoldResult, seats: PickerSeat[], handoff: CheckoutHandoff) => void;
374
+ /**
375
+ * The held seats were BOOKED (P4) — your server completed payment and the
376
+ * booking landed over the realtime channel while the widget was still open.
377
+ * The widget shows a success state; use this to advance your own UI (receipt,
378
+ * redirect). Fires once per hold.
336
379
  */
337
- onCheckout?: (hold: HoldResult, seats: PickerSeat[]) => void;
380
+ onBooked?: (handoff: CheckoutHandoff) => void;
338
381
  /** Selection changed (tap or best-available). */
339
382
  onSelectionChange?: (seats: PickerSeat[]) => void;
340
383
  /** The open hold expired server-side (widget already reset itself). */
@@ -351,11 +394,21 @@ declare class SeatPicker {
351
394
  private rendered;
352
395
  private destroyed;
353
396
  private els;
397
+ /** Feature 6 anchor regions — positioned flex containers over the map. */
398
+ private regions;
354
399
  private ro;
355
400
  private holdTimer;
356
401
  private toastTimer;
357
402
  private currency;
358
403
  private hold;
404
+ /** Latest server expiry for the open hold (moves on extend). */
405
+ private holdExpiresAt;
406
+ /** True once we handed off to checkout — arms booked-confirmation detection. */
407
+ private handedOff;
408
+ /** Guards single onBooked + single success overlay per hold. */
409
+ private bookedShown;
410
+ private extendEl;
411
+ private bookedEl;
359
412
  private gaQty;
360
413
  private tipEl;
361
414
  private tipPos;
@@ -371,6 +424,22 @@ declare class SeatPicker {
371
424
  private viewEl;
372
425
  private viewCleanup;
373
426
  private allSeatsCache;
427
+ private miniEl;
428
+ private miniCanvas;
429
+ private miniBase;
430
+ private miniTf;
431
+ private priceBandKeys;
432
+ private priceFilterEl;
433
+ /** Last surfaced section summary (re-rendered when the price band changes). */
434
+ private lastSection;
435
+ /** Section card collapsed to its slim pill (seat-picking has begun). */
436
+ private secCardCollapsed;
437
+ /** When the card was (re)shown — the focus glide's own view change must not collapse it. */
438
+ private secCardShownAt;
439
+ /** Previous tray ticket count — first 0→n transition auto-expands the mobile sheet. */
440
+ private lastTrayCount;
441
+ private a11yChipsEl;
442
+ private cbEl;
374
443
  private modalScrim;
375
444
  private prevFocus;
376
445
  private escHandler;
@@ -386,6 +455,54 @@ declare class SeatPicker {
386
455
  static open(options: Omit<SeatPickerOptions, 'container'>): Promise<SeatPicker>;
387
456
  constructor(options: SeatPickerOptions);
388
457
  render(): Promise<this>;
458
+ /**
459
+ * Move layout-dependent chrome between its wide dock (map regions / zoom
460
+ * column) and its narrow dock (the sheet's consolidated Filters row), and
461
+ * re-render the section card in the form the layout wants (docked card/pill
462
+ * on wide, sheet strip on narrow). Runs on every layout flip + once post-render.
463
+ */
464
+ private dockLayoutChrome;
465
+ /** The "Need more time?" prompt shown in the hold's final EXTEND_PROMPT_MS. */
466
+ private buildExtendPrompt;
467
+ /** Success overlay + onBooked fire when the held seats settle to booked. */
468
+ private buildBookedOverlay;
469
+ /**
470
+ * Create the positioned flex containers that own every persistent map overlay.
471
+ * Appended once after controller.render(); each chrome piece is then appended
472
+ * INTO its region and flows within it, so nothing free-floats over anything
473
+ * else. Regions carve the map into non-overlapping zones (top strip split into
474
+ * left/center/right, left rail, and the three used corners).
475
+ */
476
+ private buildRegions;
477
+ /** Read a resolved --sl-* token value (canvas needs a real color, not var()). */
478
+ private cssVar;
479
+ /** Section-bearing objects on the active floor (single-floor → doc.objects). */
480
+ private activeFloorObjects;
481
+ /**
482
+ * Build the overview minimap: a static venue thumbnail (section outlines, or
483
+ * seat dots when the chart has no sections) with the live viewport rectangle
484
+ * drawn on top. The rect tracks pan/zoom via the constructor's onViewChange.
485
+ */
486
+ private buildMinimap;
487
+ /** Repaint the static overview + rect (floor switch, live open/close). */
488
+ private refreshMinimap;
489
+ /** Paint the venue overview into the offscreen base canvas. */
490
+ private drawMinimapStatic;
491
+ /** Blit the base overview, then stroke the current viewport rectangle on top. */
492
+ private drawMinimapRect;
493
+ /** Minimap click → focus the section under the point (or overview on a miss). */
494
+ private minimapJump;
495
+ /** Effective price of a category (first tier when tiered, else base price). */
496
+ private catPrice;
497
+ /** Derive price bands: one chip per distinct price (≤5), else quantile ranges. */
498
+ private priceBands;
499
+ /**
500
+ * Build the price-band chip row in the side panel, directly under the "Prices"
501
+ * header and above the legend it dims. Living in the panel (not a map overlay)
502
+ * keeps it clear of the top-center rung pills and top-left a11y chips, and it
503
+ * rides the bottom sheet on narrow layouts. Skipped when there's <2 bands.
504
+ */
505
+ private buildPriceFilter;
389
506
  /** Build the rung pills (charts with sections) and floor switcher (>1 floor). */
390
507
  private buildArenaChrome;
391
508
  /** Reflect the engine's current LOD rung onto the pill group. */
@@ -394,6 +511,22 @@ declare class SeatPicker {
394
511
  private syncFloors;
395
512
  /** Show (or clear, on null) the tapped-section summary card. */
396
513
  private showSectionCard;
514
+ /**
515
+ * Render the section card in the form the layout + state want: expanded card
516
+ * or slim pill in the top-center anchor region (wide), or a compact strip in
517
+ * the sheet head (narrow). Never floats over the seats at the tap point.
518
+ */
519
+ private renderSectionCard;
520
+ /** Collapse the expanded card to its slim pill (seat-picking started). */
521
+ private collapseSectionCard;
522
+ /**
523
+ * onViewChange hook for the card. The focus glide's own settle (within the
524
+ * grace window) enforces the ~25% coverage rule with the FINAL viewport; any
525
+ * later pan/zoom means seat-picking has begun → collapse to the pill.
526
+ */
527
+ private sectionCardOnView;
528
+ /** Fraction of the focused section's on-screen bbox covered by the card. */
529
+ private sectionCardCoverage;
397
530
  /** aria-live readout when keyboard focus lands on a seat. */
398
531
  private announceSeat;
399
532
  private showConfirm;
@@ -418,6 +551,21 @@ declare class SeatPicker {
418
551
  private handleCta;
419
552
  private startHoldTimer;
420
553
  private stopHoldTimer;
554
+ /** Show/refresh (or hide) the "Need more time?" prompt with the live seconds left. */
555
+ private setExtendPrompt;
556
+ private handleExtend;
557
+ /**
558
+ * Fire the booked-confirmation state once the buyer's held seats settle to
559
+ * booked. The controller clears its own hold the moment every held label reads
560
+ * 'booked' over the realtime channel (clearBookedHoldIfSettled), and this runs
561
+ * on the same onStatusChange — so `currentHold() === null` while we still hold
562
+ * a checkout handoff means "sold", not expired (expiry clears via onHoldExpired
563
+ * on a different path, which nulls this.hold first).
564
+ */
565
+ private detectBooked;
566
+ private showBooked;
567
+ /** Assemble the stable {@link CheckoutHandoff} from a hold's server line items. */
568
+ private buildHandoff;
421
569
  private toast;
422
570
  private placeTooltip;
423
571
  private updateTooltip;
@@ -427,4 +575,4 @@ declare class SeatPicker {
427
575
  destroy(): void;
428
576
  }
429
577
 
430
- export { ApiError, type BestAvailableResult, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };
578
+ export { ApiError, type BestAvailableResult, type CheckoutHandoff, type CheckoutLineItem, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };