@seatlayer/core 0.1.2 → 0.1.3
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/de-Y3E6YTGP.js +70 -0
- package/dist/de-Y3E6YTGP.js.map +1 -0
- package/dist/es-UM4ZS357.js +70 -0
- package/dist/es-UM4ZS357.js.map +1 -0
- package/dist/fr-IGRD2M4W.js +70 -0
- package/dist/fr-IGRD2M4W.js.map +1 -0
- package/dist/index.cjs +1140 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +432 -8
- package/dist/index.d.ts +432 -8
- package/dist/index.js +883 -90
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -15,8 +15,21 @@ interface Category {
|
|
|
15
15
|
key: string;
|
|
16
16
|
label: string;
|
|
17
17
|
color: string;
|
|
18
|
-
/**
|
|
18
|
+
/** Base price — used when the category has no explicit tiers. */
|
|
19
19
|
price?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier
|
|
22
|
+
* per seat in this category and the tier's price applies; the first tier is the
|
|
23
|
+
* default. Per-category (not per-seat) pricing — see Batch 3.5. Empty/absent =
|
|
24
|
+
* a single price (the `price` above).
|
|
25
|
+
*/
|
|
26
|
+
tiers?: CategoryTier[];
|
|
27
|
+
}
|
|
28
|
+
/** One ticket tier within a category: a named price (Adult, Child, Senior…). */
|
|
29
|
+
interface CategoryTier {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
price: number;
|
|
20
33
|
}
|
|
21
34
|
/**
|
|
22
35
|
* Accessibility accommodations a seat can carry. Mirrors the taxonomy real
|
|
@@ -103,7 +116,9 @@ interface RowObject {
|
|
|
103
116
|
seatLabelStart?: number;
|
|
104
117
|
/** Seat numbering within the row (default ltr, step 1). */
|
|
105
118
|
seatNumbering?: {
|
|
106
|
-
|
|
119
|
+
/** ltr / rtl number from an end; `center` numbers outward from the middle
|
|
120
|
+
* (centre seat lowest — the premium-centre theatre convention). */
|
|
121
|
+
direction: 'ltr' | 'rtl' | 'center';
|
|
107
122
|
/** 2 = odd/even numbering (1,3,5… — start at 2 for evens). */
|
|
108
123
|
step?: 1 | 2;
|
|
109
124
|
};
|
|
@@ -170,6 +185,13 @@ interface TableObject {
|
|
|
170
185
|
rotation: number;
|
|
171
186
|
/** Round tables. */
|
|
172
187
|
radius?: number;
|
|
188
|
+
/**
|
|
189
|
+
* Round tables: the arc (in degrees) the seats occupy, default 360 (full
|
|
190
|
+
* ring). Below 360 leaves an open side — e.g. a service gap for waiters, a
|
|
191
|
+
* head table facing the room, or clearance against a wall. The opening is
|
|
192
|
+
* centred on the `rotation` direction; seats spread across the rest.
|
|
193
|
+
*/
|
|
194
|
+
seatArc?: number;
|
|
173
195
|
/** Rect tables. */
|
|
174
196
|
width?: number;
|
|
175
197
|
height?: number;
|
|
@@ -246,15 +268,33 @@ interface TextObject {
|
|
|
246
268
|
color?: string;
|
|
247
269
|
}
|
|
248
270
|
type ChartObject = RowObject | GAAreaObject | ShapeObject | TableObject | BoothObject | TextObject | SectionObject;
|
|
271
|
+
/**
|
|
272
|
+
* One floor / level of a multi-floor venue (Batch 5). Each floor owns its own
|
|
273
|
+
* geometry, stage focal point, and trace image; categories/zones/tiers stay
|
|
274
|
+
* chart-global (one event, one inventory). A single-floor chart has NO `floors`
|
|
275
|
+
* — its `objects[]` is the whole venue — so all existing charts are untouched.
|
|
276
|
+
*/
|
|
277
|
+
interface Floor {
|
|
278
|
+
id: string;
|
|
279
|
+
name: string;
|
|
280
|
+
objects: ChartObject[];
|
|
281
|
+
focalPoint: Point;
|
|
282
|
+
backgroundImage?: ChartDoc['backgroundImage'];
|
|
283
|
+
}
|
|
249
284
|
interface ChartDoc {
|
|
250
285
|
version: 1;
|
|
251
286
|
name: string;
|
|
252
287
|
venueType: 'SIMPLE' | 'MIXED';
|
|
253
|
-
/** The stage / point every seat looks at. Anchors seat-view + sightlines.
|
|
288
|
+
/** The stage / point every seat looks at. Anchors seat-view + sightlines.
|
|
289
|
+
* Multi-floor: mirrors floor 0; each floor also carries its own focalPoint. */
|
|
254
290
|
focalPoint: Point;
|
|
255
291
|
categories: Category[];
|
|
256
292
|
/** Section groupings for far-zoom navigation + pricing (optional; sections reference by id). */
|
|
257
293
|
zones?: ZoneDef[];
|
|
294
|
+
/** Multi-floor venues (Batch 5): present ⇒ floors[] is the source of truth;
|
|
295
|
+
* absent ⇒ single-floor and `objects` below is the whole chart. `objects`
|
|
296
|
+
* is kept mirroring floor 0 so single-floor readers never branch. */
|
|
297
|
+
floors?: Floor[];
|
|
258
298
|
objects: ChartObject[];
|
|
259
299
|
/** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */
|
|
260
300
|
backgroundImage?: {
|
|
@@ -267,6 +307,13 @@ interface ChartDoc {
|
|
|
267
307
|
};
|
|
268
308
|
/** Brand/venue theming (colors); categories carry their own colors separately. */
|
|
269
309
|
theme?: ChartTheme;
|
|
310
|
+
/** Parametric-template provenance: present ⇒ the chart came from a capacity-
|
|
311
|
+
* adjustable template family, and the designer offers a capacity control that
|
|
312
|
+
* regenerates it at a new target seat count (Batch 4 "curated singles + resize"). */
|
|
313
|
+
template?: {
|
|
314
|
+
family: string;
|
|
315
|
+
targetSeats: number;
|
|
316
|
+
};
|
|
270
317
|
}
|
|
271
318
|
interface ExpandedSeat {
|
|
272
319
|
/** Stable id: `${rowId}:${index}` */
|
|
@@ -298,9 +345,22 @@ interface RendererCallbacks {
|
|
|
298
345
|
onFps?: (fps: number) => void;
|
|
299
346
|
/** Fired when a GA area is clicked (quantity picking is UI-side). */
|
|
300
347
|
onGAClick?: (areaId: string) => void;
|
|
348
|
+
/**
|
|
349
|
+
* Fired when a tap lands on a section outline while seats are NOT the active
|
|
350
|
+
* rung (i.e. zoomed out, section/zone LOD). The host glides in + shows a
|
|
351
|
+
* section-summary card instead of trying to select a 4px seat (Slice 5).
|
|
352
|
+
*/
|
|
353
|
+
onSectionTap?: (sectionId: string) => void;
|
|
354
|
+
/**
|
|
355
|
+
* Fired when a seat/deck is tapped in the 3D all-floors stacked overview — the
|
|
356
|
+
* host drops back to the flat 2D map on that floor ("tap a deck to enter").
|
|
357
|
+
*/
|
|
358
|
+
onDeckTap?: (floorId: string) => void;
|
|
301
359
|
/** Fired after any pan/zoom/resize settles — re-anchor screen-space overlays. */
|
|
302
360
|
onViewChange?: () => void;
|
|
303
361
|
}
|
|
362
|
+
/** Far-zoom level-of-detail rung: whole zones → section blocks → individual seats. */
|
|
363
|
+
type LodRung = 'zones' | 'sections' | 'seats';
|
|
304
364
|
interface RendererOptions extends RendererCallbacks {
|
|
305
365
|
/** Max seats selectable at once (default 10). */
|
|
306
366
|
maxSelection?: number;
|
|
@@ -314,10 +374,16 @@ interface RendererOptions extends RendererCallbacks {
|
|
|
314
374
|
* pushing straight into the cart; `deselect([seat.id])` on Cancel un-highlights.
|
|
315
375
|
*/
|
|
316
376
|
confirmSelection?: boolean;
|
|
377
|
+
/** ISO 4217 currency for on-map prices ("FROM …"); defaults to money.DEFAULT_CURRENCY.
|
|
378
|
+
* Locale for grouping/symbol placement comes from the active i18n locale. */
|
|
379
|
+
currency?: string;
|
|
317
380
|
}
|
|
318
381
|
interface ISeatmapRenderer {
|
|
319
|
-
/** Replace the chart. Resets selection and statuses, zooms to fit.
|
|
320
|
-
|
|
382
|
+
/** Replace the chart. Resets selection and statuses, zooms to fit.
|
|
383
|
+
* `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */
|
|
384
|
+
setChart(doc: ChartDoc, opts?: {
|
|
385
|
+
floorId?: string;
|
|
386
|
+
}): void;
|
|
321
387
|
/** Bulk status update; re-renders affected seats only. */
|
|
322
388
|
setStatus(seatIds: string[], status: SeatStatus): void;
|
|
323
389
|
getStatus(seatId: string): SeatStatus;
|
|
@@ -357,12 +423,26 @@ interface ISeatmapRenderer {
|
|
|
357
423
|
setAccessibilityFilter(types: AccessibilityType[] | null): void;
|
|
358
424
|
/** Legend hover-highlight: dim free seats of other categories (null clears). */
|
|
359
425
|
setCategoryHighlight?(key: string | null): void;
|
|
426
|
+
/** Dim the seats of these section/zone ids (organizer manager: held-back inventory). */
|
|
427
|
+
setDimmedSections?(ids: string[] | null): void;
|
|
360
428
|
/**
|
|
361
429
|
* Switch the projection. `'flat'` = normal top-down; `'isometric'` = the "3D"
|
|
362
430
|
* view (affine skew/rotate + elevation lift), hit-testing preserved in screen
|
|
363
431
|
* space. Purely visual — the chart is authored flat. Animated unless reduced-motion.
|
|
364
432
|
*/
|
|
365
433
|
setViewMode?(mode: 'flat' | 'isometric'): void;
|
|
434
|
+
/** Current projection (defaults to 'flat' when unimplemented). */
|
|
435
|
+
getViewMode?(): 'flat' | 'isometric';
|
|
436
|
+
/** Multi-floor (Batch 5): switch the shown floor; list floors; read the active id. */
|
|
437
|
+
setActiveFloor?(floorId: string): void;
|
|
438
|
+
getFloors?(): {
|
|
439
|
+
id: string;
|
|
440
|
+
name: string;
|
|
441
|
+
}[];
|
|
442
|
+
getActiveFloorId?(): string;
|
|
443
|
+
/** Render all floors stacked (3D overview) vs the active floor. No-op single-floor. */
|
|
444
|
+
setStacked?(on: boolean): void;
|
|
445
|
+
isStacked?(): boolean;
|
|
366
446
|
/**
|
|
367
447
|
* Section id whose outline contains a container-relative screen point (or null).
|
|
368
448
|
* Feeds the far-zoom "tap a section to zoom in" flow (Slice 5).
|
|
@@ -370,6 +450,23 @@ interface ISeatmapRenderer {
|
|
|
370
450
|
sectionAt?(clientPoint: Point): string | null;
|
|
371
451
|
/** Seat ids belonging to a section — for the section-summary card (Slice 5). */
|
|
372
452
|
sectionMembers?(id: string): string[];
|
|
453
|
+
/**
|
|
454
|
+
* Smoothly glide (pan+zoom) the camera to frame a section (by id) or a world-
|
|
455
|
+
* space bounds rect over ~450ms easeInOutCubic. `prefers-reduced-motion` snaps.
|
|
456
|
+
* A pointer-down (grab/pan) cancels an in-flight glide. Slice 5 "glide in".
|
|
457
|
+
*/
|
|
458
|
+
focusRegion?(target: string | {
|
|
459
|
+
x: number;
|
|
460
|
+
y: number;
|
|
461
|
+
width: number;
|
|
462
|
+
height: number;
|
|
463
|
+
}, opts?: {
|
|
464
|
+
animate?: boolean;
|
|
465
|
+
}): void;
|
|
466
|
+
/** Current LOD rung derived from zoom (for the ZONES/SECTIONS/SEATS pill). */
|
|
467
|
+
getRung?(): LodRung;
|
|
468
|
+
/** Jump the camera to a rung's zoom band, centred on the chart (glided). */
|
|
469
|
+
setRung?(rung: LodRung): void;
|
|
373
470
|
destroy(): void;
|
|
374
471
|
}
|
|
375
472
|
/** localStorage key the Designer writes and the Picker reads. */
|
|
@@ -417,7 +514,24 @@ declare function pointInPolygon(p: Point, poly: Point[]): boolean;
|
|
|
417
514
|
* shape: bbox centre; text: its position.
|
|
418
515
|
*/
|
|
419
516
|
declare function objectCenter(o: ChartObject): Point;
|
|
420
|
-
/**
|
|
517
|
+
/**
|
|
518
|
+
* Normalized floor list (Batch 5): a multi-floor chart's `floors`, or a synthetic
|
|
519
|
+
* single floor wrapping a single-floor chart's `objects`. Every consumer that needs
|
|
520
|
+
* to reason about floors goes through this so single-floor charts stay untouched.
|
|
521
|
+
*/
|
|
522
|
+
declare function floorsOf(doc: ChartDoc): Floor[];
|
|
523
|
+
/** Objects of one floor by id (defaults to the first floor). */
|
|
524
|
+
declare function floorObjects(doc: ChartDoc, floorId?: string): ChartObject[];
|
|
525
|
+
/** Every object across ALL floors — the whole venue (single-floor = `doc.objects`). */
|
|
526
|
+
declare function allObjects(doc: ChartDoc): ChartObject[];
|
|
527
|
+
/**
|
|
528
|
+
* Multi-floor 3D stack (Batch 5): flatten every floor into ONE doc with floor `i`
|
|
529
|
+
* lifted by `i * spread` in −y, so the isometric view shows the floors as stacked
|
|
530
|
+
* decks (ground at the bottom). Returns a single-floor doc (no `floors`). Meant
|
|
531
|
+
* only for the 3D overview render — 2D still shows one floor via `floorObjects`.
|
|
532
|
+
*/
|
|
533
|
+
declare function stackFloors(doc: ChartDoc, spread?: number): ChartDoc;
|
|
534
|
+
/** Expand every seat-bearing object across all floors (rows, tables, booths). */
|
|
421
535
|
declare function expandChart(doc: ChartDoc): ExpandedSeat[];
|
|
422
536
|
/** Axis-aligned bounds over every object plus the background image, with padding. */
|
|
423
537
|
declare function chartBounds(doc: ChartDoc): {
|
|
@@ -427,6 +541,78 @@ declare function chartBounds(doc: ChartDoc): {
|
|
|
427
541
|
height: number;
|
|
428
542
|
};
|
|
429
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Section membership + hide/show resolution (Batch 3.3).
|
|
546
|
+
*
|
|
547
|
+
* A `SectionObject` is a polygon drawn over existing seat objects; an object
|
|
548
|
+
* "belongs" to a section when its visual centre (`objectCenter`) falls inside
|
|
549
|
+
* the section outline, first section in doc order winning. This is the same
|
|
550
|
+
* spatial notion `objectCenter`'s doc-comment describes, resolved once here so
|
|
551
|
+
* BOTH the event manager (Sections tab counts) and the buyer picker (omit
|
|
552
|
+
* hidden seats) agree on which seats live in which section.
|
|
553
|
+
*
|
|
554
|
+
* Hiding is per-EVENT (the EventDO holds the hidden id set), not a chart edit —
|
|
555
|
+
* so a republish of the chart never disturbs it. A hidden id may be a section
|
|
556
|
+
* id, a zone id (hides every section in the zone), or `UNGROUPED_ID` (the
|
|
557
|
+
* catch-all bucket of seat objects that sit in no section).
|
|
558
|
+
*/
|
|
559
|
+
|
|
560
|
+
/** Synthetic section id for seat objects that fall in no drawn section. */
|
|
561
|
+
declare const UNGROUPED_ID = "__ungrouped__";
|
|
562
|
+
/**
|
|
563
|
+
* A per section/zone availability window (Batch 3.4). Wire-compatible with the
|
|
564
|
+
* EventDO's own `AvailabilityRule`. Absence of a rule for an id = on sale.
|
|
565
|
+
* 'hidden' — manual: hidden until the organizer reveals it (3.3).
|
|
566
|
+
* 'timed' — hidden until `revealAt` (epoch ms), then auto-reveals.
|
|
567
|
+
* 'threshold' — auto-reveals once the on-sale inventory is `thresholdPct`% sold.
|
|
568
|
+
* `labels` are the seat labels the id governs, so a threshold's denominator can
|
|
569
|
+
* exclude still-hidden seats.
|
|
570
|
+
*/
|
|
571
|
+
interface AvailabilityRule {
|
|
572
|
+
mode: 'hidden' | 'timed' | 'threshold';
|
|
573
|
+
revealAt?: number;
|
|
574
|
+
thresholdPct?: number;
|
|
575
|
+
labels?: string[];
|
|
576
|
+
}
|
|
577
|
+
interface SectionNode {
|
|
578
|
+
/** Section id (a `SectionObject.id`, or `UNGROUPED_ID`). */
|
|
579
|
+
id: string;
|
|
580
|
+
label: string;
|
|
581
|
+
/** Zone id this section points at (`SectionObject.zone`), if any. */
|
|
582
|
+
zone?: string;
|
|
583
|
+
/** Total seats across the member objects. */
|
|
584
|
+
seatCount: number;
|
|
585
|
+
/** Ids of the seat-bearing objects that belong to this section. */
|
|
586
|
+
objectIds: string[];
|
|
587
|
+
/** Seat labels across the member objects (for availability-rule denominators). */
|
|
588
|
+
seatLabels: string[];
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Resolve section membership for a chart. Returns one node per drawn section
|
|
592
|
+
* (doc order), a synthetic "Ungrouped" node for loose seat objects (null when
|
|
593
|
+
* every seat sits in a section), and the object→section id map.
|
|
594
|
+
*/
|
|
595
|
+
declare function computeSections(doc: ChartDoc): {
|
|
596
|
+
sections: SectionNode[];
|
|
597
|
+
ungrouped: SectionNode | null;
|
|
598
|
+
/** seat-object id → owning section id (or `UNGROUPED_ID`). */
|
|
599
|
+
objectToSection: Map<string, string>;
|
|
600
|
+
};
|
|
601
|
+
/** Is a drawn section hidden under `hidden` — directly, or via its zone? */
|
|
602
|
+
declare function isSectionHidden(s: SectionObject, hidden: ReadonlySet<string>): boolean;
|
|
603
|
+
/**
|
|
604
|
+
* The set of seat-object ids to omit from the buyer view for a given hidden id
|
|
605
|
+
* set. An object is hidden when its owning section is hidden (directly or via
|
|
606
|
+
* zone), or it is ungrouped and the catch-all bucket is hidden.
|
|
607
|
+
*/
|
|
608
|
+
declare function hiddenObjectIds(doc: ChartDoc, hidden: ReadonlySet<string>): Set<string>;
|
|
609
|
+
/**
|
|
610
|
+
* A copy of the doc with hidden sections' member objects removed, plus the
|
|
611
|
+
* hidden section overlays themselves (so no empty block renders). Returns the
|
|
612
|
+
* SAME reference when nothing is hidden — callers can skip a re-render on `===`.
|
|
613
|
+
*/
|
|
614
|
+
declare function applyHidden(doc: ChartDoc, hidden: ReadonlySet<string>): ChartDoc;
|
|
615
|
+
|
|
430
616
|
/**
|
|
431
617
|
* SeatmapRenderer — the shared canvas rendering core (buyer picker shell).
|
|
432
618
|
*
|
|
@@ -447,6 +633,11 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
447
633
|
private labelGroup;
|
|
448
634
|
private seats;
|
|
449
635
|
private seatById;
|
|
636
|
+
/** Multi-floor (Batch 5): the last-set chart + which floor we're rendering. */
|
|
637
|
+
private chartDoc;
|
|
638
|
+
private activeFloorId;
|
|
639
|
+
/** When true on a multi-floor chart, render ALL floors stacked (3D overview). */
|
|
640
|
+
private stacked;
|
|
450
641
|
/** Interactive node per seat/booth — a Circle for seats, a Rect for booths. */
|
|
451
642
|
private circleById;
|
|
452
643
|
/** Booth block geometry, keyed by booth id (= the unit's rowId). */
|
|
@@ -471,6 +662,12 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
471
662
|
private zones;
|
|
472
663
|
private seatSection;
|
|
473
664
|
private catPrice;
|
|
665
|
+
/** ISO 4217 currency for on-map "FROM …" prices (undefined ⇒ money default). */
|
|
666
|
+
private currency;
|
|
667
|
+
/** Section/zone ids to render dimmed (organizer manager: held-back inventory). */
|
|
668
|
+
private dimmedSections;
|
|
669
|
+
/** Object id → floor id (multi-floor only) — resolves a deck tap in the 3D stack. */
|
|
670
|
+
private objectFloor;
|
|
474
671
|
/** Zone id → colour (drives extruded side faces in iso view). */
|
|
475
672
|
private zoneColor;
|
|
476
673
|
private hasSections;
|
|
@@ -482,6 +679,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
482
679
|
private isoRaf;
|
|
483
680
|
/** Chart centre the iso projection pivots about (bounds centre). */
|
|
484
681
|
private isoCentre;
|
|
682
|
+
/** rAF for an in-flight camera glide (focusRegion / setRung); 0 = none. */
|
|
683
|
+
private glideRaf;
|
|
485
684
|
/** Set in destroy() so an in-flight iso tween bails. */
|
|
486
685
|
private destroyed;
|
|
487
686
|
/** Cached scale the section/zone labels were last sized for (scale-compensation). */
|
|
@@ -507,7 +706,24 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
507
706
|
/** Cumulative gesture movement in px — clicks are suppressed after a real pan/pinch. */
|
|
508
707
|
private moved;
|
|
509
708
|
constructor(container: HTMLDivElement, options?: RendererOptions);
|
|
510
|
-
setChart(doc: ChartDoc
|
|
709
|
+
setChart(doc: ChartDoc, opts?: {
|
|
710
|
+
floorId?: string;
|
|
711
|
+
}): void;
|
|
712
|
+
/** The chart to render: all floors stacked (3D overview), the active floor, or
|
|
713
|
+
* the whole chart for single-floor charts. */
|
|
714
|
+
private floorView;
|
|
715
|
+
/** Toggle the 3D all-floors stacked overview (Batch 5). Re-renders; no-op on
|
|
716
|
+
* single-floor charts. The caller re-applies statuses + animates the iso view. */
|
|
717
|
+
setStacked(on: boolean): void;
|
|
718
|
+
isStacked(): boolean;
|
|
719
|
+
/** Switch which floor is shown (2D). Re-renders + re-fits; no-op if unchanged. */
|
|
720
|
+
setActiveFloor(floorId: string): void;
|
|
721
|
+
/** Floors for the host's switcher (single-floor charts return one synthetic floor). */
|
|
722
|
+
getFloors(): {
|
|
723
|
+
id: string;
|
|
724
|
+
name: string;
|
|
725
|
+
}[];
|
|
726
|
+
getActiveFloorId(): string;
|
|
511
727
|
setStatus(seatIds: string[], status: SeatStatus): void;
|
|
512
728
|
getStatus(seatId: string): SeatStatus;
|
|
513
729
|
getSelection(): ExpandedSeat[];
|
|
@@ -541,6 +757,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
541
757
|
* inverse) keeps landing on the projected seats/sections.
|
|
542
758
|
*/
|
|
543
759
|
setViewMode(mode: 'flat' | 'isometric'): void;
|
|
760
|
+
/** Current projection — reflects the tween target, not the mid-tween isoT. */
|
|
761
|
+
getViewMode(): 'flat' | 'isometric';
|
|
544
762
|
/** Iso angle (rad) + y-squash for the current isoT. */
|
|
545
763
|
private isoParams;
|
|
546
764
|
/** Effective vertical scale = stage scale × iso squash — legibility math uses this. */
|
|
@@ -581,6 +799,12 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
581
799
|
private renderBoothUnit;
|
|
582
800
|
/** Apply fill/stroke/opacity for a seat's current status + selection. */
|
|
583
801
|
private paintSeat;
|
|
802
|
+
/**
|
|
803
|
+
* Dim the seats of these section/zone ids (organizer manager use) so held-back
|
|
804
|
+
* inventory is visually distinct on the canvas without hiding it. `null`/empty
|
|
805
|
+
* clears. Unlike the buyer's applyHidden, the sections stay rendered.
|
|
806
|
+
*/
|
|
807
|
+
setDimmedSections(ids: string[] | null): void;
|
|
584
808
|
/** Legend hover: highlight one category (dim the rest), or null to clear. */
|
|
585
809
|
setCategoryHighlight(key: string | null): void;
|
|
586
810
|
private renderBackground;
|
|
@@ -639,6 +863,14 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
639
863
|
private toggleSeat;
|
|
640
864
|
private setSelected;
|
|
641
865
|
private wireInteraction;
|
|
866
|
+
/**
|
|
867
|
+
* Which deck (floor) a screen tap landed on in the 3D stacked overview. The
|
|
868
|
+
* seat layer is melt-cached at that zoom so individual seat nodes aren't
|
|
869
|
+
* hit-testable; instead we invert the iso+stage transform via the layer's
|
|
870
|
+
* relative pointer and take the nearest seat's floor. Only the floor matters,
|
|
871
|
+
* so within-floor elevation offsets don't affect the result. Null if none.
|
|
872
|
+
*/
|
|
873
|
+
private deckFloorAt;
|
|
642
874
|
private toLocal;
|
|
643
875
|
private onPointerDown;
|
|
644
876
|
private onPointerMove;
|
|
@@ -652,6 +884,27 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
|
|
|
652
884
|
private zoomAbout;
|
|
653
885
|
/** Zoom + pan so world-rect `b` fills the viewport (with a small margin). */
|
|
654
886
|
private zoomToBounds;
|
|
887
|
+
/**
|
|
888
|
+
* Smoothly glide the camera to frame a section (by id) or a world-space bounds
|
|
889
|
+
* rect — the Slice 5 "glide in". Pan+zoom tween over ~450ms easeInOutCubic; the
|
|
890
|
+
* melt/LOD rides the camera every frame. `prefers-reduced-motion` (or
|
|
891
|
+
* `opts.animate === false`) snaps via zoomToBounds. A grab (pointer-down) or a
|
|
892
|
+
* newer glide cancels an in-flight one.
|
|
893
|
+
*/
|
|
894
|
+
focusRegion(target: string | {
|
|
895
|
+
x: number;
|
|
896
|
+
y: number;
|
|
897
|
+
width: number;
|
|
898
|
+
height: number;
|
|
899
|
+
}, opts?: {
|
|
900
|
+
animate?: boolean;
|
|
901
|
+
}): void;
|
|
902
|
+
/** Cancel an in-flight camera glide (a grab or a newer glide interrupts it). */
|
|
903
|
+
private cancelGlide;
|
|
904
|
+
/** Current LOD rung derived from effective zoom — drives the ZONES/SECTIONS/SEATS pill. */
|
|
905
|
+
getRung(): LodRung;
|
|
906
|
+
/** Jump the camera to a rung's zoom band, centred on the chart (glided). */
|
|
907
|
+
setRung(rung: LodRung): void;
|
|
655
908
|
/** Recompute LOD (cache/labels) after any pan/zoom settles. */
|
|
656
909
|
private afterViewChange;
|
|
657
910
|
/** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */
|
|
@@ -668,7 +921,12 @@ interface PickerSeat {
|
|
|
668
921
|
id: string;
|
|
669
922
|
label: string;
|
|
670
923
|
categoryKey: string;
|
|
924
|
+
/** Price for the chosen tier when the category has tiers, else the base price. */
|
|
671
925
|
price: number;
|
|
926
|
+
/** Ticket tiers the seat's category offers (Adult/Child/…); absent when none. */
|
|
927
|
+
tiers?: CategoryTier[];
|
|
928
|
+
/** The chosen tier's id — defaults to the first tier; absent when no tiers. */
|
|
929
|
+
tierId?: string;
|
|
672
930
|
}
|
|
673
931
|
interface HoldConflict {
|
|
674
932
|
label: string;
|
|
@@ -679,6 +937,35 @@ interface HoldInfo {
|
|
|
679
937
|
holdId: string;
|
|
680
938
|
labels: string[];
|
|
681
939
|
expiresAt: number;
|
|
940
|
+
/** The held seats with their chosen ticket tier — what the host books against. */
|
|
941
|
+
seats: PickerSeat[];
|
|
942
|
+
}
|
|
943
|
+
/** One category's slice of a section (dot + price + count) for the summary card. */
|
|
944
|
+
interface SectionCategory {
|
|
945
|
+
key: string;
|
|
946
|
+
label: string;
|
|
947
|
+
color: string;
|
|
948
|
+
price: number;
|
|
949
|
+
count: number;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Big-venue section-summary — everything the tapped-section card renders: name,
|
|
953
|
+
* its zone, live seats-left, price range, and the per-category breakdown.
|
|
954
|
+
* Computed from the renderer's spatial section membership (Slice 5).
|
|
955
|
+
*/
|
|
956
|
+
interface SectionSummary {
|
|
957
|
+
id: string;
|
|
958
|
+
label: string;
|
|
959
|
+
/** Zone label (from ChartDoc.zones); '' when the section has no zone. */
|
|
960
|
+
zoneLabel: string;
|
|
961
|
+
/** Mix/section colour for the card's dot (section.color → zone colour → dominant category). */
|
|
962
|
+
color: string;
|
|
963
|
+
/** Free member seats right now. */
|
|
964
|
+
seatsLeft: number;
|
|
965
|
+
priceMin: number;
|
|
966
|
+
priceMax: number;
|
|
967
|
+
/** Per-category breakdown, cheapest first. */
|
|
968
|
+
categories: SectionCategory[];
|
|
682
969
|
}
|
|
683
970
|
interface HoldResponse {
|
|
684
971
|
holdId: string;
|
|
@@ -697,10 +984,12 @@ interface PickerTransport {
|
|
|
697
984
|
salesClosed?: boolean;
|
|
698
985
|
venue?: string | null;
|
|
699
986
|
startsAt?: number | null;
|
|
987
|
+
currency?: string;
|
|
700
988
|
};
|
|
701
989
|
}>;
|
|
702
990
|
objects(key: string): Promise<{
|
|
703
991
|
seats: Record<string, string>;
|
|
992
|
+
hidden?: string[];
|
|
704
993
|
}>;
|
|
705
994
|
hold(key: string, labels: string[]): Promise<HoldResponse>;
|
|
706
995
|
bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;
|
|
@@ -722,6 +1011,14 @@ interface PickerCallbacks extends RendererCallbacks {
|
|
|
722
1011
|
onStatusChange?: () => void;
|
|
723
1012
|
/** The server declared the event closed (a 409 event_closed). */
|
|
724
1013
|
onSalesClosed?: () => void;
|
|
1014
|
+
/**
|
|
1015
|
+
* A section block was tapped at the far/zone rung — the controller has glided
|
|
1016
|
+
* the camera in and passes the computed summary (or null when cleared, e.g.
|
|
1017
|
+
* overview() / zoom-to-zones) so the host can show/hide the summary card.
|
|
1018
|
+
*/
|
|
1019
|
+
onSectionFocus?: (summary: SectionSummary | null) => void;
|
|
1020
|
+
/** A deck was tapped in the 3D all-floors overview — host enters that floor in 2D. */
|
|
1021
|
+
onDeckTap?: (floorId: string) => void;
|
|
725
1022
|
onError?: (err: unknown) => void;
|
|
726
1023
|
}
|
|
727
1024
|
interface PickerOptions extends PickerCallbacks {
|
|
@@ -730,6 +1027,8 @@ interface PickerOptions extends PickerCallbacks {
|
|
|
730
1027
|
maxSelection?: number;
|
|
731
1028
|
/** Renderer confirm-card mode (host shows a confirm popover instead of instant cart add). */
|
|
732
1029
|
confirmSelection?: boolean;
|
|
1030
|
+
/** ISO 4217 currency for on-map prices (default from money.DEFAULT_CURRENCY). */
|
|
1031
|
+
currency?: string;
|
|
733
1032
|
/** Flash a pulse when a seat we didn't touch goes free→taken (live-activity cue). */
|
|
734
1033
|
flashOnLiveChange?: boolean;
|
|
735
1034
|
}
|
|
@@ -740,9 +1039,15 @@ declare class PickerController {
|
|
|
740
1039
|
private readonly maxSelection;
|
|
741
1040
|
private renderer;
|
|
742
1041
|
private _doc;
|
|
1042
|
+
/** Section/zone ids hidden from buyers this event (3.3) — seats vanish, not grey. */
|
|
1043
|
+
private hidden;
|
|
743
1044
|
/** label ⇄ id maps — backend speaks labels, the engine speaks ids. */
|
|
744
1045
|
private labelToId;
|
|
745
1046
|
private labelToSeat;
|
|
1047
|
+
/** seatId → chosen ticket-tier id (absent ⇒ the category's first/default tier). */
|
|
1048
|
+
private seatTiers;
|
|
1049
|
+
/** id → seat, for the section-summary breakdown (renderer members are ids). */
|
|
1050
|
+
private seatById;
|
|
746
1051
|
private allIds;
|
|
747
1052
|
private ws;
|
|
748
1053
|
private reconnectTimer;
|
|
@@ -752,6 +1057,10 @@ declare class PickerController {
|
|
|
752
1057
|
private expiryTimer;
|
|
753
1058
|
constructor(options: PickerOptions);
|
|
754
1059
|
get doc(): ChartDoc | null;
|
|
1060
|
+
/** The chart with hidden sections' seats removed — what buyers actually see. */
|
|
1061
|
+
private visibleDoc;
|
|
1062
|
+
/** Adopt a new hidden set; rebuild the visible chart only if it differs. */
|
|
1063
|
+
private syncHidden;
|
|
755
1064
|
currentHold(): HoldInfo | null;
|
|
756
1065
|
getRenderer(): ISeatmapRenderer | null;
|
|
757
1066
|
seatByLabel(label: string): ExpandedSeat | undefined;
|
|
@@ -763,6 +1072,7 @@ declare class PickerController {
|
|
|
763
1072
|
eventName: string;
|
|
764
1073
|
venue?: string | null;
|
|
765
1074
|
startsAt?: number | null;
|
|
1075
|
+
currency?: string;
|
|
766
1076
|
} | null>;
|
|
767
1077
|
getSelection(): PickerSeat[];
|
|
768
1078
|
clearSelection(): void;
|
|
@@ -806,9 +1116,51 @@ declare class PickerController {
|
|
|
806
1116
|
y: number;
|
|
807
1117
|
};
|
|
808
1118
|
setAccessibilityFilter(types: string[] | null): void;
|
|
1119
|
+
/** Floors for the buyer's switcher (>1 ⇒ show it). Single-floor ⇒ one entry. */
|
|
1120
|
+
getFloors(): {
|
|
1121
|
+
id: string;
|
|
1122
|
+
name: string;
|
|
1123
|
+
}[];
|
|
1124
|
+
getActiveFloorId(): string;
|
|
1125
|
+
/** Switch the shown floor (2D), then re-apply live seat statuses onto it. */
|
|
1126
|
+
setFloor(id: string): void;
|
|
1127
|
+
/** 3D all-floors stacked overview ⇄ active floor. Re-applies statuses after. */
|
|
1128
|
+
setStacked(on: boolean): void;
|
|
1129
|
+
isMultiFloor(): boolean;
|
|
1130
|
+
/** Tap-a-deck-to-enter: leave the 3D stack, drop to flat 2D on `floorId`, and
|
|
1131
|
+
* tell the host so it can sync its 2D/3D toggle + floor-switcher state. */
|
|
1132
|
+
private handleDeckTap;
|
|
1133
|
+
/** Switch the map projection (2D flat ⇄ 3D isometric). No-op on a flat renderer. */
|
|
1134
|
+
setViewMode(mode: 'flat' | 'isometric'): void;
|
|
1135
|
+
getViewMode(): 'flat' | 'isometric';
|
|
1136
|
+
/** Current LOD rung (for the ZONES/SECTIONS/SEATS pill). */
|
|
1137
|
+
getRung(): LodRung;
|
|
1138
|
+
/** Jump to a rung; ZONES clears any focused summary (back to overview). */
|
|
1139
|
+
setRung(rung: LodRung): void;
|
|
1140
|
+
/** Glide in on a section and surface its summary (same path as a section tap). */
|
|
1141
|
+
focusSection(id: string): void;
|
|
1142
|
+
/** Zoom back out to the whole chart and clear the section-summary card. */
|
|
1143
|
+
overview(): void;
|
|
1144
|
+
/** Glide the camera into a tapped section and emit its computed summary. */
|
|
1145
|
+
private handleSectionTap;
|
|
1146
|
+
/**
|
|
1147
|
+
* Build a section summary from the renderer's spatial membership: section +
|
|
1148
|
+
* zone labels, live seats-left, price range, and the per-category breakdown.
|
|
1149
|
+
*/
|
|
1150
|
+
private sectionSummary;
|
|
809
1151
|
destroy(): void;
|
|
810
1152
|
private toSeat;
|
|
811
1153
|
private priceFor;
|
|
1154
|
+
private tiersFor;
|
|
1155
|
+
/**
|
|
1156
|
+
* Choose a ticket tier for a selected seat (e.g. Adult → Child). Re-emits the
|
|
1157
|
+
* selection so the host's cart + the eventual hold carry the new tier + price.
|
|
1158
|
+
* `tierId = null` reverts to the category's first (default) tier. No-op if the
|
|
1159
|
+
* seat's category has no tiers or the id isn't one of them.
|
|
1160
|
+
*/
|
|
1161
|
+
setSeatTier(seatId: string, tierId: string | null): void;
|
|
1162
|
+
/** PickerSeats (with chosen tier) for a set of held labels. */
|
|
1163
|
+
private seatsForLabels;
|
|
812
1164
|
private emitSelectionChange;
|
|
813
1165
|
private emitError;
|
|
814
1166
|
private holdCovers;
|
|
@@ -823,4 +1175,76 @@ declare class PickerController {
|
|
|
823
1175
|
private scheduleReconnect;
|
|
824
1176
|
}
|
|
825
1177
|
|
|
826
|
-
|
|
1178
|
+
/**
|
|
1179
|
+
* i18n core — deliberately tiny and framework-free so the embed SDK can share
|
|
1180
|
+
* it without dragging in a runtime library (the 60KB-gzipped SDK budget is a
|
|
1181
|
+
* product contract).
|
|
1182
|
+
*
|
|
1183
|
+
* Scope (docs/design-port-plan.md): the buyer surface (picker, public event
|
|
1184
|
+
* page, SDK) ships fully translated in en/es/de/fr; dashboard pages route
|
|
1185
|
+
* their strings through t() as they are rebuilt but ship English this round.
|
|
1186
|
+
*
|
|
1187
|
+
* Keys are flat dot-namespaced strings ("picker.holdSeats"). Interpolation
|
|
1188
|
+
* uses {name} placeholders. Missing keys fall back to English, then to the
|
|
1189
|
+
* key itself — a page never crashes over a translation.
|
|
1190
|
+
*/
|
|
1191
|
+
type Locale = 'en' | 'es' | 'de' | 'fr';
|
|
1192
|
+
declare const SUPPORTED_LOCALES: Locale[];
|
|
1193
|
+
type Dict = Record<string, string>;
|
|
1194
|
+
/** explicit setting → stored preference → browser language → en */
|
|
1195
|
+
declare function resolveLocale(explicit?: string | null, stored?: string | null): Locale;
|
|
1196
|
+
declare function getLocale(): Locale;
|
|
1197
|
+
/**
|
|
1198
|
+
* Set the active locale. Locale bundles other than English are registered by
|
|
1199
|
+
* the surface that needs them (the picker imports its own es/de/fr bundles;
|
|
1200
|
+
* the dashboard stays English until its translations ship).
|
|
1201
|
+
*/
|
|
1202
|
+
declare function setLocale(locale: Locale, bundle?: Dict): void;
|
|
1203
|
+
declare function setStringOverrides(next: Dict): void;
|
|
1204
|
+
declare function t(key: string, vars?: Record<string, string | number>): string;
|
|
1205
|
+
/** "1 seat" / "3 seats" without hand-rolled concatenation. */
|
|
1206
|
+
declare function tCount(key: string, count: number, vars?: Record<string, string | number>): string;
|
|
1207
|
+
declare function formatDate(value: number | Date, opts?: Intl.DateTimeFormatOptions): string;
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
* Locale bundle loader — keeps non-English translations OUT of the initial
|
|
1211
|
+
* bundle (the 60 KB SDK budget is a product contract) and code-splits each
|
|
1212
|
+
* locale so a page/SDK only downloads the language it actually uses.
|
|
1213
|
+
*
|
|
1214
|
+
* `loadLocale('de')` dynamic-imports the German dictionary, registers it via
|
|
1215
|
+
* setLocale(), and resolves once it's active. English is built in, so
|
|
1216
|
+
* `loadLocale('en')` is synchronous and never fetches. Unknown/unsupported
|
|
1217
|
+
* codes fall back to English without throwing.
|
|
1218
|
+
*/
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Resolve `code` to a supported locale, load its bundle if needed, and make it
|
|
1222
|
+
* active. Returns the locale that ended up active (English on any failure).
|
|
1223
|
+
*/
|
|
1224
|
+
declare function loadLocale(code?: string | null): Promise<Locale>;
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Money formatting — the ONE place currency rendering happens.
|
|
1228
|
+
*
|
|
1229
|
+
* Ticket money is multi-currency: the org sets a default and each event can
|
|
1230
|
+
* override it (ISO 4217 code delivered with the event/chart payload). Until
|
|
1231
|
+
* those backend fields land, callers fall back to DEFAULT_CURRENCY, which is
|
|
1232
|
+
* kept at EUR so live buyer pages render exactly what they rendered when the
|
|
1233
|
+
* symbol was hardcoded. Flipping an org to USD/INR/… later is data, not code.
|
|
1234
|
+
*
|
|
1235
|
+
* Amounts are in MAJOR units (45 === €45) matching Category.price in
|
|
1236
|
+
* src/core/types.ts. If/when backend money fields arrive in minor units,
|
|
1237
|
+
* convert at the API boundary, not here.
|
|
1238
|
+
*/
|
|
1239
|
+
declare const DEFAULT_CURRENCY = "USD";
|
|
1240
|
+
declare function setMoneyLocale(locale: string | undefined): void;
|
|
1241
|
+
/**
|
|
1242
|
+
* "€45" / "$1,500" / "45 €" (locale-dependent placement).
|
|
1243
|
+
* Whole amounts render without ".00" (design shows "$45", "$120"); pass
|
|
1244
|
+
* `fractionDigits` for fixed precision (e.g. 3 for "$0.045 / credit").
|
|
1245
|
+
*/
|
|
1246
|
+
declare function formatMoney(amount: number, currency?: string, fractionDigits?: number): string;
|
|
1247
|
+
/** Bare symbol for input adornments ("€", "$", "₹"). */
|
|
1248
|
+
declare function currencySymbol(currency?: string): string;
|
|
1249
|
+
|
|
1250
|
+
export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type ISeatmapRenderer, type Locale, type LodRung, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, getLocale, hiddenObjectIds, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
|