ngwr 10.2.0 → 10.2.1

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.
Files changed (165) hide show
  1. package/dialog/styles/_index.scss +31 -0
  2. package/fesm2022/ngwr-action-sheet.mjs +3 -3
  3. package/fesm2022/ngwr-affix.mjs +3 -3
  4. package/fesm2022/ngwr-alert.mjs +3 -3
  5. package/fesm2022/ngwr-anchor.mjs +3 -3
  6. package/fesm2022/ngwr-aurora.mjs +3 -3
  7. package/fesm2022/ngwr-avatar.mjs +3 -3
  8. package/fesm2022/ngwr-back-top.mjs +3 -3
  9. package/fesm2022/ngwr-badge.mjs +6 -6
  10. package/fesm2022/ngwr-bar-chart.mjs +3 -3
  11. package/fesm2022/ngwr-blur-text.mjs +3 -3
  12. package/fesm2022/ngwr-border-glow.mjs +3 -3
  13. package/fesm2022/ngwr-breadcrumbs.mjs +8 -7
  14. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  15. package/fesm2022/ngwr-burger.mjs +3 -3
  16. package/fesm2022/ngwr-button.mjs +59 -11
  17. package/fesm2022/ngwr-button.mjs.map +1 -1
  18. package/fesm2022/ngwr-calendar-heatmap.mjs +3 -3
  19. package/fesm2022/ngwr-calendar.mjs +88 -8
  20. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  21. package/fesm2022/ngwr-card.mjs +9 -9
  22. package/fesm2022/ngwr-carousel.mjs +6 -6
  23. package/fesm2022/ngwr-cascader.mjs +3 -3
  24. package/fesm2022/ngwr-checkbox.mjs +6 -6
  25. package/fesm2022/ngwr-circular-text.mjs +3 -3
  26. package/fesm2022/ngwr-click-spark.mjs +3 -3
  27. package/fesm2022/ngwr-clipboard.mjs +18 -4
  28. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  29. package/fesm2022/ngwr-collapse.mjs +9 -9
  30. package/fesm2022/ngwr-color-picker.mjs +6 -6
  31. package/fesm2022/ngwr-command-palette.mjs +3 -3
  32. package/fesm2022/ngwr-compare.mjs +3 -3
  33. package/fesm2022/ngwr-confetti.mjs +3 -3
  34. package/fesm2022/ngwr-context-menu.mjs +12 -12
  35. package/fesm2022/ngwr-cookie.mjs +3 -3
  36. package/fesm2022/ngwr-counter.mjs +6 -6
  37. package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
  38. package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
  39. package/fesm2022/ngwr-date-adapter.mjs +3 -3
  40. package/fesm2022/ngwr-date-picker.mjs +336 -54
  41. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  42. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  43. package/fesm2022/ngwr-density.mjs +6 -6
  44. package/fesm2022/ngwr-descriptions.mjs +6 -6
  45. package/fesm2022/ngwr-dialog.mjs +33 -17
  46. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  47. package/fesm2022/ngwr-directives.mjs +12 -12
  48. package/fesm2022/ngwr-divider.mjs +3 -3
  49. package/fesm2022/ngwr-donut-chart.mjs +3 -3
  50. package/fesm2022/ngwr-drag-drop.mjs +6 -6
  51. package/fesm2022/ngwr-drawer.mjs +37 -19
  52. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  53. package/fesm2022/ngwr-dropdown.mjs +9 -9
  54. package/fesm2022/ngwr-empty.mjs +3 -3
  55. package/fesm2022/ngwr-event-calendar.mjs +6 -6
  56. package/fesm2022/ngwr-falling-text.mjs +3 -3
  57. package/fesm2022/ngwr-file-upload.mjs +3 -3
  58. package/fesm2022/ngwr-form.mjs +9 -9
  59. package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
  60. package/fesm2022/ngwr-gauge.mjs +3 -3
  61. package/fesm2022/ngwr-glitch-text.mjs +3 -3
  62. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  63. package/fesm2022/ngwr-hotkey.mjs +31 -10
  64. package/fesm2022/ngwr-hotkey.mjs.map +1 -1
  65. package/fesm2022/ngwr-i18n-en.mjs +11 -0
  66. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  67. package/fesm2022/ngwr-i18n-ru.mjs +11 -0
  68. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  69. package/fesm2022/ngwr-i18n.mjs +9 -9
  70. package/fesm2022/ngwr-icon.mjs +6 -6
  71. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  72. package/fesm2022/ngwr-input-number.mjs +3 -3
  73. package/fesm2022/ngwr-input-otp.mjs +3 -3
  74. package/fesm2022/ngwr-input.mjs +15 -15
  75. package/fesm2022/ngwr-keyboard.mjs +3 -3
  76. package/fesm2022/ngwr-knob.mjs +3 -3
  77. package/fesm2022/ngwr-layout.mjs +15 -15
  78. package/fesm2022/ngwr-lightbox.mjs +3 -3
  79. package/fesm2022/ngwr-line-chart.mjs +3 -3
  80. package/fesm2022/ngwr-list.mjs +13 -8
  81. package/fesm2022/ngwr-list.mjs.map +1 -1
  82. package/fesm2022/ngwr-loading-bar.mjs +70 -30
  83. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  84. package/fesm2022/ngwr-marquee.mjs +3 -3
  85. package/fesm2022/ngwr-media.mjs +3 -3
  86. package/fesm2022/ngwr-mention.mjs +6 -6
  87. package/fesm2022/ngwr-meta.mjs +6 -6
  88. package/fesm2022/ngwr-meter-group.mjs +3 -3
  89. package/fesm2022/ngwr-overlay.mjs +16 -7
  90. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  91. package/fesm2022/ngwr-page-header.mjs +3 -3
  92. package/fesm2022/ngwr-pagination.mjs +13 -9
  93. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  94. package/fesm2022/ngwr-pipes.mjs +21 -21
  95. package/fesm2022/ngwr-platform.mjs +9 -9
  96. package/fesm2022/ngwr-popconfirm.mjs +6 -6
  97. package/fesm2022/ngwr-popover.mjs +28 -8
  98. package/fesm2022/ngwr-popover.mjs.map +1 -1
  99. package/fesm2022/ngwr-progress.mjs +3 -3
  100. package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
  101. package/fesm2022/ngwr-qr.mjs +3 -3
  102. package/fesm2022/ngwr-radio.mjs +6 -6
  103. package/fesm2022/ngwr-rating.mjs +3 -3
  104. package/fesm2022/ngwr-result.mjs +12 -12
  105. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  106. package/fesm2022/ngwr-scroll.mjs +3 -3
  107. package/fesm2022/ngwr-segmented.mjs +3 -3
  108. package/fesm2022/ngwr-select.mjs +9 -9
  109. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  110. package/fesm2022/ngwr-sidebar.mjs +3 -3
  111. package/fesm2022/ngwr-skeleton.mjs +3 -3
  112. package/fesm2022/ngwr-slider.mjs +3 -3
  113. package/fesm2022/ngwr-sparkline.mjs +3 -3
  114. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  115. package/fesm2022/ngwr-spinner.mjs +3 -3
  116. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  117. package/fesm2022/ngwr-split-text.mjs +3 -3
  118. package/fesm2022/ngwr-splitter.mjs +3 -3
  119. package/fesm2022/ngwr-spotlight-card.mjs +6 -6
  120. package/fesm2022/ngwr-squircle.mjs +6 -6
  121. package/fesm2022/ngwr-star-border.mjs +3 -3
  122. package/fesm2022/ngwr-statistic.mjs +9 -9
  123. package/fesm2022/ngwr-stepper.mjs +6 -6
  124. package/fesm2022/ngwr-storage.mjs +27 -17
  125. package/fesm2022/ngwr-storage.mjs.map +1 -1
  126. package/fesm2022/ngwr-switch.mjs +3 -3
  127. package/fesm2022/ngwr-table.mjs +19 -31
  128. package/fesm2022/ngwr-table.mjs.map +1 -1
  129. package/fesm2022/ngwr-tabs.mjs +6 -6
  130. package/fesm2022/ngwr-textarea.mjs +3 -3
  131. package/fesm2022/ngwr-theme.mjs +3 -3
  132. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  133. package/fesm2022/ngwr-timeline.mjs +6 -6
  134. package/fesm2022/ngwr-toast.mjs +54 -20
  135. package/fesm2022/ngwr-toast.mjs.map +1 -1
  136. package/fesm2022/ngwr-toolbar.mjs +3 -3
  137. package/fesm2022/ngwr-tour.mjs +6 -6
  138. package/fesm2022/ngwr-transfer.mjs +3 -3
  139. package/fesm2022/ngwr-tree.mjs +3 -3
  140. package/fesm2022/ngwr-typewriter.mjs +3 -3
  141. package/fesm2022/ngwr-typography.mjs +3 -3
  142. package/fesm2022/ngwr-version.mjs +1 -1
  143. package/fesm2022/ngwr-version.mjs.map +1 -1
  144. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  145. package/fesm2022/ngwr-waves.mjs +3 -3
  146. package/fesm2022/ngwr-window.mjs +80 -18
  147. package/fesm2022/ngwr-window.mjs.map +1 -1
  148. package/i18n/en.json +8 -0
  149. package/i18n/ru.json +8 -0
  150. package/package.json +1 -1
  151. package/types/ngwr-button.d.ts +32 -0
  152. package/types/ngwr-calendar.d.ts +27 -1
  153. package/types/ngwr-clipboard.d.ts +8 -1
  154. package/types/ngwr-date-picker.d.ts +124 -8
  155. package/types/ngwr-dialog.d.ts +13 -0
  156. package/types/ngwr-drawer.d.ts +15 -0
  157. package/types/ngwr-hotkey.d.ts +2 -0
  158. package/types/ngwr-list.d.ts +7 -2
  159. package/types/ngwr-loading-bar.d.ts +4 -7
  160. package/types/ngwr-pagination.d.ts +6 -1
  161. package/types/ngwr-popover.d.ts +10 -2
  162. package/types/ngwr-storage.d.ts +10 -1
  163. package/types/ngwr-toast.d.ts +19 -4
  164. package/types/ngwr-version.d.ts +1 -1
  165. package/types/ngwr-window.d.ts +23 -2
