@kerusiweb/angular 2.3.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 -642
- package/fesm2022/kerusiweb-angular.mjs +94 -77
- package/fesm2022/kerusiweb-angular.mjs.map +1 -1
- package/package.json +3 -3
- package/types/kerusiweb-angular.d.ts +57 -48
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,5 +1,5 @@
|
|
|
1
1
|
import * as _kerusiweb_core from '@kerusiweb/core';
|
|
2
|
-
import { KerusiSeatContext, KerusiMap, KerusiState, KerusiSession, SeatAriaStrings, KerusiSeatmapColors, SeatStyleFn, 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
4
|
import { TemplateRef, Signal } from '@angular/core';
|
|
5
5
|
|
|
@@ -59,11 +59,8 @@ type ValidationMode =
|
|
|
59
59
|
| 'off';
|
|
60
60
|
/** Per-section rendering overrides, keyed by `Section.id`. */
|
|
61
61
|
interface SectionRenderOptions {
|
|
62
|
+
/** Leaves the section out. Its space on the canvas stays empty (D4). */
|
|
62
63
|
hidden?: boolean;
|
|
63
|
-
/** Overrides `Section.aspectRatio`. */
|
|
64
|
-
aspectRatio?: string;
|
|
65
|
-
/** Overrides the seat size for this section only. */
|
|
66
|
-
seatSize?: number;
|
|
67
64
|
/** Overrides the localized `Section.label`. */
|
|
68
65
|
label?: string;
|
|
69
66
|
}
|
|
@@ -83,8 +80,10 @@ interface SeatDisallowed {
|
|
|
83
80
|
* Renders a Kerusi seat map.
|
|
84
81
|
*
|
|
85
82
|
* Takes a `KerusiMap` and its `KerusiState` directly — no adapter, no
|
|
86
|
-
* intermediate row model.
|
|
87
|
-
*
|
|
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,
|
|
88
87
|
* every seat is keyboard-reachable and announced with its type, price, status
|
|
89
88
|
* and §4.3.4 accessibility properties, and selection is an immutable set of
|
|
90
89
|
* seat ids the caller can two-way bind.
|
|
@@ -131,17 +130,18 @@ declare class KerusiSeatmapComponent {
|
|
|
131
130
|
* of every seat in place of the stock glyph. See {@link KerusiSeatTemplateDirective}.
|
|
132
131
|
*/
|
|
133
132
|
protected readonly seatTemplate: _angular_core.Signal<KerusiSeatTemplateDirective | undefined>;
|
|
134
|
-
/** Grid cell edge, in viewBox units. */
|
|
135
|
-
readonly seatSize: _angular_core.InputSignal<number>;
|
|
136
|
-
/** Gap between grid cells, in viewBox units. */
|
|
137
|
-
readonly seatGap: _angular_core.InputSignal<number>;
|
|
138
|
-
/** Freeform viewBox width; height follows the section's aspect ratio. */
|
|
139
|
-
readonly freeformBasis: _angular_core.InputSignal<number>;
|
|
140
133
|
/**
|
|
141
|
-
* CSS pixels per
|
|
142
|
-
*
|
|
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`.
|
|
143
138
|
*/
|
|
144
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
|
+
*/
|
|
145
145
|
readonly showSectionLabels: _angular_core.InputSignal<boolean>;
|
|
146
146
|
readonly showLegend: _angular_core.InputSignal<boolean>;
|
|
147
147
|
readonly showLegendPrices: _angular_core.InputSignal<boolean>;
|
|
@@ -149,7 +149,7 @@ declare class KerusiSeatmapComponent {
|
|
|
149
149
|
readonly sectionIds: _angular_core.InputSignal<readonly string[] | undefined>;
|
|
150
150
|
readonly sectionOverrides: _angular_core.InputSignal<Readonly<Record<string, SectionRenderOptions>>>;
|
|
151
151
|
/** Statuses in which a seat may be picked. Default: `['available']`. */
|
|
152
|
-
readonly selectableStatuses: _angular_core.InputSignal<readonly ("
|
|
152
|
+
readonly selectableStatuses: _angular_core.InputSignal<readonly ("held" | "booked" | "blocked" | "available")[]>;
|
|
153
153
|
/** `auto` selects a seat's companion closure together (§4.6). */
|
|
154
154
|
readonly companionMode: _angular_core.InputSignal<"auto" | "independent">;
|
|
155
155
|
readonly maxSelection: _angular_core.InputSignal<number | undefined>;
|
|
@@ -231,8 +231,14 @@ declare class KerusiSeatmapComponent {
|
|
|
231
231
|
protected readonly showToolbar: _angular_core.Signal<boolean>;
|
|
232
232
|
protected readonly atMaxZoom: _angular_core.Signal<boolean>;
|
|
233
233
|
protected readonly atFit: _angular_core.Signal<boolean>;
|
|
234
|
-
/**
|
|
235
|
-
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>;
|
|
236
242
|
/** Navigation graphs per section — arrows move within, Tab moves between. */
|
|
237
243
|
private readonly graphs;
|
|
238
244
|
protected readonly ariaLabels: _angular_core.Signal<ReadonlyMap<string, string>>;
|
|
@@ -241,17 +247,15 @@ declare class KerusiSeatmapComponent {
|
|
|
241
247
|
protected readonly liveMessage: _angular_core.Signal<string>;
|
|
242
248
|
/** The selection's seats and total, for callers that want it off the template. */
|
|
243
249
|
readonly summary: _angular_core.Signal<_kerusiweb_core.SelectionSummary>;
|
|
244
|
-
protected layoutFor(section: RenderSection): SectionLayout;
|
|
245
250
|
protected labelFor(section: RenderSection): string | undefined;
|
|
246
|
-
protected labelId(section: RenderSection): string;
|
|
247
251
|
/** The seat holding this section's tab stop. */
|
|
248
252
|
protected focusedSeatIn(section: RenderSection): string | null;
|
|
249
253
|
protected onSeatActivate(seatId: string): void;
|
|
250
254
|
protected onSeatFocused(seatId: string): void;
|
|
251
255
|
/**
|
|
252
|
-
* Arrow keys walk the navigation graph, which
|
|
253
|
-
*
|
|
254
|
-
*
|
|
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).
|
|
255
259
|
*/
|
|
256
260
|
protected onKeydown(section: RenderSection, event: KeyboardEvent): void;
|
|
257
261
|
private setFocusedSeat;
|
|
@@ -272,8 +276,15 @@ declare class KerusiSeatmapComponent {
|
|
|
272
276
|
zoomIn(): void;
|
|
273
277
|
/** Zooms out one step about the centre. No-op unless `zoomable`. */
|
|
274
278
|
zoomOut(): void;
|
|
275
|
-
/** Back to fit-to-container: the
|
|
279
|
+
/** Back to fit-to-container: the whole canvas. No-op unless `zoomable`. */
|
|
276
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;
|
|
277
288
|
private stepZoom;
|
|
278
289
|
/** Sizes in CSS pixels, read when needed: `offset*` ignores the zoom transform. */
|
|
279
290
|
private measure;
|
|
@@ -309,23 +320,32 @@ declare class KerusiSeatmapComponent {
|
|
|
309
320
|
private announce;
|
|
310
321
|
private visibleSectionIds;
|
|
311
322
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiSeatmapComponent, never>;
|
|
312
|
-
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; }; "
|
|
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>;
|
|
313
324
|
}
|
|
314
325
|
|
|
315
326
|
/**
|
|
316
|
-
* Draws one Kerusi `Section` as a
|
|
327
|
+
* Draws one Kerusi `Section` as a `<g>` on the map's shared canvas (D1).
|
|
317
328
|
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
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.
|
|
323
335
|
*
|
|
324
336
|
* This component holds no state. It takes a placed layout and emits intent.
|
|
325
337
|
*/
|
|
326
338
|
declare class KerusiSectionComponent {
|
|
327
|
-
|
|
328
|
-
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>;
|
|
329
349
|
/** Currently selected seat ids. */
|
|
330
350
|
readonly selection: _angular_core.InputSignal<ReadonlySet<string>>;
|
|
331
351
|
/** The seat holding the section's single tab stop, if any. */
|
|
@@ -343,22 +363,12 @@ declare class KerusiSectionComponent {
|
|
|
343
363
|
readonly seatTemplate: _angular_core.InputSignal<TemplateRef<SeatTemplateOutletContext> | undefined>;
|
|
344
364
|
/** When false, seats render but do not respond to pointer or keyboard. */
|
|
345
365
|
readonly interactive: _angular_core.InputSignal<boolean>;
|
|
346
|
-
/**
|
|
347
|
-
* CSS pixels per viewBox unit, at the section's natural size.
|
|
348
|
-
*
|
|
349
|
-
* Without a cap every section stretches to the full container width, so in a
|
|
350
|
-
* four-tier theatre the narrow box row would draw seats several times the
|
|
351
|
-
* size of the orchestra's. Capping each section at its own intrinsic width
|
|
352
|
-
* keeps a seat the same size everywhere; a section too wide to fit still
|
|
353
|
-
* scales down to the container.
|
|
354
|
-
*/
|
|
355
|
-
readonly unitScale: _angular_core.InputSignal<number>;
|
|
356
366
|
readonly seatActivate: _angular_core.OutputEmitterRef<string>;
|
|
357
367
|
readonly seatFocused: _angular_core.OutputEmitterRef<string>;
|
|
358
368
|
readonly seatKeydown: _angular_core.OutputEmitterRef<KeyboardEvent>;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
protected readonly
|
|
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>;
|
|
362
372
|
/**
|
|
363
373
|
* Every seat with its glyph resolved, once per change of layout, selection or
|
|
364
374
|
* theme rather than once per binding per change detection.
|
|
@@ -368,7 +378,6 @@ declare class KerusiSectionComponent {
|
|
|
368
378
|
selected: boolean;
|
|
369
379
|
glyph: _kerusiweb_core.SeatGlyph;
|
|
370
380
|
}[]>;
|
|
371
|
-
protected backdrop(): string;
|
|
372
381
|
/** The section's single tab stop; every other seat is reachable by arrow key. */
|
|
373
382
|
protected tabIndex(placed: PlacedSeat): number;
|
|
374
383
|
protected ariaLabel(placed: PlacedSeat): string;
|
|
@@ -390,7 +399,7 @@ declare class KerusiSectionComponent {
|
|
|
390
399
|
protected onSeatFocus(placed: PlacedSeat): void;
|
|
391
400
|
protected onKeydown(event: KeyboardEvent): void;
|
|
392
401
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KerusiSectionComponent, never>;
|
|
393
|
-
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>;
|
|
394
403
|
}
|
|
395
404
|
|
|
396
405
|
/** Which marks, beyond the body fill, a status swatch draws. */
|