@kerusiweb/core 2.0.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 +22 -0
- package/README.md +68 -0
- package/dist/kerusi/index.d.ts +19 -0
- package/dist/kerusi/index.d.ts.map +1 -0
- package/dist/kerusi/index.js +19 -0
- package/dist/kerusi/index.js.map +1 -0
- package/dist/kerusi/kerusi-layout-mode.d.ts +58 -0
- package/dist/kerusi/kerusi-layout-mode.d.ts.map +1 -0
- package/dist/kerusi/kerusi-layout-mode.js +117 -0
- package/dist/kerusi/kerusi-layout-mode.js.map +1 -0
- package/dist/kerusi/kerusi-locale.d.ts +43 -0
- package/dist/kerusi/kerusi-locale.d.ts.map +1 -0
- package/dist/kerusi/kerusi-locale.js +111 -0
- package/dist/kerusi/kerusi-locale.js.map +1 -0
- package/dist/kerusi/kerusi-map.model.d.ts +258 -0
- package/dist/kerusi/kerusi-map.model.d.ts.map +1 -0
- package/dist/kerusi/kerusi-map.model.js +11 -0
- package/dist/kerusi/kerusi-map.model.js.map +1 -0
- package/dist/kerusi/kerusi-price.d.ts +22 -0
- package/dist/kerusi/kerusi-price.d.ts.map +1 -0
- package/dist/kerusi/kerusi-price.js +48 -0
- package/dist/kerusi/kerusi-price.js.map +1 -0
- package/dist/kerusi/kerusi-rows.d.ts +25 -0
- package/dist/kerusi/kerusi-rows.d.ts.map +1 -0
- package/dist/kerusi/kerusi-rows.js +36 -0
- package/dist/kerusi/kerusi-rows.js.map +1 -0
- package/dist/kerusi/kerusi-state.d.ts +85 -0
- package/dist/kerusi/kerusi-state.d.ts.map +1 -0
- package/dist/kerusi/kerusi-state.js +117 -0
- package/dist/kerusi/kerusi-state.js.map +1 -0
- package/dist/kerusi/kerusi-state.model.d.ts +79 -0
- package/dist/kerusi/kerusi-state.model.d.ts.map +1 -0
- package/dist/kerusi/kerusi-state.model.js +7 -0
- package/dist/kerusi/kerusi-state.model.js.map +1 -0
- package/dist/kerusi/kerusi-validator.d.ts +96 -0
- package/dist/kerusi/kerusi-validator.d.ts.map +1 -0
- package/dist/kerusi/kerusi-validator.js +525 -0
- package/dist/kerusi/kerusi-validator.js.map +1 -0
- package/dist/kerusi/kerusi-violation.d.ts +36 -0
- package/dist/kerusi/kerusi-violation.d.ts.map +1 -0
- package/dist/kerusi/kerusi-violation.js +13 -0
- package/dist/kerusi/kerusi-violation.js.map +1 -0
- package/dist/public-api.d.ts +4 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +13 -0
- package/dist/public-api.js.map +1 -0
- package/dist/render/build-render-model.d.ts +36 -0
- package/dist/render/build-render-model.d.ts.map +1 -0
- package/dist/render/build-render-model.js +258 -0
- package/dist/render/build-render-model.js.map +1 -0
- package/dist/render/element-shapes.d.ts +34 -0
- package/dist/render/element-shapes.d.ts.map +1 -0
- package/dist/render/element-shapes.js +41 -0
- package/dist/render/element-shapes.js.map +1 -0
- package/dist/render/index.d.ts +14 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +14 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/navigation-order.d.ts +49 -0
- package/dist/render/navigation-order.d.ts.map +1 -0
- package/dist/render/navigation-order.js +109 -0
- package/dist/render/navigation-order.js.map +1 -0
- package/dist/render/render-model.d.ts +151 -0
- package/dist/render/render-model.d.ts.map +1 -0
- package/dist/render/render-model.js +2 -0
- package/dist/render/render-model.js.map +1 -0
- package/dist/render/seat-shapes.d.ts +72 -0
- package/dist/render/seat-shapes.d.ts.map +1 -0
- package/dist/render/seat-shapes.js +161 -0
- package/dist/render/seat-shapes.js.map +1 -0
- package/dist/render/section-layout.d.ts +66 -0
- package/dist/render/section-layout.d.ts.map +1 -0
- package/dist/render/section-layout.js +173 -0
- package/dist/render/section-layout.js.map +1 -0
- package/dist/view/index.d.ts +12 -0
- package/dist/view/index.d.ts.map +1 -0
- package/dist/view/index.js +12 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/kerusi-seatmap-colors.d.ts +176 -0
- package/dist/view/kerusi-seatmap-colors.d.ts.map +1 -0
- package/dist/view/kerusi-seatmap-colors.js +215 -0
- package/dist/view/kerusi-seatmap-colors.js.map +1 -0
- package/dist/view/rtl.d.ts +17 -0
- package/dist/view/rtl.d.ts.map +1 -0
- package/dist/view/rtl.js +29 -0
- package/dist/view/rtl.js.map +1 -0
- package/dist/view/seat-aria.d.ts +44 -0
- package/dist/view/seat-aria.d.ts.map +1 -0
- package/dist/view/seat-aria.js +103 -0
- package/dist/view/seat-aria.js.map +1 -0
- package/dist/view/selection.d.ts +84 -0
- package/dist/view/selection.d.ts.map +1 -0
- package/dist/view/selection.js +98 -0
- package/dist/view/selection.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { KerusiMap } from '../kerusi/kerusi-map.model.js';
|
|
2
|
+
import { KerusiState } from '../kerusi/kerusi-state.model.js';
|
|
3
|
+
import { RenderMap, RenderSeat, SeatRenderStatus } from './render-model.js';
|
|
4
|
+
/** Which statuses a seat may be picked in, unless the caller says otherwise. */
|
|
5
|
+
export declare const DEFAULT_SELECTABLE_STATUSES: readonly SeatRenderStatus[];
|
|
6
|
+
export interface BuildRenderModelOptions {
|
|
7
|
+
/** Overrides `KerusiMap.locale` for label resolution. */
|
|
8
|
+
locale?: string;
|
|
9
|
+
/** Render only these sections, in this order. Default: all, by `Section.index`. */
|
|
10
|
+
sectionIds?: readonly string[];
|
|
11
|
+
/** Statuses in which a seat may be picked. Default: `['available']`. */
|
|
12
|
+
selectableStatuses?: readonly SeatRenderStatus[];
|
|
13
|
+
/** A final say on whether a seat is selectable, applied after the status test. */
|
|
14
|
+
seatSelectable?: (seat: RenderSeat) => boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds the renderer's view of a `KerusiMap` with its `KerusiState` merged in.
|
|
18
|
+
*
|
|
19
|
+
* Everything the standard makes a consumer resolve happens here, once:
|
|
20
|
+
* - sections ordered by `Section.index`, and each given its own layout mode
|
|
21
|
+
* per §4.5 — this is what lets a grid balcony and a freeform orchestra
|
|
22
|
+
* coexist in one map;
|
|
23
|
+
* - every row a section declares materialized, empty rows included, in the
|
|
24
|
+
* §4.2.1 order, with seats grouped into them by `Seat.row` and ordered by
|
|
25
|
+
* `col` (grid, mixed) or `x` (freeform);
|
|
26
|
+
* - availability merged by `Seat.id`, honoring §5.1's sparse rule that an
|
|
27
|
+
* absent seat is available;
|
|
28
|
+
* - price resolved through the §4.9 precedence order;
|
|
29
|
+
* - `Section.label` and `SeatType.label` localized against the map's locale.
|
|
30
|
+
*
|
|
31
|
+
* It does NOT validate — call `validateKerusiMap` or `checkKerusiMap` first.
|
|
32
|
+
* Given an invalid document it builds the best model it can rather than
|
|
33
|
+
* throwing, so a caller in "collect" mode can render and report at once.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildRenderModel(map: KerusiMap, state?: KerusiState, options?: BuildRenderModelOptions): RenderMap;
|
|
36
|
+
//# sourceMappingURL=build-render-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-render-model.d.ts","sourceRoot":"","sources":["../../src/render/build-render-model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA0B,MAAM,+BAA+B,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAK9D,OAAO,EAIL,SAAS,EAET,UAAU,EAEV,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAK3B,gFAAgF;AAChF,eAAO,MAAM,2BAA2B,EAAE,SAAS,gBAAgB,EAAkB,CAAC;AAEtF,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD,kFAAkF;IAClF,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,EACd,KAAK,CAAC,EAAE,WAAW,EACnB,OAAO,GAAE,uBAA4B,GACpC,SAAS,CA6CX"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { resolveSectionLayoutMode } from '../kerusi/kerusi-layout-mode.js';
|
|
2
|
+
import { resolveLocalizedText, resolveMapLocale } from '../kerusi/kerusi-locale.js';
|
|
3
|
+
import { resolveSeatPrice, resolveTierPrice } from '../kerusi/kerusi-price.js';
|
|
4
|
+
import { orderRowMeta } from '../kerusi/kerusi-rows.js';
|
|
5
|
+
/** The default section proportions when none is declared (§4.5). */
|
|
6
|
+
const DEFAULT_ASPECT_RATIO = '1:1';
|
|
7
|
+
/** Which statuses a seat may be picked in, unless the caller says otherwise. */
|
|
8
|
+
export const DEFAULT_SELECTABLE_STATUSES = ['available'];
|
|
9
|
+
/**
|
|
10
|
+
* Builds the renderer's view of a `KerusiMap` with its `KerusiState` merged in.
|
|
11
|
+
*
|
|
12
|
+
* Everything the standard makes a consumer resolve happens here, once:
|
|
13
|
+
* - sections ordered by `Section.index`, and each given its own layout mode
|
|
14
|
+
* per §4.5 — this is what lets a grid balcony and a freeform orchestra
|
|
15
|
+
* coexist in one map;
|
|
16
|
+
* - every row a section declares materialized, empty rows included, in the
|
|
17
|
+
* §4.2.1 order, with seats grouped into them by `Seat.row` and ordered by
|
|
18
|
+
* `col` (grid, mixed) or `x` (freeform);
|
|
19
|
+
* - availability merged by `Seat.id`, honoring §5.1's sparse rule that an
|
|
20
|
+
* absent seat is available;
|
|
21
|
+
* - price resolved through the §4.9 precedence order;
|
|
22
|
+
* - `Section.label` and `SeatType.label` localized against the map's locale.
|
|
23
|
+
*
|
|
24
|
+
* It does NOT validate — call `validateKerusiMap` or `checkKerusiMap` first.
|
|
25
|
+
* Given an invalid document it builds the best model it can rather than
|
|
26
|
+
* throwing, so a caller in "collect" mode can render and report at once.
|
|
27
|
+
*/
|
|
28
|
+
export function buildRenderModel(map, state, options = {}) {
|
|
29
|
+
const locale = resolveMapLocale(map, options.locale);
|
|
30
|
+
const selectableStatuses = new Set(options.selectableStatuses ?? DEFAULT_SELECTABLE_STATUSES);
|
|
31
|
+
const legendById = new Map((map.legend ?? []).map((t) => [t.id, t]));
|
|
32
|
+
const seatsById = new Map();
|
|
33
|
+
const typeCounts = new Map();
|
|
34
|
+
const currencies = new Set();
|
|
35
|
+
const sections = selectSections(map, options.sectionIds).map((section) => buildSection(section, {
|
|
36
|
+
map,
|
|
37
|
+
state,
|
|
38
|
+
locale,
|
|
39
|
+
selectableStatuses,
|
|
40
|
+
seatSelectable: options.seatSelectable,
|
|
41
|
+
legendById,
|
|
42
|
+
seatsById,
|
|
43
|
+
typeCounts,
|
|
44
|
+
currencies,
|
|
45
|
+
}));
|
|
46
|
+
const legend = (map.legend ?? []).map((type) => {
|
|
47
|
+
const price = resolveTierPrice(map, type.defaultPriceTier);
|
|
48
|
+
return {
|
|
49
|
+
id: type.id,
|
|
50
|
+
label: resolveLocalizedText(type.label, locale) ?? type.id,
|
|
51
|
+
color: type.color,
|
|
52
|
+
defaultTier: map.priceTiers?.find((t) => t.id === type.defaultPriceTier),
|
|
53
|
+
price,
|
|
54
|
+
seatCount: typeCounts.get(type.id) ?? 0,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
id: map.id,
|
|
59
|
+
name: map.name,
|
|
60
|
+
locale,
|
|
61
|
+
domain: map.domain,
|
|
62
|
+
sections,
|
|
63
|
+
legend,
|
|
64
|
+
// §4.9 forbids mixing currencies, so the first is the map's.
|
|
65
|
+
currency: [...currencies][0],
|
|
66
|
+
seatsById,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function buildSection(section, ctx) {
|
|
70
|
+
const layoutMode = resolveSectionLayoutMode(section);
|
|
71
|
+
const rows = buildRows(section, layoutMode, ctx);
|
|
72
|
+
return {
|
|
73
|
+
id: section.id,
|
|
74
|
+
label: resolveLocalizedText(section.label, ctx.locale),
|
|
75
|
+
layoutMode,
|
|
76
|
+
aspectRatio: section.aspectRatio ?? DEFAULT_ASPECT_RATIO,
|
|
77
|
+
rows,
|
|
78
|
+
seats: rows.flatMap((r) => r.seats),
|
|
79
|
+
elements: buildElements(section, rows),
|
|
80
|
+
directions: buildDirections(section, ctx.locale),
|
|
81
|
+
source: section,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Localizes `Section.directions` (§4.10) and carries it through. Both ends of a
|
|
86
|
+
* `Direction` may be a locale map, exactly as `Section.label` may be.
|
|
87
|
+
*
|
|
88
|
+
* Nothing downstream reads this — §4.10 forbids a renderer deciding layout or
|
|
89
|
+
* screen placement from it. It exists so an application can print "front of
|
|
90
|
+
* train" beside the axis the document says means that.
|
|
91
|
+
*/
|
|
92
|
+
function buildDirections(section, locale) {
|
|
93
|
+
if (!section.directions?.length) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
return section.directions.map((direction) => ({
|
|
97
|
+
axis: direction.axis,
|
|
98
|
+
low: resolveLocalizedText(direction.low, locale) ?? '',
|
|
99
|
+
high: resolveLocalizedText(direction.high, locale) ?? '',
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Materializes a section's rows and groups its flat seat list into them.
|
|
104
|
+
*
|
|
105
|
+
* `Section.rows` is not a container (§4.2) — seats never live inside a row — but
|
|
106
|
+
* where it is present it *is* the section's complete row registry (§4.2.2), so
|
|
107
|
+
* the rows come from it rather than from the seats that happen to reference
|
|
108
|
+
* one. That is what makes an **empty row** real: a `RowMeta` no seat mentions
|
|
109
|
+
* still takes a slot, and the grid layout reserves a row of vertical space for
|
|
110
|
+
* it. Without that, a document could not open the throw between a cinema screen
|
|
111
|
+
* and row A, because rows would exist only where seats did.
|
|
112
|
+
*
|
|
113
|
+
* With no registry, a seat's `row` is opaque free text (§4.6) and the rows are
|
|
114
|
+
* exactly those the seats name, in first-appearance order — a document that
|
|
115
|
+
* declares no row metadata still renders in the order its author wrote it.
|
|
116
|
+
*/
|
|
117
|
+
function buildRows(section, layoutMode, ctx) {
|
|
118
|
+
const byRowKey = new Map();
|
|
119
|
+
const firstSeen = new Map();
|
|
120
|
+
(section.seats ?? []).forEach((seat, i) => {
|
|
121
|
+
const key = seat.row ?? '';
|
|
122
|
+
if (!byRowKey.has(key)) {
|
|
123
|
+
byRowKey.set(key, []);
|
|
124
|
+
firstSeen.set(key, i);
|
|
125
|
+
}
|
|
126
|
+
byRowKey.get(key).push(seat);
|
|
127
|
+
});
|
|
128
|
+
const registry = section.rows;
|
|
129
|
+
const ordered = registry
|
|
130
|
+
? orderRowMeta(registry).map((meta) => ({ key: meta.id, meta }))
|
|
131
|
+
: [...byRowKey.keys()]
|
|
132
|
+
.sort((a, b) => firstSeen.get(a) - firstSeen.get(b))
|
|
133
|
+
.map((key) => ({ key }));
|
|
134
|
+
if (registry) {
|
|
135
|
+
// A seat naming a row the registry does not declare is a §4.6 violation the
|
|
136
|
+
// validator reports. Render it anyway, after the declared rows — dropping
|
|
137
|
+
// seats would hide the error rather than show it.
|
|
138
|
+
const declared = new Set(registry.map((r) => r.id));
|
|
139
|
+
for (const key of byRowKey.keys()) {
|
|
140
|
+
if (!declared.has(key)) {
|
|
141
|
+
ordered.push({ key });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return ordered.map(({ key, meta }, rowIndex) => {
|
|
146
|
+
const seats = byRowKey.get(key) ?? [];
|
|
147
|
+
const label = meta?.label ?? (key || undefined);
|
|
148
|
+
const row = {
|
|
149
|
+
id: key,
|
|
150
|
+
label,
|
|
151
|
+
index: rowIndex,
|
|
152
|
+
seats: sortSeats(seats, layoutMode).map((seat) => buildSeat(seat, section, { rowIndex, rowLabel: label }, ctx)),
|
|
153
|
+
empty: seats.length === 0,
|
|
154
|
+
};
|
|
155
|
+
return row;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Orders seats within a row. `col` is the adjacency ordinal in grid and mixed
|
|
160
|
+
* sections — including mixed, where `x`/`y` places the seat but `col` is what
|
|
161
|
+
* "the seat to the right" means (§4.3.1). Freeform rows have no columns, so
|
|
162
|
+
* they order by `x`.
|
|
163
|
+
*/
|
|
164
|
+
function sortSeats(seats, layoutMode) {
|
|
165
|
+
const byCol = layoutMode !== 'freeform';
|
|
166
|
+
return [...seats]
|
|
167
|
+
.map((seat, order) => ({ seat, order }))
|
|
168
|
+
.sort((a, b) => {
|
|
169
|
+
const left = byCol ? a.seat.col : a.seat.x;
|
|
170
|
+
const right = byCol ? b.seat.col : b.seat.x;
|
|
171
|
+
if (left === undefined || right === undefined || left === right) {
|
|
172
|
+
return (a.seat.y ?? 0) - (b.seat.y ?? 0) || a.order - b.order;
|
|
173
|
+
}
|
|
174
|
+
return left - right;
|
|
175
|
+
})
|
|
176
|
+
.map((entry) => entry.seat);
|
|
177
|
+
}
|
|
178
|
+
function buildSeat(seat, section, row, ctx) {
|
|
179
|
+
const type = ctx.legendById.get(seat.type) ?? { id: seat.type };
|
|
180
|
+
const price = resolveSeatPrice(seat, ctx.map);
|
|
181
|
+
if (price?.currency) {
|
|
182
|
+
ctx.currencies.add(price.currency);
|
|
183
|
+
}
|
|
184
|
+
ctx.typeCounts.set(seat.type, (ctx.typeCounts.get(seat.type) ?? 0) + 1);
|
|
185
|
+
// §5.1: a seat absent from the state document is available.
|
|
186
|
+
const status = ctx.state?.seats?.[seat.id];
|
|
187
|
+
const rendered = {
|
|
188
|
+
id: seat.id,
|
|
189
|
+
sectionId: section.id,
|
|
190
|
+
label: seat.label ?? seat.id,
|
|
191
|
+
row: seat.row,
|
|
192
|
+
rowLabel: row.rowLabel,
|
|
193
|
+
rowIndex: row.rowIndex,
|
|
194
|
+
col: seat.col,
|
|
195
|
+
x: seat.x,
|
|
196
|
+
y: seat.y,
|
|
197
|
+
rotation: seat.rotation,
|
|
198
|
+
type,
|
|
199
|
+
typeLabel: resolveLocalizedText(type.label, ctx.locale) ?? type.id,
|
|
200
|
+
typeColor: type.color,
|
|
201
|
+
attributes: seat.attributes ?? [],
|
|
202
|
+
accessibility: seat.accessibility,
|
|
203
|
+
price,
|
|
204
|
+
companions: seat.companions ?? [],
|
|
205
|
+
status: status?.status ?? 'available',
|
|
206
|
+
holdExpires: status?.holdExpires,
|
|
207
|
+
selectable: false,
|
|
208
|
+
source: seat,
|
|
209
|
+
};
|
|
210
|
+
rendered.selectable =
|
|
211
|
+
ctx.selectableStatuses.has(rendered.status) && (ctx.seatSelectable?.(rendered) ?? true);
|
|
212
|
+
ctx.seatsById.set(rendered.id, rendered);
|
|
213
|
+
return rendered;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Carries elements through with their `id` intact — the pre-1.0 adapter dropped
|
|
217
|
+
* it, leaving the render model with no element identity. A grid-addressed
|
|
218
|
+
* element gets its row's index so the layout can place it in the cell grid.
|
|
219
|
+
*/
|
|
220
|
+
function buildElements(section, rows) {
|
|
221
|
+
const rowIndexById = new Map(rows.map((r) => [r.id, r.index]));
|
|
222
|
+
return (section.elements ?? []).map((element) => ({
|
|
223
|
+
id: element.id,
|
|
224
|
+
kind: element.kind,
|
|
225
|
+
label: element.label,
|
|
226
|
+
row: element.row,
|
|
227
|
+
rowIndex: element.row !== undefined ? rowIndexById.get(element.row) : undefined,
|
|
228
|
+
col: element.col,
|
|
229
|
+
x: element.x,
|
|
230
|
+
y: element.y,
|
|
231
|
+
width: element.width,
|
|
232
|
+
height: element.height,
|
|
233
|
+
rotation: element.rotation,
|
|
234
|
+
source: element,
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
/** Sections in `Section.index` order, optionally filtered to an explicit set. */
|
|
238
|
+
function selectSections(map, sectionIds) {
|
|
239
|
+
const all = map.sections ?? [];
|
|
240
|
+
if (sectionIds) {
|
|
241
|
+
// An explicit list is also an explicit order — honor it verbatim.
|
|
242
|
+
return sectionIds
|
|
243
|
+
.map((id) => all.find((s) => s.id === id))
|
|
244
|
+
.filter((s) => s !== undefined);
|
|
245
|
+
}
|
|
246
|
+
return [...all]
|
|
247
|
+
.map((section, order) => ({ section, order }))
|
|
248
|
+
.sort((a, b) => orderKey(a.section.index, a.order) - orderKey(b.section.index, b.order))
|
|
249
|
+
.map((entry) => entry.section);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* A sort key that keeps entries without an explicit `index` in declaration
|
|
253
|
+
* order, and after every entry that has one.
|
|
254
|
+
*/
|
|
255
|
+
function orderKey(index, fallbackOrder) {
|
|
256
|
+
return index ?? Number.MAX_SAFE_INTEGER - 1_000_000 + fallbackOrder;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=build-render-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-render-model.js","sourceRoot":"","sources":["../../src/render/build-render-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How each `Element.kind` is drawn.
|
|
3
|
+
*
|
|
4
|
+
* `kind` is open — the spec lists "screen" | "stage" | "exit" | "lavatory" |
|
|
5
|
+
* "gap" | "aisle" and explicitly allows implementation-defined values (§4.4) —
|
|
6
|
+
* so this is a lookup with a sensible default, never an exhaustive switch. An
|
|
7
|
+
* unrecognized kind draws as a labelled rectangle, which is what the pre-1.0
|
|
8
|
+
* renderer did for every kind including the ones it should have distinguished.
|
|
9
|
+
*/
|
|
10
|
+
export type ElementShape =
|
|
11
|
+
/** A rounded rectangle. The default. */
|
|
12
|
+
'rect'
|
|
13
|
+
/** A shallow arc bulging toward the audience — a cinema or theatre screen. */
|
|
14
|
+
| 'screen'
|
|
15
|
+
/** A rectangle with a heavier outline, reading as a raised platform. */
|
|
16
|
+
| 'stage'
|
|
17
|
+
/** A dashed outline: space that is deliberately empty. */
|
|
18
|
+
| 'void';
|
|
19
|
+
export interface ElementStyle {
|
|
20
|
+
shape: ElementShape;
|
|
21
|
+
/** Which themed color the element takes. */
|
|
22
|
+
tone: 'neutral' | 'accent' | 'muted';
|
|
23
|
+
/** Whether the element's label is drawn on it. */
|
|
24
|
+
showLabel: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** The style for an element kind. Unknown kinds get the labelled rectangle. */
|
|
27
|
+
export declare function elementStyle(kind: string): ElementStyle;
|
|
28
|
+
/**
|
|
29
|
+
* An SVG path for a screen: a shallow arc across the top of its box, bulging
|
|
30
|
+
* downward toward the seats. Drawn as a filled sliver rather than a stroke so
|
|
31
|
+
* it reads at any size.
|
|
32
|
+
*/
|
|
33
|
+
export declare function screenPath(x: number, y: number, width: number, height: number): string;
|
|
34
|
+
//# sourceMappingURL=element-shapes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-shapes.d.ts","sourceRoot":"","sources":["../../src/render/element-shapes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,YAAY;AACtB,wCAAwC;AACtC,MAAM;AACR,8EAA8E;GAC5E,QAAQ;AACV,wEAAwE;GACtE,OAAO;AACT,0DAA0D;GACxD,MAAM,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAC;CACpB;AAmBD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQtF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How each `Element.kind` is drawn.
|
|
3
|
+
*
|
|
4
|
+
* `kind` is open — the spec lists "screen" | "stage" | "exit" | "lavatory" |
|
|
5
|
+
* "gap" | "aisle" and explicitly allows implementation-defined values (§4.4) —
|
|
6
|
+
* so this is a lookup with a sensible default, never an exhaustive switch. An
|
|
7
|
+
* unrecognized kind draws as a labelled rectangle, which is what the pre-1.0
|
|
8
|
+
* renderer did for every kind including the ones it should have distinguished.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_STYLE = { shape: 'rect', tone: 'neutral', showLabel: true };
|
|
11
|
+
const STYLES = {
|
|
12
|
+
screen: { shape: 'screen', tone: 'neutral', showLabel: true },
|
|
13
|
+
stage: { shape: 'stage', tone: 'neutral', showLabel: true },
|
|
14
|
+
pitch: { shape: 'stage', tone: 'muted', showLabel: true },
|
|
15
|
+
field: { shape: 'stage', tone: 'muted', showLabel: true },
|
|
16
|
+
exit: { shape: 'rect', tone: 'accent', showLabel: true },
|
|
17
|
+
door: { shape: 'rect', tone: 'accent', showLabel: true },
|
|
18
|
+
lavatory: { shape: 'rect', tone: 'muted', showLabel: true },
|
|
19
|
+
galley: { shape: 'rect', tone: 'muted', showLabel: true },
|
|
20
|
+
table: { shape: 'rect', tone: 'muted', showLabel: true },
|
|
21
|
+
aisle: { shape: 'void', tone: 'muted', showLabel: false },
|
|
22
|
+
gap: { shape: 'void', tone: 'muted', showLabel: true },
|
|
23
|
+
stairs: { shape: 'void', tone: 'muted', showLabel: true },
|
|
24
|
+
};
|
|
25
|
+
/** The style for an element kind. Unknown kinds get the labelled rectangle. */
|
|
26
|
+
export function elementStyle(kind) {
|
|
27
|
+
return STYLES[kind?.toLowerCase()] ?? DEFAULT_STYLE;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* An SVG path for a screen: a shallow arc across the top of its box, bulging
|
|
31
|
+
* downward toward the seats. Drawn as a filled sliver rather than a stroke so
|
|
32
|
+
* it reads at any size.
|
|
33
|
+
*/
|
|
34
|
+
export function screenPath(x, y, width, height) {
|
|
35
|
+
const bulge = height * 1.6;
|
|
36
|
+
return (`M ${x} ${y} ` +
|
|
37
|
+
`Q ${x + width / 2} ${y + bulge} ${x + width} ${y} ` +
|
|
38
|
+
`L ${x + width} ${y + height} ` +
|
|
39
|
+
`Q ${x + width / 2} ${y + height + bulge} ${x} ${y + height} Z`);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=element-shapes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-shapes.js","sourceRoot":"","sources":["../../src/render/element-shapes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,MAAM,aAAa,GAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAExF,MAAM,MAAM,GAA2C;IACrD,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;IAC7D,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;IAC3D,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IACzD,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IACzD,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;IACxD,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;IACxD,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IAC3D,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IACzD,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IACxD,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;IACzD,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;IACtD,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;CAC1D,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,IAAI,aAAa,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc;IAC5E,MAAM,KAAK,GAAG,MAAM,GAAG,GAAG,CAAC;IAC3B,OAAO,CACL,KAAK,CAAC,IAAI,CAAC,GAAG;QACd,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG;QACpD,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,MAAM,GAAG;QAC/B,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAChE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure render model: a `KerusiMap` + `KerusiState` resolved into everything
|
|
3
|
+
* a renderer needs, and the geometry to place it.
|
|
4
|
+
*
|
|
5
|
+
* Nothing here imports a framework — the model can be built in a test, a
|
|
6
|
+
* build step, or on a server.
|
|
7
|
+
*/
|
|
8
|
+
export * from './render-model.js';
|
|
9
|
+
export * from './build-render-model.js';
|
|
10
|
+
export * from './section-layout.js';
|
|
11
|
+
export * from './navigation-order.js';
|
|
12
|
+
export * from './element-shapes.js';
|
|
13
|
+
export * from './seat-shapes.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure render model: a `KerusiMap` + `KerusiState` resolved into everything
|
|
3
|
+
* a renderer needs, and the geometry to place it.
|
|
4
|
+
*
|
|
5
|
+
* Nothing here imports a framework — the model can be built in a test, a
|
|
6
|
+
* build step, or on a server.
|
|
7
|
+
*/
|
|
8
|
+
export * from './render-model.js';
|
|
9
|
+
export * from './build-render-model.js';
|
|
10
|
+
export * from './section-layout.js';
|
|
11
|
+
export * from './navigation-order.js';
|
|
12
|
+
export * from './element-shapes.js';
|
|
13
|
+
export * from './seat-shapes.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RenderSection } from './render-model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Keyboard navigation order over a seat map.
|
|
4
|
+
*
|
|
5
|
+
* §4.3.1 gives `col` a second job beyond drawing: it is the *logical adjacency
|
|
6
|
+
* ordinal*, which is exactly what "the seat to my right" must mean for a
|
|
7
|
+
* keyboard or a screen reader. That holds in `mixed` sections too, where
|
|
8
|
+
* `x`/`y` places the seat but `col` still orders it — so a stand curving away
|
|
9
|
+
* from the pitch still reads seat 1, 2, 3.
|
|
10
|
+
*
|
|
11
|
+
* Freeform sections have no columns. Where their seats carry a `row` label,
|
|
12
|
+
* that grouping is used; where they carry nothing, seats are banded by `y` and
|
|
13
|
+
* ordered by `x`. That last case is a heuristic, and documented as one.
|
|
14
|
+
*/
|
|
15
|
+
/** The seats reachable from a given seat, by id. */
|
|
16
|
+
export interface SeatNeighbours {
|
|
17
|
+
left?: string;
|
|
18
|
+
right?: string;
|
|
19
|
+
up?: string;
|
|
20
|
+
down?: string;
|
|
21
|
+
rowStart?: string;
|
|
22
|
+
rowEnd?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface NavigationGraph {
|
|
25
|
+
/** Seats in traversal order: row by row, position by position. */
|
|
26
|
+
order: readonly string[];
|
|
27
|
+
/** Per-seat neighbours. */
|
|
28
|
+
neighbours: ReadonlyMap<string, SeatNeighbours>;
|
|
29
|
+
/** The first seat in the section, or `undefined` when it has none. */
|
|
30
|
+
first?: string;
|
|
31
|
+
/** The last seat in the section. */
|
|
32
|
+
last?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface NavigationOptions {
|
|
35
|
+
/** Swaps left/right so arrow keys stay visually correct in RTL locales. */
|
|
36
|
+
rtl?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Restrict traversal to seats passing this test — e.g. to skip unselectable
|
|
39
|
+
* seats. Default: every seat is reachable, since a screen-reader user needs
|
|
40
|
+
* to hear that a seat is booked, not have it hidden.
|
|
41
|
+
*/
|
|
42
|
+
includes?: (seatId: string) => boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Builds the navigation graph for one section. Sections are navigated
|
|
46
|
+
* independently: Tab moves between them, arrows move within.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildNavigationGraph(section: RenderSection, options?: NavigationOptions): NavigationGraph;
|
|
49
|
+
//# sourceMappingURL=navigation-order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-order.d.ts","sourceRoot":"","sources":["../../src/render/navigation-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE9D;;;;;;;;;;;;GAYG;AAEH,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,2BAA2B;IAC3B,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAChD,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,GAAG,CAAC,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,iBAAsB,GAC9B,eAAe,CAkCjB"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the navigation graph for one section. Sections are navigated
|
|
3
|
+
* independently: Tab moves between them, arrows move within.
|
|
4
|
+
*/
|
|
5
|
+
export function buildNavigationGraph(section, options = {}) {
|
|
6
|
+
const bands = section.layoutMode === 'freeform' ? freeformBands(section) : gridBands(section);
|
|
7
|
+
const included = options.includes;
|
|
8
|
+
const filtered = bands
|
|
9
|
+
.map((band) => band.filter((s) => !included || included(s.id)))
|
|
10
|
+
.filter((band) => band.length > 0);
|
|
11
|
+
const neighbours = new Map();
|
|
12
|
+
const order = [];
|
|
13
|
+
filtered.forEach((band, bandIndex) => {
|
|
14
|
+
band.forEach((seat, i) => {
|
|
15
|
+
order.push(seat.id);
|
|
16
|
+
const prev = band[i - 1]?.id;
|
|
17
|
+
const next = band[i + 1]?.id;
|
|
18
|
+
neighbours.set(seat.id, {
|
|
19
|
+
left: options.rtl ? next : prev,
|
|
20
|
+
right: options.rtl ? prev : next,
|
|
21
|
+
up: nearest(filtered[bandIndex - 1], seat),
|
|
22
|
+
down: nearest(filtered[bandIndex + 1], seat),
|
|
23
|
+
rowStart: band[0]?.id,
|
|
24
|
+
rowEnd: band[band.length - 1]?.id,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
order,
|
|
30
|
+
neighbours,
|
|
31
|
+
first: order[0],
|
|
32
|
+
last: order[order.length - 1],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Grid and mixed sections: the rows the render model already grouped, with
|
|
37
|
+
* seats ordered by `col`. `RenderRow.seats` is already in that order.
|
|
38
|
+
*
|
|
39
|
+
* Empty rows (§4.2.2) are skipped: they reserve space on the canvas but hold
|
|
40
|
+
* nothing to move to, and an empty band would strand an arrow press between two
|
|
41
|
+
* rows of seats.
|
|
42
|
+
*/
|
|
43
|
+
function gridBands(section) {
|
|
44
|
+
return section.rows
|
|
45
|
+
.filter((row) => row.seats.length > 0)
|
|
46
|
+
.map((row) => row.seats.map((seat, i) => ({ id: seat.id, ordinal: seat.col ?? i })));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Freeform sections: group by the seats' `row` labels when they have them,
|
|
50
|
+
* since §4.5 permits `row` as a pure label in freeform mode and an author who
|
|
51
|
+
* supplied one has told us how the seats group.
|
|
52
|
+
*
|
|
53
|
+
* With no row labels at all, seats are banded by `y`: sorted top to bottom and
|
|
54
|
+
* split wherever the vertical step exceeds the median step, which separates
|
|
55
|
+
* distinct arcs without assuming they are level. This is a heuristic; a
|
|
56
|
+
* document that wants exact reading order should carry `row` labels.
|
|
57
|
+
*/
|
|
58
|
+
function freeformBands(section) {
|
|
59
|
+
const toNav = (seats) => [...seats]
|
|
60
|
+
.sort((a, b) => (a.x ?? 0) - (b.x ?? 0))
|
|
61
|
+
.map((seat) => ({ id: seat.id, ordinal: seat.x ?? 0 }));
|
|
62
|
+
const hasRowLabels = section.seats.some((s) => s.row !== undefined && s.row !== '');
|
|
63
|
+
if (hasRowLabels) {
|
|
64
|
+
return section.rows.filter((row) => row.seats.length > 0).map((row) => toNav(row.seats));
|
|
65
|
+
}
|
|
66
|
+
const sorted = [...section.seats].sort((a, b) => (a.y ?? 0) - (b.y ?? 0));
|
|
67
|
+
if (sorted.length === 0) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
// Split where the vertical step is far larger than a typical one. "Typical"
|
|
71
|
+
// is the 25th percentile rather than the median: the between-row jumps are
|
|
72
|
+
// themselves steps, and in a section with few rows they drag the median up
|
|
73
|
+
// until no jump looks unusual any more.
|
|
74
|
+
const steps = sorted.slice(1).map((seat, i) => (seat.y ?? 0) - (sorted[i].y ?? 0));
|
|
75
|
+
const threshold = Math.max(percentile(steps, 0.25) * 4, 1);
|
|
76
|
+
const bands = [[sorted[0]]];
|
|
77
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
78
|
+
const gap = (sorted[i].y ?? 0) - (sorted[i - 1].y ?? 0);
|
|
79
|
+
if (gap > threshold) {
|
|
80
|
+
bands.push([]);
|
|
81
|
+
}
|
|
82
|
+
bands[bands.length - 1].push(sorted[i]);
|
|
83
|
+
}
|
|
84
|
+
return bands.map(toNav);
|
|
85
|
+
}
|
|
86
|
+
/** The seat in `band` whose ordinal is closest to `from`'s — vertical movement. */
|
|
87
|
+
function nearest(band, from) {
|
|
88
|
+
if (!band || band.length === 0) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
let best = band[0];
|
|
92
|
+
let bestDistance = Math.abs(best.ordinal - from.ordinal);
|
|
93
|
+
for (const candidate of band.slice(1)) {
|
|
94
|
+
const distance = Math.abs(candidate.ordinal - from.ordinal);
|
|
95
|
+
if (distance < bestDistance) {
|
|
96
|
+
best = candidate;
|
|
97
|
+
bestDistance = distance;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return best.id;
|
|
101
|
+
}
|
|
102
|
+
function percentile(values, fraction) {
|
|
103
|
+
if (values.length === 0) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
107
|
+
return sorted[Math.min(Math.floor(sorted.length * fraction), sorted.length - 1)];
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=navigation-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-order.js","sourceRoot":"","sources":["../../src/render/navigation-order.ts"],"names":[],"mappings":"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"}
|