@seatlayer/core 0.28.3 → 0.29.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/chunk-5MLADB2N.js +53 -0
- package/dist/chunk-5MLADB2N.js.map +1 -0
- package/dist/index.cjs +921 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -1463
- package/dist/index.d.ts +51 -1463
- package/dist/index.js +930 -161
- package/dist/index.js.map +1 -1
- package/dist/types-B-tpUFqz.d.cts +1552 -0
- package/dist/types-B-tpUFqz.d.ts +1552 -0
- package/dist/view3d/index.cjs +1972 -0
- package/dist/view3d/index.cjs.map +1 -0
- package/dist/view3d/index.d.cts +176 -0
- package/dist/view3d/index.d.ts +176 -0
- package/dist/view3d/index.js +1906 -0
- package/dist/view3d/index.js.map +1 -0
- package/package.json +22 -2
|
@@ -0,0 +1,1552 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SeatMap chart document — the single source of truth shared by the
|
|
3
|
+
* Designer (authoring) and the Renderer (buyer picker).
|
|
4
|
+
*
|
|
5
|
+
* Coordinates are abstract units (roughly "pixels at scale 1"); the renderer
|
|
6
|
+
* fits the chart to its container.
|
|
7
|
+
* Rows are PARAMETRIC (origin + count + spacing + curve + rotation) — never
|
|
8
|
+
* store per-seat coordinates in the document; expansion happens in layout.ts.
|
|
9
|
+
*/
|
|
10
|
+
interface Point {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
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
|
+
}
|
|
43
|
+
interface Category {
|
|
44
|
+
key: string;
|
|
45
|
+
label: string;
|
|
46
|
+
color: string;
|
|
47
|
+
/** Base price — used when the category has no explicit tiers. */
|
|
48
|
+
price?: number;
|
|
49
|
+
/** Durable evidence for semantic/display facts proposed while converting a
|
|
50
|
+
* private reference into sellable inventory. */
|
|
51
|
+
referenceCategorySource?: ReferenceCategorySource;
|
|
52
|
+
/**
|
|
53
|
+
* Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier
|
|
54
|
+
* per seat in this category and the tier's price applies; the first tier is the
|
|
55
|
+
* default. Per-category (not per-seat) pricing — see Batch 3.5. Empty/absent =
|
|
56
|
+
* a single price (the `price` above).
|
|
57
|
+
*/
|
|
58
|
+
tiers?: CategoryTier[];
|
|
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
|
+
}
|
|
87
|
+
/** One ticket tier within a category: a named price (Adult, Child, Senior…). */
|
|
88
|
+
interface CategoryTier {
|
|
89
|
+
id: string;
|
|
90
|
+
name: string;
|
|
91
|
+
price: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Accessibility accommodations a seat can carry. Mirrors the taxonomy real
|
|
95
|
+
* venues (and seats.io) expose so buyers can filter for exactly what they need
|
|
96
|
+
* and organizers can mark seats precisely. `wheelchair` is the legacy default.
|
|
97
|
+
*/
|
|
98
|
+
type AccessibilityType = 'wheelchair' | 'companion' | 'semi-ambulatory' | 'hearing' | 'cart' | 'sign-language' | 'plus-size' | 'lift-armrest';
|
|
99
|
+
interface AccessibilityMeta {
|
|
100
|
+
key: AccessibilityType;
|
|
101
|
+
/** Full descriptive label (designer checkbox, picker legend). */
|
|
102
|
+
label: string;
|
|
103
|
+
/** Compact label for chips/badges. */
|
|
104
|
+
short: string;
|
|
105
|
+
/** Single-glyph badge shown on seat chips + filter chips. */
|
|
106
|
+
icon: string;
|
|
107
|
+
}
|
|
108
|
+
/** Ordered taxonomy — drives the designer seat panel and the picker filters. */
|
|
109
|
+
declare const ACCESSIBILITY_TYPES: AccessibilityMeta[];
|
|
110
|
+
/** Metadata for one accessibility key (undefined for unknown keys). */
|
|
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;
|
|
120
|
+
interface SeatOverride {
|
|
121
|
+
/** 0-based seat index within the row. */
|
|
122
|
+
index: number;
|
|
123
|
+
/** Physical seat absent (pillar, sound desk) — numbering gap preserved. */
|
|
124
|
+
skip?: boolean;
|
|
125
|
+
/** Position nudge in chart units. */
|
|
126
|
+
dx?: number;
|
|
127
|
+
dy?: number;
|
|
128
|
+
/** Replace the computed label entirely. */
|
|
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;
|
|
133
|
+
categoryKey?: string;
|
|
134
|
+
/** @deprecated legacy flag — read as `['wheelchair']`; write `accessibility`. */
|
|
135
|
+
accessible?: boolean;
|
|
136
|
+
/** Accessibility accommodations of this seat (empty/absent = none). */
|
|
137
|
+
accessibility?: AccessibilityType[];
|
|
138
|
+
/**
|
|
139
|
+
* Physical wheelchair provision. Absent keeps legacy seat rendering;
|
|
140
|
+
* `seat-present` is an explicit removable/fixed accessible chair, while
|
|
141
|
+
* `no-seat` is an empty wheelchair bay that remains one sellable inventory
|
|
142
|
+
* unit. This is deliberately distinct from `skip`, which removes inventory.
|
|
143
|
+
*/
|
|
144
|
+
wheelchairSpaceType?: 'seat-present' | 'no-seat';
|
|
145
|
+
/** Commercial selling/view attributes are deliberately not accessibility. */
|
|
146
|
+
commercial?: SeatCommercialAttributes;
|
|
147
|
+
/** Seat-specific view photo; falls back to the row photo. */
|
|
148
|
+
viewFromSeatUrl?: string;
|
|
149
|
+
/** Per-seat label size/color override; falls back to the row/theme default.
|
|
150
|
+
* Size is clamped to LABEL_STYLE_MIN_SIZE..MAX_SIZE; color is passed through
|
|
151
|
+
* the shared auto-contrast rule at paint time (see {@link LabelStyle}). */
|
|
152
|
+
labelStyle?: LabelStyle;
|
|
153
|
+
}
|
|
154
|
+
interface SeatCommercialAttributes {
|
|
155
|
+
restrictedView?: boolean;
|
|
156
|
+
obstructedView?: boolean;
|
|
157
|
+
premium?: boolean;
|
|
158
|
+
note?: string;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Per-object label ink + size overrides layered on top of the chart-wide Theme
|
|
162
|
+
* defaults (rowLabelColor / textColor for rows, the section-name ink for
|
|
163
|
+
* sections). Both fields are optional: an absent field means "inherit the theme
|
|
164
|
+
* default". `color` is a preferred hex — renderers still pass it through the
|
|
165
|
+
* shared auto-contrast rule (`stateAwareBookableLabelInk`), so a choice that
|
|
166
|
+
* would be illegible over the seat/section background is switched to black or
|
|
167
|
+
* white at paint time. `size` is a font size in chart units, clamped to
|
|
168
|
+
* LABEL_STYLE_MIN_SIZE..LABEL_STYLE_MAX_SIZE by the shared ops.
|
|
169
|
+
*/
|
|
170
|
+
interface LabelStyle {
|
|
171
|
+
size?: number;
|
|
172
|
+
color?: string;
|
|
173
|
+
}
|
|
174
|
+
/** Clamp bounds for a per-object label `size`, shared by ops, MCP, and UI. */
|
|
175
|
+
declare const LABEL_STYLE_MIN_SIZE = 8;
|
|
176
|
+
declare const LABEL_STYLE_MAX_SIZE = 24;
|
|
177
|
+
interface LabelPresentation {
|
|
178
|
+
visible?: boolean;
|
|
179
|
+
/** Exact Designer-owned label anchor; public semantic MCP schemas omit it. */
|
|
180
|
+
position?: Point;
|
|
181
|
+
rotation?: number;
|
|
182
|
+
style?: 'plain' | 'pill';
|
|
183
|
+
/** Per-object size/color override for this row's or section's label. */
|
|
184
|
+
labelStyle?: LabelStyle;
|
|
185
|
+
/**
|
|
186
|
+
* End-position preset for a ROW label — which end(s) of the row show it:
|
|
187
|
+
* - `start` (default/undefined) — the row's numbering-start end (legacy behaviour).
|
|
188
|
+
* - `end` — the far end of the row.
|
|
189
|
+
* - `both` — a label at BOTH ends.
|
|
190
|
+
* - `none` — hidden (kept coherent with `visible: false`).
|
|
191
|
+
* A free-drag `position` overrides the preset (the designer shows a 'custom'
|
|
192
|
+
* state). Ignored for sections (they use `position`/`visible` only).
|
|
193
|
+
*/
|
|
194
|
+
positionPreset?: 'start' | 'end' | 'both' | 'none';
|
|
195
|
+
}
|
|
196
|
+
/** Brand/venue theming — applied by the renderer in both designer and picker. */
|
|
197
|
+
interface ChartTheme {
|
|
198
|
+
/** Canvas background color (default dark: #0e1117-ish radial). */
|
|
199
|
+
background?: string;
|
|
200
|
+
/** Preferred text color for the numbers inside seat markers. */
|
|
201
|
+
seatLabelColor?: string;
|
|
202
|
+
/** Preferred color for row identifiers such as A, B, C. Falls back to textColor. */
|
|
203
|
+
rowLabelColor?: string;
|
|
204
|
+
/** Selection ring / accent color (default white ring + brand accent). */
|
|
205
|
+
selectionColor?: string;
|
|
206
|
+
/** Décor (stage/shape) default fill. */
|
|
207
|
+
decorFill?: string;
|
|
208
|
+
/** Free-text color default. */
|
|
209
|
+
textColor?: string;
|
|
210
|
+
/** Font family (CSS stack) for all rendered text — row labels, seat numbers, sections, décor text. */
|
|
211
|
+
fontFamily?: string;
|
|
212
|
+
/** Seat size multiplier on the base radius (0.7–1.6, default 1) — bigger seats fit longer labels. */
|
|
213
|
+
seatScale?: number;
|
|
214
|
+
/** Brand accent color — recolors buttons, links, the hold pill, selection UI. */
|
|
215
|
+
accent?: string;
|
|
216
|
+
/** Ink color for text on the accent (e.g. button labels). Default light. */
|
|
217
|
+
accentInk?: string;
|
|
218
|
+
/** Organizer logo shown in the picker header (data/R2 URL). Falls back to the name. */
|
|
219
|
+
logoUrl?: string;
|
|
220
|
+
/** Brand/venue name shown in the picker header when no event name is set. */
|
|
221
|
+
brandName?: string;
|
|
222
|
+
/** Paid-tier flag: hide the "Powered by SeatMap" badge. */
|
|
223
|
+
hideBadge?: boolean;
|
|
224
|
+
}
|
|
225
|
+
interface RowObject {
|
|
226
|
+
type: 'row';
|
|
227
|
+
id: string;
|
|
228
|
+
/** Present when this row was materialized by the in-canvas reference scan.
|
|
229
|
+
* A re-scan of the same asset replaces rows carrying this marker and NEVER
|
|
230
|
+
* touches hand-authored rows — the same replace-generated-only invariant as
|
|
231
|
+
* applyReferenceInventory. */
|
|
232
|
+
referenceScan?: {
|
|
233
|
+
assetId: string;
|
|
234
|
+
};
|
|
235
|
+
/** Row label, e.g. "A". Seat labels are `${label}-${n}`. */
|
|
236
|
+
label: string;
|
|
237
|
+
/** Buyer-facing row name. `label` remains the legacy inventory prefix. */
|
|
238
|
+
displayLabel?: string;
|
|
239
|
+
/**
|
|
240
|
+
* Buyer-facing type word override (seats.io "Displayed type"). Replaces the
|
|
241
|
+
* hardcoded "Row" in the picker tooltip/confirm/cart, e.g. "Table", "Bench",
|
|
242
|
+
* "Aisle". ≤24 chars; absent = the default "Row". Pure presentation.
|
|
243
|
+
*/
|
|
244
|
+
displayType?: string;
|
|
245
|
+
labelPresentation?: LabelPresentation;
|
|
246
|
+
/** Position of the FIRST seat. */
|
|
247
|
+
origin: Point;
|
|
248
|
+
/** Degrees, clockwise. 0 = seats laid out along +x. */
|
|
249
|
+
rotation: number;
|
|
250
|
+
/**
|
|
251
|
+
* Total arc sweep in degrees across the whole row. 0 = straight.
|
|
252
|
+
* Positive bends away from +y (concave toward the focal point when the
|
|
253
|
+
* row faces it). Typical theatre rows: 10–40.
|
|
254
|
+
*/
|
|
255
|
+
curve: number;
|
|
256
|
+
seatCount: number;
|
|
257
|
+
/** Distance between adjacent seat centers, in chart units. */
|
|
258
|
+
seatSpacing: number;
|
|
259
|
+
/** Optional exact cubic centreline. Normal code owns these coordinates and
|
|
260
|
+
* distributes seats by arc length; MCP/model inputs never submit them. */
|
|
261
|
+
path?: CubicPath;
|
|
262
|
+
categoryKey: string;
|
|
263
|
+
/** Deterministic provenance for rows fitted from confirmed reference
|
|
264
|
+
* inventory. It enables revision-safe replacement without touching manually
|
|
265
|
+
* authored rows or accepting client coordinates. */
|
|
266
|
+
referenceInventorySource?: ReferenceInventorySource;
|
|
267
|
+
/** Semantic parameters for a row produced by the shared Arc/Fan operation.
|
|
268
|
+
* Designer can reopen these parameters while every segment in the group
|
|
269
|
+
* still carries the same generation signature. Public MCP tools never accept
|
|
270
|
+
* the stored center/angles as arbitrary model-authored coordinates. */
|
|
271
|
+
arcFanGeneration?: {
|
|
272
|
+
kind: 'arc-fan-v1';
|
|
273
|
+
groupId: string;
|
|
274
|
+
center: Point;
|
|
275
|
+
innerRadius: number;
|
|
276
|
+
rowCount: number;
|
|
277
|
+
rowGap: number;
|
|
278
|
+
startAngle: number;
|
|
279
|
+
endAngle: number;
|
|
280
|
+
seatPitch: number;
|
|
281
|
+
fit: 'seat-pitch' | 'fixed-count';
|
|
282
|
+
seatsPerRow?: number;
|
|
283
|
+
facing: 'inward' | 'outward';
|
|
284
|
+
taperDegrees: number;
|
|
285
|
+
skewDegrees: number;
|
|
286
|
+
aisleGaps: {
|
|
287
|
+
left: number;
|
|
288
|
+
center: number;
|
|
289
|
+
right: number;
|
|
290
|
+
};
|
|
291
|
+
rowLabelStart: number;
|
|
292
|
+
seatLabelStart: number;
|
|
293
|
+
rowIndex: number;
|
|
294
|
+
segmentIndex: number;
|
|
295
|
+
};
|
|
296
|
+
/**
|
|
297
|
+
* Membership in one buyer-facing segmented row. Physical component rows and
|
|
298
|
+
* their `${rowId}:${slotIndex}` inventory ids remain authoritative; this
|
|
299
|
+
* metadata only supplies logical ordering/presentation and explicit aisle
|
|
300
|
+
* continuity. The descriptor is repeated on every component so selecting any
|
|
301
|
+
* one can resolve the complete logical row without a chart-level side table.
|
|
302
|
+
*/
|
|
303
|
+
segmentedRow?: {
|
|
304
|
+
kind: 'segmented-row-v1';
|
|
305
|
+
groupId: string;
|
|
306
|
+
componentIndex: number;
|
|
307
|
+
componentCount: number;
|
|
308
|
+
/** The first component must use `start`; later boundaries are explicit. */
|
|
309
|
+
boundaryBefore: 'start' | 'continuous' | 'break';
|
|
310
|
+
/** Buyer-facing row name; technical component `label` values never change. */
|
|
311
|
+
displayLabel: string;
|
|
312
|
+
displayType?: string;
|
|
313
|
+
labelPresentation?: LabelPresentation;
|
|
314
|
+
viewFromSeatUrl?: string;
|
|
315
|
+
/** Presentation intent for a continuous node-defined centreline. */
|
|
316
|
+
smoothing?: boolean;
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* Versioned provenance for rows created by the multiple/intertwined block
|
|
320
|
+
* generator. Manual geometry edits remove this marker rather than allowing a
|
|
321
|
+
* later regeneration to overwrite hand-authored work.
|
|
322
|
+
*/
|
|
323
|
+
rowBlockGeneration?: {
|
|
324
|
+
kind: 'row-block-v1';
|
|
325
|
+
groupId: string;
|
|
326
|
+
style: 'multiple' | 'intertwined';
|
|
327
|
+
rowIndex: number;
|
|
328
|
+
rowCount: number;
|
|
329
|
+
seatsPerRow: number;
|
|
330
|
+
origin: Point;
|
|
331
|
+
rotation: number;
|
|
332
|
+
rowGap: number;
|
|
333
|
+
seatSpacing: number;
|
|
334
|
+
curve: number;
|
|
335
|
+
/** Stable canonical generator signature shared by every intact member. */
|
|
336
|
+
signature: string;
|
|
337
|
+
};
|
|
338
|
+
/** First seat number (default 1). Roman/letters read it as a 1-based ordinal
|
|
339
|
+
* (start 1 → I / A). */
|
|
340
|
+
seatLabelStart?: number;
|
|
341
|
+
/** Seat numbering within the row (default decimal, ltr, step 1). */
|
|
342
|
+
seatNumbering?: {
|
|
343
|
+
/** ltr / rtl number from an end; `center` numbers outward from the middle
|
|
344
|
+
* (centre seat lowest — the premium-centre theatre convention). */
|
|
345
|
+
direction: 'ltr' | 'rtl' | 'center';
|
|
346
|
+
/** 2 = odd/even numbering (1,3,5… — start at 2 for evens). */
|
|
347
|
+
step?: 1 | 2;
|
|
348
|
+
/**
|
|
349
|
+
* Label scheme for the seat NUMBER part (the row prefix is separate).
|
|
350
|
+
* Default `decimal`. Composition with `direction`/`step`/`seatLabelStart`:
|
|
351
|
+
* - `decimal` 1,2,3 — honours direction + step + start.
|
|
352
|
+
* - `odd` 1,3,5 — odd numbers from the first odd ≥ start.
|
|
353
|
+
* - `even` 2,4,6 — even numbers from the first even ≥ start.
|
|
354
|
+
* - `updown` 1,3,5,…,6,4,2 — odd-up-even-back; REPLACES direction (uses
|
|
355
|
+
* physical left→right order); start shifts.
|
|
356
|
+
* - `updown-descending` …5,3,1,2,4,6 — odd-back-even-up; the distinct
|
|
357
|
+
* reverse up/down sequence. Also replaces
|
|
358
|
+
* direction and uses physical order.
|
|
359
|
+
* - `roman` I,II,III — honours direction + step + start (uppercase).
|
|
360
|
+
* - `letters-upper` A,B,C…Z,AA — honours direction + step + start.
|
|
361
|
+
* - `letters-lower` a,b,c…z,aa — honours direction + step + start.
|
|
362
|
+
* Like `step`/`direction` today, the scheme changes the seat's inventory
|
|
363
|
+
* label (its booking identity), by design.
|
|
364
|
+
*/
|
|
365
|
+
scheme?: 'decimal' | 'odd' | 'even' | 'updown' | 'updown-descending' | 'roman' | 'letters-upper' | 'letters-lower';
|
|
366
|
+
/** Optional prefix prepended to every seat number, e.g. 'R' → 'R1', 'R2'. */
|
|
367
|
+
prefix?: string;
|
|
368
|
+
/**
|
|
369
|
+
* End-at preset ("useEndAt"): the row's numbering ENDS at this value instead
|
|
370
|
+
* of starting at `seatLabelStart`. The start is derived so the last-numbered
|
|
371
|
+
* seat (highest position rank) lands on `endAt`, respecting the scheme's step
|
|
372
|
+
* (odd/even = 2). When set it WINS over the stored `seatLabelStart` (which is
|
|
373
|
+
* left untouched). For letters it is a 1-based number index (26 → last seat
|
|
374
|
+
* 'Z'); `updown` owns its own sequence and ignores `endAt`.
|
|
375
|
+
*/
|
|
376
|
+
endAt?: number;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Per-seat exceptions, keyed by seat index (0-based position in the row).
|
|
380
|
+
* `skip` removes the physical seat but keeps the numbering gap (theatre
|
|
381
|
+
* convention: a pillar eats A-3; A-4 stays A-4).
|
|
382
|
+
*/
|
|
383
|
+
overrides?: SeatOverride[];
|
|
384
|
+
/**
|
|
385
|
+
* Organizer-supplied equirectangular 360 (or wide photo) shown as the
|
|
386
|
+
* view-from-seat for every seat in this row. When absent, the picker
|
|
387
|
+
* generates a synthetic panorama from chart geometry.
|
|
388
|
+
*/
|
|
389
|
+
viewFromSeatUrl?: string;
|
|
390
|
+
/** Default commercial attributes inherited by seats without an override. */
|
|
391
|
+
commercial?: SeatCommercialAttributes;
|
|
392
|
+
}
|
|
393
|
+
interface GAAreaObject {
|
|
394
|
+
type: 'gaArea';
|
|
395
|
+
id: string;
|
|
396
|
+
/** Stable technical/inventory label. */
|
|
397
|
+
label: string;
|
|
398
|
+
/** Buyer-facing area name; technical `label` and GA unit ids stay stable. */
|
|
399
|
+
displayLabel?: string;
|
|
400
|
+
/** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
|
|
401
|
+
* Absent = the default type word. Pure presentation. */
|
|
402
|
+
displayType?: string;
|
|
403
|
+
/** Closed polygon, in chart units. */
|
|
404
|
+
points: Point[];
|
|
405
|
+
/** Explicit aisles/pillars/cutouts excluded from the sellable GA surface. */
|
|
406
|
+
holes?: Point[][];
|
|
407
|
+
capacity: number;
|
|
408
|
+
categoryKey: string;
|
|
409
|
+
/** Corner-rounding radius in chart units (default 0 = sharp corners). Pure
|
|
410
|
+
* presentation — softens the polygon's corners in every renderer without
|
|
411
|
+
* touching capacity, unit identities, or the stored points. Clamped per
|
|
412
|
+
* corner to half the shorter adjacent edge at draw time. */
|
|
413
|
+
cornerRadius?: number;
|
|
414
|
+
/**
|
|
415
|
+
* Durable inventory provenance for a surface produced by Join Areas.
|
|
416
|
+
*
|
|
417
|
+
* A GA unit is identified by the id and zero-based range of the area that
|
|
418
|
+
* originally authored it, not by the current polygon which happens to own
|
|
419
|
+
* it. Keeping those source ranges means a geometric join never renumbers an
|
|
420
|
+
* already published/booked unit. Ordinary (never-joined) areas omit this
|
|
421
|
+
* field and implicitly own `[0, capacity)` under their own id.
|
|
422
|
+
*
|
|
423
|
+
* The ranges must be non-overlapping, contain positive whole counts, and sum
|
|
424
|
+
* exactly to `capacity`; validation rejects malformed metadata. Capacity
|
|
425
|
+
* growth appends a new range under the surviving area id, while shrinking a
|
|
426
|
+
* joined area is deliberately refused because it would silently destroy
|
|
427
|
+
* stable inventory identities.
|
|
428
|
+
*/
|
|
429
|
+
inventorySegments?: GAInventorySegment[];
|
|
430
|
+
referenceInventorySource?: ReferenceInventorySource;
|
|
431
|
+
}
|
|
432
|
+
interface GAInventorySegment {
|
|
433
|
+
sourceAreaId: string;
|
|
434
|
+
startIndex: number;
|
|
435
|
+
count: number;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Durable evidence link for sellable objects generated from a private reference.
|
|
439
|
+
* The client supplies facts and stable logical-section ids, never coordinates.
|
|
440
|
+
*/
|
|
441
|
+
interface ReferenceAccessibilitySource {
|
|
442
|
+
placementDerivation: 'server-synthesized-row-edges';
|
|
443
|
+
groupLogicalSectionIds: string[];
|
|
444
|
+
assignmentEvidence: 'user-confirmed' | 'authoritative-source';
|
|
445
|
+
assignmentSourceDescription: string;
|
|
446
|
+
counts: Array<{
|
|
447
|
+
type: AccessibilityType;
|
|
448
|
+
count: number;
|
|
449
|
+
evidence: 'user-confirmed' | 'authoritative-source';
|
|
450
|
+
sourceDescription: string;
|
|
451
|
+
}>;
|
|
452
|
+
}
|
|
453
|
+
interface ReferenceInventorySource {
|
|
454
|
+
assetId: string;
|
|
455
|
+
logicalSectionId: string;
|
|
456
|
+
evidence: 'user-confirmed' | 'authoritative-source';
|
|
457
|
+
sourceDescription: string;
|
|
458
|
+
/** Distinguishes directly supplied inventory from a user-approved server
|
|
459
|
+
* distribution based only on an aggregate capacity. */
|
|
460
|
+
derivation?: 'explicit-inventory' | 'server-synthesized-from-aggregate';
|
|
461
|
+
/** Evidence for the aggregate figure; synthesized rows remain
|
|
462
|
+
* `user-confirmed` and are never mislabeled as source-extracted. */
|
|
463
|
+
aggregateEvidence?: 'user-confirmed' | 'authoritative-source';
|
|
464
|
+
/** Separate evidence for assigning standing inventory to this logical
|
|
465
|
+
* section. Aggregate evidence alone cannot prove section placement. */
|
|
466
|
+
sectionAssignmentEvidence?: 'user-confirmed' | 'authoritative-source';
|
|
467
|
+
sectionAssignmentSourceDescription?: string;
|
|
468
|
+
/** Aggregate row synthesis may propose numbering, but persistence requires
|
|
469
|
+
* the applying user/agent to confirm that policy explicitly. */
|
|
470
|
+
numberingEvidence?: 'user-confirmed';
|
|
471
|
+
numberingSourceDescription?: string;
|
|
472
|
+
/** Evidence and deterministic placement contract for synthesized accessible
|
|
473
|
+
* units in this logical section. */
|
|
474
|
+
accessibility?: ReferenceAccessibilitySource;
|
|
475
|
+
}
|
|
476
|
+
/** Durable evidence that a visible source-backed section shell intentionally
|
|
477
|
+
* carries no generated sellable inventory in this reference configuration. */
|
|
478
|
+
interface ReferenceInventoryExclusionSource {
|
|
479
|
+
assetId: string;
|
|
480
|
+
logicalSectionId: string;
|
|
481
|
+
reason: string;
|
|
482
|
+
evidence: 'user-confirmed' | 'authoritative-source';
|
|
483
|
+
sourceDescription: string;
|
|
484
|
+
}
|
|
485
|
+
/** Open-path stroke semantics. Optional ShapeObject fields retain the legacy
|
|
486
|
+
* round/round/no-ending rendering when absent. */
|
|
487
|
+
type ShapeLineCap = 'butt' | 'round' | 'square';
|
|
488
|
+
type ShapeLineJoin = 'miter' | 'round' | 'bevel';
|
|
489
|
+
type ShapeLineEnding = 'none' | 'arrow';
|
|
490
|
+
/** Non-bookable décor: stage, walls, exits. */
|
|
491
|
+
interface ShapeObject {
|
|
492
|
+
type: 'shape';
|
|
493
|
+
id: string;
|
|
494
|
+
/**
|
|
495
|
+
* Closed area shapes (`rect`/`ellipse`/`polygon`) take a `fill`; open path
|
|
496
|
+
* primitives (`line` = two points, `polyline` = n points) are stroke-only and
|
|
497
|
+
* never filled. All kinds honour the optional `stroke`.
|
|
498
|
+
*/
|
|
499
|
+
kind: 'rect' | 'ellipse' | 'polygon' | 'line' | 'polyline';
|
|
500
|
+
label?: string;
|
|
501
|
+
/** For rect/ellipse: bounding box. For a stage polygon: the base (pre-shape) box, so its kind can be regenerated. */
|
|
502
|
+
x?: number;
|
|
503
|
+
y?: number;
|
|
504
|
+
width?: number;
|
|
505
|
+
height?: number;
|
|
506
|
+
/** For polygon/line/polyline. */
|
|
507
|
+
points?: Point[];
|
|
508
|
+
fill?: string;
|
|
509
|
+
/** Optional outline. `width` is in chart units; both fields are required together. */
|
|
510
|
+
stroke?: {
|
|
511
|
+
color: string;
|
|
512
|
+
width: number;
|
|
513
|
+
};
|
|
514
|
+
/** Open line/polyline only. Absent fields preserve round/round/no-ending legacy rendering. */
|
|
515
|
+
lineCap?: ShapeLineCap;
|
|
516
|
+
/** Controls corners between open-path segments. */
|
|
517
|
+
lineJoin?: ShapeLineJoin;
|
|
518
|
+
/** Independent open-path start/end decorations. Closed outlines never use these fields. */
|
|
519
|
+
startEnding?: ShapeLineEnding;
|
|
520
|
+
endEnding?: ShapeLineEnding;
|
|
521
|
+
/** Rect only — corner rounding radius in chart units, clamped to half the short side at edit time. */
|
|
522
|
+
cornerRadius?: number;
|
|
523
|
+
/** Whole-shape opacity 0.1–1 (default 1). */
|
|
524
|
+
opacity?: number;
|
|
525
|
+
/** Degrees clockwise about the shape's center (default 0). Applied at render time. */
|
|
526
|
+
rotation?: number;
|
|
527
|
+
/**
|
|
528
|
+
* Semantic tag driving special rendering. `'stage'` gets the gradient +
|
|
529
|
+
* prominent uppercase label treatment; a décor landmark role (bar, exit…)
|
|
530
|
+
* gets a quieter label. Loose string to avoid a circular import with
|
|
531
|
+
* stage.ts / decor.ts (see StageKind / DecorRole there).
|
|
532
|
+
*/
|
|
533
|
+
role?: string;
|
|
534
|
+
/** For a stage: which `StageKind` its polygon was generated from. */
|
|
535
|
+
stageKind?: string;
|
|
536
|
+
}
|
|
537
|
+
type RectTableSide = 'top' | 'bottom' | 'left' | 'right';
|
|
538
|
+
/** Exact rectangular-table chair distribution. The four keys are deliberately
|
|
539
|
+
* required: zero means that edge has no chair, while the sum is the authored
|
|
540
|
+
* `seatCount`. Numeric chair identity remains `${table.id}:${index}` in the
|
|
541
|
+
* canonical top, bottom, left, right expansion order. */
|
|
542
|
+
interface RectTableSeatCounts {
|
|
543
|
+
top: number;
|
|
544
|
+
bottom: number;
|
|
545
|
+
left: number;
|
|
546
|
+
right: number;
|
|
547
|
+
}
|
|
548
|
+
/** Seats arranged around a table. Grouped selling is activated only by an
|
|
549
|
+
* event's explicit inventory-model-2 snapshot; model-1 events continue to
|
|
550
|
+
* treat every authored chair as an independent unit. */
|
|
551
|
+
interface TableObject {
|
|
552
|
+
type: 'table';
|
|
553
|
+
id: string;
|
|
554
|
+
/** e.g. "T1" — seat labels are `${label}-${n}`. */
|
|
555
|
+
label: string;
|
|
556
|
+
/** Buyer-facing table name; technical chair/group labels stay stable. */
|
|
557
|
+
displayLabel?: string;
|
|
558
|
+
/** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
|
|
559
|
+
* Absent = the default "Row"/"Table" word. Pure presentation. */
|
|
560
|
+
displayType?: string;
|
|
561
|
+
center: Point;
|
|
562
|
+
shape: 'round' | 'rect';
|
|
563
|
+
/** Seats around the perimeter (round) or along the enabled edges (rect). */
|
|
564
|
+
seatCount: number;
|
|
565
|
+
/** Rect tables: which edges get seats (default ['top','bottom']). */
|
|
566
|
+
sides?: RectTableSide[];
|
|
567
|
+
/**
|
|
568
|
+
* Rect tables only: exact chairs on every edge. Absent preserves the legacy
|
|
569
|
+
* `seatCount` + `sides` round-robin distribution byte-for-byte. When present,
|
|
570
|
+
* all four values are whole numbers >= 0 and their sum equals `seatCount`.
|
|
571
|
+
*/
|
|
572
|
+
seatCountsBySide?: RectTableSeatCounts;
|
|
573
|
+
/** Individual-chair semantic overrides. Grouped whole/variable tables cannot
|
|
574
|
+
* author these because their only sellable identity is the table itself. */
|
|
575
|
+
overrides?: SeatOverride[];
|
|
576
|
+
rotation: number;
|
|
577
|
+
/** Round tables. */
|
|
578
|
+
radius?: number;
|
|
579
|
+
/**
|
|
580
|
+
* Round tables: the arc (in degrees) the seats occupy, default 360 (full
|
|
581
|
+
* ring). Below 360 leaves an open side — e.g. a service gap for waiters, a
|
|
582
|
+
* head table facing the room, or clearance against a wall. The opening is
|
|
583
|
+
* centred on the `rotation` direction; seats spread across the rest.
|
|
584
|
+
*/
|
|
585
|
+
seatArc?: number;
|
|
586
|
+
/** Rect tables. */
|
|
587
|
+
width?: number;
|
|
588
|
+
height?: number;
|
|
589
|
+
categoryKey: string;
|
|
590
|
+
/** One buyer owns the complete table at exactly `seatCount` guests. */
|
|
591
|
+
bookAsWhole?: boolean;
|
|
592
|
+
/** One buyer owns the complete table and chooses a bounded guest quantity. */
|
|
593
|
+
variableOccupancy?: boolean;
|
|
594
|
+
/** Required inclusive guest bounds when `variableOccupancy` is true. */
|
|
595
|
+
minOccupancy?: number;
|
|
596
|
+
maxOccupancy?: number;
|
|
597
|
+
referenceInventorySource?: ReferenceInventorySource;
|
|
598
|
+
}
|
|
599
|
+
/** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */
|
|
600
|
+
interface BoothObject {
|
|
601
|
+
type: 'booth';
|
|
602
|
+
id: string;
|
|
603
|
+
/** Stable technical/inventory label. */
|
|
604
|
+
label: string;
|
|
605
|
+
/** Buyer-facing booth name; technical `label` stays stable. */
|
|
606
|
+
displayLabel?: string;
|
|
607
|
+
/** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
|
|
608
|
+
* Absent = the default type word. Pure presentation. */
|
|
609
|
+
displayType?: string;
|
|
610
|
+
center: Point;
|
|
611
|
+
width: number;
|
|
612
|
+
height: number;
|
|
613
|
+
rotation: number;
|
|
614
|
+
/**
|
|
615
|
+
* Optional custom outline (closed polygon, absolute chart coordinates) for
|
|
616
|
+
* non-rectangular booths — L-shaped, corner, or island units on expo floors.
|
|
617
|
+
* Absent = the default axis-aligned rectangle described by `width`/`height`/
|
|
618
|
+
* `rotation`. A booth stays exactly ONE atomic sellable unit whatever its
|
|
619
|
+
* outline; `points` is purely geometric. `width`/`height` are retained as the
|
|
620
|
+
* last rectangular size so "Back to rectangle" can restore it. When `points`
|
|
621
|
+
* is present, renderers draw the polygon and ignore `rotation`.
|
|
622
|
+
*/
|
|
623
|
+
points?: Point[];
|
|
624
|
+
categoryKey: string;
|
|
625
|
+
referenceInventorySource?: ReferenceInventorySource;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* A named region of the venue (Balcony Left, Floor B…). Sections are outlines
|
|
629
|
+
* only — objects belong to a section spatially (center inside the outline),
|
|
630
|
+
* keeping the document flat (no nesting; simpler for tools and for AI edits).
|
|
631
|
+
* Renderer: far zoom shows section shapes/labels instead of seats; clicking
|
|
632
|
+
* a section zooms into it.
|
|
633
|
+
*/
|
|
634
|
+
interface SectionObject {
|
|
635
|
+
type: 'section';
|
|
636
|
+
id: string;
|
|
637
|
+
label: string;
|
|
638
|
+
/** Buyer-facing section name; logical/id fields remain stable. */
|
|
639
|
+
displayLabel?: string;
|
|
640
|
+
/**
|
|
641
|
+
* Buyer-facing entrance/door hint shown in the picker section card
|
|
642
|
+
* ("Entrance X"). ≤40 chars; absent = no entrance line. Pure presentation.
|
|
643
|
+
*/
|
|
644
|
+
entrance?: string;
|
|
645
|
+
/**
|
|
646
|
+
* Organizer-supplied view image inherited by buyer inventory whose owning
|
|
647
|
+
* row/table/booth sits in this logical section. Seat and row photos take
|
|
648
|
+
* precedence; multipart components are kept in sync by the shared section
|
|
649
|
+
* metadata operation.
|
|
650
|
+
*/
|
|
651
|
+
viewFromSeatUrl?: string;
|
|
652
|
+
labelPresentation?: LabelPresentation;
|
|
653
|
+
/**
|
|
654
|
+
* Stable management/inventory identity shared by disconnected visual
|
|
655
|
+
* components of one logical section. When absent, `id` is the logical id.
|
|
656
|
+
* Each component keeps its own `id` and reference provenance so rendering,
|
|
657
|
+
* editing, measured diffs, and source restoration remain exact.
|
|
658
|
+
*/
|
|
659
|
+
logicalSectionId?: string;
|
|
660
|
+
/** Shared semantic Arc/Fan group wrapped by this section. The section id is
|
|
661
|
+
* preserved when the fan parameters are reopened and regenerated. */
|
|
662
|
+
arcFanGroupId?: string;
|
|
663
|
+
/** Closed polygon, chart units. */
|
|
664
|
+
outline: Point[];
|
|
665
|
+
/** Optional true line/arc/cubic boundary. `outline` is a deterministic sample
|
|
666
|
+
* of this path and remains authoritative for membership, validation, and
|
|
667
|
+
* clients that predate curved section rendering. */
|
|
668
|
+
outlinePath?: SectionOutlinePath;
|
|
669
|
+
/** Explicit aisle/cutout polygons excluded from rendering, hit-testing, and membership. */
|
|
670
|
+
holes?: Point[][];
|
|
671
|
+
/** Durable opaque link to the private reference component. Unlike generator
|
|
672
|
+
* provenance, this survives manual geometry edits so a measured diff can
|
|
673
|
+
* report drift and server-owned code can restore the source contour. */
|
|
674
|
+
referenceSource?: {
|
|
675
|
+
assetId: string;
|
|
676
|
+
regionId: string;
|
|
677
|
+
};
|
|
678
|
+
/** Evidence-backed reason this source section remains a visible shell without
|
|
679
|
+
* synthesized sellable inventory (press, closed technical zone, etc.). */
|
|
680
|
+
referenceInventoryExclusion?: ReferenceInventoryExclusionSource;
|
|
681
|
+
/** Deterministic generator provenance for editable reference/parametric shells. */
|
|
682
|
+
geometry?: {
|
|
683
|
+
kind: 'rectangle' | 'tapered' | 'bezier' | 'contour';
|
|
684
|
+
sourceRegionId?: string;
|
|
685
|
+
contourMethod?: 'pixel-edge-loops-rdp' | 'shared-edge-vector-fit-v1';
|
|
686
|
+
simplificationTolerancePx?: number;
|
|
687
|
+
vectorFitErrorPx?: number;
|
|
688
|
+
sharedEdgeCount?: number;
|
|
689
|
+
};
|
|
690
|
+
/** Optional tint override (defaults to a neutral fill / dominant category mix). */
|
|
691
|
+
color?: string;
|
|
692
|
+
/** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */
|
|
693
|
+
zone?: string;
|
|
694
|
+
/**
|
|
695
|
+
* Tier height. 0 = floor (default). Higher values lift the section in the
|
|
696
|
+
* picker's isometric ("3D") view, drawn on extruded side faces. Same field a
|
|
697
|
+
* future multi-floor mode reuses — authored in 2D, never drawn by the user.
|
|
698
|
+
*
|
|
699
|
+
* This is the coarse, back-compat source for {@link height}/{@link rake}: when
|
|
700
|
+
* those are absent, {@link sectionGeometry} derives real geometry from this
|
|
701
|
+
* tier so legacy charts render pixel-identical.
|
|
702
|
+
*/
|
|
703
|
+
elevation?: number;
|
|
704
|
+
/**
|
|
705
|
+
* 3D foundations (Phase A, additive — no migration; charts are JSON blobs).
|
|
706
|
+
* Metres the section's **front edge** sits above floor 0 (a balcony/tier floor
|
|
707
|
+
* height). Absent ⇒ derived from the coarse {@link elevation} tier via
|
|
708
|
+
* {@link sectionGeometry}. Deliberately two scalars, not a foundation polygon:
|
|
709
|
+
* front-height + {@link rake} fully determine a rectangular tier's back-height.
|
|
710
|
+
*
|
|
711
|
+
* NOTE: no consumer reads this raw field directly — all callers go through
|
|
712
|
+
* {@link sectionGeometry}. Phase B consumers (iso view lift in
|
|
713
|
+
* `SeatmapRenderer`, per-seat eye-height in the `generatePanorama` 360°
|
|
714
|
+
* generator) are intentionally NOT wired in Phase A. Range 0–120 m.
|
|
715
|
+
*/
|
|
716
|
+
height?: number;
|
|
717
|
+
/**
|
|
718
|
+
* Degrees of seating incline within the section (0 = flat; typical stalls
|
|
719
|
+
* 5–15°, steep tiers 25–35°). Absent ⇒ 0. Consumed alongside {@link height}
|
|
720
|
+
* by the future Phase B iso-lift shear and 360° sightline math — never in
|
|
721
|
+
* Phase A. Range 0–45°.
|
|
722
|
+
*/
|
|
723
|
+
rake?: number;
|
|
724
|
+
/** Uniform scale about the outline centroid (1 = as drawn). Scales members too. */
|
|
725
|
+
scale?: number;
|
|
726
|
+
/** 0–100: reviewed strength last used to bend member rows toward a common fitted arc. */
|
|
727
|
+
smoothing?: number;
|
|
728
|
+
/**
|
|
729
|
+
* Corner smoothing: the raw clicked polygon this section was drawn from, kept
|
|
730
|
+
* verbatim so {@link cornerSmoothing} stays re-derivable and fully reversible.
|
|
731
|
+
* When present, {@link outlinePath} is a curve computed from THIS polygon (not
|
|
732
|
+
* a reference/blueprint contour); {@link outline} is its deterministic sample.
|
|
733
|
+
* Additive and optional — legacy charts and reference-derived curves omit it.
|
|
734
|
+
*/
|
|
735
|
+
sourceOutline?: Point[];
|
|
736
|
+
/**
|
|
737
|
+
* 0–100 corner-smoothing strength applied to {@link sourceOutline} to produce
|
|
738
|
+
* the curved {@link outlinePath}. 0/absent = exact clicked corners. Higher
|
|
739
|
+
* rounds the wide (gently-angled) corners more; sharp corners stay crisp.
|
|
740
|
+
* Coordinate-free, so it round-trips over MCP (`update_sections`).
|
|
741
|
+
*/
|
|
742
|
+
cornerSmoothing?: number;
|
|
743
|
+
/** Degrees clockwise about the outline centroid (default 0). Rotates members too. */
|
|
744
|
+
rotation?: number;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* A group of sections (Lower Bowl, Upper Bowl, Floor…). One concept, three jobs:
|
|
748
|
+
* the farthest-zoom navigation unit, a pricing group, and (Batch 3) a timed-
|
|
749
|
+
* release unit. Kept as a flat list on the doc; sections point back by `zone` id.
|
|
750
|
+
*/
|
|
751
|
+
interface ZoneDef {
|
|
752
|
+
id: string;
|
|
753
|
+
label: string;
|
|
754
|
+
color?: string;
|
|
755
|
+
/**
|
|
756
|
+
* Authored point this zone faces. Optional only for legacy documents: runtime
|
|
757
|
+
* consumers fall back to the active floor/chart focal, while publication of
|
|
758
|
+
* a zone-mode draft requires every used zone to carry an explicit point.
|
|
759
|
+
*/
|
|
760
|
+
focalPoint?: Point;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Selection layer — a hit-test/dim filter in the designer, NOT z-order management.
|
|
764
|
+
* Fixed set of four; derived from object type via `layerOf()` (no per-object field yet).
|
|
765
|
+
*/
|
|
766
|
+
type SelectionLayer = 'interactive' | 'background' | 'foreground' | 'surroundings';
|
|
767
|
+
/** Shape roles emitted by the curated venue-landmark palette. Keep this list in
|
|
768
|
+
* lockstep with `DECOR_PRESETS`; the selection-layer unit test fails if either
|
|
769
|
+
* vocabulary changes without an explicit routing decision. `reference-focal`
|
|
770
|
+
* is source-backed venue context rather than an authoring-palette preset. */
|
|
771
|
+
declare const SURROUNDINGS_SHAPE_ROLES: readonly ["reference-focal", "bar", "entrance", "exit", "restroom", "screen", "sound", "concession", "coat", "wall"];
|
|
772
|
+
/** Derive an object's selection layer from its type. */
|
|
773
|
+
declare function layerOf(obj: ChartObject): SelectionLayer;
|
|
774
|
+
/** Free-standing text on the chart (aisle names, door labels…). */
|
|
775
|
+
interface TextObject {
|
|
776
|
+
type: 'text';
|
|
777
|
+
id: string;
|
|
778
|
+
/** Persisted provenance for objects created from the venue-icon palette. */
|
|
779
|
+
semanticKind?: 'icon';
|
|
780
|
+
/**
|
|
781
|
+
* Registry key for a vector wayfinding icon (see src/core/icons.ts). Present
|
|
782
|
+
* on modern icon placements; the object then renders as a single-color vector
|
|
783
|
+
* Path instead of `text`. Absent on legacy emoji icons, which keep rendering
|
|
784
|
+
* `text` through the shared glyph path — old charts are never rewritten.
|
|
785
|
+
*/
|
|
786
|
+
iconKey?: string;
|
|
787
|
+
text: string;
|
|
788
|
+
position: Point;
|
|
789
|
+
fontSize: number;
|
|
790
|
+
/** Optional CSS family stack for this annotation; absent inherits ChartTheme.fontFamily. */
|
|
791
|
+
fontFamily?: string;
|
|
792
|
+
rotation: number;
|
|
793
|
+
color?: string;
|
|
794
|
+
/** Render weight (default false). Maps to Konva fontStyle bold. */
|
|
795
|
+
bold?: boolean;
|
|
796
|
+
/** Render slant (default false). Maps to Konva fontStyle italic. */
|
|
797
|
+
italic?: boolean;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* A raster/vector decor graphic drawn IN the chart, beneath the seats and
|
|
801
|
+
* sections (ice rink, basketball court, stage art, pitch markings). Purely
|
|
802
|
+
* visual venue context — never bookable, never hit-tested, so it never steals a
|
|
803
|
+
* seat click. `href` is a self-contained data URL (image or SVG) produced by the
|
|
804
|
+
* same client-side downscale used for row photos, so it travels with the doc and
|
|
805
|
+
* caches as a single bitmap blit (zero per-frame cost). Placed by top-left
|
|
806
|
+
* (x,y) + size, rotated about its centre — the same handles a shape rect uses.
|
|
807
|
+
*/
|
|
808
|
+
interface DecorImageObject {
|
|
809
|
+
type: 'decorImage';
|
|
810
|
+
id: string;
|
|
811
|
+
/** Image or SVG data URL. */
|
|
812
|
+
href: string;
|
|
813
|
+
x: number;
|
|
814
|
+
y: number;
|
|
815
|
+
width: number;
|
|
816
|
+
height: number;
|
|
817
|
+
/** Degrees clockwise about the image centre (default 0). */
|
|
818
|
+
rotation?: number;
|
|
819
|
+
/** 0–1 (default 1). Multiplied by any chart-theme dimming at render time. */
|
|
820
|
+
opacity?: number;
|
|
821
|
+
/**
|
|
822
|
+
* Z-layer relative to the interactive seat layer. `background` (default)
|
|
823
|
+
* draws beneath the seats/sections; `foreground` draws above them (a roof
|
|
824
|
+
* canopy, an overlay graphic). Absent = background — no migration needed.
|
|
825
|
+
*/
|
|
826
|
+
layer?: 'background' | 'foreground';
|
|
827
|
+
/** Optional caption for the designer inspector / accessibility (not drawn). */
|
|
828
|
+
label?: string;
|
|
829
|
+
}
|
|
830
|
+
type ChartObject = RowObject | GAAreaObject | ShapeObject | TableObject | BoothObject | TextObject | SectionObject | DecorImageObject;
|
|
831
|
+
/**
|
|
832
|
+
* One floor / level of a multi-floor venue (Batch 5). Each floor owns its own
|
|
833
|
+
* geometry, stage focal point, and trace image; categories/zones/tiers stay
|
|
834
|
+
* chart-global (one event, one inventory). A single-floor chart has NO `floors`
|
|
835
|
+
* — its `objects[]` is the whole venue — so all existing charts are untouched.
|
|
836
|
+
*/
|
|
837
|
+
interface Floor {
|
|
838
|
+
id: string;
|
|
839
|
+
name: string;
|
|
840
|
+
/**
|
|
841
|
+
* Absolute physical deck height in metres above the venue/stage datum.
|
|
842
|
+
* Optional for backwards compatibility; an absent value resolves to ground
|
|
843
|
+
* level (0 m). Section tiers and rakes are separate, section-local metadata.
|
|
844
|
+
* Range 0–120 m.
|
|
845
|
+
*/
|
|
846
|
+
baseHeightM?: number;
|
|
847
|
+
objects: ChartObject[];
|
|
848
|
+
focalPoint: Point;
|
|
849
|
+
/**
|
|
850
|
+
* Private organizer trace/calibration layer. This is authoring evidence and
|
|
851
|
+
* must never be served to, or rendered by, a buyer surface.
|
|
852
|
+
*/
|
|
853
|
+
referenceImage?: ChartReferenceImage;
|
|
854
|
+
/**
|
|
855
|
+
* Buyer-visible aesthetic background. Canonical documents store URL-only
|
|
856
|
+
* images here. Historical `assetId` values are interpreted as a trace layer
|
|
857
|
+
* by the background compatibility helpers.
|
|
858
|
+
*/
|
|
859
|
+
backgroundImage?: ChartDoc['backgroundImage'];
|
|
860
|
+
}
|
|
861
|
+
interface ReferenceCalibration {
|
|
862
|
+
type: 'two-point';
|
|
863
|
+
/** Points in immutable source-image pixels, selected by a human or trusted detector. */
|
|
864
|
+
sourceA: Point;
|
|
865
|
+
sourceB: Point;
|
|
866
|
+
/** Verified real-world distance between the two source points. */
|
|
867
|
+
distance: number;
|
|
868
|
+
unit: 'm' | 'ft' | 'chart-unit';
|
|
869
|
+
/** Derived and stored for deterministic geometry compilers. */
|
|
870
|
+
pixelsPerUnit: number;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* A single human-placed seat probe: the author clicks one seat on the reference
|
|
874
|
+
* image and the server reads the surrounding seat lattice from it.
|
|
875
|
+
*
|
|
876
|
+
* COORDINATE-POLICY CARVE-OUT (owner decision 2026-07-21). The reference
|
|
877
|
+
* blueprint pipeline runs `coordinatePolicy: 'opaque-region-ids-only'` — the
|
|
878
|
+
* server is the sole source of chart coordinates and MCP clients select opaque
|
|
879
|
+
* `reg_*` ids, never points. This type is a deliberate, narrow exception on the
|
|
880
|
+
* same grounds as `ReferenceCalibration`: the point is placed by a human in the
|
|
881
|
+
* designer canvas, not proposed by a model.
|
|
882
|
+
*
|
|
883
|
+
* Therefore this is DESIGNER-ONLY and is intentionally NOT exposed over MCP.
|
|
884
|
+
* That is an accepted, documented exception to the MCP-parity rule — the
|
|
885
|
+
* server-is-sole-source guarantee for model-driven edits is worth more than
|
|
886
|
+
* parity here. Do not "fix" it by adding a seed point to an MCP tool schema.
|
|
887
|
+
*/
|
|
888
|
+
interface ReferenceSeatSeed {
|
|
889
|
+
/** Seed centre in immutable source-image pixels (never chart coordinates). */
|
|
890
|
+
source: Point;
|
|
891
|
+
/** Half-width of the author's sizing ring, in source pixels — the "this is how
|
|
892
|
+
* big one seat is" hint that replaces seats.io's zoom-until-it-matches step. */
|
|
893
|
+
radius: number;
|
|
894
|
+
/** Whether `radius` was fitted from image pixels or set by hand. Detection
|
|
895
|
+
* weights an author-set radius more heavily than one we guessed. */
|
|
896
|
+
origin: 'auto-fit' | 'manual';
|
|
897
|
+
}
|
|
898
|
+
/** One detected row in a scan proposal — a straight seat run in CHART
|
|
899
|
+
* coordinates (the server maps source pixels through referencePixelToChart;
|
|
900
|
+
* clients never see source-pixel geometry back). */
|
|
901
|
+
interface ReferenceScanRowProposal {
|
|
902
|
+
start: Point;
|
|
903
|
+
end: Point;
|
|
904
|
+
seatCount: number;
|
|
905
|
+
}
|
|
906
|
+
/** Detected rows attributed to one compiled section (or unattributed when the
|
|
907
|
+
* lattice extends outside every compiled polygon). */
|
|
908
|
+
interface ReferenceScanSectionProposal {
|
|
909
|
+
/** Id of the compiled SectionObject the rows landed in; null = unattributed. */
|
|
910
|
+
sectionId: string | null;
|
|
911
|
+
name: string;
|
|
912
|
+
rows: ReferenceScanRowProposal[];
|
|
913
|
+
seatCount: number;
|
|
914
|
+
/** 0..1 — how well this section's lattice agreed with the probe's pitch. */
|
|
915
|
+
confidence: number;
|
|
916
|
+
/** Index of the seed (multi-probe) whose pitch produced these rows. */
|
|
917
|
+
seedIndex: number;
|
|
918
|
+
}
|
|
919
|
+
/** Server response for an in-canvas reference scan. A PROPOSAL — nothing is
|
|
920
|
+
* committed until the author applies it in the designer (chartOps + undo). */
|
|
921
|
+
interface ReferenceScanProposal {
|
|
922
|
+
assetId: string;
|
|
923
|
+
/** Measured seat diameter / centre-to-centre pitch, in chart units. */
|
|
924
|
+
seatDiameter: number;
|
|
925
|
+
seatPitch: number;
|
|
926
|
+
totalSeats: number;
|
|
927
|
+
totalRows: number;
|
|
928
|
+
sections: ReferenceScanSectionProposal[];
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Human-only Magic Trace request. `source` is one click in immutable
|
|
932
|
+
* source-image pixels; it is accepted only by the browser Designer HTTP
|
|
933
|
+
* surfaces and must never be added to an MCP schema.
|
|
934
|
+
*/
|
|
935
|
+
interface ReferenceSectionTraceInput {
|
|
936
|
+
assetId: string;
|
|
937
|
+
floorId?: string;
|
|
938
|
+
expectedUpdatedAt: number;
|
|
939
|
+
source: Point;
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Whole-reference Magic Trace request. Unlike the one-region request this
|
|
943
|
+
* carries no source coordinates: the server returns every persisted closed
|
|
944
|
+
* region as an ID-free proposal for explicit browser review.
|
|
945
|
+
*/
|
|
946
|
+
interface ReferenceSectionTraceBatchInput {
|
|
947
|
+
assetId: string;
|
|
948
|
+
floorId?: string;
|
|
949
|
+
expectedUpdatedAt: number;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Read-only Magic Trace result. This is deliberately not a SectionObject:
|
|
953
|
+
* there is no object id or label until the author accepts the proposal through
|
|
954
|
+
* the normal Designer command/undo boundary.
|
|
955
|
+
*
|
|
956
|
+
* All geometry is in chart coordinates. Source pixels, private contour
|
|
957
|
+
* vertices and reference bounds are never returned.
|
|
958
|
+
*/
|
|
959
|
+
interface ReferenceSectionTraceProposal {
|
|
960
|
+
assetId: string;
|
|
961
|
+
floorId: string;
|
|
962
|
+
outline: Point[];
|
|
963
|
+
/** Required exact fitted line/arc/cubic boundary. */
|
|
964
|
+
outlinePath: SectionOutlinePath;
|
|
965
|
+
/** Only structural source voids; printed labels/icons are filtered out. */
|
|
966
|
+
holes: Point[][];
|
|
967
|
+
color: string;
|
|
968
|
+
referenceSource: {
|
|
969
|
+
assetId: string;
|
|
970
|
+
regionId: string;
|
|
971
|
+
};
|
|
972
|
+
geometry: {
|
|
973
|
+
kind: 'contour';
|
|
974
|
+
sourceRegionId: string;
|
|
975
|
+
contourMethod: 'shared-edge-vector-fit-v1';
|
|
976
|
+
simplificationTolerancePx: number;
|
|
977
|
+
vectorFitErrorPx: number;
|
|
978
|
+
sharedEdgeCount: number;
|
|
979
|
+
};
|
|
980
|
+
provenance: {
|
|
981
|
+
regionId: string;
|
|
982
|
+
analysisVersion: number;
|
|
983
|
+
vectorTopologyVersion: number;
|
|
984
|
+
selection: 'human-source-pixel-seed' | 'human-bulk-reference-review';
|
|
985
|
+
registration: 'persisted-reference-registration-v1';
|
|
986
|
+
};
|
|
987
|
+
/** Coordinate-free evidence suitable for an author-facing confirmation. */
|
|
988
|
+
diagnostics: {
|
|
989
|
+
regionMarker: string;
|
|
990
|
+
structuralHoleCount: number;
|
|
991
|
+
fittedComponentCount: number;
|
|
992
|
+
sharedBoundaryCount: number;
|
|
993
|
+
maximumAllowedVectorErrorPx: number;
|
|
994
|
+
measuredVectorErrorPx: number;
|
|
995
|
+
/** Source component footprint, as a percentage of the analyzed image. */
|
|
996
|
+
sourceAreaPercent?: number;
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
/** Read-only whole-reference proposal. The author may approve each proposal or
|
|
1000
|
+
* all proposals; the Designer then materializes the accepted set atomically. */
|
|
1001
|
+
interface ReferenceSectionTraceBatchProposal {
|
|
1002
|
+
assetId: string;
|
|
1003
|
+
floorId: string;
|
|
1004
|
+
proposals: ReferenceSectionTraceProposal[];
|
|
1005
|
+
diagnostics: {
|
|
1006
|
+
analyzedRegionCount: number;
|
|
1007
|
+
proposalCount: number;
|
|
1008
|
+
alreadyTracedCount: number;
|
|
1009
|
+
withinToleranceCount: number;
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
/** Coordinate-free physical scale derived by server code from a confirmed
|
|
1013
|
+
* semantic feature. Unlike manual two-point calibration, no source points pass
|
|
1014
|
+
* through an MCP client or language model. */
|
|
1015
|
+
interface ReferenceDerivedScale {
|
|
1016
|
+
method: 'confirmed-focal-axis-v1';
|
|
1017
|
+
feature: 'focal-long-axis' | 'focal-short-axis';
|
|
1018
|
+
distance: number;
|
|
1019
|
+
unit: 'm' | 'ft';
|
|
1020
|
+
evidence: 'user-confirmed' | 'authoritative-source';
|
|
1021
|
+
sourceDescription: string;
|
|
1022
|
+
chartUnitsPerUnit: number;
|
|
1023
|
+
}
|
|
1024
|
+
interface ChartReferenceImage {
|
|
1025
|
+
/** Stable private reference asset. New cloud-authored charts use this. */
|
|
1026
|
+
assetId?: string;
|
|
1027
|
+
/** Legacy/self-contained source. Optional when assetId is present. */
|
|
1028
|
+
url?: string;
|
|
1029
|
+
center: Point;
|
|
1030
|
+
/** Rendered width in chart units (height follows the cropped image aspect). */
|
|
1031
|
+
width: number;
|
|
1032
|
+
opacity: number;
|
|
1033
|
+
rotation?: number;
|
|
1034
|
+
visible?: boolean;
|
|
1035
|
+
layer?: 'below' | 'above';
|
|
1036
|
+
locked?: boolean;
|
|
1037
|
+
/** Normalized source crop; defaults to the full image. */
|
|
1038
|
+
crop?: {
|
|
1039
|
+
x: number;
|
|
1040
|
+
y: number;
|
|
1041
|
+
width: number;
|
|
1042
|
+
height: number;
|
|
1043
|
+
};
|
|
1044
|
+
calibration?: ReferenceCalibration;
|
|
1045
|
+
/** Server-derived semantic calibration without source-image coordinates. */
|
|
1046
|
+
derivedScale?: ReferenceDerivedScale;
|
|
1047
|
+
}
|
|
1048
|
+
interface ChartDoc {
|
|
1049
|
+
version: 1;
|
|
1050
|
+
name: string;
|
|
1051
|
+
venueType: 'SIMPLE' | 'MIXED';
|
|
1052
|
+
/** The stage / point every seat looks at. Anchors seat-view + sightlines.
|
|
1053
|
+
* Multi-floor: mirrors floor 0; each floor also carries its own focalPoint. */
|
|
1054
|
+
focalPoint: Point;
|
|
1055
|
+
categories: Category[];
|
|
1056
|
+
/** Section groupings for far-zoom navigation + pricing (optional; sections reference by id). */
|
|
1057
|
+
zones?: ZoneDef[];
|
|
1058
|
+
/** Multi-floor venues (Batch 5): present ⇒ floors[] is the source of truth;
|
|
1059
|
+
* absent ⇒ single-floor and `objects` below is the whole chart. `objects`
|
|
1060
|
+
* is kept mirroring floor 0 so single-floor readers never branch. */
|
|
1061
|
+
floors?: Floor[];
|
|
1062
|
+
objects: ChartObject[];
|
|
1063
|
+
/**
|
|
1064
|
+
* Private floor-plan source used for tracing, calibration, scanning and
|
|
1065
|
+
* reference-backed generation. Buyer projections always remove this field.
|
|
1066
|
+
*/
|
|
1067
|
+
referenceImage?: ChartReferenceImage;
|
|
1068
|
+
/**
|
|
1069
|
+
* Buyer-visible aesthetic background. Canonical values are URL-only.
|
|
1070
|
+
* Compatibility: a historical value containing `assetId` is trace-only and
|
|
1071
|
+
* is never rendered or exposed to buyers.
|
|
1072
|
+
*/
|
|
1073
|
+
backgroundImage?: ChartReferenceImage;
|
|
1074
|
+
/** Brand/venue theming (colors); categories carry their own colors separately. */
|
|
1075
|
+
theme?: ChartTheme;
|
|
1076
|
+
/** Parametric-template provenance: present ⇒ the chart came from a capacity-
|
|
1077
|
+
* adjustable template family, and the designer offers a capacity control that
|
|
1078
|
+
* regenerates it at a new target seat count (Batch 4 "curated singles + resize"). */
|
|
1079
|
+
template?: {
|
|
1080
|
+
family: string;
|
|
1081
|
+
targetSeats: number;
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
interface ExpandedSeat {
|
|
1085
|
+
/** Stable id: `${rowId}:${index}` */
|
|
1086
|
+
id: string;
|
|
1087
|
+
/** Public label: `${rowLabel}-${seatNumber}` */
|
|
1088
|
+
label: string;
|
|
1089
|
+
/** Buyer-facing copy; absent on legacy charts, where `label` is displayed. */
|
|
1090
|
+
displayLabel?: string;
|
|
1091
|
+
x: number;
|
|
1092
|
+
y: number;
|
|
1093
|
+
rowId: string;
|
|
1094
|
+
/** Owning logical section and navigation zone, resolved once at expand time. */
|
|
1095
|
+
sectionId?: string;
|
|
1096
|
+
zoneId?: string;
|
|
1097
|
+
/** Zone focal when authored, otherwise the active floor/chart legacy fallback. */
|
|
1098
|
+
focalPoint?: Point;
|
|
1099
|
+
/** Buyer-facing segmented-row identity. `rowId` stays the physical owner id. */
|
|
1100
|
+
logicalRowId?: string;
|
|
1101
|
+
/**
|
|
1102
|
+
* Seat order inside the logical row. A deliberate missing integer is inserted
|
|
1103
|
+
* at every aisle boundary, so numerical adjacency cannot bridge a gap.
|
|
1104
|
+
*/
|
|
1105
|
+
logicalSeatIndex?: number;
|
|
1106
|
+
categoryKey: string;
|
|
1107
|
+
/** 'booth' units render as blocks (dimensions looked up via rowId = booth id). */
|
|
1108
|
+
kind?: 'seat' | 'booth';
|
|
1109
|
+
/** True when the seat has any accessibility accommodation — renderer rings/dims these. */
|
|
1110
|
+
accessible?: boolean;
|
|
1111
|
+
/** Specific accessibility accommodations (absent = none) — picker badges/filters these. */
|
|
1112
|
+
accessibility?: AccessibilityType[];
|
|
1113
|
+
/** Physical wheelchair provision resolved from the seat override. */
|
|
1114
|
+
wheelchairSpaceType?: 'seat-present' | 'no-seat';
|
|
1115
|
+
commercial?: SeatCommercialAttributes;
|
|
1116
|
+
/** Organizer-supplied view-from-seat image (inherited from the row). */
|
|
1117
|
+
viewUrl?: string;
|
|
1118
|
+
/** Per-seat label size/color override; absent = inherit the row/theme default. */
|
|
1119
|
+
labelStyle?: LabelStyle;
|
|
1120
|
+
/**
|
|
1121
|
+
* Real-world eye height in metres above the focal/stage datum, resolved at
|
|
1122
|
+
* expand time from the owning section's `{height, rake}` + drawn depth (Phase B2).
|
|
1123
|
+
* Feeds the auto-360° generator's stage-pitch math. Absent ⇒ flat seated eye
|
|
1124
|
+
* height (legacy / seats in no section) — so old charts stay pixel-identical.
|
|
1125
|
+
*/
|
|
1126
|
+
eyeHeightM?: number;
|
|
1127
|
+
}
|
|
1128
|
+
type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';
|
|
1129
|
+
/** Buyer canvas projection. Perspective is a view-only projected-2.5D lane. */
|
|
1130
|
+
type RendererViewMode = 'flat' | 'isometric' | 'perspective';
|
|
1131
|
+
interface RendererCallbacks {
|
|
1132
|
+
onSelect?: (seat: ExpandedSeat) => void;
|
|
1133
|
+
onDeselect?: (seat: ExpandedSeat) => void;
|
|
1134
|
+
/** Buyer tried to add a seat after the active selection cap was reached. */
|
|
1135
|
+
onSelectionLimit?: (maxSelection: number) => void;
|
|
1136
|
+
/** seat is null when the pointer leaves any seat. */
|
|
1137
|
+
onHover?: (seat: ExpandedSeat | null) => void;
|
|
1138
|
+
/** Keyboard focus moved to a seat (arrow-key navigation) — for screen-reader announcements. */
|
|
1139
|
+
onFocusSeat?: (seat: ExpandedSeat | null) => void;
|
|
1140
|
+
/** Called ~1×/sec with the measured frames-per-second. */
|
|
1141
|
+
onFps?: (fps: number) => void;
|
|
1142
|
+
/** Fired when a GA area is clicked (quantity picking is UI-side). */
|
|
1143
|
+
onGAClick?: (areaId: string) => void;
|
|
1144
|
+
/**
|
|
1145
|
+
* Fired when a tap lands on a section outline while seats are NOT the active
|
|
1146
|
+
* rung (i.e. zoomed out, section/zone LOD). The host glides in + shows a
|
|
1147
|
+
* section-summary card instead of trying to select a 4px seat (Slice 5).
|
|
1148
|
+
*/
|
|
1149
|
+
onSectionTap?: (sectionId: string) => void;
|
|
1150
|
+
/**
|
|
1151
|
+
* Fired when a seat/deck is tapped in the 3D all-floors stacked overview — the
|
|
1152
|
+
* host drops back to the flat 2D map on that floor ("tap a deck to enter").
|
|
1153
|
+
*/
|
|
1154
|
+
onDeckTap?: (floorId: string) => void;
|
|
1155
|
+
/** Fired after any pan/zoom/resize settles — re-anchor screen-space overlays. */
|
|
1156
|
+
onViewChange?: () => void;
|
|
1157
|
+
/**
|
|
1158
|
+
* Organizer manage-mode only (`manageMode` + `marqueeSelect`): fired on
|
|
1159
|
+
* pointer-UP after a rubber-band marquee drag, or a ⌘A/Escape bulk shortcut,
|
|
1160
|
+
* with the FULL current selection (selectable seats only). The host toolbar
|
|
1161
|
+
* reads this to drive bulk block/unblock. Never fires when manageMode is off.
|
|
1162
|
+
*/
|
|
1163
|
+
onMarquee?: (seats: ExpandedSeat[]) => void;
|
|
1164
|
+
}
|
|
1165
|
+
/** Far-zoom level-of-detail rung: whole zones → section blocks → individual seats. */
|
|
1166
|
+
type LodRung = 'zones' | 'sections' | 'seats';
|
|
1167
|
+
interface RendererOptions extends RendererCallbacks {
|
|
1168
|
+
/** Max seats selectable at once (default 10). */
|
|
1169
|
+
maxSelection?: number;
|
|
1170
|
+
/** Only these statuses are clickable (default ['free']). */
|
|
1171
|
+
selectableStatuses?: SeatStatus[];
|
|
1172
|
+
/**
|
|
1173
|
+
* Opt-in host behaviour flag — the renderer's own click/selection logic is
|
|
1174
|
+
* unchanged (it still selects + fires `onSelect` immediately, so the seat
|
|
1175
|
+
* highlights right away). When true, the host (e.g. PublicEventPage) treats
|
|
1176
|
+
* that `onSelect` as a pending candidate and shows a confirm card instead of
|
|
1177
|
+
* pushing straight into the cart; `deselect([seat.id])` on Cancel un-highlights.
|
|
1178
|
+
*/
|
|
1179
|
+
confirmSelection?: boolean;
|
|
1180
|
+
/** ISO 4217 currency for on-map prices ("FROM …"); defaults to money.DEFAULT_CURRENCY.
|
|
1181
|
+
* Locale for grouping/symbol placement comes from the active i18n locale. */
|
|
1182
|
+
currency?: string;
|
|
1183
|
+
/**
|
|
1184
|
+
* Organizer manage surface (SDK SeatManager). Opt-in — enables the manage-mode
|
|
1185
|
+
* gestures (marquee, ⌘A/Escape) and the bulk-selection helpers. Buyer pan /
|
|
1186
|
+
* pinch / tap and every existing code path are byte-identical when this is
|
|
1187
|
+
* false (every manage branch is gated on it). Default false.
|
|
1188
|
+
*/
|
|
1189
|
+
manageMode?: boolean;
|
|
1190
|
+
/**
|
|
1191
|
+
* When `manageMode` is on, a mouse/pen primary-button drag at the seats rung
|
|
1192
|
+
* draws a rubber-band marquee that bulk-selects the seats it covers (emitting
|
|
1193
|
+
* `onMarquee` on pointer-up) instead of panning. Touch keeps single-finger
|
|
1194
|
+
* pan (pinch to zoom); a middle-button drag pans with a mouse. Disabled below
|
|
1195
|
+
* the seats rung (zoom in first). No effect unless `manageMode` is also set.
|
|
1196
|
+
*/
|
|
1197
|
+
marqueeSelect?: boolean;
|
|
1198
|
+
}
|
|
1199
|
+
type RenderedLabelHiddenReason = 'below-minimum-size' | 'outside-viewport' | 'dimmed-or-unavailable' | 'clutter-or-fit' | 'renderer-hidden';
|
|
1200
|
+
/** Browser-renderer evidence used by visual QA and catalog release gates. */
|
|
1201
|
+
interface RenderedBookableLabelEvidence {
|
|
1202
|
+
seatId: string;
|
|
1203
|
+
label: string;
|
|
1204
|
+
kind: 'seat' | 'booth';
|
|
1205
|
+
/** Painted inventory silhouette. Empty wheelchair bays are deliberately
|
|
1206
|
+
* square, while physical seats retain the ordinary circular marker. */
|
|
1207
|
+
markerShape: 'circle' | 'square' | 'booth';
|
|
1208
|
+
/** Physical wheelchair provision represented by this inventory unit. */
|
|
1209
|
+
wheelchairSpaceType?: 'seat-present' | 'no-seat';
|
|
1210
|
+
categoryKey: string;
|
|
1211
|
+
sectionId?: string;
|
|
1212
|
+
zoneId?: string;
|
|
1213
|
+
status: SeatStatus;
|
|
1214
|
+
selected: boolean;
|
|
1215
|
+
visible: boolean;
|
|
1216
|
+
renderedFontPx: number;
|
|
1217
|
+
fill: string;
|
|
1218
|
+
ink: string;
|
|
1219
|
+
opacity: number;
|
|
1220
|
+
/** Buyer-visible accessibility glyph evidence. Filter emphasis uses a
|
|
1221
|
+
* screen-space minimum so wheelchair provision remains recognizable at fit. */
|
|
1222
|
+
accessibilityMarker?: {
|
|
1223
|
+
glyphVisible: boolean;
|
|
1224
|
+
glyphWidthPx: number;
|
|
1225
|
+
emphasizedByFilter: boolean;
|
|
1226
|
+
};
|
|
1227
|
+
/** Direct Konva shape bounds and the production near-miss rescue combined. */
|
|
1228
|
+
pointerTarget: {
|
|
1229
|
+
active: boolean;
|
|
1230
|
+
directWidthPx: number;
|
|
1231
|
+
directHeightPx: number;
|
|
1232
|
+
effectiveMinimumPx: number;
|
|
1233
|
+
};
|
|
1234
|
+
/** Centre of the painted unit, even when its text is intentionally hidden. */
|
|
1235
|
+
screenCenter: {
|
|
1236
|
+
x: number;
|
|
1237
|
+
y: number;
|
|
1238
|
+
};
|
|
1239
|
+
screenBox?: {
|
|
1240
|
+
x: number;
|
|
1241
|
+
y: number;
|
|
1242
|
+
width: number;
|
|
1243
|
+
height: number;
|
|
1244
|
+
};
|
|
1245
|
+
hiddenReason?: RenderedLabelHiddenReason;
|
|
1246
|
+
}
|
|
1247
|
+
interface RenderedHierarchyLabelEvidence {
|
|
1248
|
+
id: string;
|
|
1249
|
+
kind: 'section' | 'zone';
|
|
1250
|
+
role: 'name' | 'availability' | 'price';
|
|
1251
|
+
label: string;
|
|
1252
|
+
visible: boolean;
|
|
1253
|
+
renderedFontPx: number;
|
|
1254
|
+
opacity: number;
|
|
1255
|
+
fill: string;
|
|
1256
|
+
ink: string;
|
|
1257
|
+
/** Independent geometric containment check for section-owned text. */
|
|
1258
|
+
fitsContainer?: boolean;
|
|
1259
|
+
screenBox?: {
|
|
1260
|
+
x: number;
|
|
1261
|
+
y: number;
|
|
1262
|
+
width: number;
|
|
1263
|
+
height: number;
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
interface RenderedFreeTextEvidence {
|
|
1267
|
+
objectId: string;
|
|
1268
|
+
kind: 'free-text' | 'stage' | 'table' | 'decor' | 'ga-label' | 'ga-capacity';
|
|
1269
|
+
text: string;
|
|
1270
|
+
visible: boolean;
|
|
1271
|
+
renderedFontPx: number;
|
|
1272
|
+
ink: string;
|
|
1273
|
+
background: string;
|
|
1274
|
+
opacity: number;
|
|
1275
|
+
screenBox?: {
|
|
1276
|
+
x: number;
|
|
1277
|
+
y: number;
|
|
1278
|
+
width: number;
|
|
1279
|
+
height: number;
|
|
1280
|
+
};
|
|
1281
|
+
hiddenReason?: 'below-minimum-size' | 'outside-viewport' | 'renderer-hidden';
|
|
1282
|
+
}
|
|
1283
|
+
interface RenderedGAAreaEvidence {
|
|
1284
|
+
areaId: string;
|
|
1285
|
+
label: string;
|
|
1286
|
+
capacity: number;
|
|
1287
|
+
categoryKey: string;
|
|
1288
|
+
/** Owning logical section when the rendered GA surface is section-contained. */
|
|
1289
|
+
sectionId?: string;
|
|
1290
|
+
visible: boolean;
|
|
1291
|
+
interactive: boolean;
|
|
1292
|
+
opacity: number;
|
|
1293
|
+
fill: string;
|
|
1294
|
+
effectiveBackground: string;
|
|
1295
|
+
screenBox?: {
|
|
1296
|
+
x: number;
|
|
1297
|
+
y: number;
|
|
1298
|
+
width: number;
|
|
1299
|
+
height: number;
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
interface RendererQualityEvidence {
|
|
1303
|
+
viewport: {
|
|
1304
|
+
width: number;
|
|
1305
|
+
height: number;
|
|
1306
|
+
};
|
|
1307
|
+
/** Runtime projection actually used for the pixels and hit graph below. */
|
|
1308
|
+
projection: RendererViewMode;
|
|
1309
|
+
/** Phase-C proof metadata. Present only in the projected-2.5D lane. */
|
|
1310
|
+
perspective?: {
|
|
1311
|
+
model: 'pinhole-exact-seat-anchors';
|
|
1312
|
+
sectionSurfaceModel: 'tangent-plane';
|
|
1313
|
+
exactSeatAnchorCount: number;
|
|
1314
|
+
depthSorted: true;
|
|
1315
|
+
};
|
|
1316
|
+
canvasBackground: string;
|
|
1317
|
+
effectiveScale: number;
|
|
1318
|
+
rung: LodRung;
|
|
1319
|
+
minimumVisibleLabelPx: number;
|
|
1320
|
+
totalLabelledBookableUnits: number;
|
|
1321
|
+
visibleLabels: number;
|
|
1322
|
+
hiddenLabels: number;
|
|
1323
|
+
/** Seats/table-seats/booths plus the full GA capacity. */
|
|
1324
|
+
totalBookableUnits: number;
|
|
1325
|
+
selectionRingSeatIds: string[];
|
|
1326
|
+
selectionRingColor: string;
|
|
1327
|
+
focusedSectionId: string | null;
|
|
1328
|
+
focusBackdropVisible: boolean;
|
|
1329
|
+
categoryFilterKeys: string[] | null;
|
|
1330
|
+
/** Exact scene-graph proof for the clean section-first overview contract. */
|
|
1331
|
+
overviewStyle: {
|
|
1332
|
+
visibleSectionShells: number;
|
|
1333
|
+
categoryPaintedSectionShells: number;
|
|
1334
|
+
visibleCategoryDetailOutlines: number;
|
|
1335
|
+
visibleSectionRowHints: number;
|
|
1336
|
+
visibleSectionAvailabilityLabels: number;
|
|
1337
|
+
visibleSectionGADetails: number;
|
|
1338
|
+
};
|
|
1339
|
+
labels: RenderedBookableLabelEvidence[];
|
|
1340
|
+
gaAreas: RenderedGAAreaEvidence[];
|
|
1341
|
+
hierarchyLabels: RenderedHierarchyLabelEvidence[];
|
|
1342
|
+
freeTextLabels: RenderedFreeTextEvidence[];
|
|
1343
|
+
}
|
|
1344
|
+
interface ISeatmapRenderer {
|
|
1345
|
+
/** Replace the chart. Resets selection and statuses, zooms to fit.
|
|
1346
|
+
* `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */
|
|
1347
|
+
setChart(doc: ChartDoc, opts?: {
|
|
1348
|
+
floorId?: string;
|
|
1349
|
+
}): void;
|
|
1350
|
+
/** Bulk status update; re-renders affected seats only. */
|
|
1351
|
+
setStatus(seatIds: string[], status: SeatStatus): void;
|
|
1352
|
+
/**
|
|
1353
|
+
* Mark the active buyer's own held seats. They remain server-status `held`,
|
|
1354
|
+
* but render with the buyer selection treatment instead of the anonymous
|
|
1355
|
+
* unavailable treatment used for another buyer's hold.
|
|
1356
|
+
*/
|
|
1357
|
+
setOwnedHold?(seatIds: string[] | null): void;
|
|
1358
|
+
/**
|
|
1359
|
+
* Mark one selected seat as the buyer's pending confirmation candidate.
|
|
1360
|
+
* The candidate receives a strong focus halo while unrelated seats recede;
|
|
1361
|
+
* pass null after Select/Cancel. This is visual only and never mutates the
|
|
1362
|
+
* renderer selection.
|
|
1363
|
+
*/
|
|
1364
|
+
setSelectionFocus?(seatId: string | null): void;
|
|
1365
|
+
/**
|
|
1366
|
+
* SYNCHRONOUS repaint that bypasses requestAnimationFrame. Konva's batchDraw()
|
|
1367
|
+
* (used by setStatus and friends) schedules the actual paint on the next rAF
|
|
1368
|
+
* tick, which Chrome throttles/pauses on hidden, backgrounded, or occluded
|
|
1369
|
+
* tabs — so a seat-status delta updates the scene graph but the pixels never
|
|
1370
|
+
* change until the tab is foregrounded again. forceDraw() paints the affected
|
|
1371
|
+
* layers immediately (Layer.draw() is synchronous) and flushes any pending
|
|
1372
|
+
* cache-debounce, so a caller (visibilitychange catch-up, or an opted-in
|
|
1373
|
+
* always-live board) can guarantee the canvas reflects current state
|
|
1374
|
+
* regardless of tab visibility. No-op difference in the foreground.
|
|
1375
|
+
*/
|
|
1376
|
+
forceDraw(): void;
|
|
1377
|
+
getStatus(seatId: string): SeatStatus;
|
|
1378
|
+
getSelection(): ExpandedSeat[];
|
|
1379
|
+
clearSelection(): void;
|
|
1380
|
+
/** Update the buyer selection cap without rebuilding the chart or camera. */
|
|
1381
|
+
setMaxSelection?(maxSelection: number): void;
|
|
1382
|
+
/**
|
|
1383
|
+
* Programmatically restore free seats (for example an Undo action). Added
|
|
1384
|
+
* seats respect the active cap and do not reopen a confirmation popover.
|
|
1385
|
+
*/
|
|
1386
|
+
select?(seatIds: string[]): ExpandedSeat[];
|
|
1387
|
+
/**
|
|
1388
|
+
* Dynamically update organizer-only interaction without rebuilding the
|
|
1389
|
+
* renderer. No buyer surface calls this; every behavior remains gated by
|
|
1390
|
+
* `manageMode` exactly as it is at construction time.
|
|
1391
|
+
*/
|
|
1392
|
+
setManageInteraction?(options: {
|
|
1393
|
+
manageMode: boolean;
|
|
1394
|
+
marqueeSelect: boolean;
|
|
1395
|
+
selectableStatuses: SeatStatus[];
|
|
1396
|
+
maxSelection?: number;
|
|
1397
|
+
}): void;
|
|
1398
|
+
/** Organizer-only section heat overlay. Values are normalized 0..1. */
|
|
1399
|
+
setSectionHeat?(scores: Record<string, number> | null): void;
|
|
1400
|
+
/**
|
|
1401
|
+
* Manage-mode bulk selection helpers (no-op / empty unless `manageMode`).
|
|
1402
|
+
* They select the matching SELECTABLE seats (respecting `selectableStatuses`
|
|
1403
|
+
* + closed sections), union with the current selection, and return the seats
|
|
1404
|
+
* they added — the SDK SeatManager expands category/row/section picks to
|
|
1405
|
+
* labels and drives one batched block/unblock from them.
|
|
1406
|
+
*/
|
|
1407
|
+
selectAllSelectable?(): ExpandedSeat[];
|
|
1408
|
+
selectByLabels?(labels: string[]): ExpandedSeat[];
|
|
1409
|
+
/** Exact-render QA only: select one server-chosen unit without label ambiguity. */
|
|
1410
|
+
setEvidenceSelection?(seatId: string): boolean;
|
|
1411
|
+
/** Selectable seats belonging to a section OR zone id (no selection side-effect). */
|
|
1412
|
+
getSelectableInSection?(sectionId: string): ExpandedSeat[];
|
|
1413
|
+
/** Programmatic deselect of specific seats (e.g. chip × in the cart). */
|
|
1414
|
+
deselect(seatIds: string[]): void;
|
|
1415
|
+
/**
|
|
1416
|
+
* Brief attention pulse on a seat (a ring that expands + fades once) — used to
|
|
1417
|
+
* signal live activity, e.g. a seat "just taken" by another buyer via a WS
|
|
1418
|
+
* delta. Purely visual; no state change. `color` overrides the default.
|
|
1419
|
+
*/
|
|
1420
|
+
flashSeat(seatId: string, color?: string): void;
|
|
1421
|
+
/**
|
|
1422
|
+
* Brief organizer attention pulse around a whole section. This is a visual
|
|
1423
|
+
* overlay only: it never changes section geometry, hit targets, selection, or
|
|
1424
|
+
* the active camera. Useful for grouped realtime operations at venue overview.
|
|
1425
|
+
*/
|
|
1426
|
+
flashSection?(sectionId: string, color?: string): void;
|
|
1427
|
+
zoomToFit(): void;
|
|
1428
|
+
/** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */
|
|
1429
|
+
zoomIn(): void;
|
|
1430
|
+
/** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */
|
|
1431
|
+
zoomOut(): void;
|
|
1432
|
+
/** Individually status-managed seats/table-seats/booths; excludes GA capacity. */
|
|
1433
|
+
seatCount(): number;
|
|
1434
|
+
/** Seats/table-seats/booths plus the full capacity of rendered GA areas. */
|
|
1435
|
+
bookableCount(): number;
|
|
1436
|
+
/**
|
|
1437
|
+
* Maps a chart-space point (or a seat, by its x/y) to container-relative
|
|
1438
|
+
* screen pixels, using the current stage scale/position. Lets host UI anchor
|
|
1439
|
+
* DOM overlays (confirm card, tooltip) over a live seat and re-anchor them
|
|
1440
|
+
* on `onViewChange`.
|
|
1441
|
+
*/
|
|
1442
|
+
worldToScreen(point: Point): {
|
|
1443
|
+
x: number;
|
|
1444
|
+
y: number;
|
|
1445
|
+
};
|
|
1446
|
+
/** When on, dim non-accessible free seats so accessible seats stand out. */
|
|
1447
|
+
setAccessibleFilter(on: boolean): void;
|
|
1448
|
+
/**
|
|
1449
|
+
* Dim free seats that lack ANY of these accessibility types. `null` clears the
|
|
1450
|
+
* filter; `[]` means "any accessible seat" (same as setAccessibleFilter(true)).
|
|
1451
|
+
*/
|
|
1452
|
+
setAccessibilityFilter(types: AccessibilityType[] | null): void;
|
|
1453
|
+
/** Legend hover-highlight: dim free seats of other categories (null clears). */
|
|
1454
|
+
setCategoryHighlight?(key: string | null): void;
|
|
1455
|
+
/** Price-band filter (F4): dim free seats whose category is NOT in `keys`
|
|
1456
|
+
* (null clears). The widget resolves which categories fall in the band. */
|
|
1457
|
+
setCategoryFilter?(keys: string[] | null): void;
|
|
1458
|
+
/** Smoothly frame the currently available seats in these categories. `null`
|
|
1459
|
+
* returns to the full chart. Used after an explicit buyer price-filter action. */
|
|
1460
|
+
focusCategories?(keys: string[] | null): void;
|
|
1461
|
+
/** Dim the seats of these section/zone ids (organizer manager: held-back inventory). */
|
|
1462
|
+
setDimmedSections?(ids: string[] | null): void;
|
|
1463
|
+
/**
|
|
1464
|
+
* Phase 2 event-level section states: mark these section/zone ids `closed` —
|
|
1465
|
+
* flat grey block, seats greyed + not pickable, section stays rendered.
|
|
1466
|
+
* `null`/empty clears. (Distinct from the buyer's applyHidden seat-strip.)
|
|
1467
|
+
*/
|
|
1468
|
+
setClosedSections?(ids: string[] | null): void;
|
|
1469
|
+
/**
|
|
1470
|
+
* AXS section-focus: dim + desaturate every other section, draw a calm backdrop
|
|
1471
|
+
* behind this section, and glide the camera to frame it. Seat-picking is gated
|
|
1472
|
+
* until seats are large enough on screen (≥ LABEL_SCALE). Slice 5 / Phase 2 §4.
|
|
1473
|
+
*/
|
|
1474
|
+
focusSection?(id: string): void;
|
|
1475
|
+
/** Clear an AXS section focus (restore full-bowl brightness + drop backdrop). */
|
|
1476
|
+
clearSectionFocus?(): void;
|
|
1477
|
+
/** The currently AXS-focused section id, or null. */
|
|
1478
|
+
getFocusedSection?(): string | null;
|
|
1479
|
+
/** World-space rect currently visible in the viewport (minimap viewport frame). */
|
|
1480
|
+
getVisibleWorldRect?(): {
|
|
1481
|
+
x: number;
|
|
1482
|
+
y: number;
|
|
1483
|
+
width: number;
|
|
1484
|
+
height: number;
|
|
1485
|
+
};
|
|
1486
|
+
/** Axis-aligned world bounds of all seats + section outlines (minimap frame). */
|
|
1487
|
+
getWorldBounds?(): {
|
|
1488
|
+
x: number;
|
|
1489
|
+
y: number;
|
|
1490
|
+
width: number;
|
|
1491
|
+
height: number;
|
|
1492
|
+
};
|
|
1493
|
+
/**
|
|
1494
|
+
* Colorblind-safe mode: category hues switch to an Okabe-Ito palette and
|
|
1495
|
+
* booked seats render hollow (a non-color cue), so seat state never relies
|
|
1496
|
+
* on hue alone. Off (the default) renders exactly as before.
|
|
1497
|
+
*/
|
|
1498
|
+
setColorblindSafe?(on: boolean): void;
|
|
1499
|
+
/**
|
|
1500
|
+
* Switch the projection. `'flat'` = normal top-down; `'isometric'` = the
|
|
1501
|
+
* legacy affine preview; `'perspective'` = projected 2.5D with exact pinhole
|
|
1502
|
+
* seat anchors/native hit shapes and bounded per-section tangent surfaces.
|
|
1503
|
+
* Purely visual — the chart is authored flat.
|
|
1504
|
+
*/
|
|
1505
|
+
setViewMode?(mode: RendererViewMode): void;
|
|
1506
|
+
/** Current projection (defaults to 'flat' when unimplemented). */
|
|
1507
|
+
getViewMode?(): RendererViewMode;
|
|
1508
|
+
/** Multi-floor (Batch 5): switch the shown floor; list floors; read the active id. */
|
|
1509
|
+
setActiveFloor?(floorId: string): void;
|
|
1510
|
+
getFloors?(): {
|
|
1511
|
+
id: string;
|
|
1512
|
+
name: string;
|
|
1513
|
+
}[];
|
|
1514
|
+
getActiveFloorId?(): string;
|
|
1515
|
+
/** Render all floors stacked (3D overview) vs the active floor. No-op single-floor. */
|
|
1516
|
+
setStacked?(on: boolean): void;
|
|
1517
|
+
isStacked?(): boolean;
|
|
1518
|
+
/**
|
|
1519
|
+
* Section id whose outline contains a container-relative screen point (or null).
|
|
1520
|
+
* Feeds the far-zoom "tap a section to zoom in" flow (Slice 5).
|
|
1521
|
+
*/
|
|
1522
|
+
sectionAt?(clientPoint: Point): string | null;
|
|
1523
|
+
/** Seat ids belonging to a section — for the section-summary card (Slice 5). */
|
|
1524
|
+
sectionMembers?(id: string): string[];
|
|
1525
|
+
/**
|
|
1526
|
+
* Smoothly glide (pan+zoom) the camera to frame a section (by id) or a world-
|
|
1527
|
+
* space bounds rect over a calm easeInOutCubic glide. `prefers-reduced-motion` snaps.
|
|
1528
|
+
* A pointer-down (grab/pan) cancels an in-flight glide. Slice 5 "glide in".
|
|
1529
|
+
*/
|
|
1530
|
+
focusRegion?(target: string | {
|
|
1531
|
+
x: number;
|
|
1532
|
+
y: number;
|
|
1533
|
+
width: number;
|
|
1534
|
+
height: number;
|
|
1535
|
+
}, opts?: {
|
|
1536
|
+
animate?: boolean;
|
|
1537
|
+
minScale?: number;
|
|
1538
|
+
durationMs?: number;
|
|
1539
|
+
}): void;
|
|
1540
|
+
/** Current LOD rung derived from zoom (for the ZONES/SECTIONS/SEATS pill). */
|
|
1541
|
+
getRung?(): LodRung;
|
|
1542
|
+
/** Jump the camera to a rung's zoom band, centred on the chart (glided). */
|
|
1543
|
+
setRung?(rung: LodRung): void;
|
|
1544
|
+
/** Read actual browser-rendered label visibility, size, fill, ink and state.
|
|
1545
|
+
* Pure diagnostic: it never changes chart or renderer state. */
|
|
1546
|
+
getRenderedQualityEvidence(): RendererQualityEvidence;
|
|
1547
|
+
destroy(): void;
|
|
1548
|
+
}
|
|
1549
|
+
/** localStorage key the Designer writes and the Picker reads. */
|
|
1550
|
+
declare const CHART_STORAGE_KEY = "seatmap.chart";
|
|
1551
|
+
|
|
1552
|
+
export { type RenderedGAAreaEvidence as $, type AccessibilityType as A, type BoothObject as B, type ChartDoc as C, type DecorImageObject as D, type ExpandedSeat as E, type Floor as F, type GAAreaObject as G, type ReferenceCalibration as H, type ISeatmapRenderer as I, type ReferenceCategorySource as J, type ReferenceDerivedScale as K, type LabelStyle as L, type ReferenceInventoryExclusionSource as M, type ReferenceInventorySource as N, type ReferenceScanProposal as O, type Point as P, type ReferenceScanRowProposal as Q, type RowObject as R, type SeatOverride as S, type TableObject as T, type ReferenceScanSectionProposal as U, type ReferenceSeatSeed as V, type ReferenceSectionTraceBatchInput as W, type ReferenceSectionTraceBatchProposal as X, type ReferenceSectionTraceInput as Y, type ReferenceSectionTraceProposal as Z, type RenderedBookableLabelEvidence as _, type RectTableSide as a, type RenderedHierarchyLabelEvidence as a0, type RenderedLabelHiddenReason as a1, SURROUNDINGS_SHAPE_ROLES as a2, type SectionOutlinePath as a3, type SectionPathSegment as a4, type SelectionLayer as a5, type ShapeLineCap as a6, type ShapeLineEnding as a7, type ShapeLineJoin as a8, type ShapeObject as a9, type TextObject as aa, type ZoneDef as ab, accessibilityMeta as ac, accessibilityRingColor as ad, layerOf as ae, type ChartObject as b, type SectionObject as c, type RectTableSeatCounts as d, type GAInventorySegment as e, type RendererQualityEvidence as f, type RenderedFreeTextEvidence as g, type RendererOptions as h, type SeatStatus as i, type RendererViewMode as j, type LodRung as k, type CategoryTier as l, type SeatCommercialAttributes as m, type RendererCallbacks as n, ACCESSIBILITY_RING_COLOR as o, ACCESSIBILITY_TYPES as p, type AccessibilityMeta as q, CHART_STORAGE_KEY as r, type Category as s, type ChartReferenceImage as t, type ChartTheme as u, type CubicPath as v, LABEL_STYLE_MAX_SIZE as w, LABEL_STYLE_MIN_SIZE as x, type LabelPresentation as y, type ReferenceAccessibilitySource as z };
|