ngwr 14.5.1 → 14.7.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/alert/styles/_index.scss +14 -3
- package/avatar/styles/_index.scss +90 -0
- package/cascader/styles/_rules.scss +0 -4
- package/collapse/styles/_index.scss +0 -1
- package/fesm2022/ngwr-avatar.mjs +76 -8
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper-testing.mjs +34 -3
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +245 -65
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +2 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +1 -1
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +1 -1
- package/fesm2022/ngwr-schema-form.mjs.map +1 -1
- package/fesm2022/ngwr-select-testing.mjs +21 -2
- package/fesm2022/ngwr-select-testing.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +299 -50
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/image-cropper/styles/_index.scss +7 -0
- package/input/styles/_index.scss +8 -2
- package/lightbox/styles/_rules.scss +7 -1
- package/llms-full.txt +4 -4
- package/package.json +1 -1
- package/schematics/use/symbol-map.json +1 -0
- package/select/styles/_index.scss +50 -4
- package/skills/ngwr/references/catalog.md +1 -1
- package/table/styles/_index.scss +55 -0
- package/toast/styles/_index.scss +9 -3
- package/tree/styles/_index.scss +0 -3
- package/types/ngwr-avatar.d.ts +51 -4
- package/types/ngwr-image-cropper-testing.d.ts +25 -3
- package/types/ngwr-image-cropper.d.ts +136 -2
- package/types/ngwr-select-testing.d.ts +18 -1
- package/types/ngwr-select.d.ts +238 -10
- package/types/ngwr-version.d.ts +1 -1
|
@@ -18,6 +18,45 @@ interface WrCropRect {
|
|
|
18
18
|
type WrCropHandle = 'move' | 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
|
|
19
19
|
/** Supported output MIME types for {@link WrImageCropper.toBlob}. */
|
|
20
20
|
type WrImageOutputType = 'image/png' | 'image/jpeg' | 'image/webp';
|
|
21
|
+
/**
|
|
22
|
+
* Where the cropper's source stands.
|
|
23
|
+
*
|
|
24
|
+
* - `empty` — no `src`, so the placeholder is showing.
|
|
25
|
+
* - `loading` — a `src` has been handed to the `<img>` and the browser has not
|
|
26
|
+
* answered yet.
|
|
27
|
+
* - `loaded` — the image decoded. The crop window opens once it also has a
|
|
28
|
+
* measured size, which in a browser is the same moment.
|
|
29
|
+
* - `failed` — the browser could not decode it (a renamed `.heic`, a truncated
|
|
30
|
+
* file, a URL that 404s). `(loadError)` fired with the details.
|
|
31
|
+
*/
|
|
32
|
+
type WrImageCropperStatus = 'empty' | 'loading' | 'loaded' | 'failed';
|
|
33
|
+
/**
|
|
34
|
+
* The payload of `(loadError)` — plain strings and numbers, so it can be logged,
|
|
35
|
+
* sent to an error tracker or put into a store as it is.
|
|
36
|
+
*
|
|
37
|
+
* The browser's `error` event carries no reason at all, so none is invented here:
|
|
38
|
+
* what the source DECLARED is the most a host has to work with, and for the common
|
|
39
|
+
* case (a phone photo in a format this browser cannot decode) `type` and `name`
|
|
40
|
+
* are what tell the two apart from a broken upload.
|
|
41
|
+
*/
|
|
42
|
+
interface WrImageLoadError {
|
|
43
|
+
/**
|
|
44
|
+
* The URL the `<img>` was given — the `src` string itself, or the object URL
|
|
45
|
+
* made for a `File` / `Blob`. An object URL is revoked as soon as `src` changes,
|
|
46
|
+
* so it identifies the attempt rather than being something to fetch later.
|
|
47
|
+
*/
|
|
48
|
+
readonly url: string;
|
|
49
|
+
/** `File.name` for a `File` source; `null` for a `Blob` or a string. */
|
|
50
|
+
readonly name: string | null;
|
|
51
|
+
/**
|
|
52
|
+
* The MIME type a `File` / `Blob` declares — `''` when it declares none, and
|
|
53
|
+
* `null` for a string source. A `File`'s type comes from its extension, so a
|
|
54
|
+
* renamed file declares the type of the name it was given.
|
|
55
|
+
*/
|
|
56
|
+
readonly type: string | null;
|
|
57
|
+
/** Size in bytes for a `File` / `Blob`; `null` for a string source. */
|
|
58
|
+
readonly size: number | null;
|
|
59
|
+
}
|
|
21
60
|
|
|
22
61
|
interface RectPx {
|
|
23
62
|
x: number;
|
|
@@ -37,12 +76,18 @@ interface RectPx {
|
|
|
37
76
|
* freshly-rendered `Blob` of the cropped region. For one-off reads use
|
|
38
77
|
* `toBlob()` / `toDataUrl()`.
|
|
39
78
|
*
|
|
79
|
+
* A source the browser cannot decode fires `(loadError)` once, sets `status()` to
|
|
80
|
+
* `'failed'` and puts `wr-image-cropper--failed` on the host. The component renders
|
|
81
|
+
* no message of its own for it — what went wrong and what to do next is the host's
|
|
82
|
+
* to say.
|
|
83
|
+
*
|
|
40
84
|
* @example
|
|
41
85
|
* ```html
|
|
42
86
|
* <wr-image-cropper
|
|
43
87
|
* [src]="file"
|
|
44
88
|
* [aspectRatio]="1"
|
|
45
89
|
* (cropped)="onBlob($event)"
|
|
90
|
+
* (loadError)="onUnreadable($event)"
|
|
46
91
|
* />
|
|
47
92
|
* ```
|
|
48
93
|
*
|
|
@@ -61,8 +106,23 @@ declare class WrImageCropper {
|
|
|
61
106
|
readonly outputType: _angular_core.InputSignal<WrImageOutputType>;
|
|
62
107
|
/** JPEG / WebP quality for `(cropped)` in [0, 1]. @default 0.92 */
|
|
63
108
|
readonly outputQuality: _angular_core.InputSignal<number>;
|
|
109
|
+
/**
|
|
110
|
+
* Longest side of the exported image, in pixels — for `(cropped)`, `toBlob()` and
|
|
111
|
+
* `toDataUrl()` alike. A crop larger than this is scaled down to fit, keeping its
|
|
112
|
+
* aspect ratio; a smaller one is exported as it is, never upscaled. The crop itself
|
|
113
|
+
* — `cropRect()`, in source pixels — is not affected. `null` (or anything that is
|
|
114
|
+
* not a positive number) exports at the source image's own resolution.
|
|
115
|
+
* @default null
|
|
116
|
+
*/
|
|
117
|
+
readonly maxOutputSize: _angular_core.InputSignalWithTransform<number | null, unknown>;
|
|
64
118
|
/** Emits a Blob after each drag end. */
|
|
65
119
|
readonly cropped: _angular_core.OutputEmitterRef<Blob>;
|
|
120
|
+
/**
|
|
121
|
+
* Fires once when the browser cannot decode the current `src` — a format it does
|
|
122
|
+
* not support, a broken file, a URL that fails. Nothing is rendered for it; show
|
|
123
|
+
* your own message. A new `src` clears the failure.
|
|
124
|
+
*/
|
|
125
|
+
readonly loadError: _angular_core.OutputEmitterRef<WrImageLoadError>;
|
|
66
126
|
protected readonly imgEl: _angular_core.Signal<ElementRef<HTMLImageElement>>;
|
|
67
127
|
/** Resolved object URL for `src` (so File / Blob render in `<img>`). */
|
|
68
128
|
protected readonly emptyText: _angular_core.Signal<string>;
|
|
@@ -97,7 +157,20 @@ declare class WrImageCropper {
|
|
|
97
157
|
private active;
|
|
98
158
|
private startPointer;
|
|
99
159
|
private startRect;
|
|
160
|
+
/** The element the live drag set pointer capture on, so the end releases that one. */
|
|
161
|
+
private captureTarget;
|
|
162
|
+
/** The pointer the live drag belongs to. Every other pointer's events are ignored. */
|
|
163
|
+
private pointerId;
|
|
164
|
+
/** How far past each side of the crop the live resize was pressed — see `onPointerMove`. */
|
|
165
|
+
private overhang;
|
|
100
166
|
private readonly destroyRef;
|
|
167
|
+
private readonly statusState;
|
|
168
|
+
/**
|
|
169
|
+
* Where the source stands: `'empty'`, `'loading'`, `'loaded'` or `'failed'`. Reset
|
|
170
|
+
* to `'loading'` (or `'empty'`) whenever `src` changes, so a failure never outlives
|
|
171
|
+
* the source that caused it.
|
|
172
|
+
*/
|
|
173
|
+
readonly status: _angular_core.Signal<WrImageCropperStatus>;
|
|
101
174
|
/** Resolved crop rect in natural (source) pixel coordinates. */
|
|
102
175
|
readonly cropRect: _angular_core.Signal<WrCropRect>;
|
|
103
176
|
constructor();
|
|
@@ -113,6 +186,18 @@ declare class WrImageCropper {
|
|
|
113
186
|
*/
|
|
114
187
|
private resetGeometry;
|
|
115
188
|
protected onImageLoad(): void;
|
|
189
|
+
/**
|
|
190
|
+
* The `<img>` could not decode its source.
|
|
191
|
+
*
|
|
192
|
+
* Before this handler existed a failed decode left the component exactly as it
|
|
193
|
+
* looks while loading — an image with no size, no crop window, nothing emitted —
|
|
194
|
+
* so a host had no way to tell "still decoding" from "never going to", and a user
|
|
195
|
+
* who picked a `.heic` the browser cannot read saw an empty box and no reason.
|
|
196
|
+
*
|
|
197
|
+
* Once per source: `status` is reset by a new `src` and by nothing else, so a
|
|
198
|
+
* second `error` for the same source says nothing new and is not re-emitted.
|
|
199
|
+
*/
|
|
200
|
+
protected onImageError(): void;
|
|
116
201
|
/**
|
|
117
202
|
* Keep `display` on the box the image is actually rendered at.
|
|
118
203
|
*
|
|
@@ -138,8 +223,50 @@ declare class WrImageCropper {
|
|
|
138
223
|
private initialCrop;
|
|
139
224
|
protected readonly handles: readonly WrCropHandle[];
|
|
140
225
|
protected onPointerDown(handle: WrCropHandle, event: PointerEvent): void;
|
|
226
|
+
/**
|
|
227
|
+
* A resize ENDS when the pointer leaves the image, exactly as `pointerup` would end it:
|
|
228
|
+
* the move that carried it out is applied — clamped to the image like any other — and
|
|
229
|
+
* then the drag is over. Nothing after that resumes it or changes the crop, pointer
|
|
230
|
+
* back over the image or not, until a new `pointerdown`. A move drag is not affected:
|
|
231
|
+
* its size is fixed, so it simply rests against the edge.
|
|
232
|
+
*
|
|
233
|
+
* The move that leaves is applied rather than dropped because pointer moves are
|
|
234
|
+
* SAMPLES. Dropped, a quick drag toward a corner would stop wherever its last sample
|
|
235
|
+
* inside happened to fall — a single move from a handle to past the image would change
|
|
236
|
+
* nothing at all — and even a slow one would stop a fraction of a pixel short of the
|
|
237
|
+
* edge. A drag that leaves across one edge still ends there: heading for a corner at a
|
|
238
|
+
* slant that crosses the bottom first, the crop's right edge stays where it was then.
|
|
239
|
+
*
|
|
240
|
+
* "The image" is the `<img>`'s own box — the bounds `applyMove` / `applyResize` clamp
|
|
241
|
+
* the crop to — with its edges counting as inside, since the crop may reach them. The
|
|
242
|
+
* box is re-measured on every move and compared with `clientX` / `clientY`: both are
|
|
243
|
+
* viewport coordinates, so a scroll mid-drag cannot put them out of step. The moves
|
|
244
|
+
* outside reach this handler at all only because the drag holds pointer capture.
|
|
245
|
+
*
|
|
246
|
+
* One allowance, fixed at `pointerdown`: the box is widened on each side by however far
|
|
247
|
+
* past that side of the CROP the press landed — at most as far as the pressed handle
|
|
248
|
+
* reaches past it. Half of an edge handle, and three quarters of a corner handle, lies
|
|
249
|
+
* outside the crop, so a press there already has the pointer ahead of the edge it drags.
|
|
250
|
+
* Measured without the allowance, that pointer would leave the image while the crop was
|
|
251
|
+
* still short of the image's edge by the same distance, with nothing able to close the
|
|
252
|
+
* gap; and a handle resting on the image's edge, pressed on its outer part, would begin
|
|
253
|
+
* its drag already outside. A press on a handle's inner part widens nothing.
|
|
254
|
+
*/
|
|
141
255
|
protected onPointerMove(event: PointerEvent): void;
|
|
256
|
+
/**
|
|
257
|
+
* Ends the drag — for `pointerup`, `pointercancel`, a capture lost to something else,
|
|
258
|
+
* and a resize whose pointer left the image. Once per drag: the capture released here
|
|
259
|
+
* fires `lostpointercapture` afterwards, and by then there is nothing left to end.
|
|
260
|
+
*
|
|
261
|
+
* Only for the pointer that started it. A second finger is refused a drag of its own at
|
|
262
|
+
* `pointerdown`, but its moves and its lifting reach these handlers all the same, and
|
|
263
|
+
* would otherwise drive or end the first finger's drag.
|
|
264
|
+
*/
|
|
142
265
|
protected onPointerUp(event: PointerEvent): void;
|
|
266
|
+
/** How far past each side of the crop window the pointer is, in CSS pixels. */
|
|
267
|
+
private pastCrop;
|
|
268
|
+
/** Whether the pointer is on the image, edges and the press's `overhang` included. */
|
|
269
|
+
private withinImage;
|
|
143
270
|
/** Whether a key has moved the crop since the last `keyup`. */
|
|
144
271
|
private keyboardDirty;
|
|
145
272
|
/**
|
|
@@ -176,11 +303,18 @@ declare class WrImageCropper {
|
|
|
176
303
|
toDataUrl(type?: WrImageOutputType, quality?: number): string;
|
|
177
304
|
/** Re-emit the crop without waiting for a drag (e.g. after a programmatic change). */
|
|
178
305
|
refresh(): Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* The exported image's pixel size: the crop in source pixels, scaled down so its
|
|
308
|
+
* longer side fits `maxOutputSize`. `Math.min(1, …)` is the never-upscale rule — a
|
|
309
|
+
* crop already inside the cap keeps its own size, which is also the whole of the
|
|
310
|
+
* uncapped path.
|
|
311
|
+
*/
|
|
312
|
+
private outputSize;
|
|
179
313
|
private toCanvas;
|
|
180
314
|
private emitCropped;
|
|
181
315
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrImageCropper, never>;
|
|
182
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrImageCropper, "wr-image-cropper", never, { "src": { "alias": "src"; "required": false; "isSignal": true; }; "aspectRatio": { "alias": "aspectRatio"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "outputType": { "alias": "outputType"; "required": false; "isSignal": true; }; "outputQuality": { "alias": "outputQuality"; "required": false; "isSignal": true; }; }, { "cropped": "cropped"; }, never, never, true, never>;
|
|
316
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrImageCropper, "wr-image-cropper", never, { "src": { "alias": "src"; "required": false; "isSignal": true; }; "aspectRatio": { "alias": "aspectRatio"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "outputType": { "alias": "outputType"; "required": false; "isSignal": true; }; "outputQuality": { "alias": "outputQuality"; "required": false; "isSignal": true; }; "maxOutputSize": { "alias": "maxOutputSize"; "required": false; "isSignal": true; }; }, { "cropped": "cropped"; "loadError": "loadError"; }, never, never, true, never>;
|
|
183
317
|
}
|
|
184
318
|
|
|
185
319
|
export { WrImageCropper };
|
|
186
|
-
export type { WrCropHandle, WrCropRect, WrImageOutputType };
|
|
320
|
+
export type { WrCropHandle, WrCropRect, WrImageCropperStatus, WrImageLoadError, WrImageOutputType };
|
|
@@ -51,8 +51,25 @@ declare class WrOptionHarness extends ComponentHarness {
|
|
|
51
51
|
static hostSelector: string;
|
|
52
52
|
/** Build a predicate that narrows the query. */
|
|
53
53
|
static with(options?: WrOptionHarnessFilters): HarnessPredicate<WrOptionHarness>;
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The option's text as drawn, trimmed — without its leading visual.
|
|
56
|
+
*
|
|
57
|
+
* A `wrOptionLeading` template renders INSIDE the row, so reading the whole
|
|
58
|
+
* host would hand back an avatar's initials as the first word of the name. It
|
|
59
|
+
* is excluded here for the same reason the select excludes it from the label.
|
|
60
|
+
*
|
|
61
|
+
* This is the drawn text, not the `label` input: an option whose `label` is
|
|
62
|
+
* shorter than what it draws still answers with what it draws. What the select
|
|
63
|
+
* REPORTS for it is on the select harness, as `getValueText()` or
|
|
64
|
+
* `getChipLabels()`.
|
|
65
|
+
*/
|
|
55
66
|
getText(): Promise<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Whether the row is drawing a leading visual right now. Reads the slot the
|
|
69
|
+
* select renders the template into, so it answers `false` for an option that
|
|
70
|
+
* declares a template while the panel is closed — which is the contract.
|
|
71
|
+
*/
|
|
72
|
+
hasLeading(): Promise<boolean>;
|
|
56
73
|
/** Whether the option is currently selected. */
|
|
57
74
|
isSelected(): Promise<boolean>;
|
|
58
75
|
/** Whether the option refuses selection. */
|
package/types/ngwr-select.d.ts
CHANGED
|
@@ -39,6 +39,25 @@ type WrSelectTagValidator = (value: string, existing: readonly string[]) => bool
|
|
|
39
39
|
type WrSelectSearchLoader<T> = (query: string) => Observable<readonly T[]> | Promise<readonly T[]> | readonly T[];
|
|
40
40
|
/** Control size for `<wr-select>` — shares the `--wr-control-*` contract. */
|
|
41
41
|
type WrSelectSize = 'sm' | 'md' | 'lg';
|
|
42
|
+
/**
|
|
43
|
+
* Where a `wrOptionLeading` template is being drawn:
|
|
44
|
+
*
|
|
45
|
+
* - `'option'` — the row in the open panel.
|
|
46
|
+
* - `'chip'` — a selected chip on a `mode="multi"` trigger.
|
|
47
|
+
* - `'value'` — the selected value on a single-mode trigger: beside the label on
|
|
48
|
+
* a button trigger, and before the input on a search-shaped one while that
|
|
49
|
+
* input is showing the label. One placement rather than two, because it is one
|
|
50
|
+
* surface — the same size is right on both, and splitting it would ask every
|
|
51
|
+
* consumer to name a case they do not have.
|
|
52
|
+
*/
|
|
53
|
+
type WrOptionLeadingPlacement = 'option' | 'chip' | 'value';
|
|
54
|
+
/** Template context of `<ng-template wrOptionLeading>`. */
|
|
55
|
+
interface WrOptionLeadingContext<T = unknown> {
|
|
56
|
+
/** The option's value — `let-value`. */
|
|
57
|
+
readonly $implicit: T;
|
|
58
|
+
/** Where this copy is drawn, so one template can size itself per surface. */
|
|
59
|
+
readonly placement: WrOptionLeadingPlacement;
|
|
60
|
+
}
|
|
42
61
|
|
|
43
62
|
/**
|
|
44
63
|
* @license
|
|
@@ -67,6 +86,13 @@ interface WrSelectOptionRegistration {
|
|
|
67
86
|
* registration that cannot supply an element simply keeps its place.
|
|
68
87
|
*/
|
|
69
88
|
readonly host?: HTMLElement;
|
|
89
|
+
/**
|
|
90
|
+
* The option's own `wrOptionLeading` template, when it declares one. Chips
|
|
91
|
+
* look it up by value, since a chip is drawn by the select and not by the
|
|
92
|
+
* option. Optional, like `host`: a registration without one falls back to the
|
|
93
|
+
* select's default template.
|
|
94
|
+
*/
|
|
95
|
+
readonly leading?: Signal<TemplateRef<WrOptionLeadingContext> | null>;
|
|
70
96
|
}
|
|
71
97
|
/**
|
|
72
98
|
* Contract a `<wr-option>` uses to talk to its parent `<wr-select>`.
|
|
@@ -103,6 +129,17 @@ interface WrSelectContext {
|
|
|
103
129
|
* `[serverSearch]`), in which case options must NOT self-hide.
|
|
104
130
|
*/
|
|
105
131
|
readonly clientFilter: Signal<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* Whether the panel is open. An option draws its leading visual only while it
|
|
134
|
+
* is, because projected options exist — detached — for the whole life of the
|
|
135
|
+
* select, and a template instantiated there would be every avatar at once.
|
|
136
|
+
*/
|
|
137
|
+
readonly panelOpen: Signal<boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* The select-wide `wrOptionLeading` template — one declared as a direct child
|
|
140
|
+
* of `<wr-select>` — or `null`. An option with a template of its own ignores it.
|
|
141
|
+
*/
|
|
142
|
+
readonly optionLeading: Signal<TemplateRef<WrOptionLeadingContext> | null>;
|
|
106
143
|
/** Is the given option value currently selected? Handles both single and multi. */
|
|
107
144
|
isSelected(value: unknown): boolean;
|
|
108
145
|
/**
|
|
@@ -125,6 +162,8 @@ declare const WR_SELECT: InjectionToken<WrSelectContext>;
|
|
|
125
162
|
interface SelectedChip {
|
|
126
163
|
readonly value: unknown;
|
|
127
164
|
readonly label: string;
|
|
165
|
+
/** The leading template this chip draws, or `null`. */
|
|
166
|
+
readonly leading: TemplateRef<WrOptionLeadingContext> | null;
|
|
128
167
|
}
|
|
129
168
|
/**
|
|
130
169
|
* Combobox primitive. Renders a button that opens a CDK overlay
|
|
@@ -514,6 +553,61 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
|
|
|
514
553
|
/** Id of the active option (for `aria-activedescendant`). */
|
|
515
554
|
readonly activeOptionId: _angular_core.Signal<string | null>;
|
|
516
555
|
protected readonly open: _angular_core.WritableSignal<boolean>;
|
|
556
|
+
/** WrSelectContext — whether the panel is open. Options gate their leading visual on it. */
|
|
557
|
+
readonly panelOpen: _angular_core.Signal<boolean>;
|
|
558
|
+
/**
|
|
559
|
+
* A `<ng-template wrOptionLeading>` declared as a DIRECT child of the select —
|
|
560
|
+
* `descendants: false`, so an option's own template is never mistaken for the
|
|
561
|
+
* select-wide default.
|
|
562
|
+
*/
|
|
563
|
+
private readonly defaultLeading;
|
|
564
|
+
/**
|
|
565
|
+
* WrSelectContext — the select-wide leading template, or `null`. The only
|
|
566
|
+
* way to give a leading visual to the rows the select draws itself (`[options]`,
|
|
567
|
+
* `[loader]` results, virtual rows), and the default for projected options that
|
|
568
|
+
* declare none of their own.
|
|
569
|
+
*/
|
|
570
|
+
readonly optionLeading: _angular_core.Signal<TemplateRef<WrOptionLeadingContext<unknown>> | null>;
|
|
571
|
+
/**
|
|
572
|
+
* The leading template for a value: the registered option's (its own, or the
|
|
573
|
+
* default it resolved to), else the select-wide default for a value with no
|
|
574
|
+
* registered option — a virtual row, or one a loader has since dropped.
|
|
575
|
+
*/
|
|
576
|
+
private leadingFor;
|
|
577
|
+
/**
|
|
578
|
+
* The leading visual beside the selected value on a single-mode BUTTON trigger
|
|
579
|
+
* — one instance, for the one selected value. A search-shaped trigger draws the
|
|
580
|
+
* same visual through {@link searchLeading}, on a narrower condition.
|
|
581
|
+
*/
|
|
582
|
+
protected readonly selectedLeading: _angular_core.Signal<TemplateRef<WrOptionLeadingContext<unknown>> | null>;
|
|
583
|
+
/**
|
|
584
|
+
* The same visual on a SEARCH-shaped trigger (`mode="search"`, a searchable
|
|
585
|
+
* single), drawn before the input — the surface an assignee picker actually
|
|
586
|
+
* uses, and the one that lost its avatar the moment the trigger became a field.
|
|
587
|
+
*
|
|
588
|
+
* The condition is {@link searchShowsValue} rather than `hasSelection()`, and
|
|
589
|
+
* the two part company on every open panel: focusing the field replaces the
|
|
590
|
+
* label with the live query, which starts empty, so what is on screen is the
|
|
591
|
+
* placeholder. An avatar left standing there names a value the field no longer
|
|
592
|
+
* shows, and then sits in front of whatever the user types next — the visual
|
|
593
|
+
* would be answering a different question from the text beside it. It comes
|
|
594
|
+
* back with the label, which is one signal flipping rather than two things
|
|
595
|
+
* kept in step: committing a choice clears the query and closes the panel.
|
|
596
|
+
*
|
|
597
|
+
* Nothing is instantiated for a search select with no selection, panel open or
|
|
598
|
+
* shut — `selectedLabel()` is `null` there, and this returns `null` with it.
|
|
599
|
+
*
|
|
600
|
+
* The COST of that rule, stated because it is a consumer's to weigh: stepping
|
|
601
|
+
* aside is a destroy, so opening the picker and dismissing it unchanged
|
|
602
|
+
* re-creates the visual — a template built on an `<img>` re-mounts once per
|
|
603
|
+
* round trip, and re-requests unless the cache answers. Kept rather than
|
|
604
|
+
* traded for a hidden-but-alive node: the panel's own rows already create and
|
|
605
|
+
* destroy one apiece on the same gesture, so holding this one back buys a
|
|
606
|
+
* fraction of that, and a node retained while it must not be seen is a second
|
|
607
|
+
* piece of state to keep in step with the field. Pinned in `option.spec.ts`
|
|
608
|
+
* ("re-creates it after a round trip"), so a future change here has to say so.
|
|
609
|
+
*/
|
|
610
|
+
protected readonly searchLeading: _angular_core.Signal<TemplateRef<WrOptionLeadingContext<unknown>> | null>;
|
|
517
611
|
/**
|
|
518
612
|
* Trigger label for single mode. Multi reads `selectedChips` instead.
|
|
519
613
|
*
|
|
@@ -686,6 +780,26 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
|
|
|
686
780
|
protected onSearchFocus(): void;
|
|
687
781
|
protected onSearchBlur(): void;
|
|
688
782
|
protected onSearchKey(event: KeyboardEvent): void;
|
|
783
|
+
/**
|
|
784
|
+
* Whether the search field is showing the SELECTED VALUE rather than a query.
|
|
785
|
+
* `searchDisplay` takes its text off this, and `searchLeading` the visual that
|
|
786
|
+
* goes before it, so the two can never disagree about which of the two things
|
|
787
|
+
* the field is holding.
|
|
788
|
+
*
|
|
789
|
+
* FOCUS as well as open, and that second term is the whole `[minChars]` story.
|
|
790
|
+
* Backspacing under the threshold closes the panel, and falling back to the
|
|
791
|
+
* selected label the moment `open()` goes false rewrote the field out from
|
|
792
|
+
* under someone who was still typing — "sma" -> "sm" showed an empty box.
|
|
793
|
+
*
|
|
794
|
+
* A NON-EMPTY query, though: picking an option clears it and leaves focus in
|
|
795
|
+
* the field, and there the label is what belongs on screen.
|
|
796
|
+
*
|
|
797
|
+
* Only the search-shaped trigger reads it. A searchable MULTI binds its input
|
|
798
|
+
* to `searchQuery()` directly and shows its selection as chips, which carry
|
|
799
|
+
* their own leading visuals whatever the field holds.
|
|
800
|
+
* @internal
|
|
801
|
+
*/
|
|
802
|
+
protected readonly searchShowsValue: _angular_core.Signal<boolean>;
|
|
689
803
|
/**
|
|
690
804
|
* Display text for the search input. Shows the selected option's
|
|
691
805
|
* label when collapsed, or the live query while typing / panel open.
|
|
@@ -768,19 +882,25 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
|
|
|
768
882
|
private openOverlay;
|
|
769
883
|
private closeOverlay;
|
|
770
884
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSelect, never>;
|
|
771
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSelect, "wr-select", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchQuery": { "alias": "searchQuery"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "displayWith": { "alias": "displayWith"; "required": false; "isSignal": true; }; "loader": { "alias": "loader"; "required": false; "isSignal": true; }; "serverSearch": { "alias": "serverSearch"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; "minChars": { "alias": "minChars"; "required": false; "isSignal": true; }; "freeText": { "alias": "freeText"; "required": false; "isSignal": true; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "viewportHeight": { "alias": "viewportHeight"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "noResultsText": { "alias": "noResultsText"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "separators": { "alias": "separators"; "required": false; "isSignal": true; }; "allowDuplicates": { "alias": "allowDuplicates"; "required": false; "isSignal": true; }; "validate": { "alias": "validate"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "maxItems": { "alias": "maxItems"; "required": false; "isSignal": true; }; "maxTagCount": { "alias": "maxTagCount"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "searchQuery": "searchQueryChange"; "searchChange": "searchChange"; "value": "valueChange"; "touch": "touch"; }, ["projectedOptions"], ["*"], true, never>;
|
|
885
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSelect, "wr-select", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchQuery": { "alias": "searchQuery"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "displayWith": { "alias": "displayWith"; "required": false; "isSignal": true; }; "loader": { "alias": "loader"; "required": false; "isSignal": true; }; "serverSearch": { "alias": "serverSearch"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; "minChars": { "alias": "minChars"; "required": false; "isSignal": true; }; "freeText": { "alias": "freeText"; "required": false; "isSignal": true; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "viewportHeight": { "alias": "viewportHeight"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "noResultsText": { "alias": "noResultsText"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "separators": { "alias": "separators"; "required": false; "isSignal": true; }; "allowDuplicates": { "alias": "allowDuplicates"; "required": false; "isSignal": true; }; "validate": { "alias": "validate"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "maxItems": { "alias": "maxItems"; "required": false; "isSignal": true; }; "maxTagCount": { "alias": "maxTagCount"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "searchQuery": "searchQueryChange"; "searchChange": "searchChange"; "value": "valueChange"; "touch": "touch"; }, ["defaultLeading", "projectedOptions"], ["*"], true, never>;
|
|
772
886
|
}
|
|
773
887
|
|
|
774
888
|
/**
|
|
775
889
|
* Single option inside a `<wr-select>`.
|
|
776
890
|
*
|
|
777
|
-
* The option's display label is taken from its projected text content
|
|
778
|
-
* the form value is its `value` input.
|
|
891
|
+
* The option's display label is taken from its projected text content — or
|
|
892
|
+
* from `label`, when that is set — and the form value is its `value` input. A
|
|
893
|
+
* leading visual goes in an `<ng-template wrOptionLeading>`, which keeps it out
|
|
894
|
+
* of the label and uninstantiated while the panel is closed.
|
|
779
895
|
*
|
|
780
896
|
* @example
|
|
781
897
|
* ```html
|
|
782
898
|
* <wr-option value="sm">Small</wr-option>
|
|
783
899
|
* <wr-option [value]="42">Forty-two</wr-option>
|
|
900
|
+
* <wr-option [value]="p.id" [label]="p.name">
|
|
901
|
+
* <ng-template wrOptionLeading><wr-avatar shape="circle" size="1.5rem">{{ p.initials }}</wr-avatar></ng-template>
|
|
902
|
+
* {{ p.name }}
|
|
903
|
+
* </wr-option>
|
|
784
904
|
* ```
|
|
785
905
|
*/
|
|
786
906
|
declare class WrOption {
|
|
@@ -788,10 +908,40 @@ declare class WrOption {
|
|
|
788
908
|
readonly value: _angular_core.InputSignal<unknown>;
|
|
789
909
|
/** Disable this option. @default false */
|
|
790
910
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
911
|
+
/**
|
|
912
|
+
* The text the select reports for this option — the trigger label, the chip,
|
|
913
|
+
* the chip's remove label and the search filter all read it. Unset (or empty),
|
|
914
|
+
* the option's own text is used, as it always was.
|
|
915
|
+
*
|
|
916
|
+
* Set it when the row shows more than the name: a projected email under a
|
|
917
|
+
* person, a count beside a category. It does NOT rename the row itself — the
|
|
918
|
+
* option's accessible name stays the text it draws, since a screen reader user
|
|
919
|
+
* browsing the list should hear what a sighted one reads there.
|
|
920
|
+
*
|
|
921
|
+
* @default null
|
|
922
|
+
*/
|
|
923
|
+
readonly label: _angular_core.InputSignal<string | null>;
|
|
791
924
|
/** Stable id used for `aria-activedescendant`. */
|
|
792
925
|
readonly id: string;
|
|
793
926
|
private readonly host;
|
|
794
927
|
private readonly parent;
|
|
928
|
+
/** This option's own `<ng-template wrOptionLeading>`, if it declares one. */
|
|
929
|
+
private readonly ownLeading;
|
|
930
|
+
/**
|
|
931
|
+
* The leading template that applies to this option: its own, else the
|
|
932
|
+
* select-wide default. Registered with the parent so a chip can draw it.
|
|
933
|
+
*/
|
|
934
|
+
private readonly leading;
|
|
935
|
+
/**
|
|
936
|
+
* The leading template to draw in THIS row right now — `null` while the panel
|
|
937
|
+
* is closed. A projected option is created with the page and lives, detached,
|
|
938
|
+
* for as long as the select does, so gating on the template alone would
|
|
939
|
+
* instantiate every row's avatar the moment the page renders. An option with
|
|
940
|
+
* no parent select has no panel to wait for.
|
|
941
|
+
*/
|
|
942
|
+
protected readonly rowLeading: Signal<TemplateRef<WrOptionLeadingContext<unknown>> | null>;
|
|
943
|
+
/** The wrapper the leading visual renders into — skipped when reading the text. */
|
|
944
|
+
private readonly leadingSlot;
|
|
795
945
|
/**
|
|
796
946
|
* The option's own text, as a signal — the parent's trigger label and the
|
|
797
947
|
* client-side filter both read it from here.
|
|
@@ -815,7 +965,12 @@ declare class WrOption {
|
|
|
815
965
|
* @internal
|
|
816
966
|
*/
|
|
817
967
|
private readonly labelText;
|
|
818
|
-
|
|
968
|
+
/**
|
|
969
|
+
* `label` when set, otherwise the option's own text. What the parent reads.
|
|
970
|
+
* Not `??`: an EMPTY label falls back too, since a blank trigger or a nameless
|
|
971
|
+
* chip is never what a `[label]="person.name"` on a missing name meant.
|
|
972
|
+
*/
|
|
973
|
+
private readonly resolvedLabel;
|
|
819
974
|
/**
|
|
820
975
|
* @internal — true when this option is currently selected. Works for
|
|
821
976
|
* both single and multi-select parents via `WrSelectContext.isSelected`.
|
|
@@ -825,7 +980,8 @@ declare class WrOption {
|
|
|
825
980
|
protected readonly active: Signal<boolean>;
|
|
826
981
|
/**
|
|
827
982
|
* @internal — searchable selects only. True when the parent has a query that
|
|
828
|
-
* the option's
|
|
983
|
+
* the option's label does not match (case-insensitive substring) — `label`
|
|
984
|
+
* when set, the option's text otherwise, and never its leading visual.
|
|
829
985
|
* Hidden options stay in the DOM so registration order survives but
|
|
830
986
|
* collapse via CSS.
|
|
831
987
|
*/
|
|
@@ -834,13 +990,20 @@ declare class WrOption {
|
|
|
834
990
|
constructor();
|
|
835
991
|
/**
|
|
836
992
|
* Read the projected text back off the DOM. Setting the same string again is
|
|
837
|
-
* a signal no-op, so the render hook costs a
|
|
838
|
-
* else on the passes where nothing moved.
|
|
993
|
+
* a signal no-op, so the render hook costs a short walk over the host's
|
|
994
|
+
* children and nothing else on the passes where nothing moved.
|
|
995
|
+
*
|
|
996
|
+
* A walk rather than the host's `textContent`, because the leading visual
|
|
997
|
+
* renders INSIDE the host while the panel is open: a `textContent` read turned
|
|
998
|
+
* an avatar's initials into the first word of the label, so the chip and the
|
|
999
|
+
* search filter read "ХР Хегай Роман". Only text and element children count —
|
|
1000
|
+
* a comment's `textContent` is its data, and Angular anchors every
|
|
1001
|
+
* `<ng-template>` with one.
|
|
839
1002
|
*/
|
|
840
1003
|
private syncLabel;
|
|
841
1004
|
protected onClick(): void;
|
|
842
1005
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrOption, never>;
|
|
843
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrOption, "wr-option", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {},
|
|
1006
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrOption, "wr-option", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, ["ownLeading"], ["*"], true, never>;
|
|
844
1007
|
}
|
|
845
1008
|
|
|
846
1009
|
/**
|
|
@@ -866,5 +1029,70 @@ declare class WrOptionGroup {
|
|
|
866
1029
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrOptionGroup, "wr-option-group", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
867
1030
|
}
|
|
868
1031
|
|
|
869
|
-
|
|
870
|
-
|
|
1032
|
+
/**
|
|
1033
|
+
* @license
|
|
1034
|
+
*
|
|
1035
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
1036
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
1037
|
+
*/
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* A leading visual — an avatar, an icon, a colour dot — drawn before an
|
|
1041
|
+
* option's label, and kept out of that label.
|
|
1042
|
+
*
|
|
1043
|
+
* It is a TEMPLATE, and that is the point. Projected `<wr-option>` children are
|
|
1044
|
+
* created as soon as the page renders, panel open or not, so an avatar written
|
|
1045
|
+
* straight into each option is 200 components and 200 image requests for an
|
|
1046
|
+
* assignee picker nobody has opened. A template is only instantiated where it is
|
|
1047
|
+
* drawn:
|
|
1048
|
+
*
|
|
1049
|
+
* - in an option row, while the panel is OPEN — destroyed again when it closes,
|
|
1050
|
+
* and under `virtualScroll` only for the rows in the rendered window;
|
|
1051
|
+
* - in a selected chip on a `mode="multi"` trigger, one per visible chip;
|
|
1052
|
+
* - beside the selected value on a single-mode BUTTON trigger — one copy;
|
|
1053
|
+
* - before the input on a SEARCH-shaped trigger (`mode="search"`, a searchable
|
|
1054
|
+
* single), while that input is showing the selected label. It goes beside the
|
|
1055
|
+
* field rather than into it — an `<input>` holds a string — and it steps aside
|
|
1056
|
+
* while a query is on screen, panel open or half-typed, because the value it
|
|
1057
|
+
* names is not what the field is showing then. Picking an option brings it
|
|
1058
|
+
* back with the label. Stepping aside is a DESTROY, like a closing panel's
|
|
1059
|
+
* rows, so an `<img>`-backed visual re-mounts once per open-and-dismiss.
|
|
1060
|
+
*
|
|
1061
|
+
* Every copy sits in an `aria-hidden` wrapper and is skipped when the option's
|
|
1062
|
+
* text is read, so the trigger label, the chip, the search filter and the
|
|
1063
|
+
* option's accessible name all stay the option's words — never "ХР Хегай Роман".
|
|
1064
|
+
* Anything the visual says has to be said by the label as well.
|
|
1065
|
+
*
|
|
1066
|
+
* Two places to declare it. Inside a `<wr-option>` it belongs to that option.
|
|
1067
|
+
* As a DIRECT child of `<wr-select>` it is the default for every row, which is the
|
|
1068
|
+
* only way to reach rows the select draws itself — `[options]`, `[loader]`
|
|
1069
|
+
* results and virtual rows. An option's own template wins over the select's.
|
|
1070
|
+
*
|
|
1071
|
+
* @example
|
|
1072
|
+
* ```html
|
|
1073
|
+
* <wr-select mode="multi" placeholder="Assignees" [(value)]="assignees">
|
|
1074
|
+
* @for (p of people; track p.id) {
|
|
1075
|
+
* <wr-option [value]="p.id">
|
|
1076
|
+
* <ng-template wrOptionLeading let-placement="placement">
|
|
1077
|
+
* <wr-avatar shape="circle" [size]="placement === 'chip' ? 16 : 24" [url]="p.photo">{{ p.initials }}</wr-avatar>
|
|
1078
|
+
* </ng-template>
|
|
1079
|
+
* {{ p.name }}
|
|
1080
|
+
* </wr-option>
|
|
1081
|
+
* }
|
|
1082
|
+
* </wr-select>
|
|
1083
|
+
* ```
|
|
1084
|
+
*/
|
|
1085
|
+
declare class WrOptionLeading {
|
|
1086
|
+
readonly template: TemplateRef<WrOptionLeadingContext<unknown>>;
|
|
1087
|
+
/**
|
|
1088
|
+
* Types the template's `let-` variables under `strictTemplates`. Without it
|
|
1089
|
+
* `let-placement` is `any`, and indexing a `Record<WrOptionLeadingPlacement, …>`
|
|
1090
|
+
* with it — the obvious way to size one visual per surface — does not compile.
|
|
1091
|
+
*/
|
|
1092
|
+
static ngTemplateContextGuard(_dir: WrOptionLeading, _ctx: unknown): _ctx is WrOptionLeadingContext;
|
|
1093
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrOptionLeading, never>;
|
|
1094
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<WrOptionLeading, "ng-template[wrOptionLeading]", never, {}, {}, never, never, true, never>;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
export { WR_SELECT, WrOption, WrOptionGroup, WrOptionLeading, WrSelect };
|
|
1098
|
+
export type { WrOptionLeadingContext, WrOptionLeadingPlacement, WrSelectContext, WrSelectMode, WrSelectSearchLoader, WrSelectSize, WrSelectTagValidator };
|
package/types/ngwr-version.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { InjectionToken } from '@angular/core';
|
|
|
16
16
|
* Distinct from `Version` exported by `@angular/core`, which reports the
|
|
17
17
|
* loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.
|
|
18
18
|
*/
|
|
19
|
-
declare const NGWR_VERSION = "14.
|
|
19
|
+
declare const NGWR_VERSION = "14.7.0";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|