@seatlayer/core 0.16.1 → 0.18.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.ts CHANGED
@@ -11,12 +11,44 @@ interface Point {
11
11
  x: number;
12
12
  y: number;
13
13
  }
14
+ interface CubicPath {
15
+ start: Point;
16
+ control1: Point;
17
+ control2: Point;
18
+ end: Point;
19
+ }
20
+ /** A real closed section boundary. `outline` remains its sampled collision and
21
+ * persistence fallback; this path is the smooth authoring/buyer paint source. */
22
+ type SectionPathSegment = {
23
+ kind: 'line';
24
+ end: Point;
25
+ } | {
26
+ kind: 'arc';
27
+ center: Point;
28
+ radius: number;
29
+ clockwise: boolean;
30
+ end: Point;
31
+ } | {
32
+ kind: 'bezier';
33
+ control1: Point;
34
+ control2: Point;
35
+ end: Point;
36
+ };
37
+ interface SectionOutlinePath {
38
+ version: 1;
39
+ closed: true;
40
+ start: Point;
41
+ segments: SectionPathSegment[];
42
+ }
14
43
  interface Category {
15
44
  key: string;
16
45
  label: string;
17
46
  color: string;
18
47
  /** Base price — used when the category has no explicit tiers. */
19
48
  price?: number;
49
+ /** Durable evidence for semantic/display facts proposed while converting a
50
+ * private reference into sellable inventory. */
51
+ referenceCategorySource?: ReferenceCategorySource;
20
52
  /**
21
53
  * Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier
22
54
  * per seat in this category and the tier's price applies; the first tier is the
@@ -25,6 +57,33 @@ interface Category {
25
57
  */
26
58
  tiers?: CategoryTier[];
27
59
  }
60
+ interface ReferenceCategorySource {
61
+ assetId: string;
62
+ /** Original sampled section color. `Category.color` is the approved output
63
+ * color and may differ only with separately recorded evidence. */
64
+ sourceColor: string;
65
+ /** Every exact sampled color normalized into the same original 4-bit/channel
66
+ * segmentation class. Older documents may contain only `sourceColor`. */
67
+ sourceColors?: string[];
68
+ /** Logical sections whose generated inventory uses this category. */
69
+ logicalSectionIds?: string[];
70
+ /** Source-color grouping is deterministic; a semantic regrouping needs its
71
+ * own confirmed assignment evidence. */
72
+ assignmentDerivation?: 'source-color-class' | 'confirmed-logical-sections';
73
+ assignmentEvidence?: 'user-confirmed' | 'authoritative-source';
74
+ assignmentSourceDescription?: string;
75
+ /** Optional legend/commercial swatch stated by the source. This remains
76
+ * immutable provenance when the approved accessible output color differs. */
77
+ sourcePaletteColor?: string;
78
+ sourcePaletteColorEvidence?: 'user-confirmed' | 'authoritative-source';
79
+ sourcePaletteColorSourceDescription?: string;
80
+ labelEvidence: 'user-confirmed' | 'authoritative-source';
81
+ labelSourceDescription: string;
82
+ priceEvidence: 'user-confirmed' | 'authoritative-source';
83
+ priceSourceDescription: string;
84
+ outputColorEvidence?: 'user-confirmed' | 'authoritative-source';
85
+ outputColorSourceDescription?: string;
86
+ }
28
87
  /** One ticket tier within a category: a named price (Adult, Child, Senior…). */
