@seatlayer/core 0.28.4 → 0.30.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/README.md +102 -22
- package/dist/chunk-FGS67GT3.js +1252 -0
- package/dist/chunk-FGS67GT3.js.map +1 -0
- package/dist/index.cjs +1415 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -1459
- package/dist/index.d.ts +36 -1459
- package/dist/index.js +1091 -972
- package/dist/index.js.map +1 -1
- package/dist/types-CG2pEDoI.d.cts +1608 -0
- package/dist/types-CG2pEDoI.d.ts +1608 -0
- package/dist/view3d/index.cjs +4188 -0
- package/dist/view3d/index.cjs.map +1 -0
- package/dist/view3d/index.d.cts +385 -0
- package/dist/view3d/index.d.ts +385 -0
- package/dist/view3d/index.js +3720 -0
- package/dist/view3d/index.js.map +1 -0
- package/package.json +25 -3
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { C as ChartDoc, E as ExpandedSeat } from '../types-CG2pEDoI.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dirty-flag render loop. A frame is drawn only while the camera is moving /
|
|
5
|
+
* damping or an availability update arrived; when idle, no rAF is scheduled at
|
|
6
|
+
* all (zero CPU/GPU when parked). Tracks an FPS EMA over frames actually
|
|
7
|
+
* rendered — it reads as "idle" when nothing is scheduled.
|
|
8
|
+
*/
|
|
9
|
+
interface RenderLoopStats {
|
|
10
|
+
fps: number;
|
|
11
|
+
rendered: number;
|
|
12
|
+
idle: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* view3d palette + seat-state model — the single source of colour truth for the
|
|
17
|
+
* OGL venue view. Pure data (no GPU, no DOM) so the scene builder and the unit
|
|
18
|
+
* tests share one definition. Colours are linear-ish RGB triplets in 0..1.
|
|
19
|
+
*
|
|
20
|
+
* Look brief (docs/3d-usp-strategy §3): desaturated cool greys for structure,
|
|
21
|
+
* one warm accent for the stage, availability colours only on seats.
|
|
22
|
+
*/
|
|
23
|
+
type SeatState3D = 'available' | 'held' | 'sold' | 'selected' | 'dimmed';
|
|
24
|
+
type RGB = [number, number, number];
|
|
25
|
+
/** Structure palette — cool desaturated greys + one warm stage accent. */
|
|
26
|
+
declare const STRUCTURE: {
|
|
27
|
+
readonly ground: RGB;
|
|
28
|
+
readonly tierTop: RGB;
|
|
29
|
+
readonly tierWall: RGB;
|
|
30
|
+
readonly stageTop: RGB;
|
|
31
|
+
readonly stageWall: RGB;
|
|
32
|
+
readonly decorTop: RGB;
|
|
33
|
+
readonly decorWall: RGB;
|
|
34
|
+
readonly gaTop: RGB;
|
|
35
|
+
readonly gaWall: RGB;
|
|
36
|
+
/** Exhibition / trade-show booth stand. */
|
|
37
|
+
readonly boothTop: RGB;
|
|
38
|
+
readonly boothWall: RGB;
|
|
39
|
+
/** Banquet table top — warmer, so a laid table reads apart from structure. */
|
|
40
|
+
readonly tableTop: RGB;
|
|
41
|
+
readonly tableWall: RGB;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a chart's authored theme into the 3D scene's colours.
|
|
46
|
+
*
|
|
47
|
+
* Every chart already carries a `ChartTheme` — background, brand accent, seat
|
|
48
|
+
* scale — and the 2D renderer and the picker chrome honour it. The 3D view did
|
|
49
|
+
* not: `palette.ts` was a fixed set of constants, so a white-labelled event
|
|
50
|
+
* rendered in SeatLayer's own dark grey whatever the organizer had branded. That
|
|
51
|
+
* is a visible gap in a paid feature, and it is the kind of thing a customer
|
|
52
|
+
* notices immediately when they switch from the 2D map to the 3D view.
|
|
53
|
+
*
|
|
54
|
+
* The palette in `palette.ts` stays the DEFAULT and the reference. This module
|
|
55
|
+
* only rebases it, so an unthemed chart is byte-for-byte what it was.
|
|
56
|
+
*
|
|
57
|
+
* ## How structure is rebased
|
|
58
|
+
*
|
|
59
|
+
* Structure colours are not replaced by the brand colour — a venue rendered in
|
|
60
|
+
* flat brand paint reads as a diagram, not a building, and the look brief is
|
|
61
|
+
* deliberately "desaturated greys for structure, saturated colour only on
|
|
62
|
+
* seats". Instead each structure colour is blended a little way toward the
|
|
63
|
+
* authored background, so the whole venue picks up the brand's cast and sits in
|
|
64
|
+
* its own light, while keeping the tonal relationships (tier above wall, stage
|
|
65
|
+
* warmer than tier) that make the geometry readable.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
interface Theme3D {
|
|
69
|
+
background: {
|
|
70
|
+
top: RGB;
|
|
71
|
+
bottom: RGB;
|
|
72
|
+
};
|
|
73
|
+
structure: typeof STRUCTURE;
|
|
74
|
+
seatStates: Record<SeatState3D, RGB>;
|
|
75
|
+
/** Multiplier on the seat dot's world radius. */
|
|
76
|
+
seatScale: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Venue labels — anchors, level-of-detail, and world→screen projection.
|
|
81
|
+
*
|
|
82
|
+
* ## Why labels are DOM, not geometry
|
|
83
|
+
*
|
|
84
|
+
* The renderer is deliberately texture-free at three draw calls. Drawing text on
|
|
85
|
+
* the GPU means a signed-distance font atlas: a texture, another shader, a build
|
|
86
|
+
* asset, and a resolution ceiling — a lot of machinery for the few dozen labels a
|
|
87
|
+
* venue actually needs. Projecting anchors and positioning DOM elements costs
|
|
88
|
+
* nothing when a chart has no labels, and buys properties the GPU path cannot:
|
|
89
|
+
*
|
|
90
|
+
* - **Real text.** A screen reader can read the venue's structure. That is the
|
|
91
|
+
* accessibility gap in 3D, not just a rendering convenience.
|
|
92
|
+
* - Crisp at any device pixel ratio and any zoom, with no atlas to outgrow.
|
|
93
|
+
* - `ChartTheme.fontFamily`, i18n and RTL come from the browser.
|
|
94
|
+
*
|
|
95
|
+
* This module is the pure half — what to label, where its anchor sits, and when
|
|
96
|
+
* it should show. The overlay that positions elements lives in `index.ts`.
|
|
97
|
+
*
|
|
98
|
+
* ## Why the rungs mirror 2D
|
|
99
|
+
*
|
|
100
|
+
* 2D melts through zones → sections → seats. Labels follow the same idea for the
|
|
101
|
+
* same reason: at a distance a buyer needs to know which part of the venue they
|
|
102
|
+
* are looking at, and up close they need to know which block and which door. A
|
|
103
|
+
* label set that does not thin out with distance turns a 51-section arena into
|
|
104
|
+
* unreadable confetti.
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
type LabelKind = 'zone' | 'section' | 'annotation' | 'booth';
|
|
108
|
+
interface SceneLabel {
|
|
109
|
+
id: string;
|
|
110
|
+
kind: LabelKind;
|
|
111
|
+
text: string;
|
|
112
|
+
/** World-metre anchor the label is pinned to. */
|
|
113
|
+
anchor: [number, number, number];
|
|
114
|
+
/** Authored colour (`#rrggbb`), when the object carries one. */
|
|
115
|
+
color?: string;
|
|
116
|
+
/** Authored rotation in degrees, for annotations that specify one. */
|
|
117
|
+
rotation?: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Pure geometry primitives for the view3d scene — no OGL, no DOM, so the whole
|
|
122
|
+
* scene-model builder is unit-testable in a plain runtime.
|
|
123
|
+
*
|
|
124
|
+
* Coordinate convention: chart units (x, y) map to world metres as
|
|
125
|
+
* worldX = x * METRES_PER_CHART_UNIT
|
|
126
|
+
* worldZ = y * METRES_PER_CHART_UNIT
|
|
127
|
+
* worldY = up (height in metres)
|
|
128
|
+
* i.e. the chart's audience-depth (+y) becomes world +Z, and Y is the vertical.
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
interface MeshData {
|
|
132
|
+
/** Non-indexed triangle soup: 3 floats per vertex. */
|
|
133
|
+
position: Float32Array;
|
|
134
|
+
normal: Float32Array;
|
|
135
|
+
/** Baked vertex colour incl. AO, 3 floats per vertex. */
|
|
136
|
+
color: Float32Array;
|
|
137
|
+
/**
|
|
138
|
+
* Owning floor index per vertex.
|
|
139
|
+
*
|
|
140
|
+
* Lets one merged mesh be dimmed per floor without splitting it into a draw
|
|
141
|
+
* call per floor. A multi-floor chart (the opera house has three) draws every
|
|
142
|
+
* floor at once, so the balcony sits over the parterre and hides it; isolating
|
|
143
|
+
* one is the only way to look at the level you are actually booking.
|
|
144
|
+
*/
|
|
145
|
+
floor: Float32Array;
|
|
146
|
+
/** Vertex count (position.length / 3). */
|
|
147
|
+
count: number;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Pure builder for the instanced seat cloud. Produces the per-instance arrays a
|
|
152
|
+
* single OGL InstancedMesh consumes (one draw call for every seat), plus the
|
|
153
|
+
* seatId → instanceIndex map that `setAvailability` uses to patch only the seats
|
|
154
|
+
* that actually changed via a sub-range `bufferSubData` upload.
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
interface SeatInstanceData {
|
|
158
|
+
count: number;
|
|
159
|
+
/** vec3 per instance: world (x, y, z) in metres. */
|
|
160
|
+
iPosition: Float32Array;
|
|
161
|
+
/** float per instance: index into the seat-state colour LUT. */
|
|
162
|
+
iState: Float32Array;
|
|
163
|
+
/**
|
|
164
|
+
* float per instance: the largest world radius this dot may take, metres.
|
|
165
|
+
*
|
|
166
|
+
* The shader enforces `uMinPixels` by GROWING a dot's world radius with depth,
|
|
167
|
+
* which is what merges rows into a solid mass at range — measured mean seat
|
|
168
|
+
* spacing is 0.53–0.58 m against a 0.44 m dot diameter, so there is very little
|
|
169
|
+
* slack to spend before neighbours touch. A global cap cannot fix it: spacing
|
|
170
|
+
* is a property of the chart, and varies between sections of the same venue
|
|
171
|
+
* (measured min 0.21 m on the amphitheatre against a 0.58 m mean).
|
|
172
|
+
*
|
|
173
|
+
* So the ceiling travels per seat, derived from that seat's own nearest
|
|
174
|
+
* neighbour. A dot grows to hold its minimum pixel size and then STOPS,
|
|
175
|
+
* whatever the distance. Past that point holding legibility is the LOD ladder's
|
|
176
|
+
* job (fade toward the tier tint), not the dot's.
|
|
177
|
+
*/
|
|
178
|
+
iMaxRadius: Float32Array;
|
|
179
|
+
/**
|
|
180
|
+
* vec3 per instance: accommodation ring colour, or (0,0,0) for none.
|
|
181
|
+
*
|
|
182
|
+
* 2D draws a coloured ring around every seat with an accessibility type, and
|
|
183
|
+
* 3D drew nothing at all — so a wheelchair space, a companion seat or a
|
|
184
|
+
* lift-armrest seat was indistinguishable from any other the moment a buyer
|
|
185
|
+
* switched to the 3D view. A ring mirrors the 2D treatment exactly, needs no
|
|
186
|
+
* texture, and costs one instanced attribute rather than a draw call.
|
|
187
|
+
*/
|
|
188
|
+
iRing: Float32Array;
|
|
189
|
+
/** float per instance: owning floor index, for per-floor isolation. */
|
|
190
|
+
iFloor: Float32Array;
|
|
191
|
+
/** seatId → instance index (drives targeted availability updates). */
|
|
192
|
+
idToIndex: Map<string, number>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* A navigable zone — the venue's own top-level grouping (Orchestra, Lower Bowl,
|
|
197
|
+
* Hall A), resolved for camera framing and for the section/zone LOD rung.
|
|
198
|
+
*
|
|
199
|
+
* Every shipped chart authors zones and gives every section one, and the 2D
|
|
200
|
+
* renderer uses them as its farthest LOD rung. 3D ignored them entirely, so the
|
|
201
|
+
* one structure a buyer navigates by ("take me to the Grand Circle") had no
|
|
202
|
+
* representation at all in the 3D view.
|
|
203
|
+
*/
|
|
204
|
+
interface SceneZone {
|
|
205
|
+
id: string;
|
|
206
|
+
label: string;
|
|
207
|
+
/** Authored zone colour, or null when the chart leaves it to the category mix. */
|
|
208
|
+
color: RGB | null;
|
|
209
|
+
/** Section object ids belonging to this zone. */
|
|
210
|
+
sectionIds: string[];
|
|
211
|
+
/** Seats resolved into this zone. */
|
|
212
|
+
seatCount: number;
|
|
213
|
+
/** World-metre centre of the zone's seats (camera target). */
|
|
214
|
+
center: [number, number, number];
|
|
215
|
+
/** Half-diagonal of its footprint, world metres (camera fit). */
|
|
216
|
+
radius: number;
|
|
217
|
+
/** What this zone faces — its authored focal, else the venue's. */
|
|
218
|
+
focalWorld: [number, number, number];
|
|
219
|
+
}
|
|
220
|
+
/** A navigable floor — a logical level of the venue. */
|
|
221
|
+
interface SceneFloor {
|
|
222
|
+
index: number;
|
|
223
|
+
id: string;
|
|
224
|
+
label: string;
|
|
225
|
+
seatCount: number;
|
|
226
|
+
center: [number, number, number];
|
|
227
|
+
radius: number;
|
|
228
|
+
}
|
|
229
|
+
interface SceneModel {
|
|
230
|
+
/** Every non-seat surface merged into one triangle soup (1 draw call). */
|
|
231
|
+
solids: MeshData;
|
|
232
|
+
seats: SeatInstanceData;
|
|
233
|
+
bounds: {
|
|
234
|
+
/** World-metre venue centre (camera target). */
|
|
235
|
+
center: [number, number, number];
|
|
236
|
+
/** Half-diagonal of the horizontal footprint, metres (camera fit). */
|
|
237
|
+
radius: number;
|
|
238
|
+
groundY: number;
|
|
239
|
+
};
|
|
240
|
+
/** 5 × vec3 flat LUT for the seat fragment shader. */
|
|
241
|
+
stateColorLUT: number[];
|
|
242
|
+
/** Resolved colours for this chart's authored theme (background, seat scale). */
|
|
243
|
+
theme: Theme3D;
|
|
244
|
+
seatCount: number;
|
|
245
|
+
/** Venue focal point in world metres (cinematic look-at target). */
|
|
246
|
+
focalWorld: [number, number, number];
|
|
247
|
+
/** The venue's zones, in authored order. Empty when the chart has none. */
|
|
248
|
+
zones: SceneZone[];
|
|
249
|
+
/**
|
|
250
|
+
* The venue's floors, in authored order. A single-floor chart reports one.
|
|
251
|
+
*
|
|
252
|
+
* Every shipped multi-floor template puts all its floors at baseHeightM 0 and
|
|
253
|
+
* takes height from the sections instead, so floors are a logical grouping,
|
|
254
|
+
* not a physical stack. What they need is ISOLATION: draw all three of an
|
|
255
|
+
* opera house at once and the balcony sits over the parterre.
|
|
256
|
+
*/
|
|
257
|
+
floors: SceneFloor[];
|
|
258
|
+
/**
|
|
259
|
+
* Everything worth naming, with a world anchor: zones, sections, authored
|
|
260
|
+
* wayfinding text, and booths. Rendered as a DOM overlay — see `labels.ts` for
|
|
261
|
+
* why text is not geometry here.
|
|
262
|
+
*/
|
|
263
|
+
labels: SceneLabel[];
|
|
264
|
+
}
|
|
265
|
+
interface SceneModelInput {
|
|
266
|
+
doc: ChartDoc;
|
|
267
|
+
seats: ExpandedSeat[];
|
|
268
|
+
/** Optional initial per-seat state (default all available). */
|
|
269
|
+
initialState?: (seat: ExpandedSeat) => SeatState3D;
|
|
270
|
+
}
|
|
271
|
+
declare function buildSceneModel(input: SceneModelInput): SceneModel;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Slice 3 hand-off — the DOM panorama overlay the fly-to-seat cinematic
|
|
275
|
+
* dissolves into. Decoupled by design: the CALLER supplies the equirectangular
|
|
276
|
+
* image (via mountVenue3D's getSeatView), so view3d never imports the app's
|
|
277
|
+
* panorama generator and the chunk stays lean.
|
|
278
|
+
*
|
|
279
|
+
* Technique (mirrors SeatPicker.openSeatView, reimplemented small): an equirect
|
|
280
|
+
* image panned with `repeat-x`; the initial horizontal offset is set so the
|
|
281
|
+
* panorama's bearing matches the final camera yaw — the dissolve reads as the
|
|
282
|
+
* same view sharpening, not a cut. CSS opacity fade is compositor-only.
|
|
283
|
+
*/
|
|
284
|
+
interface SeatView {
|
|
285
|
+
url: string;
|
|
286
|
+
/** Bearing (deg, 0 = facing the focal/stage) the panorama should open centred
|
|
287
|
+
* on, to match the camera's final yaw. Default 0 (both face the stage). */
|
|
288
|
+
initialBearingDeg?: number;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* view3d analytics — a tiny, decoupled event emitter for the venue view. The
|
|
293
|
+
* caller (app/harness) supplies `onAnalytics`; this class owns the per-mount
|
|
294
|
+
* state (first-orbit latch, panorama dwell timing) and, crucially, wraps EVERY
|
|
295
|
+
* callback invocation in try/catch so a throwing analytics sink can never break
|
|
296
|
+
* rendering. No DOM, no GL — unit-testable in isolation.
|
|
297
|
+
*/
|
|
298
|
+
type Analytics3DCallback = (event: string, props?: Record<string, unknown>) => void;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* view3d — the sole dynamic-import boundary for the lazy OGL venue-view chunk.
|
|
302
|
+
*
|
|
303
|
+
* const { mountVenue3D } = await import('../view3d');
|
|
304
|
+
* const handle = mountVenue3D(container, { doc, seats }, { onSeatPick, getSeatView });
|
|
305
|
+
* await handle.flyToSeat(seatId);
|
|
306
|
+
*
|
|
307
|
+
* Read-only 3D of any chart, fed entirely from the existing height contract.
|
|
308
|
+
* Slice 1: orbit camera, extruded tiers/stage/GA, instanced seat dots, sub-range
|
|
309
|
+
* availability, dispose + context-loss survival. Slice 2: GPU color-pick. Slice
|
|
310
|
+
* 3: the fly-to-seat cinematic that dissolves into the view-from-seat panorama.
|
|
311
|
+
*/
|
|
312
|
+
|
|
313
|
+
interface Venue3DInput {
|
|
314
|
+
doc: ChartDoc;
|
|
315
|
+
/** Expanded seats (from `expandChart`) — carry x/y + resolved eyeHeightM. */
|
|
316
|
+
seats: ExpandedSeat[];
|
|
317
|
+
/** Optional initial per-seat state (default all available). */
|
|
318
|
+
initialState?: (seat: ExpandedSeat) => SeatState3D;
|
|
319
|
+
}
|
|
320
|
+
interface Venue3DOptions {
|
|
321
|
+
/** Fired on a tap that hits a seat (GPU color-pick). Not fired on empty taps. */
|
|
322
|
+
onSeatPick?: (seatId: string) => void;
|
|
323
|
+
/**
|
|
324
|
+
* Supplies the view-from-seat panorama for the cinematic hand-off. Decoupled:
|
|
325
|
+
* the caller (app/harness) owns panorama generation; view3d never imports it.
|
|
326
|
+
* Called at PICK time to pre-render, so flyToSeat has zero wait on landing.
|
|
327
|
+
*/
|
|
328
|
+
getSeatView?: (seatId: string) => SeatView | Promise<SeatView>;
|
|
329
|
+
/**
|
|
330
|
+
* Decoupled analytics sink. Emits the venue-view journey: `3d_opened`,
|
|
331
|
+
* `3d_orbit_engaged` (first user gesture), `3d_seat_picked`,
|
|
332
|
+
* `3d_cinematic_played`/`_skipped`/`_cancelled`, `3d_panorama_opened`/`_closed`.
|
|
333
|
+
* Every invocation is wrapped in try/catch — a throwing sink never breaks
|
|
334
|
+
* rendering. Absent = no events emitted.
|
|
335
|
+
*/
|
|
336
|
+
onAnalytics?: Analytics3DCallback;
|
|
337
|
+
}
|
|
338
|
+
interface Venue3DStats extends RenderLoopStats {
|
|
339
|
+
drawCalls: number;
|
|
340
|
+
seatCount: number;
|
|
341
|
+
}
|
|
342
|
+
interface Venue3DHandle {
|
|
343
|
+
dispose(): void;
|
|
344
|
+
setAvailability(updates: {
|
|
345
|
+
seatId: string;
|
|
346
|
+
state: SeatState3D;
|
|
347
|
+
}[]): void;
|
|
348
|
+
setSelection(seatIds: string[]): void;
|
|
349
|
+
/** Fly the camera from the overview into `seatId` and dissolve into its
|
|
350
|
+
* view-from-seat panorama. Resolves at flight end; a drag cancels it, a second
|
|
351
|
+
* call retargets, dispose resolves early. Reduced-motion → a short fade. */
|
|
352
|
+
flyToSeat(seatId: string): Promise<void>;
|
|
353
|
+
resize(): void;
|
|
354
|
+
stats(): Venue3DStats;
|
|
355
|
+
loseContextForTest(): void;
|
|
356
|
+
/** Test hook: force (or clear) the reduced-motion path. */
|
|
357
|
+
setReducedMotionForTest(value: boolean | null): void;
|
|
358
|
+
/** The venue's zones (id, label, colour, seat count) in authored order. */
|
|
359
|
+
zones(): SceneZone[];
|
|
360
|
+
/**
|
|
361
|
+
* Frame a zone: the camera moves to sit over that zone looking at what the
|
|
362
|
+
* zone faces. Returns false for an unknown or empty zone.
|
|
363
|
+
*
|
|
364
|
+
* This is the navigation the venue's own structure implies — a buyer picks
|
|
365
|
+
* "Grand Circle", not a set of coordinates — and it is what the 2D renderer's
|
|
366
|
+
* farthest LOD rung already offers. Approaching from the zone's focal side
|
|
367
|
+
* means the seats face the camera rather than presenting their backs.
|
|
368
|
+
*/
|
|
369
|
+
focusZone(zoneId: string): boolean;
|
|
370
|
+
/** The venue's floors (id, name, seat count) in authored order. */
|
|
371
|
+
floors(): SceneFloor[];
|
|
372
|
+
/**
|
|
373
|
+
* Isolate one floor, or pass null to show the whole venue.
|
|
374
|
+
*
|
|
375
|
+
* Every shipped multi-floor chart puts its floors at the same base height and
|
|
376
|
+
* takes relief from the sections, so all three of an opera house draw at once
|
|
377
|
+
* and the balcony sits over the parterre. Unfocused floors are DIMMED rather
|
|
378
|
+
* than hidden, so the buyer keeps the venue as context while looking at the
|
|
379
|
+
* level they are booking. Returns false for an unknown index.
|
|
380
|
+
*/
|
|
381
|
+
focusFloor(index: number | null): boolean;
|
|
382
|
+
}
|
|
383
|
+
declare function mountVenue3D(container: HTMLElement, input: Venue3DInput, opts?: Venue3DOptions): Venue3DHandle;
|
|
384
|
+
|
|
385
|
+
export { type Analytics3DCallback, type SeatState3D, type SeatView, type Venue3DHandle, type Venue3DInput, type Venue3DOptions, type Venue3DStats, buildSceneModel, mountVenue3D };
|