@seatlayer/core 0.52.0 → 0.54.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/LICENSE +16 -17
- package/README.md +8 -18
- package/dist/categoryInventory-B4xo7hE2.d.ts +109 -0
- package/dist/categoryInventory-lRtu3VjD.d.cts +109 -0
- package/dist/chunk-3QLFGEQY.js +1 -0
- package/dist/chunk-55NOSZK5.js +1 -0
- package/dist/chunk-6LIPQU4G.js +1 -0
- package/dist/chunk-6VTTBC5F.js +1 -0
- package/dist/chunk-7PT7OQUO.js +1 -0
- package/dist/chunk-AQKYUJBX.js +1 -0
- package/dist/chunk-CXF32VPG.js +1 -0
- package/dist/chunk-DDE7IOFT.js +1 -0
- package/dist/chunk-EQM4FFN5.js +1 -0
- package/dist/chunk-EYROIZGQ.js +1 -0
- package/dist/chunk-IJI4WU57.js +1 -0
- package/dist/chunk-QUKWJQLR.js +1 -0
- package/dist/chunk-VDZ24QVV.js +1 -0
- package/dist/chunk-XPPT3OGQ.js +1 -0
- package/dist/core/chart-ops/index.cjs +1 -0
- package/dist/core/chart-ops/index.d.cts +1235 -0
- package/dist/core/chart-ops/index.d.ts +1235 -0
- package/dist/core/chart-ops/index.js +1 -0
- package/dist/core/color.cjs +1 -0
- package/dist/core/color.d.cts +192 -0
- package/dist/core/color.d.ts +192 -0
- package/dist/core/color.js +1 -0
- package/dist/core/inventory/index.cjs +1 -0
- package/dist/core/inventory/index.d.cts +209 -0
- package/dist/core/inventory/index.d.ts +209 -0
- package/dist/core/inventory/index.js +1 -0
- package/dist/core/layout/index.cjs +1 -0
- package/dist/core/layout/index.d.cts +376 -0
- package/dist/core/layout/index.d.ts +376 -0
- package/dist/core/layout/index.js +1 -0
- package/dist/core/quality/index.cjs +1 -0
- package/dist/core/quality/index.d.cts +132 -0
- package/dist/core/quality/index.d.ts +132 -0
- package/dist/core/quality/index.js +1 -0
- package/dist/core/render-assets/index.cjs +1 -0
- package/dist/core/render-assets/index.d.cts +99 -0
- package/dist/core/render-assets/index.d.ts +99 -0
- package/dist/core/render-assets/index.js +1 -0
- package/dist/core/seatConfidence.cjs +1 -76
- package/dist/core/seatConfidence.d.cts +1 -1
- package/dist/core/seatConfidence.d.ts +1 -1
- package/dist/core/seatConfidence.js +1 -51
- package/dist/core/sections/index.cjs +1 -0
- package/dist/core/sections/index.d.cts +346 -0
- package/dist/core/sections/index.d.ts +346 -0
- package/dist/core/sections/index.js +1 -0
- package/dist/de-75NWRKC5.js +1 -0
- package/dist/es-BM7EJ7PW.js +1 -0
- package/dist/fr-HPXQHIB4.js +1 -0
- package/dist/index.cjs +1 -12717
- package/dist/index.d.cts +71 -580
- package/dist/index.d.ts +71 -580
- package/dist/index.js +1 -10235
- package/dist/labeling-CsPt1mC_.d.cts +90 -0
- package/dist/labeling-w8bl86cb.d.ts +90 -0
- package/dist/layout-B5UYbwnv.d.ts +181 -0
- package/dist/layout-YFmuxw_M.d.cts +181 -0
- package/dist/picker/minimapGeometry.cjs +1 -80
- package/dist/picker/minimapGeometry.js +1 -52
- package/dist/renderedQuality-CugJarFp.d.cts +113 -0
- package/dist/renderedQuality-DbZM034G.d.ts +113 -0
- package/dist/renderer-DhUHFtsI.d.cts +531 -0
- package/dist/renderer-IBi9YKWR.d.ts +531 -0
- package/dist/sections-B7cDF0Nq.d.cts +123 -0
- package/dist/sections-mLOZrGrI.d.ts +123 -0
- package/dist/segmentedRowModel-BPTnJ7Tz.d.ts +75 -0
- package/dist/segmentedRowModel-CGoH684F.d.cts +75 -0
- package/dist/ticketRestrictions-BwAebpSK.d.cts +72 -0
- package/dist/ticketRestrictions-ChHJwvTq.d.ts +72 -0
- package/dist/{types-tLOunI-B.d.cts → types-COfJorq_.d.cts} +233 -757
- package/dist/{types-tLOunI-B.d.ts → types-COfJorq_.d.ts} +233 -757
- package/dist/view/panoramaDelivery.cjs +1 -126
- package/dist/view/panoramaDelivery.js +1 -17
- package/dist/view3d/crossfade/panorama.cjs +1 -459
- package/dist/view3d/crossfade/panorama.d.cts +2 -4
- package/dist/view3d/crossfade/panorama.d.ts +2 -4
- package/dist/view3d/crossfade/panorama.js +1 -30
- package/dist/view3d/index.cjs +27 -7929
- package/dist/view3d/index.d.cts +64 -22
- package/dist/view3d/index.d.ts +64 -22
- package/dist/view3d/index.js +27 -7062
- package/package.json +95 -11
- package/dist/chunk-AZODENEL.js +0 -97
- package/dist/chunk-AZODENEL.js.map +0 -1
- package/dist/chunk-BE3F7CT3.js +0 -341
- package/dist/chunk-BE3F7CT3.js.map +0 -1
- package/dist/chunk-UID7KN44.js +0 -1569
- package/dist/chunk-UID7KN44.js.map +0 -1
- package/dist/core/seatConfidence.cjs.map +0 -1
- package/dist/core/seatConfidence.js.map +0 -1
- package/dist/de-YGODYJ3E.js +0 -292
- package/dist/de-YGODYJ3E.js.map +0 -1
- package/dist/es-VMBTGVFQ.js +0 -292
- package/dist/es-VMBTGVFQ.js.map +0 -1
- package/dist/fr-SLBE2ULB.js +0 -292
- package/dist/fr-SLBE2ULB.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/picker/minimapGeometry.cjs.map +0 -1
- package/dist/picker/minimapGeometry.js.map +0 -1
- package/dist/view/panoramaDelivery.cjs.map +0 -1
- package/dist/view/panoramaDelivery.js.map +0 -1
- package/dist/view3d/crossfade/panorama.cjs.map +0 -1
- package/dist/view3d/crossfade/panorama.js.map +0 -1
- package/dist/view3d/index.cjs.map +0 -1
- package/dist/view3d/index.js.map +0 -1
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { P as Point, r as CubicPath, s as TextObject } from '../../types-COfJorq_.cjs';
|
|
2
|
+
export { E as ExpandChartOptions, R as RowSeatSlot, T as TableSeatSlot, a as allObjects, c as chartBounds, e as expandBooth, b as expandChart, d as expandRow, f as expandRowSlots, g as expandTable, h as expandTableSlots, i as floorObjects, j as floorOverviewTranslations, k as floorsOf, l as layoutFloorOverview, o as objectCenter, m as owningSectionForObject, p as pointInPolygon, n as pointInPolygonWithHoles, q as polygonLabelPoint, r as rowInventoryCount, s as rowSeatPositions, t as stackFloors, u as tableInventoryCount, v as tableSeatCountsBySide, w as translateObject } from '../../layout-YFmuxw_M.cjs';
|
|
3
|
+
export { a as SegmentedRowComponent, S as SegmentedRowPlacement, r as resolveSegmentedRowGroups, s as segmentedRowComponentSeats, b as segmentedRowComponents, c as segmentedRowSeatTotal } from '../../segmentedRowModel-CGoH684F.cjs';
|
|
4
|
+
import { E as ExpandedSeat } from '../../renderer-DhUHFtsI.cjs';
|
|
5
|
+
|
|
6
|
+
type SectionShellMode = 'auto' | 'rectangle' | 'tapered' | 'bezier';
|
|
7
|
+
declare function cubicPoint(path: CubicPath, t: number): Point;
|
|
8
|
+
/**
|
|
9
|
+
* Build a predictable single-bend cubic whose midpoint passes exactly through
|
|
10
|
+
* `middle`. At t=.5 a cubic weighs both controls by 3/8, so moving both
|
|
11
|
+
* controls together by 4/3 of the requested midpoint offset makes the visible
|
|
12
|
+
* curve pass through the point the author dragged to.
|
|
13
|
+
*
|
|
14
|
+
* Lives here rather than in the Designer because two features need the same
|
|
15
|
+
* answer: the row bend handle (`renderRowPathHandles`) and the row curvature
|
|
16
|
+
* operations in `controller/rowOpsFacet`.
|
|
17
|
+
*/
|
|
18
|
+
declare function smoothCubicThroughMiddle(start: Point, end: Point, middle: Point): CubicPath;
|
|
19
|
+
/** Equal-arc-length points on a cubic path, including both endpoints. */
|
|
20
|
+
declare function distributeAlongCubic(path: CubicPath, count: number, resolution?: number): Point[];
|
|
21
|
+
/**
|
|
22
|
+
* Convert a server-mapped rectangle into an editable complex shell. The four
|
|
23
|
+
* corners must be clockwise. No caller-supplied control points are accepted.
|
|
24
|
+
*/
|
|
25
|
+
declare function buildSectionShell(corners: Point[], focal: Point, requested: SectionShellMode): {
|
|
26
|
+
mode: Exclude<SectionShellMode, 'auto'>;
|
|
27
|
+
outline: Point[];
|
|
28
|
+
};
|
|
29
|
+
/** Server-owned straight aisle cutouts spanning the near/far edges. */
|
|
30
|
+
declare function buildAisleHoles(corners: Point[], focal: Point, count: number, mode: Exclude<SectionShellMode, 'auto'>): Point[][];
|
|
31
|
+
|
|
32
|
+
/** Axis-aligned chart bounds used to derive a stable, document-relative camera. */
|
|
33
|
+
interface PerspectiveBounds {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A deterministic pinhole camera for the projected 2.5D buyer/Designer views.
|
|
41
|
+
* Coordinates stay in chart units so the ordinary Stage camera (pan/zoom) can
|
|
42
|
+
* remain the only screen-space transform.
|
|
43
|
+
*/
|
|
44
|
+
interface PerspectiveCamera {
|
|
45
|
+
target: Point;
|
|
46
|
+
/** Horizontal distance from target to camera, in chart units. */
|
|
47
|
+
distance: number;
|
|
48
|
+
/** Camera height above the chart datum, in chart units. */
|
|
49
|
+
height: number;
|
|
50
|
+
/** Pinhole focal length, in chart units. */
|
|
51
|
+
focalLength: number;
|
|
52
|
+
/** Small plan rotation which keeps the venue from reading as a flat elevation. */
|
|
53
|
+
yawRad: number;
|
|
54
|
+
}
|
|
55
|
+
/** Canvas/Konva affine: x' = a·x + c·y + e; y' = b·x + d·y + f. */
|
|
56
|
+
interface Affine2D {
|
|
57
|
+
a: number;
|
|
58
|
+
b: number;
|
|
59
|
+
c: number;
|
|
60
|
+
d: number;
|
|
61
|
+
e: number;
|
|
62
|
+
f: number;
|
|
63
|
+
}
|
|
64
|
+
interface PerspectivePoint extends Point {
|
|
65
|
+
/** Positive camera-space distance; larger values are farther away. */
|
|
66
|
+
depth: number;
|
|
67
|
+
/** Perspective size multiplier at this point (1 at the camera target). */
|
|
68
|
+
scale: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Choose a camera from venue bounds rather than fixed pixels. The camera rises
|
|
72
|
+
* above the tallest authored surface, so even the (deliberately generous)
|
|
73
|
+
* 120-m validation ceiling cannot cross the near plane.
|
|
74
|
+
*/
|
|
75
|
+
declare function createPerspectiveCamera(bounds: PerspectiveBounds, maxSurfaceHeightWorld?: number): PerspectiveCamera;
|
|
76
|
+
/** Project one 3D chart point through the pinhole camera. */
|
|
77
|
+
declare function projectPerspectivePoint(camera: PerspectiveCamera, point: Point, heightWorld?: number): PerspectivePoint;
|
|
78
|
+
declare function applyAffine(affine: Affine2D, point: Point): Point;
|
|
79
|
+
declare function invertAffine(affine: Affine2D): Affine2D;
|
|
80
|
+
/** Return `left(right(point))`. */
|
|
81
|
+
declare function composeAffine(left: Affine2D, right: Affine2D): Affine2D;
|
|
82
|
+
/**
|
|
83
|
+
* First-order projection around one object/section anchor. The height callback
|
|
84
|
+
* may describe a raked surface; sampling one chart unit along x/y captures its
|
|
85
|
+
* local slope. Per-section tangents are the intentional shell-performance
|
|
86
|
+
* contract. Buyer seat anchors are projected exactly by `projectPerspectivePoint`;
|
|
87
|
+
* only non-interactive section surfaces use this bounded approximation.
|
|
88
|
+
*/
|
|
89
|
+
declare function perspectiveTangentAffine(camera: PerspectiveCamera, anchor: Point, heightAt?: (point: Point) => number): Affine2D;
|
|
90
|
+
/** Parameters accepted by Konva's rotation/scale/skew decomposition. */
|
|
91
|
+
declare function decomposeAffineLinear(affine: Affine2D): {
|
|
92
|
+
rotationDeg: number;
|
|
93
|
+
scaleX: number;
|
|
94
|
+
scaleY: number;
|
|
95
|
+
skewX: number;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Where a label belongs inside a polygon.
|
|
100
|
+
*
|
|
101
|
+
* A polygon's average-of-vertices centroid is not a label anchor. Two things
|
|
102
|
+
* break it on real venue geometry:
|
|
103
|
+
*
|
|
104
|
+
* - Concavity. An L-shaped concourse block, a C-shaped bowl tier, or a wedge
|
|
105
|
+
* with an aisle cut out can have its centroid land in the notch — outside
|
|
106
|
+
* the shape entirely.
|
|
107
|
+
* - Vertex density. A traced contour samples a curved outer arc with dozens of
|
|
108
|
+
* points and the two straight radial edges with two. The average is dragged
|
|
109
|
+
* onto the arc, so the label sits hard against the boundary and its pill
|
|
110
|
+
* spills into the neighbouring section.
|
|
111
|
+
*
|
|
112
|
+
* The right anchor is the *pole of inaccessibility*: the interior point
|
|
113
|
+
* furthest from every edge — the centre of the largest circle that fits inside
|
|
114
|
+
* the polygon. That is the fattest part of the shape, which is exactly where a
|
|
115
|
+
* label has room. This is the Mapbox `polylabel` algorithm: subdivide the
|
|
116
|
+
* bounding box into cells, keep the cell whose optimistic upper bound is best,
|
|
117
|
+
* and stop once no cell can beat the incumbent by more than `precision`.
|
|
118
|
+
*
|
|
119
|
+
* The returned `radius` is as useful as the point: it is the half-width of the
|
|
120
|
+
* room available, so a caller can shrink a label to fit — or decide it never
|
|
121
|
+
* will — without measuring glyphs.
|
|
122
|
+
*/
|
|
123
|
+
interface InscribedAnchor {
|
|
124
|
+
/** Interior point furthest from every ring (outer boundary and holes). */
|
|
125
|
+
point: Point;
|
|
126
|
+
/** Distance from `point` to the nearest edge — the inscribed circle radius. */
|
|
127
|
+
radius: number;
|
|
128
|
+
}
|
|
129
|
+
/** Distance from `p` to the closest edge of any ring (unsigned). */
|
|
130
|
+
declare function distanceToRings(p: Point, rings: readonly (readonly Point[])[]): number;
|
|
131
|
+
/** Area of a ring (absolute, shoelace). */
|
|
132
|
+
declare function polygonArea(ring: readonly Point[]): number;
|
|
133
|
+
/** Net area of a polygon with holes — the space a section actually occupies. */
|
|
134
|
+
declare function polygonNetArea(outer: readonly Point[], holes?: readonly (readonly Point[])[]): number;
|
|
135
|
+
/**
|
|
136
|
+
* Largest-inscribed-circle anchor for a polygon (with optional holes).
|
|
137
|
+
*
|
|
138
|
+
* Deterministic: no randomness, no dependence on vertex order or winding, so
|
|
139
|
+
* the same geometry always produces the same anchor. Callers can therefore
|
|
140
|
+
* memoize on geometry alone.
|
|
141
|
+
*/
|
|
142
|
+
declare function polygonInscribedAnchor(outer: readonly Point[], holes?: readonly (readonly Point[])[]): InscribedAnchor;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Pure-TypeScript spatial index for seat hit-testing.
|
|
146
|
+
*
|
|
147
|
+
* WHY THIS EXISTS
|
|
148
|
+
* ---------------
|
|
149
|
+
* `src/engine/SeatmapRenderer.ts` currently leans on Konva's built-in hit graph
|
|
150
|
+
* (the `listening` property, ~58 call sites) for "which seat did the pointer
|
|
151
|
+
* land on". No other renderer we care about ships an equivalent: React Native
|
|
152
|
+
* Skia has nothing at all, and Flutter / SwiftUI / Compose canvases all expect
|
|
153
|
+
* the app to own hit-testing. So the index has to exist on every path — and on
|
|
154
|
+
* the web it additionally lets us drop Konva's hit graph, which is a real win at
|
|
155
|
+
* 5k–13k seats (no per-seat hit-canvas rasterisation, no hit-graph traversal).
|
|
156
|
+
*
|
|
157
|
+
* This module is deliberately DEPENDENCY-FREE: no DOM, no Konva, no browser
|
|
158
|
+
* globals. It runs unchanged in a Web Worker, in workerd, and under React
|
|
159
|
+
* Native. All coordinates are WORLD space — converting screen→world is the
|
|
160
|
+
* caller's job, exactly as `SeatmapRenderer.screenToWorld` does today.
|
|
161
|
+
*
|
|
162
|
+
* STRUCTURE: uniform grid, not a quadtree
|
|
163
|
+
* ---------------------------------------
|
|
164
|
+
* Seats in a venue chart are close to uniformly dense by construction — they sit
|
|
165
|
+
* in rows on a near-regular pitch. That is the single case a uniform grid is
|
|
166
|
+
* optimal for, and it beats a quadtree on every axis that matters here:
|
|
167
|
+
* O(n) build with no rebalancing, flat typed-array storage (one contiguous
|
|
168
|
+
* scan per query, no pointer chasing), and O(1) expected candidates per point
|
|
169
|
+
* query. A quadtree only starts to pay when density varies by orders of
|
|
170
|
+
* magnitude across the extent, which a seating chart does not do. If a future
|
|
171
|
+
* chart shape ever breaks that assumption, `gridStats()` exposes the occupancy
|
|
172
|
+
* numbers needed to prove it before reaching for a tree.
|
|
173
|
+
*
|
|
174
|
+
* Each seat is inserted into EVERY cell its axis-aligned bounding box overlaps
|
|
175
|
+
* (not just the cell holding its centre). That is what makes {@link hitTest}
|
|
176
|
+
* examine exactly one cell: any seat whose shape contains a point also has an
|
|
177
|
+
* AABB containing that point, so it is guaranteed to be registered in that
|
|
178
|
+
* point's cell.
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Default seat radius in world units. Mirrors `SEAT_RADIUS` in
|
|
183
|
+
* `SeatmapRenderer.ts` and `DesignerController.ts` (both 9). The renderer scales
|
|
184
|
+
* this by `theme.seatScale` clamped to [0.7, 1.6]; callers that do the same must
|
|
185
|
+
* pass the scaled value via {@link BuildOptions.seatRadius} so the index agrees
|
|
186
|
+
* with what is actually drawn.
|
|
187
|
+
*/
|
|
188
|
+
declare const DEFAULT_SEAT_RADIUS = 9;
|
|
189
|
+
/**
|
|
190
|
+
* Hit geometry for one seat. Real seats are circles; trade-show booths render as
|
|
191
|
+
* rotated rounded rects whose dimensions live on the booth object in the
|
|
192
|
+
* ChartDoc, not on `ExpandedSeat` — so the caller supplies them through
|
|
193
|
+
* {@link BuildOptions.shapeOf} rather than this module reaching for the doc.
|
|
194
|
+
*/
|
|
195
|
+
type SeatShape = {
|
|
196
|
+
kind: 'circle';
|
|
197
|
+
r: number;
|
|
198
|
+
} | {
|
|
199
|
+
kind: 'rect';
|
|
200
|
+
width: number;
|
|
201
|
+
height: number;
|
|
202
|
+
rotation?: number;
|
|
203
|
+
};
|
|
204
|
+
interface BuildOptions {
|
|
205
|
+
/** Radius for circular seats when {@link shapeOf} is absent. Default {@link DEFAULT_SEAT_RADIUS}. */
|
|
206
|
+
seatRadius?: number;
|
|
207
|
+
/**
|
|
208
|
+
* Per-seat hit geometry. Return `null`/`undefined` to fall back to a circle of
|
|
209
|
+
* `seatRadius`. Called exactly once per seat during construction.
|
|
210
|
+
*/
|
|
211
|
+
shapeOf?: (seat: ExpandedSeat) => SeatShape | null | undefined;
|
|
212
|
+
/**
|
|
213
|
+
* Upper bound on grid cells, to stop a chart with one far-flung stray object
|
|
214
|
+
* from allocating a huge sparse grid. Default `max(64, 4 * seats.length)`.
|
|
215
|
+
* When the natural cell size would exceed this, cells are grown until it fits.
|
|
216
|
+
*/
|
|
217
|
+
maxCells?: number;
|
|
218
|
+
}
|
|
219
|
+
interface QueryOptions {
|
|
220
|
+
/**
|
|
221
|
+
* Restrict results to seats this predicate accepts — used to reproduce the
|
|
222
|
+
* renderer's `isSelectable(id) || selection.has(id)` gate. Kept as a query
|
|
223
|
+
* argument rather than build state on purpose: seat statuses change on every
|
|
224
|
+
* websocket tick, and the geometry does not.
|
|
225
|
+
*/
|
|
226
|
+
filter?: (id: string, seat: ExpandedSeat) => boolean;
|
|
227
|
+
}
|
|
228
|
+
interface Rect {
|
|
229
|
+
x: number;
|
|
230
|
+
y: number;
|
|
231
|
+
width: number;
|
|
232
|
+
height: number;
|
|
233
|
+
}
|
|
234
|
+
interface RectQueryOptions extends QueryOptions {
|
|
235
|
+
/**
|
|
236
|
+
* `'center'` (default) keeps a seat when its CENTRE falls inside the rect,
|
|
237
|
+
* bounds inclusive. This is what `SeatmapRenderer.finishMarquee` does today,
|
|
238
|
+
* so it is the default in order to be a drop-in replacement.
|
|
239
|
+
*
|
|
240
|
+
* `'overlap'` keeps a seat when its hit SHAPE intersects the rect at all —
|
|
241
|
+
* the right mode for "which seats are on screen" viewport culling and
|
|
242
|
+
* label-rendering passes, where a partially visible seat still counts.
|
|
243
|
+
*/
|
|
244
|
+
mode?: 'center' | 'overlap';
|
|
245
|
+
}
|
|
246
|
+
interface IndexedSeat {
|
|
247
|
+
seat: ExpandedSeat;
|
|
248
|
+
shape: SeatShape;
|
|
249
|
+
/** Half-extents of the shape's axis-aligned bounding box (rotation applied). */
|
|
250
|
+
hx: number;
|
|
251
|
+
hy: number;
|
|
252
|
+
}
|
|
253
|
+
interface SeatIndex {
|
|
254
|
+
readonly seats: readonly ExpandedSeat[];
|
|
255
|
+
/** @internal */
|
|
256
|
+
readonly entries: readonly IndexedSeat[];
|
|
257
|
+
/** @internal */
|
|
258
|
+
readonly minX: number;
|
|
259
|
+
/** @internal */
|
|
260
|
+
readonly minY: number;
|
|
261
|
+
/** @internal */
|
|
262
|
+
readonly cell: number;
|
|
263
|
+
/** @internal */
|
|
264
|
+
readonly cols: number;
|
|
265
|
+
/** @internal */
|
|
266
|
+
readonly rows: number;
|
|
267
|
+
/** @internal Prefix-sum offsets into {@link items}; length cols*rows+1. */
|
|
268
|
+
readonly cellStart: Int32Array;
|
|
269
|
+
/** @internal Seat indices grouped by cell. */
|
|
270
|
+
readonly items: Int32Array;
|
|
271
|
+
/** @internal Per-seat visit stamps, for dedup across multi-cell scans. */
|
|
272
|
+
readonly stamp: Int32Array;
|
|
273
|
+
/** @internal Monotonically increasing stamp epoch. */
|
|
274
|
+
epoch: number;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Build a uniform-grid index over `seats`. O(n) in time and memory.
|
|
278
|
+
*
|
|
279
|
+
* CELL SIZE
|
|
280
|
+
* ---------
|
|
281
|
+
* The nominal cell is `4 × maxHalfExtent`, i.e. twice the largest seat's
|
|
282
|
+
* bounding-box width. Two properties fall out of that choice:
|
|
283
|
+
*
|
|
284
|
+
* - A seat's AABB is at most half a cell across, so it lands in at most 2×2 = 4
|
|
285
|
+
* cells. Build stays O(n) with a small constant, and the index does not blow
|
|
286
|
+
* up in memory from duplicated references.
|
|
287
|
+
* - For the default 9px seat radius the cell is 36 world units, versus a real
|
|
288
|
+
* row/seat pitch of roughly 20–26. That works out to ~1–2 seats per occupied
|
|
289
|
+
* cell, so a point query examines about one or two candidates. Halving the
|
|
290
|
+
* cell would quadruple cell count to shave a fraction of a candidate;
|
|
291
|
+
* doubling it would put ~6 seats in every cell. 4× the half-extent is the
|
|
292
|
+
* flat part of that curve.
|
|
293
|
+
*
|
|
294
|
+
* The one pathological input is a chart whose bounds are enormous relative to
|
|
295
|
+
* its seat count — a single stray object parked far from the venue. `maxCells`
|
|
296
|
+
* caps the grid and grows the cell size until it fits, trading query sharpness
|
|
297
|
+
* for bounded memory. Real charts never hit it.
|
|
298
|
+
*/
|
|
299
|
+
declare function buildSeatIndex(seats: readonly ExpandedSeat[], opts?: BuildOptions): SeatIndex;
|
|
300
|
+
/**
|
|
301
|
+
* The seat whose hit shape contains `p`, or null.
|
|
302
|
+
*
|
|
303
|
+
* On overlap — seats drawn close enough that their circles intersect — the seat
|
|
304
|
+
* whose CENTRE is nearest to `p` wins. That matches what a user perceives (you
|
|
305
|
+
* hit the thing you aimed at) and, unlike Konva, is order-independent: Konva's
|
|
306
|
+
* hit graph resolves overlap by draw order, returning the topmost/last-added
|
|
307
|
+
* node regardless of how far off-centre the pointer was.
|
|
308
|
+
*/
|
|
309
|
+
declare function hitTest(index: SeatIndex, p: Point, opts?: QueryOptions): string | null;
|
|
310
|
+
/**
|
|
311
|
+
* Nearest seat CENTRE strictly within `radius` world units of `p`, or null.
|
|
312
|
+
*
|
|
313
|
+
* This is the near-miss rescue from `SeatmapRenderer.nearestSeatToScreen`,
|
|
314
|
+
* lifted verbatim. The caller computes the radius the same way the renderer
|
|
315
|
+
* does today:
|
|
316
|
+
*
|
|
317
|
+
* const reachWorld = seatR + slopPx / stageScale; // SEAT_TAP_SLOP_PX = 14
|
|
318
|
+
* nearestWithin(index, screenToWorld(pointer), reachWorld, { filter });
|
|
319
|
+
*
|
|
320
|
+
* Note the comparison is STRICTLY less-than, mirroring the renderer's
|
|
321
|
+
* `bestD = reachWorld; ... if (d < bestD)` loop: a seat centre sitting exactly
|
|
322
|
+
* `reachWorld` away does not qualify. Distance is measured to the seat centre,
|
|
323
|
+
* not the shape edge — so for the default circle, "centre within seatR + slop"
|
|
324
|
+
* is identical to "edge within slop", which is what the renderer's docstring
|
|
325
|
+
* describes.
|
|
326
|
+
*/
|
|
327
|
+
declare function nearestWithin(index: SeatIndex, p: Point, radius: number, opts?: QueryOptions): string | null;
|
|
328
|
+
/**
|
|
329
|
+
* Seat ids inside a world-space rect. Negative width/height are normalised, so a
|
|
330
|
+
* marquee dragged up-and-left works without the caller sorting the corners.
|
|
331
|
+
*
|
|
332
|
+
* Default `mode: 'center'` reproduces `SeatmapRenderer.finishMarquee` exactly:
|
|
333
|
+
* a seat is kept when its centre is within the rect, bounds INCLUSIVE. Use
|
|
334
|
+
* `mode: 'overlap'` for viewport culling, where a seat straddling the edge
|
|
335
|
+
* should still be drawn.
|
|
336
|
+
*
|
|
337
|
+
* Results come back in ascending seat-array order, so the output is stable
|
|
338
|
+
* across calls regardless of grid layout.
|
|
339
|
+
*/
|
|
340
|
+
declare function queryRect(index: SeatIndex, rect: Rect, opts?: RectQueryOptions): string[];
|
|
341
|
+
/**
|
|
342
|
+
* Occupancy stats for the built grid. Diagnostic only — this is the evidence to
|
|
343
|
+
* check before anyone argues the uniform grid has stopped being good enough and
|
|
344
|
+
* a tree is warranted.
|
|
345
|
+
*/
|
|
346
|
+
declare function gridStats(index: SeatIndex): {
|
|
347
|
+
cell: number;
|
|
348
|
+
cols: number;
|
|
349
|
+
rows: number;
|
|
350
|
+
cells: number;
|
|
351
|
+
occupiedCells: number;
|
|
352
|
+
refs: number;
|
|
353
|
+
maxPerCell: number;
|
|
354
|
+
meanPerOccupiedCell: number;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
declare const TEXT_WIDTH_MIN = 40;
|
|
358
|
+
declare const TEXT_WIDTH_MAX = 1200;
|
|
359
|
+
declare const TEXT_LINE_HEIGHT_MIN = 0.8;
|
|
360
|
+
declare const TEXT_LINE_HEIGHT_MAX = 3;
|
|
361
|
+
declare const TEXT_LETTER_SPACING_MIN = -2;
|
|
362
|
+
declare const TEXT_LETTER_SPACING_MAX = 20;
|
|
363
|
+
declare const TEXT_OPACITY_MIN = 0.1;
|
|
364
|
+
declare const TEXT_BACKGROUND_PADDING_MAX = 40;
|
|
365
|
+
declare const TEXT_BACKGROUND_RADIUS_MAX = 40;
|
|
366
|
+
interface TextLayoutMetrics {
|
|
367
|
+
width: number;
|
|
368
|
+
height: number;
|
|
369
|
+
lineCount: number;
|
|
370
|
+
padding: number;
|
|
371
|
+
}
|
|
372
|
+
/** Conservative renderer-independent box used by chart bounds, quality and
|
|
373
|
+
* collision checks. Konva remains authoritative for exact glyph metrics. */
|
|
374
|
+
declare function textLayoutMetrics(text: TextObject): TextLayoutMetrics;
|
|
375
|
+
|
|
376
|
+
export { type Affine2D, type BuildOptions, DEFAULT_SEAT_RADIUS, type InscribedAnchor, type PerspectiveBounds, type PerspectiveCamera, type PerspectivePoint, type QueryOptions, type Rect, type RectQueryOptions, type SeatIndex, type SeatShape, type SectionShellMode, TEXT_BACKGROUND_PADDING_MAX, TEXT_BACKGROUND_RADIUS_MAX, TEXT_LETTER_SPACING_MAX, TEXT_LETTER_SPACING_MIN, TEXT_LINE_HEIGHT_MAX, TEXT_LINE_HEIGHT_MIN, TEXT_OPACITY_MIN, TEXT_WIDTH_MAX, TEXT_WIDTH_MIN, type TextLayoutMetrics, applyAffine, buildAisleHoles, buildSeatIndex, buildSectionShell, composeAffine, createPerspectiveCamera, cubicPoint, decomposeAffineLinear, distanceToRings, distributeAlongCubic, gridStats, hitTest, invertAffine, nearestWithin, perspectiveTangentAffine, polygonArea, polygonInscribedAnchor, polygonNetArea, projectPerspectivePoint, queryRect, smoothCubicThroughMiddle, textLayoutMetrics };
|