@@ -56,10 +56,20 @@ declare class WrCalendar {
56
56
  readonly max: _angular_core.InputSignal<Date | null>;
57
57
  /** Predicate — return `false` to disable specific dates (e.g. weekends only). */
58
58
  readonly dateFilter: _angular_core.InputSignal<((date: Date) => boolean) | null>;
59
+ /**
60
+ * Move real focus onto the roving cell as soon as the grid is on screen.
61
+ *
62
+ * Off by default: a standalone `<wr-calendar>` sitting in a page must not
63
+ * steal focus on load. `wr-date-picker` turns it on for the popup it opens
64
+ * from its trigger, where the user asked to be taken to the calendar.
65
+ * @default false
66
+ */
67
+ readonly autoFocus: _angular_core.InputSignalWithTransform<boolean, any>;
59
68
  /** Disable interaction entirely. @default false */
60
69
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
61
70
  private readonly adapter;
62
71
  private readonly host;
72
+ private readonly injector;
63
73
  /** Currently displayed month (any date inside it). */
64
74
  protected readonly viewDate: _angular_core.WritableSignal<Date>;
65
75
  /** Date currently focused by keyboard (single roving tabindex). */
@@ -105,11 +115,27 @@ declare class WrCalendar {
105
115
  protected onCellLeave(): void;
106
116
  private applyRangeClick;
107
117
  protected onKeyDown(event: KeyboardEvent): void;
118
+ /**
119
+ * The first selectable day at or after `candidate`, else the first before it,
120
+ * else `candidate` unchanged when everything nearby is closed off. Bounded at
121
+ * a year each way so a pathological `dateFilter` cannot spin.
122
+ */
123
+ private nearestEnabled;
124
+ /**
125
+ * The first selectable day at `candidate` or beyond it in `step`'s direction,
126
+ * else null when that whole direction is closed off — which is the answer for
127
+ * an ArrowLeft that would cross `min`: stay put.
128
+ *
129
+ * Direction matters. Reusing `nearestEnabled`, which probes forward first,
130
+ * would send an ArrowLeft over a disabled weekend straight back to the day it
131
+ * started from, so the ring could never cross the hole.
132
+ */
133
+ private nearestEnabledToward;
108
134
  private focusActiveCell;
109
135
  /** Used by the template's `track` expression. */
110
136
  protected trackByTime(_: number, date: Date): number;
111
137
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrCalendar, never>;
112
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCalendar, "wr-calendar", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "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; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "date": "dateChange"; "range": "rangeChange"; }, never, never, true, never>;
138
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCalendar, "wr-calendar", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "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; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "date": "dateChange"; "range": "rangeChange"; }, never, never, true, never>;
113
139
  }
114
140
 
115
141
  export { WrCalendar };
@@ -54,7 +54,14 @@ declare class WrClipboard {
54
54
  * return `'unsupported'` when the capability genuinely isn't there.
55
55
  */
56
56
  permission(name: 'read' | 'write'): Promise<WrClipboardPermission>;
57
- /** Hidden-textarea + `execCommand('copy')` write. Synchronous, no permissions. */
57
+ /**
58
+ * Hidden-textarea + `execCommand('copy')` write. Synchronous, no permissions.
59
+ *
60
+ * `select()` takes focus, and the textarea is removed a moment later — so
61
+ * without putting focus back, every copy on a non-secure origin (plain
62
+ * `http://`, which is exactly where the async clipboard is missing) leaves
63
+ * focus on `<body>` and the user's next Tab restarts from the top of the page.
64
+ */
58
65
  private legacyWrite;
59
66
  static ɵfac: i0.ɵɵFactoryDeclaration<WrClipboard, never>;
60
67
  static ɵprov: i0.ɵɵInjectableDeclaration<WrClipboard>;
@@ -84,6 +84,7 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
84
84
  private readonly host;
85
85
  private readonly destroyRef;
86
86
  protected readonly inputEl: _angular_core.Signal<ElementRef<HTMLInputElement>>;
87
+ protected readonly triggerEl: _angular_core.Signal<ElementRef<HTMLButtonElement> | undefined>;
87
88
  /** The picked Date. Bound by `[formField]`, or two-way via `[(value)]`. */
88
89
  readonly value: _angular_core.ModelSignal<Date | null>;
89
90
  /** Emitted on blur so a bound field can mark itself touched. */
@@ -92,6 +93,14 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
92
93
  protected readonly text: _angular_core.WritableSignal<string>;
93
94
  /** Whether the popover is currently open. */
94
95
  protected readonly overlayOpen: _angular_core.WritableSignal<boolean>;
96
+ /**
97
+ * Where focus came from, captured as an explicit argument at open time —
98
+ * never read off `document.activeElement`, which by then may already be the
99
+ * pane. Every close path that took focus INTO the panel hands it back here.
100
+ */
101
+ private openedFrom;
102
+ /** Whether the panel this open cycle should take focus. */
103
+ private autoFocusPanel;
95
104
  /** Resolved format — falls back to a mode-appropriate default. */
96
105
  protected readonly resolvedFormat: _angular_core.Signal<string>;
97
106
  protected readonly isTime: _angular_core.Signal<boolean>;
@@ -99,6 +108,9 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
99
108
  private readonly labelDate;
100
109
  private readonly labelTime;
101
110
  private readonly labelDateTime;
111
+ private readonly panelLabelDate;
112
+ private readonly panelLabelTime;
113
+ private readonly panelLabelDateTime;
102
114
  /**
103
115
  * Accessible name of the text field. Falls back to the placeholder, then to
104
116
  * the same catalog string the calendar button uses — the field is a
@@ -108,6 +120,16 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
108
120
  private readonly fieldLabel;
109
121
  protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
110
122
  protected readonly triggerLabel: _angular_core.Signal<string>;
123
+ /**
124
+ * Accessible name of the popup. The trigger advertises
125
+ * `aria-haspopup="dialog"`, so the panel is a `role="dialog"` — and an unnamed
126
+ * dialog announces as a bare "dialog". Defaults to the catalog's
127
+ * `datePicker.panel*` string for the current `mode`.
128
+ */
129
+ readonly panelAriaLabel: _angular_core.InputSignal<string | null>;
130
+ /** Popup id — what the trigger's `aria-controls` points at while open. */
131
+ protected readonly panelId: string;
132
+ protected readonly resolvedPanelLabel: _angular_core.Signal<string>;
111
133
  protected readonly classes: _angular_core.Signal<string>;
112
134
  private overlayRef;
113
135
  /** Live calendar ref while the date popover is open — lets the panel track
@@ -123,6 +145,24 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
123
145
  /** Called by the input's click — opens the overlay if it isn't open already. */
124
146
  protected openOnInput(): void;
125
147
  protected toggleOverlay(): void;
148
+ /**
149
+ * The keyboard route into the panel, per the APG date-picker pattern.
150
+ *
151
+ * `Alt+ArrowDown` opens and takes focus; a bare arrow moves focus in when the
152
+ * panel is ALREADY open, which is how someone who opened it by clicking the
153
+ * field gets to the grid. Every other key — characters, Backspace, the
154
+ * horizontal arrows, Home / End — is left to the field untouched, so typing a
155
+ * date keeps working exactly as before.
156
+ */
157
+ protected onFieldKey(event: KeyboardEvent): void;
158
+ /**
159
+ * Move focus into an already-mounted panel. A plain query is right HERE and
160
+ * wrong at mount time: the panel has settled, so there is no deferral to get
161
+ * wrong — and it keeps `autoFocus` as the single piece of panel API.
162
+ */
163
+ private focusPanel;
164
+ /** Hand focus back to whatever opened the panel, if it is still on the page. */
165
+ private restoreFocus;
126
166
  private openOverlay;
127
167
  private attachDate;
128
168
  private attachTime;
@@ -131,12 +171,19 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
131
171
  /** Push a value to the model while remembering it, so the sync effect treats
132
172
  * the resulting change as an echo and leaves the display text alone. */
133
173
  private commitValue;
174
+ /**
175
+ * Focus goes back to the opener only when it was still INSIDE the panel —
176
+ * dropped there, it would land on `<body>` and the next Tab would restart
177
+ * from the top of the page. When focus had already moved elsewhere (a click
178
+ * on another control, which is itself what closed us) it is left alone:
179
+ * stealing it back would fight the user for the caret.
180
+ */
134
181
  private closeOverlay;
135
182
  private dispose;
136
183
  private isOutOfBounds;
137
184
  private sameDate;
138
185
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDatePicker, never>;
139
- 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; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
186
+ 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; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "panelAriaLabel": { "alias": "panelAriaLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
140
187
  }
141
188
 
142
189
  /**
@@ -154,6 +201,8 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
154
201
  */
155
202
  type WrDateRange = readonly [Date | null, Date | null];
156
203
 
204
+ /** Which end of the range an edit applies to. */
205
+ type RangeEnd = 0 | 1;
157
206
  /**
158
207
  * Date-range picker — two text inputs sharing one range calendar.
159
208
  *
@@ -224,7 +273,17 @@ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null>
224
273
  * @default false
225
274
  */
226
275
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
227
- /** Read-only — inputs not typeable, but the trigger icon still opens the overlay. @default false */
276
+ /**
277
+ * Read-only — neither the inputs nor the calendar can change the value.
278
+ *
279
+ * Deliberately stricter than `wr-date-picker`, which still opens its popup
280
+ * while read-only: with two fields feeding one calendar there is no reading
281
+ * of "untypeable" that leaves the grid free to rewrite both ends. The doc
282
+ * used to promise the trigger still opened; the code has always refused, and
283
+ * refusing is the behaviour worth keeping.
284
+ *
285
+ * @default false
286
+ */
228
287
  readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
229
288
  private readonly adapter;
230
289
  private readonly overlay;
@@ -233,6 +292,8 @@ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null>
233
292
  private readonly host;
234
293
  private readonly destroyRef;
235
294
  protected readonly startEl: _angular_core.Signal<ElementRef<HTMLInputElement>>;
295
+ protected readonly endEl: _angular_core.Signal<ElementRef<HTMLInputElement>>;
296
+ protected readonly triggerEl: _angular_core.Signal<ElementRef<HTMLButtonElement> | undefined>;
236
297
  /** The picked range. Bound by `[formField]`, or two-way via `[(value)]`. */
237
298
  readonly value: _angular_core.ModelSignal<WrDateRange | null>;
238
299
  /** Emitted on blur so a bound field can mark itself touched. */
@@ -242,12 +303,34 @@ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null>
242
303
  protected readonly endText: _angular_core.WritableSignal<string>;
243
304
  /** Whether the popover is currently open. */
244
305
  protected readonly overlayOpen: _angular_core.WritableSignal<boolean>;
306
+ /**
307
+ * Which element opened the popup — captured as an argument, never read off
308
+ * `document.activeElement`, which by then may already be the pane. With TWO
309
+ * text inputs this is the whole point: "restore focus to the field" is
310
+ * ambiguous here, and the old code resolved it by always picking the START
311
+ * input, so closing from the end input threw the caret across the control.
312
+ */
313
+ private openedFrom;
314
+ /** Whether the panel this open cycle should take focus. */
315
+ private autoFocusPanel;
245
316
  /** Resolved format — falls back to a mode-appropriate default. */
246
317
  protected readonly resolvedFormat: _angular_core.Signal<string>;
247
318
  protected readonly isDateTime: _angular_core.Signal<boolean>;
248
319
  protected readonly triggerLabel: string;
249
320
  protected readonly startLabel: string;
250
321
  protected readonly endLabel: string;
322
+ private readonly panelLabelRange;
323
+ private readonly panelLabelRangeDateTime;
324
+ /**
325
+ * Accessible name of the popup. The trigger advertises
326
+ * `aria-haspopup="dialog"`, so the pane is a `role="dialog"` — and an unnamed
327
+ * dialog announces as a bare "dialog". Defaults to the catalog's
328
+ * `datePicker.panelRange*` string for the current `mode`.
329
+ */
330
+ readonly panelAriaLabel: _angular_core.InputSignal<string | null>;
331
+ /** Popup id — what the trigger's `aria-controls` points at while open. */
332
+ protected readonly panelId: string;
333
+ protected readonly resolvedPanelLabel: _angular_core.Signal<string>;
251
334
  protected readonly classes: _angular_core.Signal<string>;
252
335
  private overlayRef;
253
336
  /** Live panel ref while the popover is open — lets typed edits move the
@@ -261,15 +344,39 @@ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null>
261
344
  protected onEndInput(event: Event): void;
262
345
  protected onBlur(event: FocusEvent): void;
263
346
  /** Called by an input's click — opens the overlay if it isn't open already. */
264
- protected openOnInput(): void;
347
+ protected openOnInput(end: RangeEnd): void;
265
348
  protected toggleOverlay(): void;
349
+ /**
350
+ * The keyboard route into the popup, per the APG date-picker pattern, and the
351
+ * only one either field has. `Alt+ArrowDown` opens and takes focus; a bare
352
+ * vertical arrow walks focus in when the popup is ALREADY open, which is how
353
+ * someone who opened it by clicking a field reaches the grid. Every other key
354
+ * belongs to the field, so typing a date keeps working with the popup open.
355
+ */
356
+ protected onFieldKey(event: KeyboardEvent, end: RangeEnd): void;
357
+ /** The input element for an end — the two are otherwise addressed by index. */
358
+ private fieldEl;
359
+ /**
360
+ * Move focus into an already-mounted panel. A plain query is right HERE and
361
+ * wrong at mount time: the panel has settled, so there is no deferral to get
362
+ * wrong — and it keeps `autoFocus` as the single piece of panel API.
363
+ */
364
+ private focusPanel;
365
+ /** Hand focus back to whatever opened the popup, if it is still on the page. */
366
+ private restoreFocus;
266
367
  private onRangeInput;
267
368
  private openOverlay;
268
369
  /**
269
- * Close the popover. `restoreFocus` returns focus to the start input — needed
270
- * when the overlay is dismissed while focus lives inside it (picking the
271
- * second date), because disposing then leaves focus on a removed element and
272
- * the browser falls back to `<body>`.
370
+ * Close the popover, handing focus back to whichever field or button opened
371
+ * it — but ONLY when focus was still inside the pane. Dropped there it would
372
+ * land on `<body>` and the next Tab would restart from the top of the page;
373
+ * moved on by the user, it must be left where they put it.
374
+ *
375
+ * There is deliberately no "always restore" escape hatch. Escape reaches this
376
+ * overlay from anywhere in the document (the CDK dispatches it to the topmost
377
+ * one), so forcing a restore would drag the caret backwards out of the field
378
+ * the user was actually typing in — into the one that happened to open the
379
+ * popup, possibly several Tab stops away.
273
380
  */
274
381
  private closeOverlay;
275
382
  private dispose;
@@ -300,9 +407,18 @@ declare class WrDateRangePicker implements FormValueControl<WrDateRange | null>
300
407
  */
301
408
  private isOutOfBounds;
302
409
  private sameDate;
410
+ /**
411
+ * `null` and `[null, null]` are the same VALUE — an empty range — and treating
412
+ * them as different is what let the FIRST blur on an untouched picker write
413
+ * `[null, null]` over the `null` it was bound to. No date had moved, but
414
+ * `model()` emitted: a bound `[formField]` went dirty from nothing but tabbing
415
+ * through, and a consumer's `@if (period())` flipped from empty to truthy with
416
+ * neither end picked. The write guard in `commitRange` is only as good as this
417
+ * comparison.
418
+ */
303
419
  private sameRange;
304
420
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDateRangePicker, never>;
305
- 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>;
421
+ 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; }; "panelAriaLabel": { "alias": "panelAriaLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
306
422
  }
307
423
 
308
424
  export { WrDatePicker, WrDateRangePicker };
@@ -140,6 +140,19 @@ declare class WrDialog {
140
140
  private readonly responsiveConfig;
141
141
  private readonly i18n;
142
142
  open<C, R = unknown, D = unknown>(component: ComponentType<C>, options?: WrDialogOptions<D>): WrDialogRef<C, R>;
143
+ /**
144
+ * The dismiss button's accessible name.
145
+ *
146
+ * Two failure modes, and resolving PER OPEN is what covers both. `t()` hands
147
+ * back the KEY on a miss, and `WrI18n` is root-provided with an empty catalog
148
+ * by default, so an app that never configured i18n named its dismiss button
149
+ * "dialog.close" — a name axe cannot fault, because a name is present, and a
150
+ * screen reader reads out verbatim. Resolving once at injection time fixed
151
+ * that but froze the answer: this is a root service, constructed before an
152
+ * async catalog has loaded, so a localized app got the English fallback on
153
+ * every dialog it ever opened.
154
+ */
155
+ private closeLabel;
143
156
  static ɵfac: i0.ɵɵFactoryDeclaration<WrDialog, never>;
144
157
  static ɵprov: i0.ɵɵInjectableDeclaration<WrDialog>;
145
158
  }
@@ -254,6 +254,21 @@ declare class WrDrawerManager {
254
254
  private readonly isBrowser;
255
255
  private readonly i18n;
256
256
  open<C, R = unknown, D = unknown>(component: ComponentType<C>, options?: WrDrawerOptions<D>): WrDrawerRef<C, R>;
257
+ /**
258
+ * The dismiss button's accessible name.
259
+ *
260
+ * Resolved per open, not once at injection: this is a root service, so a
261
+ * `readI18nText` field — which is what `WrDialog` uses — would be evaluated
262
+ * before an async catalog had loaded and then freeze that answer for the life
263
+ * of the app.
264
+ *
265
+ * The miss check is the point. `t()` hands back the KEY when the catalog has
266
+ * no entry, and `WrI18n` is root-provided with an empty catalog by default —
267
+ * so an app that never configured i18n got a button announced as
268
+ * "drawer.close, button". A name WAS present, which is exactly why the axe
269
+ * gate could not see it.
270
+ */
271
+ private closeLabel;
257
272
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDrawerManager, never>;
258
273
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<WrDrawerManager>;
259
274
  }
@@ -68,9 +68,11 @@ declare class WrHotkey {
68
68
  private readonly doc;
69
69
  private readonly zone;
70
70
  private readonly platform;
71
+ private readonly destroyRef;
71
72
  private readonly isMac;
72
73
  /** Bindings grouped by listener target. */
73
74
  private readonly registries;
75
+ constructor();
74
76
  /** Register a binding. */
75
77
  bind(spec: WrHotkeySpec, handler: (event: KeyboardEvent) => void, options?: WrHotkeyOptions): WrHotkeyHandle;
76
78
  private readonly listeners;
@@ -43,8 +43,13 @@ declare class WrList {
43
43
  * - default — main label / body
44
44
  * - `[wrListItemTrailing]` — meta value, action button, chevron
45
45
  *
46
- * Set `interactive` to get hover, cursor, keyboard activation, and the
47
- * appropriate ARIA role for click handling.
46
+ * Set `interactive` to get hover and cursor styles, a tab stop, and Enter /
47
+ * Space activation. The role stays `listitem`: the row lives inside a
48
+ * `<ul role="list">`, where a `button` or `option` child role would break the
49
+ * structure the container promises. That means an interactive row ANNOUNCES as
50
+ * a list item rather than as a control — deliberate, but worth knowing when the
51
+ * whole row is the only way to reach an action. Where the action needs to be
52
+ * announced as one, project a real button into `[wrListItemTrailing]`.
48
53
  *
49
54
  * @example
50
55
  * ```html
@@ -4,13 +4,6 @@ import { Signal } from '@angular/core';
4
4
  /** Public state of the loading bar. */
5
5
  type WrLoadingState = 'idle' | 'running' | 'completing';
6
6
 
7
- /**
8
- * @license
9
- *
10
- * Use of this source code is governed by an MIT-style license that can be
11
- * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
12
- */
13
-
14
7
  /**
15
8
  * Singleton state machine for a top-of-page progress indicator. Driven
16
9
  * by router events out of the box, plus a manual `start()` / `complete()`
@@ -30,6 +23,8 @@ type WrLoadingState = 'idle' | 'running' | 'completing';
30
23
  */
31
24
  declare class WrLoadingBar {
32
25
  private readonly router;
26
+ private readonly destroyRef;
27
+ private readonly isBrowser;
33
28
  /** Live count of pending "tasks" (manual + router). */
34
29
  private readonly count;
35
30
  /** Tween value `[0, 1]` — the bar's actual width. */
@@ -37,6 +32,7 @@ declare class WrLoadingBar {
37
32
  readonly progress: Signal<number>;
38
33
  readonly state: Signal<WrLoadingState>;
39
34
  private timer;
35
+ private holdTimer;
40
36
  constructor();
41
37
  /** Reserve a slot. The bar starts trickling as long as `count > 0`. */
42
38
  start(): void;
@@ -46,6 +42,7 @@ declare class WrLoadingBar {
46
42
  reset(): void;
47
43
  private beginTrickle;
48
44
  private stopTrickle;
45
+ private clearHold;
49
46
  private finish;
50
47
  static ɵfac: i0.ɵɵFactoryDeclaration<WrLoadingBar, never>;
51
48
  static ɵprov: i0.ɵɵInjectableDeclaration<WrLoadingBar>;
@@ -123,7 +123,12 @@ declare class WrPagination {
123
123
  protected readonly classes: _angular_core.Signal<string>;
124
124
  protected isCurrent(page: number): boolean;
125
125
  protected goTo(page: number | typeof ELLIPSIS): void;
126
- protected onSizeChange(size: number): void;
126
+ /**
127
+ * `wr-select` carries an `unknown` value by design, so the size arrives
128
+ * untyped and is narrowed here. It used to arrive as `any` through
129
+ * `[ngModel]`, which hid the coercion rather than removing the need for it.
130
+ */
131
+ protected onSizeChange(size: unknown): void;
127
132
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrPagination, never>;
128
133
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrPagination, "wr-pagination", never, { "currentPage": { "alias": "currentPage"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "showSizeChanger": { "alias": "showSizeChanger"; "required": false; "isSignal": true; }; "showTotal": { "alias": "showTotal"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "shape": { "alias": "shape"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "ofLabel": { "alias": "ofLabel"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "itemsPerPageLabel": { "alias": "itemsPerPageLabel"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, { "currentPage": "currentPageChange"; "pageSize": "pageSizeChange"; }, never, never, true, never>;
129
134
  }
@@ -26,7 +26,7 @@ declare class WrPopover {
26
26
  * - `'tooltip'` — text content, hover+focus trigger, `role="tooltip"`,
27
27
  * `aria-describedby` on the host.
28
28
  */
29
- readonly mode: _angular_core.InputSignal<"tooltip" | "popover">;
29
+ readonly mode: _angular_core.InputSignal<"popover" | "tooltip">;
30
30
  /**
31
31
  * How the popover opens. Ignored in tooltip mode — tooltips are always
32
32
  * hover+focus. @default 'click'
@@ -45,6 +45,13 @@ declare class WrPopover {
45
45
  * overrides it. Tooltips never become sheets. @default undefined
46
46
  */
47
47
  readonly responsive: _angular_core.InputSignalWithTransform<boolean | undefined, BooleanInput>;
48
+ /**
49
+ * Popover mode only — accessible name of the panel. `role="dialog"` with no
50
+ * name announces as a bare "dialog", so the catalog's `popover.label` is used
51
+ * when nothing is given. A popover has no universal name; whenever the panel
52
+ * has a heading or a purpose, pass it.
53
+ */
54
+ readonly ariaLabel: _angular_core.InputSignal<string | null>;
48
55
  /** Fires after the panel opens. */
49
56
  readonly opened: _angular_core.OutputEmitterRef<void>;
50
57
  /** Fires after the panel closes. */
@@ -62,6 +69,7 @@ declare class WrPopover {
62
69
  protected readonly isTooltip: _angular_core.Signal<boolean>;
63
70
  /** Auto-generated id for `aria-controls` / `aria-describedby`. */
64
71
  protected readonly panelId: string;
72
+ private readonly resolvedAriaLabel;
65
73
  private readonly resolvedPosition;
66
74
  private overlayRef;
67
75
  private hoverCloseTimer;
@@ -93,7 +101,7 @@ declare class WrPopover {
93
101
  private scheduleHoverClose;
94
102
  private clearHoverClose;
95
103
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrPopover, never>;
96
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<WrPopover, "[wrPopover]", never, { "content": { "alias": "wrPopover"; "required": true; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "showDelay": { "alias": "showDelay"; "required": false; "isSignal": true; }; "hideDelay": { "alias": "hideDelay"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; }, { "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
104
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<WrPopover, "[wrPopover]", never, { "content": { "alias": "wrPopover"; "required": true; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "showDelay": { "alias": "showDelay"; "required": false; "isSignal": true; }; "hideDelay": { "alias": "hideDelay"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
97
105
  }
98
106
 
99
107
  export { WrPopover };
@@ -37,7 +37,16 @@ declare class WrStorage {
37
37
  private readonly engine;
38
38
  private readonly config;
39
39
  private readonly isBrowser;
40
- /** Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal. */
40
+ /**
41
+ * Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal.
42
+ *
43
+ * The fallback is kept alongside the signal because every refresh has to read
44
+ * the key the same way `watch` first did. Refreshing without it made `get` and
45
+ * `watch` disagree about what an ABSENT key means: after a `remove()` the
46
+ * signal went to `null` while `get(key, fallback)` still answered with the
47
+ * default, so a consumer watching `'theme'` with a `'light'` fallback got no
48
+ * theme at all rather than the light one.
49
+ */
41
50
  private readonly watchers;
42
51
  private listenerInstalled;
43
52
  /** Is `key` present (regardless of value / expiry)? */
@@ -39,7 +39,11 @@ interface WrToastOptions {
39
39
  readonly duration?: number;
40
40
  /** Show a close (×) button. @default true */
41
41
  readonly dismissible?: boolean;
42
- /** Override the corner for this toast only. */
42
+ /**
43
+ * Corner this toast opens in. The whole stack shares one host, so this is
44
+ * not per-toast: passing a different corner relocates the toasts already on
45
+ * screen along with this one.
46
+ */
43
47
  readonly position?: WrToastPosition;
44
48
  /** Override the progress bar visibility for this toast only. */
45
49
  readonly showProgress?: boolean;
@@ -90,7 +94,16 @@ interface WrToastConfig {
90
94
  readonly showCloseAll: boolean;
91
95
  /** Minimum number of stacked toasts before "Close all" appears. @default 2 */
92
96
  readonly closeAllThreshold: number;
93
- /** Maximum toasts visible at once. Oldest is dismissed when exceeded. `0` = unlimited. @default 5 */
97
+ /**
98
+ * Maximum toasts visible at once. `0` = unlimited.
99
+ *
100
+ * Nothing on screen is taken away to make room: once the cap is reached the
101
+ * *newest* toast waits in a queue, and queued toasts are promoted FIFO as
102
+ * visible ones dismiss. A queued toast's auto-dismiss countdown only starts
103
+ * when it becomes visible, so it can never expire unseen.
104
+ *
105
+ * @default 5
106
+ */
94
107
  readonly maxStack: number;
95
108
  /** Labels rendered in the UI. Keep short — meant to be overridden for i18n. */
96
109
  readonly labels: {
@@ -195,13 +208,15 @@ declare class WrToast {
195
208
  * position: 'bottom-end',
196
209
  * showCopy: true,
197
210
  * maxStack: 3,
198
- * labels: { close: 'Закрыть', copy: 'Копировать', copied: 'Скопировано', closeAll: 'Закрыть все' },
211
+ * labels: { close: 'Закрыть' },
199
212
  * }),
200
213
  * ],
201
214
  * });
202
215
  * ```
203
216
  */
204
- declare function provideWrToastConfig(config: Partial<WrToastConfig>): EnvironmentProviders;
217
+ declare function provideWrToastConfig(config: Partial<Omit<WrToastConfig, 'labels'>> & {
218
+ readonly labels?: Partial<WrToastConfig['labels']>;
219
+ }): EnvironmentProviders;
205
220
 
206
221
  /**
207
222
  * @license
@@ -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 = "10.2.0";
19
+ declare const NGWR_VERSION = "10.2.1";
20
20
 
21
21
  /**
22
22
  * @license
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { ComponentRef, WritableSignal, Signal, InjectionToken } from '@angular/core';
3
3
  import { OverlayRef } from '@angular/cdk/overlay';
4
- import { Subject } from 'rxjs';
4
+ import { ReplaySubject, Subject } from 'rxjs';
5
5
  import { ComponentType } from '@angular/cdk/portal';
6
6
 
7
7
  /**
@@ -193,7 +193,15 @@ declare class WrWindowRef<C, R = unknown> {
193
193
  /** Stable id — used by the taskbar, workspace save, and DI. */
194
194
  readonly id: string;
195
195
  /** @internal — emits the close result once and completes. */
196
- readonly _closed: Subject<R | undefined>;
196
+ /**
197
+ * A `ReplaySubject`, not a plain `Subject`, so the result survives a late
198
+ * subscriber — the same reasoning `WrDialogRef` already carries. A caller
199
+ * that holds the ref and awaits `afterClosed()` after any intervening
200
+ * `await` subscribes to an already-completed stream, and a plain Subject
201
+ * hands it nothing but `complete`: the promise resolved `undefined` and a
202
+ * saved result was indistinguishable from a dismissal.
203
+ */
204
+ readonly _closed: ReplaySubject<R | undefined>;
197
205
  /** @internal — emits whenever the visual state changes. */
198
206
  readonly _stateChanged: Subject<WrWindowState>;
199
207
  /** @internal — set by the container right after attach. */
@@ -212,6 +220,19 @@ declare class WrWindowRef<C, R = unknown> {
212
220
  /** @internal */ readonly _width: WritableSignal<number>;
213
221
  /** @internal */ readonly _height: WritableSignal<number>;
214
222
  /** @internal */ readonly _z: WritableSignal<number>;
223
+ /**
224
+ * The geometry the USER chose, as opposed to the one the current state
225
+ * imposes. `_x` and friends mirror the window's EFFECTIVE values — a
226
+ * maximized window reports the viewport, a minimized one reports its
227
+ * collapsed header height — which is right for anything drawing the window
228
+ * and wrong for anything persisting it.
229
+ *
230
+ * @internal
231
+ */
232
+ readonly _rawX: WritableSignal<number>;
233
+ /** @internal */ readonly _rawY: WritableSignal<number>;
234
+ /** @internal */ readonly _rawWidth: WritableSignal<number>;
235
+ /** @internal */ readonly _rawHeight: WritableSignal<number>;
215
236
  /** @internal */ readonly _title: WritableSignal<string>;
216
237
  /** Window state. */
217
238
  readonly state: Signal<WrWindowState>;