29
88
  interface CategoryTier {
30
89
  id: string;
@@ -50,6 +109,14 @@ interface AccessibilityMeta {
50
109
  declare const ACCESSIBILITY_TYPES: AccessibilityMeta[];
51
110
  /** Metadata for one accessibility key (undefined for unknown keys). */
52
111
  declare function accessibilityMeta(key: AccessibilityType): AccessibilityMeta | undefined;
112
+ /**
113
+ * Outer-ring colour per accommodation. Shared by the buyer picker and the
114
+ * designer canvas so an accessible seat reads with the same hue in both — the
115
+ * seat's first-listed type wins. `wheelchair` blue is the default fallback.
116
+ */
117
+ declare const ACCESSIBILITY_RING_COLOR: Record<AccessibilityType, string>;
118
+ /** Ring colour for a seat's accessibility set (first-listed type wins). */
119
+ declare function accessibilityRingColor(types: AccessibilityType[] | undefined): string;
53
120
  interface SeatOverride {
54
121
  /** 0-based seat index within the row. */
55
122
  index: number;
@@ -60,25 +127,66 @@ interface SeatOverride {
60
127
  dy?: number;
61
128
  /** Replace the computed label entirely. */
62
129
  label?: string;
130
+ /** Buyer-facing copy only. Booking/API identity remains row id + slot index
131
+ * internally and the legacy `label` externally for backwards compatibility. */
132
+ displayLabel?: string;
63
133
  categoryKey?: string;
64
134
  /** @deprecated legacy flag — read as `['wheelchair']`; write `accessibility`. */
65
135
  accessible?: boolean;
66
136
  /** Accessibility accommodations of this seat (empty/absent = none). */
67
137
  accessibility?: AccessibilityType[];
138
+ /** Commercial selling/view attributes are deliberately not accessibility. */
139
+ commercial?: SeatCommercialAttributes;
140
+ /** Seat-specific view photo; falls back to the row photo. */
141
+ viewFromSeatUrl?: string;
142
+ }
143
+ interface SeatCommercialAttributes {
144
+ restrictedView?: boolean;
145
+ obstructedView?: boolean;
146
+ premium?: boolean;
147
+ note?: string;
148
+ }
149
+ /**
150
+ * Per-object label ink + size overrides layered on top of the chart-wide Theme
151
+ * defaults (rowLabelColor / textColor for rows, the section-name ink for
152
+ * sections). Both fields are optional: an absent field means "inherit the theme
153
+ * default". `color` is a preferred hex — renderers still pass it through the
154
+ * shared auto-contrast rule (`stateAwareBookableLabelInk`), so a choice that
155
+ * would be illegible over the seat/section background is switched to black or
156
+ * white at paint time. `size` is a font size in chart units, clamped to
157
+ * LABEL_STYLE_MIN_SIZE..LABEL_STYLE_MAX_SIZE by the shared ops.
158
+ */
159
+ interface LabelStyle {
160
+ size?: number;
161
+ color?: string;
162
+ }
163
+ /** Clamp bounds for a per-object label `size`, shared by ops, MCP, and UI. */
164
+ declare const LABEL_STYLE_MIN_SIZE = 8;
165
+ declare const LABEL_STYLE_MAX_SIZE = 24;
166
+ interface LabelPresentation {
167
+ visible?: boolean;
168
+ /** Exact Designer-owned label anchor; public semantic MCP schemas omit it. */
169
+ position?: Point;
170
+ rotation?: number;
171
+ style?: 'plain' | 'pill';
172
+ /** Per-object size/color override for this row's or section's label. */
173
+ labelStyle?: LabelStyle;
68
174
  }
69
175
  /** Brand/venue theming — applied by the renderer in both designer and picker. */
70
176
  interface ChartTheme {
71
177
  /** Canvas background color (default dark: #0e1117-ish radial). */
72
178
  background?: string;
73
- /** Seat label text color (default dark ink #0b1220). */
179
+ /** Preferred text color for the numbers inside seat markers. */
74
180
  seatLabelColor?: string;
181
+ /** Preferred color for row identifiers such as A, B, C. Falls back to textColor. */
182
+ rowLabelColor?: string;
75
183
  /** Selection ring / accent color (default white ring + brand accent). */
76
184
  selectionColor?: string;
77
185
  /** Décor (stage/shape) default fill. */
78
186
  decorFill?: string;
79
187
  /** Free-text color default. */
80
188
  textColor?: string;
81
- /** Font family (CSS stack) for all rendered text — seat labels, sections, décor text. */
189
+ /** Font family (CSS stack) for all rendered text — row labels, seat numbers, sections, décor text. */
82
190
  fontFamily?: string;
83
191
  /** Seat size multiplier on the base radius (0.7–1.6, default 1) — bigger seats fit longer labels. */
84
192
  seatScale?: number;
@@ -98,6 +206,9 @@ interface RowObject {
98
206
  id: string;
99
207
  /** Row label, e.g. "A". Seat labels are `${label}-${n}`. */
100
208
  label: string;
209
+ /** Buyer-facing row name. `label` remains the legacy inventory prefix. */
210
+ displayLabel?: string;
211
+ labelPresentation?: LabelPresentation;
101
212
  /** Position of the FIRST seat. */
102
213
  origin: Point;
103
214
  /** Degrees, clockwise. 0 = seats laid out along +x. */
@@ -111,7 +222,43 @@ interface RowObject {
111
222
  seatCount: number;
112
223
  /** Distance between adjacent seat centers, in chart units. */
113
224
  seatSpacing: number;
225
+ /** Optional exact cubic centreline. Normal code owns these coordinates and
226
+ * distributes seats by arc length; MCP/model inputs never submit them. */
227
+ path?: CubicPath;
114
228
  categoryKey: string;
229
+ /** Deterministic provenance for rows fitted from confirmed reference
230
+ * inventory. It enables revision-safe replacement without touching manually
231
+ * authored rows or accepting client coordinates. */
232
+ referenceInventorySource?: ReferenceInventorySource;
233
+ /** Semantic parameters for a row produced by the shared Arc/Fan operation.
234
+ * Designer can reopen these parameters while every segment in the group
235
+ * still carries the same generation signature. Public MCP tools never accept
236
+ * the stored center/angles as arbitrary model-authored coordinates. */
237
+ arcFanGeneration?: {
238
+ kind: 'arc-fan-v1';
239
+ groupId: string;
240
+ center: Point;
241
+ innerRadius: number;
242
+ rowCount: number;
243
+ rowGap: number;
244
+ startAngle: number;
245
+ endAngle: number;
246
+ seatPitch: number;
247
+ fit: 'seat-pitch' | 'fixed-count';
248
+ seatsPerRow?: number;
249
+ facing: 'inward' | 'outward';
250
+ taperDegrees: number;
251
+ skewDegrees: number;
252
+ aisleGaps: {
253
+ left: number;
254
+ center: number;
255
+ right: number;
256
+ };
257
+ rowLabelStart: number;
258
+ seatLabelStart: number;
259
+ rowIndex: number;
260
+ segmentIndex: number;
261
+ };
115
262
  /** First seat number (default 1). */
116
263
  seatLabelStart?: number;
117
264
  /** Seat numbering within the row (default ltr, step 1). */
@@ -134,6 +281,8 @@ interface RowObject {
134
281
  * generates a synthetic panorama from chart geometry.
135
282
  */
136
283
  viewFromSeatUrl?: string;
284
+ /** Default commercial attributes inherited by seats without an override. */
285
+ commercial?: SeatCommercialAttributes;
137
286
  }
138
287
  interface GAAreaObject {
139
288
  type: 'gaArea';
@@ -141,8 +290,59 @@ interface GAAreaObject {
141
290
  label: string;
142
291
  /** Closed polygon, in chart units. */
143
292
  points: Point[];
293
+ /** Explicit aisles/pillars/cutouts excluded from the sellable GA surface. */
294
+ holes?: Point[][];
144
295
  capacity: number;
145
296
  categoryKey: string;
297
+ referenceInventorySource?: ReferenceInventorySource;
298
+ }
299
+ /**
300
+ * Durable evidence link for sellable objects generated from a private reference.
301
+ * The client supplies facts and stable logical-section ids, never coordinates.
302
+ */
303
+ interface ReferenceAccessibilitySource {
304
+ placementDerivation: 'server-synthesized-row-edges';
305
+ groupLogicalSectionIds: string[];
306
+ assignmentEvidence: 'user-confirmed' | 'authoritative-source';
307
+ assignmentSourceDescription: string;
308
+ counts: Array<{
309
+ type: AccessibilityType;
310
+ count: number;
311
+ evidence: 'user-confirmed' | 'authoritative-source';
312
+ sourceDescription: string;
313
+ }>;
314
+ }
315
+ interface ReferenceInventorySource {
316
+ assetId: string;
317
+ logicalSectionId: string;
318
+ evidence: 'user-confirmed' | 'authoritative-source';
319
+ sourceDescription: string;
320
+ /** Distinguishes directly supplied inventory from a user-approved server
321
+ * distribution based only on an aggregate capacity. */
322
+ derivation?: 'explicit-inventory' | 'server-synthesized-from-aggregate';
323
+ /** Evidence for the aggregate figure; synthesized rows remain
324
+ * `user-confirmed` and are never mislabeled as source-extracted. */
325
+ aggregateEvidence?: 'user-confirmed' | 'authoritative-source';
326
+ /** Separate evidence for assigning standing inventory to this logical
327
+ * section. Aggregate evidence alone cannot prove section placement. */
328
+ sectionAssignmentEvidence?: 'user-confirmed' | 'authoritative-source';
329
+ sectionAssignmentSourceDescription?: string;
330
+ /** Aggregate row synthesis may propose numbering, but persistence requires
331
+ * the applying user/agent to confirm that policy explicitly. */
332
+ numberingEvidence?: 'user-confirmed';
333
+ numberingSourceDescription?: string;
334
+ /** Evidence and deterministic placement contract for synthesized accessible
335
+ * units in this logical section. */
336
+ accessibility?: ReferenceAccessibilitySource;
337
+ }
338
+ /** Durable evidence that a visible source-backed section shell intentionally
339
+ * carries no generated sellable inventory in this reference configuration. */
340
+ interface ReferenceInventoryExclusionSource {
341
+ assetId: string;
342
+ logicalSectionId: string;
343
+ reason: string;
344
+ evidence: 'user-confirmed' | 'authoritative-source';
345
+ sourceDescription: string;
146
346
  }
147
347
  /** Non-bookable décor: stage, walls, exits. */
148
348
  interface ShapeObject {
@@ -198,6 +398,7 @@ interface TableObject {
198
398
  categoryKey: string;
199
399
  /** Whole-table booking: buyers get all seats or none (per-event override later). */
200
400
  bookAsWhole?: boolean;
401
+ referenceInventorySource?: ReferenceInventorySource;
201
402
  }
202
403
  /** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */
203
404
  interface BoothObject {
@@ -209,6 +410,7 @@ interface BoothObject {
209
410
  height: number;
210
411
  rotation: number;
211
412
  categoryKey: string;
413
+ referenceInventorySource?: ReferenceInventorySource;
212
414
  }
213
415
  /**
214
416
  * A named region of the venue (Balcony Left, Floor B…). Sections are outlines
@@ -221,8 +423,46 @@ interface SectionObject {
221
423
  type: 'section';
222
424
  id: string;
223
425
  label: string;
426
+ /** Buyer-facing section name; logical/id fields remain stable. */
427
+ displayLabel?: string;
428
+ labelPresentation?: LabelPresentation;
429
+ /**
430
+ * Stable management/inventory identity shared by disconnected visual
431
+ * components of one logical section. When absent, `id` is the logical id.
432
+ * Each component keeps its own `id` and reference provenance so rendering,
433
+ * editing, measured diffs, and source restoration remain exact.
434
+ */
435
+ logicalSectionId?: string;
436
+ /** Shared semantic Arc/Fan group wrapped by this section. The section id is
437
+ * preserved when the fan parameters are reopened and regenerated. */
438
+ arcFanGroupId?: string;
224
439
  /** Closed polygon, chart units. */
225
440
  outline: Point[];
441
+ /** Optional true line/arc/cubic boundary. `outline` is a deterministic sample
442
+ * of this path and remains authoritative for membership, validation, and
443
+ * clients that predate curved section rendering. */
444
+ outlinePath?: SectionOutlinePath;
445
+ /** Explicit aisle/cutout polygons excluded from rendering, hit-testing, and membership. */
446
+ holes?: Point[][];
447
+ /** Durable opaque link to the private reference component. Unlike generator
448
+ * provenance, this survives manual geometry edits so a measured diff can
449
+ * report drift and server-owned code can restore the source contour. */
450
+ referenceSource?: {
451
+ assetId: string;
452
+ regionId: string;
453
+ };
454
+ /** Evidence-backed reason this source section remains a visible shell without
455
+ * synthesized sellable inventory (press, closed technical zone, etc.). */
456
+ referenceInventoryExclusion?: ReferenceInventoryExclusionSource;
457
+ /** Deterministic generator provenance for editable reference/parametric shells. */
458
+ geometry?: {
459
+ kind: 'rectangle' | 'tapered' | 'bezier' | 'contour';
460
+ sourceRegionId?: string;
461
+ contourMethod?: 'pixel-edge-loops-rdp' | 'shared-edge-vector-fit-v1';
462
+ simplificationTolerancePx?: number;
463
+ vectorFitErrorPx?: number;
464
+ sharedEdgeCount?: number;
465
+ };
226
466
  /** Optional tint override (defaults to a neutral fill / dominant category mix). */
227
467
  color?: string;
228
468
  /** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */
@@ -306,6 +546,53 @@ interface Floor {
306
546
  focalPoint: Point;
307
547
  backgroundImage?: ChartDoc['backgroundImage'];
308
548
  }
549
+ interface ReferenceCalibration {
550
+ type: 'two-point';
551
+ /** Points in immutable source-image pixels, selected by a human or trusted detector. */
552
+ sourceA: Point;
553
+ sourceB: Point;
554
+ /** Verified real-world distance between the two source points. */
555
+ distance: number;
556
+ unit: 'm' | 'ft' | 'chart-unit';
557
+ /** Derived and stored for deterministic geometry compilers. */
558
+ pixelsPerUnit: number;
559
+ }
560
+ /** Coordinate-free physical scale derived by server code from a confirmed
561
+ * semantic feature. Unlike manual two-point calibration, no source points pass
562
+ * through an MCP client or language model. */
563
+ interface ReferenceDerivedScale {
564
+ method: 'confirmed-focal-axis-v1';
565
+ feature: 'focal-long-axis' | 'focal-short-axis';
566
+ distance: number;
567
+ unit: 'm' | 'ft';
568
+ evidence: 'user-confirmed' | 'authoritative-source';
569
+ sourceDescription: string;
570
+ chartUnitsPerUnit: number;
571
+ }
572
+ interface ChartReferenceImage {
573
+ /** Stable private reference asset. New cloud-authored charts use this. */
574
+ assetId?: string;
575
+ /** Legacy/self-contained source. Optional when assetId is present. */
576
+ url?: string;
577
+ center: Point;
578
+ /** Rendered width in chart units (height follows the cropped image aspect). */
579
+ width: number;
580
+ opacity: number;
581
+ rotation?: number;
582
+ visible?: boolean;
583
+ layer?: 'below' | 'above';
584
+ locked?: boolean;
585
+ /** Normalized source crop; defaults to the full image. */
586
+ crop?: {
587
+ x: number;
588
+ y: number;
589
+ width: number;
590
+ height: number;
591
+ };
592
+ calibration?: ReferenceCalibration;
593
+ /** Server-derived semantic calibration without source-image coordinates. */
594
+ derivedScale?: ReferenceDerivedScale;
595
+ }
309
596
  interface ChartDoc {
310
597
  version: 1;
311
598
  name: string;
@@ -322,14 +609,7 @@ interface ChartDoc {
322
609
  floors?: Floor[];
323
610
  objects: ChartObject[];
324
611
  /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */
325
- backgroundImage?: {
326
- url: string;
327
- center: Point;
328
- /** Rendered width in chart units (height follows the image aspect). */
329
- width: number;
330
- opacity: number;
331
- locked?: boolean;
332
- };
612
+ backgroundImage?: ChartReferenceImage;
333
613
  /** Brand/venue theming (colors); categories carry their own colors separately. */
334
614
  theme?: ChartTheme;
335
615
  /** Parametric-template provenance: present ⇒ the chart came from a capacity-
@@ -345,6 +625,8 @@ interface ExpandedSeat {
345
625
  id: string;
346
626
  /** Public label: `${rowLabel}-${seatNumber}` */
347
627
  label: string;
628
+ /** Buyer-facing copy; absent on legacy charts, where `label` is displayed. */
629
+ displayLabel?: string;
348
630
  x: number;
349
631
  y: number;
350
632
  rowId: string;
@@ -355,6 +637,7 @@ interface ExpandedSeat {
355
637
  accessible?: boolean;
356
638
  /** Specific accessibility accommodations (absent = none) — picker badges/filters these. */
357
639
  accessibility?: AccessibilityType[];
640
+ commercial?: SeatCommercialAttributes;
358
641
  /** Organizer-supplied view-from-seat image (inherited from the row). */
359
642
  viewUrl?: string;
360
643
  }
@@ -427,6 +710,130 @@ interface RendererOptions extends RendererCallbacks {
427
710
  */
428
711
  marqueeSelect?: boolean;
429
712
  }
713
+ type RenderedLabelHiddenReason = 'below-minimum-size' | 'outside-viewport' | 'dimmed-or-unavailable' | 'clutter-or-fit' | 'renderer-hidden';
714
+ /** Browser-renderer evidence used by visual QA and catalog release gates. */
715
+ interface RenderedBookableLabelEvidence {
716
+ seatId: string;
717
+ label: string;
718
+ kind: 'seat' | 'booth';
719
+ categoryKey: string;
720
+ sectionId?: string;
721
+ zoneId?: string;
722
+ status: SeatStatus;
723
+ selected: boolean;
724
+ visible: boolean;
725
+ renderedFontPx: number;
726
+ fill: string;
727
+ ink: string;
728
+ opacity: number;
729
+ /** Direct Konva shape bounds and the production near-miss rescue combined. */
730
+ pointerTarget: {
731
+ active: boolean;
732
+ directWidthPx: number;
733
+ directHeightPx: number;
734
+ effectiveMinimumPx: number;
735
+ };
736
+ /** Centre of the painted unit, even when its text is intentionally hidden. */
737
+ screenCenter: {
738
+ x: number;
739
+ y: number;
740
+ };
741
+ screenBox?: {
742
+ x: number;
743
+ y: number;
744
+ width: number;
745
+ height: number;
746
+ };
747
+ hiddenReason?: RenderedLabelHiddenReason;
748
+ }
749
+ interface RenderedHierarchyLabelEvidence {
750
+ id: string;
751
+ kind: 'section' | 'zone';
752
+ role: 'name' | 'availability' | 'price';
753
+ label: string;
754
+ visible: boolean;
755
+ renderedFontPx: number;
756
+ opacity: number;
757
+ fill: string;
758
+ ink: string;
759
+ /** Independent geometric containment check for section-owned text. */
760
+ fitsContainer?: boolean;
761
+ screenBox?: {
762
+ x: number;
763
+ y: number;
764
+ width: number;
765
+ height: number;
766
+ };
767
+ }
768
+ interface RenderedFreeTextEvidence {
769
+ objectId: string;
770
+ kind: 'free-text' | 'stage' | 'table' | 'decor' | 'ga-label' | 'ga-capacity';
771
+ text: string;
772
+ visible: boolean;
773
+ renderedFontPx: number;
774
+ ink: string;
775
+ background: string;
776
+ opacity: number;
777
+ screenBox?: {
778
+ x: number;
779
+ y: number;
780
+ width: number;
781
+ height: number;
782
+ };
783
+ hiddenReason?: 'below-minimum-size' | 'outside-viewport' | 'renderer-hidden';
784
+ }
785
+ interface RenderedGAAreaEvidence {
786
+ areaId: string;
787
+ label: string;
788
+ capacity: number;
789
+ categoryKey: string;
790
+ /** Owning logical section when the rendered GA surface is section-contained. */
791
+ sectionId?: string;
792
+ visible: boolean;
793
+ interactive: boolean;
794
+ opacity: number;
795
+ fill: string;
796
+ effectiveBackground: string;
797
+ screenBox?: {
798
+ x: number;
799
+ y: number;
800
+ width: number;
801
+ height: number;
802
+ };
803
+ }
804
+ interface RendererQualityEvidence {
805
+ viewport: {
806
+ width: number;
807
+ height: number;
808
+ };
809
+ canvasBackground: string;
810
+ effectiveScale: number;
811
+ rung: LodRung;
812
+ minimumVisibleLabelPx: number;
813
+ totalLabelledBookableUnits: number;
814
+ visibleLabels: number;
815
+ hiddenLabels: number;
816
+ /** Seats/table-seats/booths plus the full GA capacity. */
817
+ totalBookableUnits: number;
818
+ selectionRingSeatIds: string[];
819
+ selectionRingColor: string;
820
+ focusedSectionId: string | null;
821
+ focusBackdropVisible: boolean;
822
+ categoryFilterKeys: string[] | null;
823
+ /** Exact scene-graph proof for the clean section-first overview contract. */
824
+ overviewStyle: {
825
+ visibleSectionShells: number;
826
+ categoryPaintedSectionShells: number;
827
+ visibleCategoryDetailOutlines: number;
828
+ visibleSectionRowHints: number;
829
+ visibleSectionAvailabilityLabels: number;
830
+ visibleSectionGADetails: number;
831
+ };
832
+ labels: RenderedBookableLabelEvidence[];
833
+ gaAreas: RenderedGAAreaEvidence[];
834
+ hierarchyLabels: RenderedHierarchyLabelEvidence[];
835
+ freeTextLabels: RenderedFreeTextEvidence[];
836
+ }
430
837
  interface ISeatmapRenderer {
431
838
  /** Replace the chart. Resets selection and statuses, zooms to fit.
432
839
  * `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */
@@ -492,6 +899,8 @@ interface ISeatmapRenderer {
492
899
  */
493
900
  selectAllSelectable?(): ExpandedSeat[];
494
901
  selectByLabels?(labels: string[]): ExpandedSeat[];
902
+ /** Exact-render QA only: select one server-chosen unit without label ambiguity. */
903
+ setEvidenceSelection?(seatId: string): boolean;
495
904
  /** Selectable seats belonging to a section OR zone id (no selection side-effect). */
496
905
  getSelectableInSection?(sectionId: string): ExpandedSeat[];
497
906
  /** Programmatic deselect of specific seats (e.g. chip × in the cart). */
@@ -502,13 +911,21 @@ interface ISeatmapRenderer {
502
911
  * delta. Purely visual; no state change. `color` overrides the default.
503
912
  */
504
913
  flashSeat(seatId: string, color?: string): void;
914
+ /**
915
+ * Brief organizer attention pulse around a whole section. This is a visual
916
+ * overlay only: it never changes section geometry, hit targets, selection, or
917
+ * the active camera. Useful for grouped realtime operations at venue overview.
918
+ */
919
+ flashSection?(sectionId: string, color?: string): void;
505
920
  zoomToFit(): void;
506
921
  /** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */
507
922
  zoomIn(): void;
508
923
  /** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */
509
924
  zoomOut(): void;
510
- /** Total seat count of the current chart. */
925
+ /** Individually status-managed seats/table-seats/booths; excludes GA capacity. */
511
926
  seatCount(): number;
927
+ /** Seats/table-seats/booths plus the full capacity of rendered GA areas. */
928
+ bookableCount(): number;
512
929
  /**
513
930
  * Maps a chart-space point (or a seat, by its x/y) to container-relative
514
931
  * screen pixels, using the current stage scale/position. Lets host UI anchor
@@ -616,6 +1033,9 @@ interface ISeatmapRenderer {
616
1033
  getRung?(): LodRung;
617
1034
  /** Jump the camera to a rung's zoom band, centred on the chart (glided). */
618
1035
  setRung?(rung: LodRung): void;
1036
+ /** Read actual browser-rendered label visibility, size, fill, ink and state.
1037
+ * Pure diagnostic: it never changes chart or renderer state. */
1038
+ getRenderedQualityEvidence(): RendererQualityEvidence;
619
1039
  destroy(): void;
620
1040
  }
621
1041
  /** localStorage key the Designer writes and the Picker reads. */
@@ -636,10 +1056,13 @@ interface RowSeatSlot {
636
1056
  x: number;
637
1057
  y: number;
638
1058
  label: string;
1059
+ displayLabel: string;
639
1060
  categoryKey: string;
640
1061
  skipped: boolean;
641
1062
  accessible: boolean;
642
1063
  accessibility: AccessibilityType[];
1064
+ commercial?: RowObject['commercial'];
1065
+ viewUrl?: string;
643
1066
  }
644
1067
  declare function expandRowSlots(row: RowObject): RowSeatSlot[];
645
1068
  declare function expandRow(row: RowObject): ExpandedSeat[];
@@ -656,6 +1079,9 @@ declare function expandTable(t: TableObject): ExpandedSeat[];
656
1079
  declare function expandBooth(b: BoothObject): ExpandedSeat[];
657
1080
  /** Ray-cast point-in-polygon test — odd crossings ⇒ inside. */
658
1081
  declare function pointInPolygon(p: Point, poly: Point[]): boolean;
1082
+ declare function pointInPolygonWithHoles(p: Point, outer: Point[], holes: Point[][] | undefined): boolean;
1083
+ /** Stable interior label anchor that cannot land inside a polygon cutout. */
1084
+ declare function polygonLabelPoint(outer: Point[], holes: Point[][] | undefined): Point;
659
1085
  /**
660
1086
  * Visual centre of any object — used for spatial section membership and for
661
1087
  * rotating an object about its centre. Rows: centroid of expanded seats (or
@@ -801,11 +1227,21 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
801
1227
  private circleById;
802
1228
  /** Booth block geometry, keyed by booth id (= the unit's rowId). */
803
1229
  private boothDims;
804
- /** Booth label node so status changes can say HELD/SOLD on the full block. */
1230
+ /** Booth labels live with the booth shape but obey the shared rendered-size LOD. */
805
1231
  private boothLabelById;
1232
+ /** Viewport seat labels are rebuilt after each settled camera change. */
1233
+ private seatLabelById;
1234
+ /** Authored free-text nodes obey the same rendered-size visibility floor. */
1235
+ private freeTextById;
1236
+ /** Stage/rink landmarks retain a readable screen-space caption at overview. */
1237
+ private primaryFocalLabels;
1238
+ /** GA paint and text share price/highlight filter state. */
1239
+ private gaById;
806
1240
  private statusById;
807
1241
  private catColor;
808
1242
  private theme;
1243
+ /** Opaque paint actually visible behind transparent Konva canvases. */
1244
+ private canvasBackground;
809
1245
  /** Effective selection/hover ring color — resolved per chart in setChart(). */
810
1246
  private effSelection;
811
1247
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
@@ -941,6 +1377,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
941
1377
  /** Select the selectable seats matching these public labels (category/row/
942
1378
  * section bulk resolves to labels host-side). Returns the newly added seats. */
943
1379
  selectByLabels(labels: string[]): ExpandedSeat[];
1380
+ /** Exact SDK capture helper. MCP never accepts this id; the SDK derives it
1381
+ * from the persisted floor and uses the normal selected paint/ring path. */
1382
+ setEvidenceSelection(seatId: string): boolean;
944
1383
  /** Selectable seats in a section OR zone id — pure read (no selection change). */
945
1384
  getSelectableInSection(sectionId: string): ExpandedSeat[];
946
1385
  /**
@@ -961,6 +1400,12 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
961
1400
  */
962
1401
  private finishMarquee;
963
1402
  flashSeat(seatId: string, color?: string): void;
1403
+ /**
1404
+ * Pulse a section outline without moving the camera or mutating the authored
1405
+ * geometry. The temporary halo is drawn in the non-listening overlay layer,
1406
+ * so the apparent 4% lift never changes hit testing or selection bounds.
1407
+ */
1408
+ flashSection(sectionId: string, color?: string): void;
964
1409
  private onKeyDown;
965
1410
  /** Nearest seat from `fromId` in a cardinal direction (aligned + close wins). */
966
1411
  private nearestSeat;
@@ -973,6 +1418,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
973
1418
  zoomIn(): void;
974
1419
  zoomOut(): void;
975
1420
  seatCount(): number;
1421
+ bookableCount(): number;
976
1422
  worldToScreen(point: Point): {
977
1423
  x: number;
978
1424
  y: number;
@@ -986,6 +1432,10 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
986
1432
  * widget resolves which categories fall inside the buyer's chosen band.
987
1433
  */
988
1434
  setCategoryFilter(keys: string[] | null): void;
1435
+ private gaCategoryDimmed;
1436
+ /** Keep GA paint and its two labels in the same legend/price-filter state. */
1437
+ private applyGAFilterState;
1438
+ private paintGAStateForView;
989
1439
  /** Frame the currently available inventory that survived a buyer price
990
1440
  * filter. Clearing the filter glides back to the full venue. */
991
1441
  focusCategories(keys: string[] | null): void;
@@ -1039,6 +1489,11 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1039
1489
  private renderBoothUnit;
1040
1490
  /** The category's display color — Okabe-Ito hue when colorblind-safe is on. */
1041
1491
  private seatBaseColor;
1492
+ /** Resolve label ink against the paint that is actually visible. The theme
1493
+ * ink remains preferred, but mixed category palettes cannot always share one
1494
+ * accessible text colour, so every free and transient state gets the same
1495
+ * deterministic dark/light fallback used by Designer. */
1496
+ private renderedBookableLabelInk;
1042
1497
  /** Apply fill/stroke/opacity for a seat's current status + selection. */
1043
1498
  private paintSeat;
1044
1499
  /** True when a seat sits in a section/zone currently marked `closed`. */
@@ -1081,7 +1536,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1081
1536
  width: number;
1082
1537
  height: number;
1083
1538
  };
1084
- /** Axis-aligned world bounds of all seats + section outlines (minimap F3 frame). */
1539
+ /** Axis-aligned world bounds of seats, section outlines, and GA polygons (minimap F3 frame). */
1085
1540
  getWorldBounds(): {
1086
1541
  x: number;
1087
1542
  y: number;
@@ -1110,22 +1565,18 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1110
1565
  /**
1111
1566
  * A section renders in three coordinated layers driven by the LOD melt:
1112
1567
  * • a faint outline (the existing near-zoom look, untouched),
1113
- * • a solid category-mix block that fades in at the block rung, and
1114
- * • a name + "N LEFT" sublabel.
1115
- * Membership (which seats live inside the outline) + the mix fill + the live
1116
- * availability count are precomputed here (once), not per frame.
1568
+ * • a neutral solid shell that fades in at the overview rung, and
1569
+ * • one readable, contained section name.
1570
+ * Category, row, seat, and availability detail belongs to section focus/zoom.
1571
+ * Membership and category mix are still precomputed for the detailed state.
1117
1572
  */
1118
1573
  private renderSection;
1119
1574
  private refreshSectionHeat;
1120
- /** Recompute a section's availability-tinted fill + "N LEFT" (cheap; on status change). */
1575
+ /** Recompute a section's neutral overview state and retained detail count. */
1121
1576
  private refreshSectionFill;
1122
1577
  /** True when a section/zone is currently in the `closed` event-state. */
1123
1578
  private isSectionClosed;
1124
- /**
1125
- * The block-fill colour for a section: flat desaturated grey when `closed`,
1126
- * else the availability-darkened category mix; then desaturated toward neutral
1127
- * when another section holds focus (AXS dim treatment).
1128
- */
1579
+ /** Clean overview shells never leak category, price, or live availability paint. */
1129
1580
  private sectionBlockFill;
1130
1581
  /**
1131
1582
  * Zone rung: one giant screen-constant label per zone (+ optional "FROM $n"),
@@ -1143,17 +1594,19 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1143
1594
  * Section/zone labels are scale-compensated to hold a roughly constant screen size.
1144
1595
  */
1145
1596
  private applySectionLod;
1597
+ /** One semantic section gets one overview label, even across split contours. */
1598
+ private dedupeLogicalSectionLabels;
1146
1599
  /**
1147
- * Greedy label de-collision for the zone/section rungs (same approach as the
1148
- * designer's cullRowLabels): price/"N LEFT" sublabels are lowest priority and
1149
- * drop first; name labels keep top-to-bottom, left-to-right; anything whose
1150
- * on-screen box (+4px gap) overlaps an already-kept box hides. Recomputed on
1151
- * every LOD pass so hidden labels reappear as zoom spreads them apart.
1152
- * Culling multiplies the opacity applySectionLod just assigned (never raises).
1600
+ * Keep transitional zone pills from covering section names. Section names
1601
+ * are already proven inside disjoint shells, so they must not cull each other.
1153
1602
  */
1154
1603
  private decollideRungLabels;
1155
1604
  /** Set a centred label's world fontSize (for a target screen px) and re-anchor it. */
1156
1605
  private sizeLabel;
1606
+ /** Fit one centred section name, rotating narrow shells like the target chart. */
1607
+ private fitSectionRungLabels;
1608
+ /** Size one screen-constant zone name/price pill around its shared anchor. */
1609
+ private sizeZonePill;
1157
1610
  /**
1158
1611
  * Map a container-relative screen point back to world coords. Inverts the
1159
1612
  * stage (scale/pos) and, in iso view, the iso affine — so screen-space taps
@@ -1179,6 +1632,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1179
1632
  * the container's computed CSS background (walking up past transparent
1180
1633
  * ancestors). Unknown/unparseable backgrounds keep the dark default.
1181
1634
  */
1635
+ private resolveCanvasBackground;
1182
1636
  private resolveSelectionColor;
1183
1637
  private setSelected;
1184
1638
  /** Rebuild one marker after selected/held/candidate state changes. */
@@ -1190,6 +1644,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1190
1644
  * whether the section already fills the viewport (small container) so the tap
1191
1645
  * must fall through and pick.
1192
1646
  */
1647
+ private sectionBounds;
1193
1648
  private sectionFrameScale;
1194
1649
  /**
1195
1650
  * Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
@@ -1252,8 +1707,17 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1252
1707
  private cancelGlide;
1253
1708
  /** Current LOD rung derived from effective zoom — drives the ZONES/SECTIONS/SEATS pill. */
1254
1709
  getRung(): LodRung;
1255
- /** Jump the camera to a rung's zoom band, centred on the chart (glided). */
1710
+ getRenderedQualityEvidence(): RendererQualityEvidence;
1711
+ /** Jump the camera to a rung's zoom band (glided). */
1256
1712
  setRung(rung: LodRung): void;
1713
+ /**
1714
+ * The seat rung must account for labels that auto-fit inside a seat circle.
1715
+ * A short `A-1` remains at the normal 7u target; a table label such as
1716
+ * `T13-10` may fit at 4u and therefore needs a deeper camera target to reach
1717
+ * the same 12 CSS-pixel floor. Measurement happens only on explicit rung
1718
+ * navigation, never during pan/zoom frames.
1719
+ */
1720
+ private seatLabelTargetScale;
1257
1721
  /** Recompute LOD (cache/labels) after any pan/zoom settles. */
1258
1722
  private afterViewChange;
1259
1723
  /** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */
@@ -1275,6 +1739,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1275
1739
  * byte-identical.
1276
1740
  */
1277
1741
  forceDraw(): void;
1742
+ private updateFreeTextVisibility;
1278
1743
  private updateLabels;
1279
1744
  private handleResize;
1280
1745
  private startFpsLoop;
@@ -1815,4 +2280,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
1815
2280
  /** Bare symbol for input adornments ("€", "$", "₹"). */
1816
2281
  declare function currencySymbol(currency?: string): string;
1817
2282
 
1818
- 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 DecorImageObject, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatHoverDetails, 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, gaAreasOf, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
2283
+ export { ACCESSIBILITY_RING_COLOR, ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartReferenceImage, type ChartTheme, type CubicPath, DEFAULT_CURRENCY, type DecorImageObject, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, LABEL_STYLE_MAX_SIZE, LABEL_STYLE_MIN_SIZE, type LabelPresentation, type LabelStyle, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type ReferenceAccessibilitySource, type ReferenceCalibration, type ReferenceCategorySource, type ReferenceDerivedScale, type ReferenceInventoryExclusionSource, type ReferenceInventorySource, type RenderedBookableLabelEvidence, type RenderedFreeTextEvidence, type RenderedGAAreaEvidence, type RenderedHierarchyLabelEvidence, type RenderedLabelHiddenReason, type RendererCallbacks, type RendererOptions, type RendererQualityEvidence, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatCommercialAttributes, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionOutlinePath, type SectionPathSegment, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, accessibilityRingColor, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, pointInPolygonWithHoles, polygonLabelPoint, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };