ngwr 9.0.1 → 9.1.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/llms-full.txt CHANGED
@@ -113,7 +113,7 @@
113
113
  - import: `import { WrCascader } from 'ngwr/cascader'`
114
114
  - selector: `wr-cascader`
115
115
  - exports: WrCascader, type WrCascaderOption, type WrCascaderSize
116
- - Multi-level select. Drills through hierarchical categories one column at a time; picking a leaf commits the full path. Implements `ControlValueAccessor` — model is `readonly T[]`.
116
+ - Multi-level select. Drills through hierarchical categories one column at a time; picking a leaf commits the full path. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model (`readonly T[]`). `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
117
117
 
118
118
  ## ngwr/checkbox
119
119
  - import: `import { WrCheckbox } from 'ngwr/checkbox'`
@@ -195,8 +195,8 @@
195
195
 
196
196
  ## ngwr/date-picker
197
197
  - import: `import { WrDatePicker } from 'ngwr/date-picker'`
198
- - selector: `wr-date-picker`
199
- - exports: WrDatePicker
198
+ - selector: `wr-date-picker`, `wr-date-range-picker`
199
+ - exports: WrDatePicker, WrDateRangePicker, WrDateRange
200
200
  - Unified date / time / date-time picker. `<input>` + popover for every mode — overlay content swaps based on `[mode]`. Parses on every keystroke (silently — only emits when valid), reformats canonical on blur. Format driven by `WrDateAdapter`.
201
201
 
202
202
  ## ngwr/decrypt-text
@@ -218,7 +218,7 @@
218
218
 
219
219
  ## ngwr/dialog
220
220
  - import: `import { WrDialog } from 'ngwr/dialog'`
221
- - exports: WrDialog, WrDialogRef, WR_DIALOG_DATA, WrDialogOptions, WrDialogTitle, WrDialogContent, WrDialogFooter, WrDialogClose
221
+ - exports: WrDialog, WrDialogRef, WR_DIALOG_DATA, WR_DIALOG_REF, WrDialogOptions, WrDialogTitle, WrDialogContent, WrDialogFooter, WrDialogClose
222
222
  - Modal dialogs via a service that wraps @angular/cdk/dialog. Open any component as a dialog and read its close result as a Promise.
223
223
 
224
224
  ## ngwr/directives
@@ -247,8 +247,8 @@
247
247
  ## ngwr/drawer
248
248
  - import: `import { WrDrawer } from 'ngwr/drawer'`
249
249
  - selector: `wr-drawer`
250
- - exports: WrDrawer, WrDrawerTitle, WrDrawerContent, WrDrawerFooter, WrDrawerClose, WrDrawerPosition
251
- - Side panel that slides in from any edge. Two-way binds `open`; renders into a CDK overlay so it sits above page content.
250
+ - exports: WrDrawer, WrDrawerManager, WrDrawerRef, WR_DRAWER_DATA, WR_DRAWER_REF, WrDrawerTitle, WrDrawerContent, WrDrawerFooter, WrDrawerClose, WrDrawerOptions, WrDrawerPosition
251
+ - Side panel that slides in from any edge. Use the component when the markup lives in your template, or `WrDrawerManager` to open any component as a drawer and read its close result.
252
252
 
253
253
  ## ngwr/dropdown
254
254
  - import: `import { WrDropdown } from 'ngwr/dropdown'`
@@ -470,7 +470,7 @@
470
470
  - import: `import { WrRadio } from 'ngwr/radio'`
471
471
  - selector: `wr-radio-group`, `wr-radio`
472
472
  - exports: WrRadio, WrRadioSize, WrRadioGroup, WR_RADIO_GROUP, type WrRadioGroupContext
473
- - Single-choice option. Always used inside <wr-radio-group>, which implements ControlValueAccessor.
473
+ - Single-choice option. Always used inside <wr-radio-group>, which is the form control: it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
474
474
 
475
475
  ## ngwr/rating
476
476
  - import: `import { WrRating } from 'ngwr/rating'`
@@ -504,7 +504,7 @@
504
504
  - import: `import { WrSelect } from 'ngwr/select'`
505
505
  - selector: `wr-option-group`, `wr-option`, `wr-select`
506
506
  - exports: WrSelect, WrOption, WrOptionGroup, WR_SELECT, type WrSelectContext, WrSelectMode, WrSelectSearchLoader, WrSelectTagValidator, WrSelectSize
507
- - Native-like select built on CDK Overlay. Implements ControlValueAccessor.
507
+ - Native-like select built on CDK Overlay. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
508
508
 
509
509
  ## ngwr/shiny-text
510
510
  - import: `import { WrShinyText } from 'ngwr/shiny-text'`
@@ -527,7 +527,7 @@
527
527
  - import: `import { WrSlider } from 'ngwr/slider'`
528
528
  - selector: `wr-slider`
529
529
  - exports: WrSlider, WrSliderValue
530
- - Drag-to-pick numeric input. Single-thumb by default, optional dual-thumb range mode. Implements `ControlValueAccessor` so it plays nicely with template-driven and reactive forms.
530
+ - Drag-to-pick numeric input. Single-thumb by default, optional dual-thumb range mode. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and template-driven `[(ngModel)]` / reactive forms keep working through Angular's bridge.
531
531
 
532
532
  ## ngwr/sparkline
533
533
  - import: `import { WrSparkline } from 'ngwr/sparkline'`
@@ -600,7 +600,7 @@
600
600
  - import: `import { WrSwitch } from 'ngwr/switch'`
601
601
  - selector: `wr-switch`
602
602
  - exports: WrSwitch, WrSwitchSize
603
- - Boolean toggle with an iOS-style slider. Implements ControlValueAccessor.
603
+ - Boolean toggle with an iOS-style slider. A signal-forms native control — it implements `FormCheckboxControl`, so `[formField]` binds straight to its `checked` model. `[(checked)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
604
604
 
605
605
  ## ngwr/table
606
606
  - import: `import { WrTable } from 'ngwr/table'`
@@ -618,7 +618,7 @@
618
618
  - import: `import { WrTextarea } from 'ngwr/textarea'`
619
619
  - selector: `wr-textarea`
620
620
  - exports: WrTextarea, WrTextareaSize, WrTextareaResize
621
- - Multi-line text input. Implements ControlValueAccessor. Optional autosize.
621
+ - Multi-line text input with optional autosize. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
622
622
 
623
623
  ## ngwr/theme
624
624
  - import: `import { WR_COLORS } from 'ngwr/theme'`
package/llms.txt CHANGED
@@ -74,10 +74,13 @@ before writing your own. Full catalog: https://ngwr.dev/reference/components.
74
74
  ## Common components (selector — import)
75
75
 
76
76
  - **Form** — `wr-btn` (ngwr/button), `wrInput` (ngwr/input), `wr-select`
77
- (ngwr/select; modes single/multi/search/tag), `wr-checkbox` (form state is
78
- `[(checked)]`; inside `<wr-checkbox-group>` the identity input is
79
- `checkboxValue`, NOT `value`), `wr-switch`, `wr-slider`, `wr-input-number`,
80
- `wr-input-otp`, `wr-date-picker` (date/time/datetime), `wr-file-upload`,
77
+ (ngwr/select; modes single/multi/search/tag, plus `searchable` for a
78
+ multi-with-typeahead and `(searchChange)` for server-side search),
79
+ `wr-checkbox` (form state is `[(checked)]`; inside `<wr-checkbox-group>` the
80
+ identity input is `checkboxValue`, NOT `value`), `wr-switch`, `wr-slider`,
81
+ `wr-input-number`, `wr-input-otp`, `wr-date-picker` (date/time/datetime) and
82
+ `wr-date-range-picker` (both in ngwr/date-picker; the range value is
83
+ `[start, end]`, hence a separate component), `wr-file-upload`,
81
84
  `wr-form-field`, `wr-color-picker`.
82
85
  - **Data** — `wr-table` (column pin/resize/drag-reorder, row selection,
83
86
  expandable rows, grouping, summary rows, CSV export, virtualized body),
@@ -89,9 +92,12 @@ before writing your own. Full catalog: https://ngwr.dev/reference/components.
89
92
  `wr-toolbar`, `wr-descriptions`, `wr-statistic`, `wr-lightbox`,
90
93
  `wr-pull-to-refresh`.
91
94
  - **Navigation** — `wr-tabs`, `wr-stepper`, `wr-breadcrumbs`, `wr-dropdown-menu`.
92
- - **Overlays** — `wr-drawer`, `wr-action-sheet`, `[wrPopover]` (directive; has a
95
+ - **Overlays** — `wr-drawer` (or `WrDrawerManager.open()` to open a component as
96
+ a drawer from code), `wr-action-sheet`, `[wrPopover]` (directive; has a
93
97
  `tooltip` mode), `wr-command-palette`, `wr-context-menu`, `wr-popconfirm`.
94
- (Dialog and toast are service-opened — inject `WrDialog` / `WrToast`.)
98
+ (Dialog and toast are service-opened — inject `WrDialog` / `WrToast`.
99
+ Content inside a service-opened dialog or drawer can `inject(WrDialogRef)` /
100
+ `inject(WrDrawerRef)` to close itself.)
95
101
 
96
102
  ## Patterns
97
103
 
package/package.json CHANGED
@@ -1,15 +1,31 @@
1
1
  {
2
2
  "name": "ngwr",
3
- "version": "9.0.1",
3
+ "version": "9.1.0",
4
4
  "license": "MIT",
5
- "description": "NGWR – Angular UI components library",
5
+ "description": "Signals-first Angular UI library: 100+ standalone, zoneless-ready components with native Signal Forms, SSR-safe rendering and CSS-variable theming.",
6
6
  "author": "Roman Khegay <rk@garuna.dev> (https://garuna.dev)",
7
7
  "keywords": [
8
8
  "ngwr",
9
9
  "angular",
10
- "ui",
11
- "ux",
12
- "framework",
10
+ "angular-components",
11
+ "angular-ui",
12
+ "angular-library",
13
+ "component-library",
14
+ "ui-components",
15
+ "design-system",
16
+ "signals",
17
+ "signal-forms",
18
+ "zoneless",
19
+ "standalone",
20
+ "ssr",
21
+ "accessibility",
22
+ "a11y",
23
+ "scss",
24
+ "theming",
25
+ "dark-mode",
26
+ "tree-shakable",
27
+ "data-table",
28
+ "typescript",
13
29
  "frontend"
14
30
  ],
15
31
  "homepage": "https://ngwr.dev",
@@ -84,6 +84,8 @@
84
84
  "WrDateFnsAdapter": "ngwr/date-adapter-fns",
85
85
  "WrLuxonAdapter": "ngwr/date-adapter-luxon",
86
86
  "WrDatePicker": "ngwr/date-picker",
87
+ "WrDateRangePicker": "ngwr/date-picker",
88
+ "WrDateRange": "ngwr/date-picker",
87
89
  "WrDecryptText": "ngwr/decrypt-text",
88
90
  "WrDecryptTextAnimateOn": "ngwr/decrypt-text",
89
91
  "WrDecryptTextClickMode": "ngwr/decrypt-text",
@@ -113,10 +115,13 @@
113
115
  "WrSortableReorderEvent": "ngwr/drag-drop",
114
116
  "WrDragHandle": "ngwr/drag-drop",
115
117
  "WrDrawer": "ngwr/drawer",
118
+ "WrDrawerManager": "ngwr/drawer",
119
+ "WrDrawerRef": "ngwr/drawer",
116
120
  "WrDrawerTitle": "ngwr/drawer",
117
121
  "WrDrawerContent": "ngwr/drawer",
118
122
  "WrDrawerFooter": "ngwr/drawer",
119
123
  "WrDrawerClose": "ngwr/drawer",
124
+ "WrDrawerOptions": "ngwr/drawer",
120
125
  "WrDrawerPosition": "ngwr/drawer",
121
126
  "WrDropdown": "ngwr/dropdown",
122
127
  "WrDropdownMenu": "ngwr/dropdown",
@@ -130,4 +130,170 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
130
130
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrDatePicker, "wr-date-picker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "timeFormat": { "alias": "timeFormat"; "required": false; "isSignal": true; }; "showSeconds": { "alias": "showSeconds"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
131
131
  }
132
132
 
133
- export { WrDatePicker };
133
+ /**
134
+ * @license
135
+ *
136
+ * Use of this source code is governed by an MIT-style license that can be
137
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
138
+ */
139
+ /**
140
+ * The `<wr-date-range-picker>` value — `[start, end]`.
141
+ *
142
+ * Either end can be `null` while the range is half-picked, so a partially
143
+ * filled range is still representable. Structurally identical to
144
+ * `WrCalendarRange`, which the picker forwards it to.
145
+ */
146
+ type WrDateRange = readonly [Date | null, Date | null];
147
+
148
+ /**
149
+ * Date-range picker — two text inputs sharing one range calendar.
150
+ *
151
+ * Separate from `<wr-date-picker>` because the value is a different type: a
152
+ * range is `[start, end]`, and folding that into the single picker's
153
+ * `Date | null` would break `[formField]` inference for every existing usage.
154
+ * Everything else matches — same input skeleton, same overlay, same
155
+ * {@link WrDateAdapter} formats.
156
+ *
157
+ * - `'date'` (default) — popover renders a range calendar. Picking the second
158
+ * date closes the overlay.
159
+ * - `'datetime'` — popover adds a time stepper per end. Picking dates does NOT
160
+ * close, since the user typically sets the times next.
161
+ *
162
+ * A signal-forms native control: it implements
163
+ * `FormValueControl<WrDateRange | null>`, so `[formField]` binds straight to
164
+ * its `value` model. `[(value)]` works standalone, and classic `[(ngModel)]` /
165
+ * reactive forms keep working through Angular's bridge.
166
+ *
167
+ * Either end may be `null` while the range is half-picked. Out-of-order ends
168
+ * are swapped on commit, matching the calendar's own behaviour.
169
+ *
170
+ * @example
171
+ * ```html
172
+ * <!-- signal forms -->
173
+ * <wr-date-range-picker [formField]="form.period" format="dd.MM.yyyy" />
174
+ *
175
+ * <!-- standalone two-way binding -->
176
+ * <wr-date-range-picker [(value)]="period" [minDate]="minDate" />
177
+ *
178
+ * <!-- date + time on both ends -->
179
+ * <wr-date-range-picker mode="datetime" [(value)]="window" timeFormat="24h" />
180
+ * ```
181
+ *
182
+ * @see https://ngwr.dev/reference/components/date-picker
183
+ */
184
+ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null> {
185
+ /** Picker behavior — see class doc. @default 'date' */
186
+ readonly mode: _angular_core.InputSignal<"date" | "datetime">;
187
+ /**
188
+ * Format used for both display and parsing, on both ends. When `null`
189
+ * (default), it is derived from `mode` (`shortDate` / `shortDateTime`). Pass
190
+ * a named key or raw token string to override.
191
+ */
192
+ readonly format: _angular_core.InputSignal<WrDateFormat | (string & {}) | null>;
193
+ /** Placeholder for the start input. */
194
+ readonly startPlaceholder: _angular_core.InputSignal<string>;
195
+ /** Placeholder for the end input. */
196
+ readonly endPlaceholder: _angular_core.InputSignal<string>;
197
+ /** Glyph rendered between the two inputs. @default '–' */
198
+ readonly separator: _angular_core.InputSignal<string>;
199
+ /** Min selectable date, applied to both ends. */
200
+ readonly minDate: _angular_core.InputSignal<Date | null>;
201
+ /** Max selectable date, applied to both ends. */
202
+ readonly maxDate: _angular_core.InputSignal<Date | null>;
203
+ /** Predicate to disable specific dates (forwarded to the calendar). */
204
+ readonly dateFilter: _angular_core.InputSignal<((date: Date) => boolean) | null>;
205
+ /** Time-panel 12 / 24-hour format. Applies in `datetime` mode. @default 'auto' */
206
+ readonly timeFormat: _angular_core.InputSignal<"auto" | "12h" | "24h">;
207
+ /** Render the seconds column. Applies in `datetime` mode. @default false */
208
+ readonly showSeconds: _angular_core.InputSignalWithTransform<boolean, any>;
209
+ /** Minute / second step for the time panels. @default 1 */
210
+ readonly step: _angular_core.InputSignalWithTransform<number, unknown>;
211
+ /**
212
+ * Disable interaction. Bound automatically from the field's disabled state
213
+ * when used with `[formField]`.
214
+ *
215
+ * @default false
216
+ */
217
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
218
+ /** Read-only — inputs not typeable, but the trigger icon still opens the overlay. @default false */
219
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
220
+ private readonly adapter;
221
+ private readonly overlay;
222
+ private readonly scrollStrategies;
223
+ private readonly host;
224
+ private readonly destroyRef;
225
+ protected readonly startEl: _angular_core.Signal<ElementRef<HTMLInputElement>>;
226
+ /** The picked range. Bound by `[formField]`, or two-way via `[(value)]`. */
227
+ readonly value: _angular_core.ModelSignal<WrDateRange | null>;
228
+ /** Emitted on blur so a bound field can mark itself touched. */
229
+ readonly touch: _angular_core.OutputEmitterRef<void>;
230
+ /** Text currently in each input (may be partial / invalid mid-type). */
231
+ protected readonly startText: _angular_core.WritableSignal<string>;
232
+ protected readonly endText: _angular_core.WritableSignal<string>;
233
+ /** Whether the popover is currently open. */
234
+ protected readonly overlayOpen: _angular_core.WritableSignal<boolean>;
235
+ /** Resolved format — falls back to a mode-appropriate default. */
236
+ protected readonly resolvedFormat: _angular_core.Signal<string>;
237
+ protected readonly isDateTime: _angular_core.Signal<boolean>;
238
+ protected readonly triggerLabel: string;
239
+ protected readonly startLabel: string;
240
+ protected readonly endLabel: string;
241
+ protected readonly classes: _angular_core.Signal<string>;
242
+ private overlayRef;
243
+ /** Live panel ref while the popover is open — lets typed edits move the
244
+ * displayed month in real time (not just on reopen). */
245
+ private readonly panelRef;
246
+ /** Last range we pushed into the model ourselves, so the sync effect can skip
247
+ * the echo of our own edits and never reformat text mid-type. */
248
+ private lastValue;
249
+ constructor();
250
+ protected onStartInput(event: Event): void;
251
+ protected onEndInput(event: Event): void;
252
+ protected onBlur(event: FocusEvent): void;
253
+ /** Called by an input's click — opens the overlay if it isn't open already. */
254
+ protected openOnInput(): void;
255
+ protected toggleOverlay(): void;
256
+ private onRangeInput;
257
+ private openOverlay;
258
+ /**
259
+ * Close the popover. `restoreFocus` returns focus to the start input — needed
260
+ * when the overlay is dismissed while focus lives inside it (picking the
261
+ * second date), because disposing then leaves focus on a removed element and
262
+ * the browser falls back to `<body>`.
263
+ */
264
+ private closeOverlay;
265
+ private dispose;
266
+ /**
267
+ * Push to the model and refresh the text of whichever ends changed. Returns
268
+ * what was actually committed.
269
+ *
270
+ * `normalise` swaps out-of-order ends. The calendar and blur ask for it; a
271
+ * keystroke does not, because reordering while the user is still typing would
272
+ * move their in-progress text into the other input.
273
+ */
274
+ private commitRange;
275
+ private current;
276
+ private display;
277
+ private parseText;
278
+ /** Keep `[start, end]` in chronological order once both ends exist. */
279
+ private normalise;
280
+ /**
281
+ * Chronological comparison at the precision the mode needs. The adapter's
282
+ * `compareDate` is day-precision by contract, which would leave an inverted
283
+ * same-day `datetime` range (18:00 → 09:00) unswapped.
284
+ */
285
+ private compareEnds;
286
+ /**
287
+ * Whether a typed date must be rejected. Covers `dateFilter` as well as the
288
+ * bounds — the calendar disables filtered days, so accepting them from the
289
+ * keyboard would make the two entry paths disagree.
290
+ */
291
+ private isOutOfBounds;
292
+ private sameDate;
293
+ private sameRange;
294
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDateRangePicker, never>;
295
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrDateRangePicker, "wr-date-range-picker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "startPlaceholder": { "alias": "startPlaceholder"; "required": false; "isSignal": true; }; "endPlaceholder": { "alias": "endPlaceholder"; "required": false; "isSignal": true; }; "separator": { "alias": "separator"; "required": false; "isSignal": true; }; "minDate": { "alias": "minDate"; "required": false; "isSignal": true; }; "maxDate": { "alias": "maxDate"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "timeFormat": { "alias": "timeFormat"; "required": false; "isSignal": true; }; "showSeconds": { "alias": "showSeconds"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
296
+ }
297
+
298
+ export { WrDatePicker, WrDateRangePicker };
299
+ export type { WrDateRange };
@@ -3,7 +3,7 @@ import { ConfigurableFocusTrap } from '@angular/cdk/a11y';
3
3
  import { OverlayRef } from '@angular/cdk/overlay';
4
4
  import * as i0 from '@angular/core';
5
5
  import { ComponentRef, InjectionToken, ElementRef } from '@angular/core';
6
- import { Subject } from 'rxjs';
6
+ import { ReplaySubject } from 'rxjs';
7
7
 
8
8
  /**
9
9
  * @license
@@ -15,18 +15,43 @@ import { Subject } from 'rxjs';
15
15
  /**
16
16
  * Handle returned by `WrDialog.open()`.
17
17
  *
18
- * Wraps the underlying `OverlayRef` and tracks the close result.
18
+ * Wraps the underlying `OverlayRef` and tracks the close result. It is also
19
+ * provided inside the dialog's own injector, so the projected content can
20
+ * inject it and close itself — the counterpart to `[wrDialogClose]` when the
21
+ * close is programmatic (after a save succeeds, say) rather than a click.
19
22
  *
20
23
  * @example
21
24
  * ```ts
25
+ * // Caller side.
22
26
  * const ref = dialog.open<ConfirmComponent, boolean>(ConfirmComponent);
23
27
  * const result = await ref.awaitClose(); // boolean | undefined
24
28
  * ```
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // Content side — the dialog closes itself.
33
+ * @Component({...})
34
+ * export class ConfirmComponent {
35
+ * private readonly ref = inject(WrDialogRef);
36
+ *
37
+ * save(): void {
38
+ * this.store.save();
39
+ * this.ref.close(true);
40
+ * }
41
+ * }
42
+ * ```
25
43
  */
26
44
  declare class WrDialogRef<C, R = unknown> {
27
45
  private readonly _overlayRef;
28
- /** Emits the close result once and completes. */
29
- readonly closed: Subject<R | undefined>;
46
+ /**
47
+ * Emits the close result once and completes.
48
+ *
49
+ * A `ReplaySubject`, not a plain `Subject`, so the result survives a late
50
+ * subscriber: content can close itself before `open()` has even returned, and
51
+ * `awaitClose()` may be called long after the dismissal — both would otherwise
52
+ * see only `complete` and resolve `undefined`.
53
+ */
54
+ readonly closed: ReplaySubject<R | undefined>;
30
55
  /** @internal */
31
56
  componentRef: ComponentRef<C> | null;
32
57
  /** @internal */
@@ -36,8 +61,10 @@ declare class WrDialogRef<C, R = unknown> {
36
61
  constructor(_overlayRef: OverlayRef);
37
62
  /** The instantiated dialog component. */
38
63
  get componentInstance(): C;
64
+ private isClosed;
39
65
  /** Close the dialog, optionally returning a result. */
40
66
  close(result?: R): void;
67
+ private teardown;
41
68
  /** Resolves with the close result when the dialog is dismissed. */
42
69
  awaitClose(): Promise<R | undefined>;
43
70
  /** Underlying overlay ref — escape hatch for advanced cases. */
@@ -128,6 +155,42 @@ declare class WrDialog {
128
155
  */
129
156
  declare const WR_DIALOG_DATA: InjectionToken<unknown>;
130
157
 
158
+ /**
159
+ * @license
160
+ *
161
+ * Use of this source code is governed by an MIT-style license that can be
162
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
163
+ */
164
+
165
+ /**
166
+ * Token exposing the open dialog's `WrDialogRef` to components and
167
+ * directives rendered inside it (e.g. `[wrDialogClose]`).
168
+ *
169
+ * **Prefer `inject(WrDialogRef)`** — the ref is provided under the class token
170
+ * too, and the class path is the documented one. It already covers both cases
171
+ * you might reach for a token for: `inject(WrDialogRef, { optional: true })`
172
+ * works for content that also renders outside a dialog, and
173
+ * `inject<WrDialogRef<ConfirmComponent, boolean>>(WrDialogRef)` types the
174
+ * generics without a cast.
175
+ *
176
+ * This token is the same object under a second key. It exists for the library's
177
+ * own directives (`[wrDialogClose]`) and for swapping the provider out — a test
178
+ * stub, say — without touching the class.
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * @Component({...})
183
+ * export class ConfirmComponent {
184
+ * private readonly ref = inject<WrDialogRef<ConfirmComponent, boolean>>(WrDialogRef);
185
+ *
186
+ * confirm(): void {
187
+ * this.ref.close(true);
188
+ * }
189
+ * }
190
+ * ```
191
+ */
192
+ declare const WR_DIALOG_REF: InjectionToken<WrDialogRef<unknown, unknown>>;
193
+
131
194
  /**
132
195
  * @license
133
196
  *
@@ -203,15 +266,15 @@ declare class WrDialogFooter {
203
266
  */
204
267
  declare class WrDialogClose<R = unknown> {
205
268
  /**
206
- * Value to pass to `close()`. When unset, the dialog closes with
207
- * `undefined`.
269
+ * Value to pass to `close()`. When unset — or used as a bare attribute — the
270
+ * dialog closes with `undefined`.
208
271
  */
209
- readonly result: i0.InputSignal<R | undefined>;
272
+ readonly result: i0.InputSignalWithTransform<R | undefined, "" | R | undefined>;
210
273
  private readonly ref;
211
274
  protected onClick(): void;
212
275
  static ɵfac: i0.ɵɵFactoryDeclaration<WrDialogClose<any>, never>;
213
276
  static ɵdir: i0.ɵɵDirectiveDeclaration<WrDialogClose<any>, "[wrDialogClose]", never, { "result": { "alias": "wrDialogClose"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
214
277
  }
215
278
 
216
- export { WR_DIALOG_DATA, WrDialog, WrDialogClose, WrDialogContent, WrDialogFooter, WrDialogRef, WrDialogTitle };
279
+ export { WR_DIALOG_DATA, WR_DIALOG_REF, WrDialog, WrDialogClose, WrDialogContent, WrDialogFooter, WrDialogRef, WrDialogTitle };
217
280
  export type { WrDialogOptions };