@kerusiweb/angular 2.2.0 → 3.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 -22
- package/README.md +673 -421
- package/fesm2022/kerusiweb-angular.mjs +187 -201
- package/fesm2022/kerusiweb-angular.mjs.map +1 -1
- package/package.json +3 -3
- package/types/kerusiweb-angular.d.ts +140 -102
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kerusiweb/angular",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "An Angular seat-map component that renders Kerusi Seat Map & Availability Format documents as interactive, accessible inline SVG.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"author": "Arsyad \"Shad Ahm\" Ahmad",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "https://github.com/ShadAhm/kerusiweb.git",
|
|
23
|
+
"url": "git+https://github.com/ShadAhm/kerusiweb.git",
|
|
24
24
|
"directory": "projects/angular"
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/ShadAhm/kerusiweb",
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@angular/common": "^22.1.0",
|
|
29
29
|
"@angular/core": "^22.1.0",
|
|
30
|
-
"@kerusiweb/core": "^
|
|
30
|
+
"@kerusiweb/core": "^3.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"tslib": "^2.3.0"
|
|
@@ -1,7 +1,53 @@
|
|
|
1
1
|
import * as _kerusiweb_core from '@kerusiweb/core';
|
|
2
|
-
import { KerusiMap, KerusiState, KerusiSession, SeatAriaStrings, KerusiSeatmapColors, RenderSeat, KerusiControlStrings, DisallowedReason, KerusiViolation, KerusiViewport, RenderMap,
|
|
2
|
+
import { KerusiSeatContext, KerusiMap, KerusiState, KerusiSession, SeatAriaStrings, KerusiSeatmapColors, SeatStyleFn, RenderSeat, KerusiControlStrings, DisallowedReason, KerusiViolation, KerusiViewport, RenderMap, MapLayout, RenderSection, PlacedSection, PlacedSeat, PlacedElement, RenderLegendEntry, SeatOccupantVariant, SequenceReader, HeldSeat, KerusiStateDelta, DeltaApplication } from '@kerusiweb/core';
|
|
3
3
|
import * as _angular_core from '@angular/core';
|
|
4
|
-
import { Signal } from '@angular/core';
|
|
4
|
+
import { TemplateRef, Signal } from '@angular/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What a `kerusiSeat` template is handed for each seat (`let-seat`): the seat,
|
|
8
|
+
* whether it is selected, the stock glyph core resolved for it, and the stock
|
|
9
|
+
* drawing itself.
|
|
10
|
+
*/
|
|
11
|
+
interface SeatTemplateContext extends KerusiSeatContext {
|
|
12
|
+
/**
|
|
13
|
+
* The library's own drawing of this seat. Render it to keep the stock seat,
|
|
14
|
+
* or alongside your own marks to add to it:
|
|
15
|
+
*
|
|
16
|
+
* ```html
|
|
17
|
+
* <ng-container *ngTemplateOutlet="seat.defaultContent; context: { $implicit: seat }" />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
defaultContent: TemplateRef<SeatTemplateOutletContext>;
|
|
21
|
+
}
|
|
22
|
+
/** The context object a seat template is stamped with. */
|
|
23
|
+
interface SeatTemplateOutletContext {
|
|
24
|
+
$implicit: SeatTemplateContext;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Marks an `<ng-template>` inside `<kerusi-seatmap>` as the drawing for every
|
|
28
|
+
* seat. The library keeps each seat's `<g>`, with its role, ARIA state, tab
|
|
29
|
+
* stop, rotation and event handlers, and stamps this template inside it.
|
|
30
|
+
*
|
|
31
|
+
* The template is declared outside any `<svg>`, so Angular cannot tell its
|
|
32
|
+
* elements are SVG: prefix each one with `svg:` (`<svg:path>`, `<svg:image>`),
|
|
33
|
+
* or it is created as an unknown HTML element and draws nothing.
|
|
34
|
+
*
|
|
35
|
+
* ```html
|
|
36
|
+
* <kerusi-seatmap [map]="map">
|
|
37
|
+
* <ng-template kerusiSeat let-seat>
|
|
38
|
+
* <ng-container *ngTemplateOutlet="seat.defaultContent; context: { $implicit: seat }" />
|
|
39
|
+
* <svg:circle [attr.cx]="seat.glyph.box.x" [attr.cy]="seat.glyph.box.y" r="3" />
|
|
40
|
+
* </ng-template>
|
|
41
|
+
* </kerusi-seatmap>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare class KerusiSeatTemplateDirective {
|
|
45
|
+
readonly template: TemplateRef<SeatTemplateOutletContext>;
|
|
46
|
+
/** Types `let-seat` as a {@link SeatTemplateContext}. */
|
|
47
|
+
static ngTemplateContextGuard(_dir: KerusiSeatTemplateDirective, ctx: unknown): ctx is SeatTemplateOutletContext;
|
|
48
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiSeatTemplateDirective, never>;
|
|
49
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KerusiSeatTemplateDirective, "ng-template[kerusiSeat]", never, {}, {}, never, never, true, never>;
|
|
50
|
+
}
|
|
5
51
|
|
|
6
52
|
/** How a document with validation errors is handled. */
|
|
7
53
|
type ValidationMode =
|
|
@@ -13,11 +59,8 @@ type ValidationMode =
|
|
|
13
59
|
| 'off';
|
|
14
60
|
/** Per-section rendering overrides, keyed by `Section.id`. */
|
|
15
61
|
interface SectionRenderOptions {
|
|
62
|
+
/** Leaves the section out. Its space on the canvas stays empty (D4). */
|
|
16
63
|
hidden?: boolean;
|
|
17
|
-
/** Overrides `Section.aspectRatio`. */
|
|
18
|
-
aspectRatio?: string;
|
|
19
|
-
/** Overrides the seat size for this section only. */
|
|
20
|
-
seatSize?: number;
|
|
21
64
|
/** Overrides the localized `Section.label`. */
|
|
22
65
|
label?: string;
|
|
23
66
|
}
|
|
@@ -37,8 +80,10 @@ interface SeatDisallowed {
|
|
|
37
80
|
* Renders a Kerusi seat map.
|
|
38
81
|
*
|
|
39
82
|
* Takes a `KerusiMap` and its `KerusiState` directly — no adapter, no
|
|
40
|
-
* intermediate row model.
|
|
41
|
-
*
|
|
83
|
+
* intermediate row model. The map is one `<svg>` whose `viewBox` is the
|
|
84
|
+
* document's canvas (§4.5), each `Section` is a group on it, every seat is
|
|
85
|
+
* drawn exactly where and as large as the document says, seats take their
|
|
86
|
+
* color from the map's legend,
|
|
42
87
|
* every seat is keyboard-reachable and announced with its type, price, status
|
|
43
88
|
* and §4.3.4 accessibility properties, and selection is an immutable set of
|
|
44
89
|
* seat ids the caller can two-way bind.
|
|
@@ -69,17 +114,34 @@ declare class KerusiSeatmapComponent {
|
|
|
69
114
|
readonly colors: _angular_core.InputSignal<KerusiSeatmapColors>;
|
|
70
115
|
/** Let an available seat take its `SeatType.color` (§4.7). */
|
|
71
116
|
readonly typeColors: _angular_core.InputSignal<boolean>;
|
|
72
|
-
/** Grid cell edge, in viewBox units. */
|
|
73
|
-
readonly seatSize: _angular_core.InputSignal<number>;
|
|
74
|
-
/** Gap between grid cells, in viewBox units. */
|
|
75
|
-
readonly seatGap: _angular_core.InputSignal<number>;
|
|
76
|
-
/** Freeform viewBox width; height follows the section's aspect ratio. */
|
|
77
|
-
readonly freeformBasis: _angular_core.InputSignal<number>;
|
|
78
117
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
118
|
+
* Styles for every seat of a type, keyed by `SeatType.id`: fill, label colour
|
|
119
|
+
* and classes. Never changes a selected or blocked seat's fill. Also shown in
|
|
120
|
+
* the legend.
|
|
121
|
+
*/
|
|
122
|
+
readonly seatTypeStyles: _angular_core.InputSignal<Readonly<Record<string, _kerusiweb_core.KerusiSeatStyle>> | undefined>;
|
|
123
|
+
/**
|
|
124
|
+
* A style for one seat, laid over its `seatTypeStyles` entry; return nothing
|
|
125
|
+
* to leave a seat be. Never changes a selected or blocked seat's fill.
|
|
126
|
+
*/
|
|
127
|
+
readonly seatStyle: _angular_core.InputSignal<SeatStyleFn | undefined>;
|
|
128
|
+
/**
|
|
129
|
+
* A `<ng-template kerusiSeat let-seat>` placed inside the map draws the inside
|
|
130
|
+
* of every seat in place of the stock glyph. See {@link KerusiSeatTemplateDirective}.
|
|
131
|
+
*/
|
|
132
|
+
protected readonly seatTemplate: _angular_core.Signal<KerusiSeatTemplateDirective | undefined>;
|
|
133
|
+
/**
|
|
134
|
+
* CSS pixels per canvas unit, at most: the map never draws wider than
|
|
135
|
+
* `canvas.width × unitScale`, and scales down to a narrower container. The
|
|
136
|
+
* document fixes every seat's size and position (§4.5); this is the only
|
|
137
|
+
* sizing control. Default `1`.
|
|
81
138
|
*/
|
|
82
139
|
readonly unitScale: _angular_core.InputSignal<number>;
|
|
140
|
+
/**
|
|
141
|
+
* Draws each section's label inside the map, at the top-left of its `bounds`.
|
|
142
|
+
* Only sections that declare `bounds` get one; every section's label is its
|
|
143
|
+
* group's accessible name either way. Default `true`.
|
|
144
|
+
*/
|
|
83
145
|
readonly showSectionLabels: _angular_core.InputSignal<boolean>;
|
|
84
146
|
readonly showLegend: _angular_core.InputSignal<boolean>;
|
|
85
147
|
readonly showLegendPrices: _angular_core.InputSignal<boolean>;
|
|
@@ -87,7 +149,7 @@ declare class KerusiSeatmapComponent {
|
|
|
87
149
|
readonly sectionIds: _angular_core.InputSignal<readonly string[] | undefined>;
|
|
88
150
|
readonly sectionOverrides: _angular_core.InputSignal<Readonly<Record<string, SectionRenderOptions>>>;
|
|
89
151
|
/** Statuses in which a seat may be picked. Default: `['available']`. */
|
|
90
|
-
readonly selectableStatuses: _angular_core.InputSignal<readonly ("held" | "booked" | "
|
|
152
|
+
readonly selectableStatuses: _angular_core.InputSignal<readonly ("held" | "booked" | "blocked" | "available")[]>;
|
|
91
153
|
/** `auto` selects a seat's companion closure together (§4.6). */
|
|
92
154
|
readonly companionMode: _angular_core.InputSignal<"auto" | "independent">;
|
|
93
155
|
readonly maxSelection: _angular_core.InputSignal<number | undefined>;
|
|
@@ -169,8 +231,14 @@ declare class KerusiSeatmapComponent {
|
|
|
169
231
|
protected readonly showToolbar: _angular_core.Signal<boolean>;
|
|
170
232
|
protected readonly atMaxZoom: _angular_core.Signal<boolean>;
|
|
171
233
|
protected readonly atFit: _angular_core.Signal<boolean>;
|
|
172
|
-
/**
|
|
173
|
-
protected readonly
|
|
234
|
+
/** Every seat and element placed on the canvas, mirrored as a whole in RTL (D3). */
|
|
235
|
+
protected readonly layout: _angular_core.Signal<MapLayout>;
|
|
236
|
+
protected readonly viewBox: _angular_core.Signal<string>;
|
|
237
|
+
/** `unitScale` CSS pixels per canvas unit, at most. */
|
|
238
|
+
protected readonly naturalWidth: _angular_core.Signal<number>;
|
|
239
|
+
/** The canvas's width over its height, so a maximized map can fit the whole canvas. */
|
|
240
|
+
protected readonly canvasAspect: _angular_core.Signal<string>;
|
|
241
|
+
protected readonly backdrop: _angular_core.Signal<string>;
|
|
174
242
|
/** Navigation graphs per section — arrows move within, Tab moves between. */
|
|
175
243
|
private readonly graphs;
|
|
176
244
|
protected readonly ariaLabels: _angular_core.Signal<ReadonlyMap<string, string>>;
|
|
@@ -179,17 +247,15 @@ declare class KerusiSeatmapComponent {
|
|
|
179
247
|
protected readonly liveMessage: _angular_core.Signal<string>;
|
|
180
248
|
/** The selection's seats and total, for callers that want it off the template. */
|
|
181
249
|
readonly summary: _angular_core.Signal<_kerusiweb_core.SelectionSummary>;
|
|
182
|
-
protected layoutFor(section: RenderSection): SectionLayout;
|
|
183
250
|
protected labelFor(section: RenderSection): string | undefined;
|
|
184
|
-
protected labelId(section: RenderSection): string;
|
|
185
251
|
/** The seat holding this section's tab stop. */
|
|
186
252
|
protected focusedSeatIn(section: RenderSection): string | null;
|
|
187
253
|
protected onSeatActivate(seatId: string): void;
|
|
188
254
|
protected onSeatFocused(seatId: string): void;
|
|
189
255
|
/**
|
|
190
|
-
* Arrow keys walk the navigation graph, which
|
|
191
|
-
*
|
|
192
|
-
*
|
|
256
|
+
* Arrow keys walk the navigation graph, which follows §4.3.5 adjacency:
|
|
257
|
+
* along a row by `col`, across an aisle (a skipped `col`) rather than into
|
|
258
|
+
* it, and between rows to the seat nearest on the canvas (D6).
|
|
193
259
|
*/
|
|
194
260
|
protected onKeydown(section: RenderSection, event: KeyboardEvent): void;
|
|
195
261
|
private setFocusedSeat;
|
|
@@ -210,8 +276,15 @@ declare class KerusiSeatmapComponent {
|
|
|
210
276
|
zoomIn(): void;
|
|
211
277
|
/** Zooms out one step about the centre. No-op unless `zoomable`. */
|
|
212
278
|
zoomOut(): void;
|
|
213
|
-
/** Back to fit-to-container: the
|
|
279
|
+
/** Back to fit-to-container: the whole canvas. No-op unless `zoomable`. */
|
|
214
280
|
resetZoom(): void;
|
|
281
|
+
/**
|
|
282
|
+
* Zooms to one section: its declared `bounds`, or the box around its seats
|
|
283
|
+
* and elements when it declares none. No-op unless `zoomable`, or for a
|
|
284
|
+
* section that is not rendered.
|
|
285
|
+
*/
|
|
286
|
+
zoomToSection(sectionId: string): void;
|
|
287
|
+
private zoomToCanvasRect;
|
|
215
288
|
private stepZoom;
|
|
216
289
|
/** Sizes in CSS pixels, read when needed: `offset*` ignores the zoom transform. */
|
|
217
290
|
private measure;
|
|
@@ -247,23 +320,32 @@ declare class KerusiSeatmapComponent {
|
|
|
247
320
|
private announce;
|
|
248
321
|
private visibleSectionIds;
|
|
249
322
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiSeatmapComponent, never>;
|
|
250
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiSeatmapComponent, "kerusi-seatmap", never, { "map": { "alias": "map"; "required": true; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "session": { "alias": "session"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "rtl": { "alias": "rtl"; "required": false; "isSignal": true; }; "ariaStrings": { "alias": "ariaStrings"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "typeColors": { "alias": "typeColors"; "required": false; "isSignal": true; }; "
|
|
323
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiSeatmapComponent, "kerusi-seatmap", never, { "map": { "alias": "map"; "required": true; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "session": { "alias": "session"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "rtl": { "alias": "rtl"; "required": false; "isSignal": true; }; "ariaStrings": { "alias": "ariaStrings"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "typeColors": { "alias": "typeColors"; "required": false; "isSignal": true; }; "seatTypeStyles": { "alias": "seatTypeStyles"; "required": false; "isSignal": true; }; "seatStyle": { "alias": "seatStyle"; "required": false; "isSignal": true; }; "unitScale": { "alias": "unitScale"; "required": false; "isSignal": true; }; "showSectionLabels": { "alias": "showSectionLabels"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "showLegendPrices": { "alias": "showLegendPrices"; "required": false; "isSignal": true; }; "sectionIds": { "alias": "sectionIds"; "required": false; "isSignal": true; }; "sectionOverrides": { "alias": "sectionOverrides"; "required": false; "isSignal": true; }; "selectableStatuses": { "alias": "selectableStatuses"; "required": false; "isSignal": true; }; "companionMode": { "alias": "companionMode"; "required": false; "isSignal": true; }; "maxSelection": { "alias": "maxSelection"; "required": false; "isSignal": true; }; "seatSelectable": { "alias": "seatSelectable"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "expireHolds": { "alias": "expireHolds"; "required": false; "isSignal": true; }; "expiryIntervalMs": { "alias": "expiryIntervalMs"; "required": false; "isSignal": true; }; "zoomable": { "alias": "zoomable"; "required": false; "isSignal": true; }; "maxZoom": { "alias": "maxZoom"; "required": false; "isSignal": true; }; "showZoomControls": { "alias": "showZoomControls"; "required": false; "isSignal": true; }; "maximizable": { "alias": "maximizable"; "required": false; "isSignal": true; }; "controlStrings": { "alias": "controlStrings"; "required": false; "isSignal": true; }; "validate": { "alias": "validate"; "required": false; "isSignal": true; }; }, { "selection": "selectionChange"; "seatSelect": "seatSelect"; "seatDeselect": "seatDeselect"; "seatDisallowed": "seatDisallowed"; "seatFocus": "seatFocus"; "validationIssues": "validationIssues"; "viewportChange": "viewportChange"; "maximizedChange": "maximizedChange"; }, ["seatTemplate"], never, true, never>;
|
|
251
324
|
}
|
|
252
325
|
|
|
253
326
|
/**
|
|
254
|
-
* Draws one Kerusi `Section` as a
|
|
327
|
+
* Draws one Kerusi `Section` as a `<g>` on the map's shared canvas (D1).
|
|
255
328
|
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
329
|
+
* Sections are zones on one canvas in rev 15 (§4.1), and two may sit side by
|
|
330
|
+
* side, so a section is a group inside the map's single `<svg>` rather than an
|
|
331
|
+
* SVG of its own. Use it on a `<g>` inside an `<svg>` whose `viewBox` is the
|
|
332
|
+
* canvas: `<g kerusi-section [layout]="placed"></g>`. Its template prefixes
|
|
333
|
+
* every element with `svg:`, because Angular cannot tell from a component's
|
|
334
|
+
* own template that it will be stamped into SVG.
|
|
261
335
|
*
|
|
262
336
|
* This component holds no state. It takes a placed layout and emits intent.
|
|
263
337
|
*/
|
|
264
338
|
declare class KerusiSectionComponent {
|
|
265
|
-
|
|
266
|
-
readonly layout: _angular_core.InputSignal<
|
|
339
|
+
/** The section with its seats and elements placed on the map's canvas. */
|
|
340
|
+
readonly layout: _angular_core.InputSignal<PlacedSection>;
|
|
341
|
+
/** The section's name: its accessible name, and its drawn label when one is shown. */
|
|
342
|
+
readonly label: _angular_core.InputSignal<string | undefined>;
|
|
343
|
+
/**
|
|
344
|
+
* Draw `label` inside the SVG, at the top-left of the section's bounds. Only
|
|
345
|
+
* a section that declares `bounds` gets one (D5); otherwise the label is the
|
|
346
|
+
* group's accessible name alone.
|
|
347
|
+
*/
|
|
348
|
+
readonly showLabel: _angular_core.InputSignal<boolean>;
|
|
267
349
|
/** Currently selected seat ids. */
|
|
268
350
|
readonly selection: _angular_core.InputSignal<ReadonlySet<string>>;
|
|
269
351
|
/** The seat holding the section's single tab stop, if any. */
|
|
@@ -273,80 +355,32 @@ declare class KerusiSectionComponent {
|
|
|
273
355
|
readonly colors: _angular_core.InputSignal<Required<KerusiSeatmapColors>>;
|
|
274
356
|
/** Whether an available seat may take its `SeatType.color` (§4.7). */
|
|
275
357
|
readonly typeColors: _angular_core.InputSignal<boolean>;
|
|
358
|
+
/** Styles for every seat of a type, keyed by `SeatType.id`. */
|
|
359
|
+
readonly seatTypeStyles: _angular_core.InputSignal<Readonly<Record<string, _kerusiweb_core.KerusiSeatStyle>> | undefined>;
|
|
360
|
+
/** A style for one seat, laid over its type's. */
|
|
361
|
+
readonly seatStyle: _angular_core.InputSignal<SeatStyleFn | undefined>;
|
|
362
|
+
/** Draws the inside of each seat in place of the stock glyph. */
|
|
363
|
+
readonly seatTemplate: _angular_core.InputSignal<TemplateRef<SeatTemplateOutletContext> | undefined>;
|
|
276
364
|
/** When false, seats render but do not respond to pointer or keyboard. */
|
|
277
365
|
readonly interactive: _angular_core.InputSignal<boolean>;
|
|
278
|
-
/**
|
|
279
|
-
* CSS pixels per viewBox unit, at the section's natural size.
|
|
280
|
-
*
|
|
281
|
-
* Without a cap every section stretches to the full container width, so in a
|
|
282
|
-
* four-tier theatre the narrow box row would draw seats several times the
|
|
283
|
-
* size of the orchestra's. Capping each section at its own intrinsic width
|
|
284
|
-
* keeps a seat the same size everywhere; a section too wide to fit still
|
|
285
|
-
* scales down to the container.
|
|
286
|
-
*/
|
|
287
|
-
readonly unitScale: _angular_core.InputSignal<number>;
|
|
288
366
|
readonly seatActivate: _angular_core.OutputEmitterRef<string>;
|
|
289
367
|
readonly seatFocused: _angular_core.OutputEmitterRef<string>;
|
|
290
368
|
readonly seatKeydown: _angular_core.OutputEmitterRef<KeyboardEvent>;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
protected readonly
|
|
294
|
-
protected isSelected(placed: PlacedSeat): boolean;
|
|
295
|
-
protected fill(placed: PlacedSeat): string;
|
|
296
|
-
protected textFill(placed: PlacedSeat): string;
|
|
297
|
-
protected backdrop(): string;
|
|
298
|
-
/** The seat's outline: square-ish front, tapered back — shape carries facing. */
|
|
299
|
-
protected bodyPath(placed: PlacedSeat): string;
|
|
300
|
-
/** `null` for an available or blocked seat — nothing to mark. */
|
|
301
|
-
protected occupantVariant(placed: PlacedSeat): SeatOccupantVariant | null;
|
|
302
|
-
/**
|
|
303
|
-
* The box a seat's decorative marks are drawn to: the seat's own, or — when
|
|
304
|
-
* it is selected — the core plate's, which is inset by the frame width.
|
|
305
|
-
*
|
|
306
|
-
* Everything over a selected seat sits on the core, so it all has to be
|
|
307
|
-
* measured from the core. Drawing to the seat's box instead leaves the
|
|
308
|
-
* occupant's hips crossing the frame, where a figure tinted `selectedBg`
|
|
309
|
-
* lands on a frame filled `selectedBg` and reads as a hard nub. Since the
|
|
310
|
-
* core is an exact scaled copy of the body (see {@link seatSelectedFrame}),
|
|
311
|
-
* routing through here reproduces every clearance the mark had against the
|
|
312
|
-
* body, scaled — so the frame width stays free to change.
|
|
313
|
-
*/
|
|
314
|
-
private markBox;
|
|
315
|
-
/** The bright plate inside a selected seat's frame. */
|
|
316
|
-
protected corePath(placed: PlacedSeat): string;
|
|
317
|
-
protected coreFill(): string;
|
|
318
|
-
/** The dimming wash over a held or booked seat's type colour. */
|
|
319
|
-
protected washFill(placed: PlacedSeat): string;
|
|
320
|
-
/** The occupant figure for a marked seat, sized to whatever it sits on. */
|
|
321
|
-
protected occupantPath(placed: PlacedSeat): string;
|
|
322
|
-
protected occupantStroke(placed: PlacedSeat): number;
|
|
323
|
-
protected wheelchairCx(placed: PlacedSeat): number;
|
|
324
|
-
protected wheelchairCy(placed: PlacedSeat): number;
|
|
325
|
-
protected wheelchairRadius(placed: PlacedSeat): number;
|
|
369
|
+
/** Whether the label is drawn: asked for, present, and with declared bounds to sit in. */
|
|
370
|
+
protected readonly drawsLabel: _angular_core.Signal<boolean>;
|
|
371
|
+
protected readonly labelFill: _angular_core.Signal<string>;
|
|
326
372
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
* The label is centred on the occupant's shoulder line, so without this it is
|
|
331
|
-
* `selectedBg` over a `selectedBg` silhouette — the figure, not the plate, is
|
|
332
|
-
* what it actually has to contrast against. The halo also rescues a label too
|
|
333
|
-
* long for the core, which would otherwise run onto the frame and vanish into
|
|
334
|
-
* it.
|
|
335
|
-
*
|
|
336
|
-
* Bound here rather than in the stylesheet on purpose: a CSS
|
|
337
|
-
* `var(--kerusi-selected-fg, …)` rule would carry the library default as its
|
|
338
|
-
* fallback and silently skip the `[colors]` input tier, which only the
|
|
339
|
-
* TypeScript side can resolve.
|
|
373
|
+
* Every seat with its glyph resolved, once per change of layout, selection or
|
|
374
|
+
* theme rather than once per binding per change detection.
|
|
340
375
|
*/
|
|
341
|
-
protected
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
376
|
+
protected readonly seats: _angular_core.Signal<{
|
|
377
|
+
placed: PlacedSeat;
|
|
378
|
+
selected: boolean;
|
|
379
|
+
glyph: _kerusiweb_core.SeatGlyph;
|
|
380
|
+
}[]>;
|
|
346
381
|
/** The section's single tab stop; every other seat is reachable by arrow key. */
|
|
347
382
|
protected tabIndex(placed: PlacedSeat): number;
|
|
348
383
|
protected ariaLabel(placed: PlacedSeat): string;
|
|
349
|
-
protected seatClasses(placed: PlacedSeat): string;
|
|
350
384
|
/** SVG rotate() about the item's center; null when it does not rotate. */
|
|
351
385
|
protected transform(item: PlacedSeat | PlacedElement): string | null;
|
|
352
386
|
/** Cancels the parent <g>'s rotation so the label stays upright and stays put. */
|
|
@@ -365,7 +399,7 @@ declare class KerusiSectionComponent {
|
|
|
365
399
|
protected onSeatFocus(placed: PlacedSeat): void;
|
|
366
400
|
protected onKeydown(event: KeyboardEvent): void;
|
|
367
401
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiSectionComponent, never>;
|
|
368
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiSectionComponent, "kerusi-section", never, { "
|
|
402
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiSectionComponent, "g[kerusi-section]", never, { "layout": { "alias": "layout"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "showLabel": { "alias": "showLabel"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "focusedSeatId": { "alias": "focusedSeatId"; "required": false; "isSignal": true; }; "ariaLabels": { "alias": "ariaLabels"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "typeColors": { "alias": "typeColors"; "required": false; "isSignal": true; }; "seatTypeStyles": { "alias": "seatTypeStyles"; "required": false; "isSignal": true; }; "seatStyle": { "alias": "seatStyle"; "required": false; "isSignal": true; }; "seatTemplate": { "alias": "seatTemplate"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "seatActivate": "seatActivate"; "seatFocused": "seatFocused"; "seatKeydown": "seatKeydown"; }, never, never, true, never>;
|
|
369
403
|
}
|
|
370
404
|
|
|
371
405
|
/** Which marks, beyond the body fill, a status swatch draws. */
|
|
@@ -398,6 +432,8 @@ declare class KerusiLegendComponent {
|
|
|
398
432
|
readonly colors: _angular_core.InputSignal<Required<KerusiSeatmapColors>>;
|
|
399
433
|
/** Whether an available seat takes its type color — mirrors the seatmap input. */
|
|
400
434
|
readonly typeColors: _angular_core.InputSignal<boolean>;
|
|
435
|
+
/** Mirrors the seatmap input: a type's style is what its swatch shows. */
|
|
436
|
+
readonly seatTypeStyles: _angular_core.InputSignal<Readonly<Record<string, _kerusiweb_core.KerusiSeatStyle>> | undefined>;
|
|
401
437
|
readonly showPrices: _angular_core.InputSignal<boolean>;
|
|
402
438
|
/** Hide types no seat in the rendered map actually uses. */
|
|
403
439
|
readonly hideUnusedTypes: _angular_core.InputSignal<boolean>;
|
|
@@ -406,6 +442,8 @@ declare class KerusiLegendComponent {
|
|
|
406
442
|
protected readonly types: _angular_core.Signal<RenderLegendEntry[]>;
|
|
407
443
|
protected readonly statuses: _angular_core.Signal<StatusEntry[]>;
|
|
408
444
|
protected swatch(entry: RenderLegendEntry): string;
|
|
445
|
+
/** The swatch outline for a type styled with its own shape; `undefined` keeps the square. */
|
|
446
|
+
protected typeShape(entry: RenderLegendEntry): string | undefined;
|
|
409
447
|
protected swatchText(entry: RenderLegendEntry): string;
|
|
410
448
|
/** The swatch's viewBox edge; the seat glyph is drawn to fill it. */
|
|
411
449
|
protected readonly glyphSize = 16;
|
|
@@ -429,7 +467,7 @@ declare class KerusiLegendComponent {
|
|
|
429
467
|
protected coreFill(): string;
|
|
430
468
|
protected price(entry: RenderLegendEntry): string;
|
|
431
469
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiLegendComponent, never>;
|
|
432
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiLegendComponent, "kerusi-legend", never, { "legend": { "alias": "legend"; "required": true; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "typeColors": { "alias": "typeColors"; "required": false; "isSignal": true; }; "showPrices": { "alias": "showPrices"; "required": false; "isSignal": true; }; "hideUnusedTypes": { "alias": "hideUnusedTypes"; "required": false; "isSignal": true; }; "headingSeatTypes": { "alias": "headingSeatTypes"; "required": false; "isSignal": true; }; "headingAvailability": { "alias": "headingAvailability"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
470
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KerusiLegendComponent, "kerusi-legend", never, { "legend": { "alias": "legend"; "required": true; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "colors": { "alias": "colors"; "required": false; "isSignal": true; }; "typeColors": { "alias": "typeColors"; "required": false; "isSignal": true; }; "seatTypeStyles": { "alias": "seatTypeStyles"; "required": false; "isSignal": true; }; "showPrices": { "alias": "showPrices"; "required": false; "isSignal": true; }; "hideUnusedTypes": { "alias": "hideUnusedTypes"; "required": false; "isSignal": true; }; "headingSeatTypes": { "alias": "headingSeatTypes"; "required": false; "isSignal": true; }; "headingAvailability": { "alias": "headingAvailability"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
433
471
|
}
|
|
434
472
|
|
|
435
473
|
/**
|
|
@@ -478,5 +516,5 @@ declare class KerusiStateStore {
|
|
|
478
516
|
startExpiryTicker(intervalMs?: number): () => void;
|
|
479
517
|
}
|
|
480
518
|
|
|
481
|
-
export { KerusiLegendComponent, KerusiSeatmapComponent, KerusiSectionComponent, KerusiStateStore };
|
|
482
|
-
export type { SeatDisallowed, SeatInteraction, SectionRenderOptions, ValidationMode };
|
|
519
|
+
export { KerusiLegendComponent, KerusiSeatTemplateDirective, KerusiSeatmapComponent, KerusiSectionComponent, KerusiStateStore };
|
|
520
|
+
export type { SeatDisallowed, SeatInteraction, SeatTemplateContext, SeatTemplateOutletContext, SectionRenderOptions, ValidationMode };
|