ngwr 12.1.0 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +11 -1
  2. package/alert/styles/_index.scss +11 -4
  3. package/badge/styles/_index.scss +30 -0
  4. package/badge/styles/_tag.scss +15 -1
  5. package/border-glow/border-glow.scss +1 -1
  6. package/border-glow/styles/_index.scss +15 -233
  7. package/border-glow/styles/_rules.scss +228 -0
  8. package/breadcrumbs/breadcrumbs.scss +1 -1
  9. package/breadcrumbs/styles/_index.scss +15 -78
  10. package/breadcrumbs/styles/_rules.scss +84 -0
  11. package/card/card.scss +1 -1
  12. package/card/styles/_index.scss +15 -96
  13. package/card/styles/_rules.scss +96 -0
  14. package/cascader/cascader.scss +1 -1
  15. package/cascader/styles/_index.scss +15 -244
  16. package/cascader/styles/_rules.scss +261 -0
  17. package/checkbox/styles/_index.scss +7 -0
  18. package/circular-text/circular-text.scss +1 -1
  19. package/circular-text/styles/_index.scss +15 -63
  20. package/circular-text/styles/_rules.scss +58 -0
  21. package/color-picker/styles/_index.scss +8 -0
  22. package/descriptions/styles/_index.scss +13 -3
  23. package/drag-drop/sortable-list.scss +1 -1
  24. package/drag-drop/styles/_index.scss +14 -143
  25. package/drag-drop/styles/_rules.scss +151 -0
  26. package/drawer/styles/_index.scss +95 -1
  27. package/falling-text/falling-text.scss +1 -1
  28. package/falling-text/styles/_index.scss +15 -36
  29. package/falling-text/styles/_rules.scss +31 -0
  30. package/fesm2022/ngwr-border-glow.mjs +2 -2
  31. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  32. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  33. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  34. package/fesm2022/ngwr-card.mjs +2 -2
  35. package/fesm2022/ngwr-card.mjs.map +1 -1
  36. package/fesm2022/ngwr-cascader.mjs +27 -9
  37. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  38. package/fesm2022/ngwr-checkbox.mjs +86 -8
  39. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  40. package/fesm2022/ngwr-circular-text.mjs +2 -2
  41. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  42. package/fesm2022/ngwr-color-picker.mjs +57 -7
  43. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  44. package/fesm2022/ngwr-date-picker.mjs +8 -0
  45. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  46. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  47. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  48. package/fesm2022/ngwr-drawer.mjs +6 -0
  49. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  50. package/fesm2022/ngwr-falling-text.mjs +2 -2
  51. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  52. package/fesm2022/ngwr-file-upload.mjs +29 -8
  53. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  54. package/fesm2022/ngwr-form.mjs +48 -1
  55. package/fesm2022/ngwr-form.mjs.map +1 -1
  56. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  57. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  58. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  59. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  60. package/fesm2022/ngwr-input-otp.mjs +41 -3
  61. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  62. package/fesm2022/ngwr-knob.mjs +17 -2
  63. package/fesm2022/ngwr-knob.mjs.map +1 -1
  64. package/fesm2022/ngwr-lightbox.mjs +2 -2
  65. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  66. package/fesm2022/ngwr-list.mjs +2 -2
  67. package/fesm2022/ngwr-list.mjs.map +1 -1
  68. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  69. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  70. package/fesm2022/ngwr-marquee.mjs +2 -2
  71. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  72. package/fesm2022/ngwr-pagination.mjs +1 -1
  73. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  74. package/fesm2022/ngwr-radio.mjs +63 -8
  75. package/fesm2022/ngwr-radio.mjs.map +1 -1
  76. package/fesm2022/ngwr-rating.mjs +17 -2
  77. package/fesm2022/ngwr-rating.mjs.map +1 -1
  78. package/fesm2022/ngwr-segmented.mjs +22 -3
  79. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  80. package/fesm2022/ngwr-select.mjs +59 -15
  81. package/fesm2022/ngwr-select.mjs.map +1 -1
  82. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  83. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  84. package/fesm2022/ngwr-slider.mjs +21 -6
  85. package/fesm2022/ngwr-slider.mjs.map +1 -1
  86. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  87. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  88. package/fesm2022/ngwr-star-border.mjs +2 -2
  89. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  90. package/fesm2022/ngwr-switch.mjs +44 -4
  91. package/fesm2022/ngwr-switch.mjs.map +1 -1
  92. package/fesm2022/ngwr-table.mjs +1 -1
  93. package/fesm2022/ngwr-table.mjs.map +1 -1
  94. package/fesm2022/ngwr-textarea.mjs +5 -2
  95. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  96. package/fesm2022/ngwr-theme.mjs +41 -1
  97. package/fesm2022/ngwr-theme.mjs.map +1 -1
  98. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  99. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  100. package/fesm2022/ngwr-transfer.mjs +38 -6
  101. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  102. package/fesm2022/ngwr-tree.mjs +33 -7
  103. package/fesm2022/ngwr-tree.mjs.map +1 -1
  104. package/fesm2022/ngwr-typewriter.mjs +2 -2
  105. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  106. package/fesm2022/ngwr-version.mjs +1 -1
  107. package/fesm2022/ngwr-version.mjs.map +1 -1
  108. package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
  109. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  110. package/fesm2022/ngwr-waves.mjs +2 -2
  111. package/fesm2022/ngwr-waves.mjs.map +1 -1
  112. package/file-upload/styles/_index.scss +6 -0
  113. package/glitch-text/glitch-text.scss +1 -1
  114. package/glitch-text/styles/_index.scss +14 -164
  115. package/glitch-text/styles/_rules.scss +160 -0
  116. package/gradient-text/gradient-text.scss +1 -1
  117. package/gradient-text/styles/_index.scss +15 -118
  118. package/gradient-text/styles/_rules.scss +113 -0
  119. package/input/styles/_index.scss +13 -0
  120. package/input-otp/styles/_index.scss +8 -0
  121. package/lightbox/lightbox.scss +1 -1
  122. package/lightbox/styles/_index.scss +15 -191
  123. package/lightbox/styles/_rules.scss +198 -0
  124. package/list/list.scss +1 -1
  125. package/list/styles/_index.scss +15 -101
  126. package/list/styles/_rules.scss +108 -0
  127. package/llms-full.txt +3 -3
  128. package/loading-bar/loading-bar.scss +1 -1
  129. package/loading-bar/styles/_index.scss +15 -33
  130. package/loading-bar/styles/_rules.scss +28 -0
  131. package/marquee/marquee.scss +1 -1
  132. package/marquee/styles/_index.scss +15 -155
  133. package/marquee/styles/_rules.scss +150 -0
  134. package/overlay/styles/_arrow.scss +243 -0
  135. package/package.json +1 -1
  136. package/popconfirm/styles/_index.scss +17 -0
  137. package/popover/styles/_index.scss +49 -207
  138. package/segmented/styles/_index.scss +8 -0
  139. package/select/styles/_index.scss +47 -5
  140. package/shiny-text/shiny-text.scss +1 -1
  141. package/shiny-text/styles/_index.scss +14 -105
  142. package/shiny-text/styles/_rules.scss +101 -0
  143. package/sidebar/styles/_index.scss +4 -1
  144. package/slider/styles/_index.scss +8 -0
  145. package/spotlight-card/spotlight-card.scss +1 -1
  146. package/spotlight-card/styles/_index.scss +15 -52
  147. package/spotlight-card/styles/_rules.scss +47 -0
  148. package/star-border/star-border.scss +1 -1
  149. package/star-border/styles/_index.scss +15 -125
  150. package/star-border/styles/_rules.scss +120 -0
  151. package/stepper/styles/_index.scss +44 -5
  152. package/switch/styles/_index.scss +7 -0
  153. package/theme/styles/_dark.scss +81 -4
  154. package/theme/styles/_index.scss +1 -0
  155. package/theme/styles/_mixins.scss +10 -0
  156. package/theme/styles/_motion.scss +94 -0
  157. package/tilt-card/styles/_index.scss +15 -45
  158. package/tilt-card/styles/_rules.scss +40 -0
  159. package/tilt-card/tilt-card.scss +1 -1
  160. package/tree/styles/_index.scss +25 -3
  161. package/types/ngwr-cascader.d.ts +17 -1
  162. package/types/ngwr-checkbox.d.ts +51 -3
  163. package/types/ngwr-color-picker.d.ts +19 -1
  164. package/types/ngwr-file-upload.d.ts +18 -1
  165. package/types/ngwr-form.d.ts +51 -2
  166. package/types/ngwr-input-otp.d.ts +23 -1
  167. package/types/ngwr-knob.d.ts +14 -0
  168. package/types/ngwr-radio.d.ts +37 -2
  169. package/types/ngwr-rating.d.ts +14 -0
  170. package/types/ngwr-segmented.d.ts +18 -1
  171. package/types/ngwr-select.d.ts +29 -3
  172. package/types/ngwr-slider.d.ts +14 -1
  173. package/types/ngwr-switch.d.ts +26 -2
  174. package/types/ngwr-textarea.d.ts +3 -0
  175. package/types/ngwr-theme.d.ts +24 -0
  176. package/types/ngwr-transfer.d.ts +17 -1
  177. package/types/ngwr-tree.d.ts +21 -1
  178. package/types/ngwr-version.d.ts +1 -1
  179. package/typewriter/styles/_index.scss +15 -38
  180. package/typewriter/styles/_rules.scss +33 -0
  181. package/typewriter/typewriter.scss +1 -1
  182. package/virtual-scroll/styles/_index.scss +15 -32
  183. package/virtual-scroll/styles/_rules.scss +27 -0
  184. package/virtual-scroll/virtual-scroll.scss +1 -1
  185. package/waves/styles/_index.scss +15 -50
  186. package/waves/styles/_rules.scss +45 -0
  187. package/waves/waves.scss +1 -1
@@ -1,5 +1,6 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { InjectionToken, Signal } from '@angular/core';
3
+ import * as ngwr_form from 'ngwr/form';
3
4
  import { FormValueControl } from '@angular/forms/signals';
4
5
 
5
6
  /**
@@ -18,7 +19,10 @@ import { FormValueControl } from '@angular/forms/signals';
18
19
  */
19
20
  type WrRadioSize = 'sm' | 'md' | 'lg';
20
21
  declare class WrRadio {
21
- /** Stable id used to associate the native input with its label. */
22
+ /**
23
+ * Stable id used to associate the native input with its label. Lands on the
24
+ * inner `<input>`; the host never keeps it.
25
+ */
22
26
  readonly id: _angular_core.InputSignal<string>;
23
27
  /** Value selected when this radio is checked. */
24
28
  readonly value: _angular_core.InputSignal<unknown>;
@@ -48,7 +52,20 @@ declare class WrRadio {
48
52
  protected readonly checked: _angular_core.Signal<boolean>;
49
53
  /** Effective disabled — this option's own `disabled` or the group's. */
50
54
  protected readonly isDisabled: _angular_core.Signal<boolean>;
55
+ /**
56
+ * Readonly is a GROUP-level state — a single option cannot be read-only while
57
+ * its siblings are not, because picking any of them rewrites the same value.
58
+ * `aria-readonly` therefore lives on the `role="radiogroup"` host and NOT here:
59
+ * role `radio` does not support it.
60
+ */
61
+ protected readonly isReadonly: _angular_core.Signal<boolean>;
51
62
  protected readonly classes: _angular_core.Signal<string>;
63
+ /**
64
+ * Cancel the selection while the group is read-only. `change` never fires for
65
+ * a click whose default was prevented, so this is the only guard the pointer
66
+ * and Space paths need; `onSelect` keeps its own for a synthetic `change`.
67
+ */
68
+ protected onInputClick(event: Event): void;
52
69
  protected onSelect(): void;
53
70
  protected onBlur(): void;
54
71
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrRadio, never>;
@@ -74,6 +91,8 @@ interface WrRadioGroupContext {
74
91
  readonly value: Signal<unknown>;
75
92
  /** Whether the entire group is disabled. */
76
93
  readonly isDisabled: Signal<boolean>;
94
+ /** Whether the entire group refuses edits while staying focusable. */
95
+ readonly isReadonly: Signal<boolean>;
77
96
  /** Select the given value. */
78
97
  select(value: unknown): void;
79
98
  /**
@@ -124,16 +143,32 @@ declare class WrRadioGroup implements FormValueControl<unknown>, WrRadioGroupCon
124
143
  * @default false
125
144
  */
126
145
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
146
+ /**
147
+ * Refuse selection changes while every option stays focusable and the value
148
+ * still submits. Bound automatically from the field's readonly state when used
149
+ * with `[formField]`.
150
+ *
151
+ * Native radios ignore the `readonly` attribute, so the group cancels the
152
+ * activation instead and mirrors the state as `aria-readonly`, which role
153
+ * `radiogroup` supports.
154
+ *
155
+ * @default false
156
+ */
157
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
158
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
159
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
127
160
  /** The selected radio's value. Bound by `[formField]`, or two-way via `[(value)]`. */
128
161
  readonly value: _angular_core.ModelSignal<unknown>;
129
162
  /** Emitted on blur from any child so a bound field can mark itself touched. */
130
163
  readonly touch: _angular_core.OutputEmitterRef<void>;
131
164
  /** Effective disabled state (WrRadioGroupContext). */
132
165
  readonly isDisabled: _angular_core.Signal<boolean>;
166
+ /** Effective readonly state (WrRadioGroupContext). */
167
+ readonly isReadonly: _angular_core.Signal<boolean>;
133
168
  select(value: unknown): void;
134
169
  markTouched(): void;
135
170
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrRadioGroup, never>;
136
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrRadioGroup, "wr-radio-group", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, ["*"], true, never>;
171
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrRadioGroup, "wr-radio-group", never, { "name": { "alias": "name"; "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, ["*"], true, never>;
137
172
  }
138
173
 
139
174
  export { WR_RADIO_GROUP, WrRadio, WrRadioGroup };
@@ -1,3 +1,4 @@
1
+ import * as ngwr_form from 'ngwr/form';
1
2
  import * as _angular_core from '@angular/core';
2
3
  import { FormValueControl } from '@angular/forms/signals';
3
4
 
@@ -56,6 +57,17 @@ declare class WrRating implements FormValueControl<number | null> {
56
57
  /** Transient hover preview — overrides `value` for display when set. */
57
58
  protected readonly hoverValue: _angular_core.WritableSignal<number | null>;
58
59
  protected readonly interactive: _angular_core.Signal<boolean>;
60
+ /**
61
+ * Whether the control keeps its tab stop — `disabled` only, never `readonly`.
62
+ *
63
+ * The two states differ precisely here: a disabled control leaves the tab
64
+ * order, a read-only one stays in it and keeps announcing `aria-valuenow`,
65
+ * because a keyboard user still has to be able to READ a value they cannot
66
+ * change. Driving `tabindex` off `interactive()` collapsed that distinction
67
+ * and made `readonly()` unreachable — with an `aria-describedby` pointing at
68
+ * an error message on an element nobody could focus.
69
+ */
70
+ protected readonly focusable: _angular_core.Signal<boolean>;
59
71
  /** What we actually render — hover wins while hovering. */
60
72
  protected readonly displayValue: _angular_core.Signal<number>;
61
73
  protected readonly slots: _angular_core.Signal<number[]>;
@@ -69,6 +81,8 @@ declare class WrRating implements FormValueControl<number | null> {
69
81
  * interaction rather than cached, so a runtime flip needs no subscription.
70
82
  */
71
83
  private readonly directionality;
84
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
85
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
72
86
  protected readonly classes: _angular_core.Signal<string>;
73
87
  constructor();
74
88
  /** Fill ratio for slot `i` in `[0, 1]` — drives the CSS clip width. */
@@ -81,6 +81,23 @@ declare class WrSegmented<T = unknown> implements FormValueControl<T | null> {
81
81
  * @default false
82
82
  */
83
83
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
84
+ /**
85
+ * Refuse changes while every segment stays focusable and the value still
86
+ * submits. Bound automatically from the field's readonly state when used with
87
+ * `[formField]`.
88
+ *
89
+ * NOTHING is mirrored into ARIA here, deliberately: the strip is a
90
+ * `role="group"` of `aria-pressed` buttons, and ARIA defines `aria-readonly`
91
+ * for neither role — it is a state of `checkbox` / `radiogroup` / `textbox`
92
+ * and their kin, and it is not global. `aria-disabled` is the only attribute
93
+ * that would apply to a button, and it says the wrong thing: these segments
94
+ * are still focusable and the value still submits. So the state is honest in
95
+ * the DOM (`wr-segmented--readonly`) and silent in the accessibility tree
96
+ * rather than announced with a word that means something else.
97
+ *
98
+ * @default false
99
+ */
100
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
84
101
  /** Control size — shares the `--wr-control-*` contract. @default 'md' */
85
102
  readonly size: _angular_core.InputSignal<WrSegmentedSize>;
86
103
  private readonly host;
@@ -169,7 +186,7 @@ declare class WrSegmented<T = unknown> implements FormValueControl<T | null> {
169
186
  */
170
187
  protected onFocusOut(event: FocusEvent): void;
171
188
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSegmented<any>, never>;
172
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSegmented<any>, "wr-segmented", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
189
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSegmented<any>, "wr-segmented", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
173
190
  }
174
191
 
175
192
  export { WrSegmented };
@@ -243,6 +243,20 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
243
243
  * @default false
244
244
  */
245
245
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
246
+ /**
247
+ * Refuse changes while the trigger stays focusable and the value still
248
+ * submits. Bound automatically from the field's readonly state when used with
249
+ * `[formField]`.
250
+ *
251
+ * The panel is where every edit happens, so a read-only select does not open —
252
+ * and with it go the clear button, the chip ×, the tag draft and the search
253
+ * query. The text-input shapes take the native `readonly` attribute, which is
254
+ * what keeps them focusable and selectable where `disabled` would not; every
255
+ * shape mirrors `aria-readonly`, which role `combobox` supports.
256
+ *
257
+ * @default false
258
+ */
259
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
246
260
  /**
247
261
  * Pill-shaped corners on the trigger. Unset falls back to the `select.rounded`
248
262
  * app default from `provideWrConfig()`; `[rounded]="false"` turns a configured
@@ -444,8 +458,18 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
444
458
  /** Tag-mode draft (text currently typed in the inline input). @internal */
445
459
  protected readonly draft: _angular_core.WritableSignal<string>;
446
460
  /**
447
- * Show a clear-all (×) button at the end of the chip row when at
448
- * least one option is selected (multi mode only). @default true
461
+ * Show a clear (×) button once at least one option is selected.
462
+ *
463
+ * NOT multi-only, which this said for a long time and which the template
464
+ * refutes: only the button trigger gates on `isMulti()`, so the chips trigger
465
+ * AND a single `mode="search"` / `[searchable]` select carry it too. The
466
+ * wording mattered little while the default was `true`; it decides what a
467
+ * reader expects to lose now that it is not.
468
+ *
469
+ * The default changed from `true` to `false`: the affordance is opt-in, so a
470
+ * trigger that grew an × on its own no longer does — pass `clearable` to keep
471
+ * it. In `search` mode this also gates Backspace-to-clear on an empty field,
472
+ * since that key is the keyboard twin of this button. @default false
449
473
  */
450
474
  readonly clearable: _angular_core.InputSignalWithTransform<boolean, any>;
451
475
  /**
@@ -498,6 +522,8 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
498
522
  protected readonly hasSelection: _angular_core.Signal<boolean>;
499
523
  /** Effective disabled state. Part of {@link WrSelectContext} for child options. */
500
524
  readonly isDisabled: _angular_core.Signal<boolean>;
525
+ /** Effective readonly state — refuses every write path without removing focus. */
526
+ protected readonly isReadonly: _angular_core.Signal<boolean>;
501
527
  protected readonly classes: _angular_core.Signal<string>;
502
528
  /**
503
529
  * Search-mode dynamic options. Loader results win when the loader is
@@ -674,7 +700,7 @@ declare class WrSelect implements FormValueControl<unknown>, WrSelectContext {
674
700
  private openOverlay;
675
701
  private closeOverlay;
676
702
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSelect, never>;
677
- 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; }; "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>;
703
+ 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>;
678
704
  }
679
705
 
680
706
  /**
@@ -67,6 +67,19 @@ declare class WrSlider implements FormValueControl<WrSliderValue> {
67
67
  * @default false
68
68
  */
69
69
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
70
+ /**
71
+ * Refuse value changes while the thumbs stay focusable and the value still
72
+ * submits. Bound automatically from the field's readonly state when used with
73
+ * `[formField]`.
74
+ *
75
+ * The thumbs keep their tab stop and keep announcing their value — arrow keys,
76
+ * Home / End and the pointer simply move nothing — which is the whole
77
+ * difference from `disabled`, where they would leave the tab order entirely.
78
+ * Mirrored as `aria-readonly`, which role `slider` supports.
79
+ *
80
+ * @default false
81
+ */
82
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
70
83
  /** Render the current value below the track. @default true */
71
84
  readonly showLabel: _angular_core.InputSignalWithTransform<boolean, any>;
72
85
  /**
@@ -210,7 +223,7 @@ declare class WrSlider implements FormValueControl<WrSliderValue> {
210
223
  private percentOf;
211
224
  private emitChange;
212
225
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSlider, never>;
213
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSlider, "wr-slider", never, { "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showLabel": { "alias": "showLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "upperLabel": { "alias": "upperLabel"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
226
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSlider, "wr-slider", never, { "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "showLabel": { "alias": "showLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "upperLabel": { "alias": "upperLabel"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
214
227
  }
215
228
 
216
229
  export { WrSlider };
@@ -1,3 +1,4 @@
1
+ import * as ngwr_form from 'ngwr/form';
1
2
  import * as _angular_core from '@angular/core';
2
3
  import { FormCheckboxControl } from '@angular/forms/signals';
3
4
 
@@ -27,7 +28,10 @@ declare class WrSwitch implements FormCheckboxControl {
27
28
  * label is empty and the input has no name at all.
28
29
  */
29
30
  readonly ariaLabel: _angular_core.InputSignal<string | null>;
30
- /** Stable id used to associate the native input with its label. */
31
+ /**
32
+ * Stable id used to associate the native input with its label. Lands on the
33
+ * inner `<input>`; the host never keeps it.
34
+ */
31
35
  readonly id: _angular_core.InputSignal<string>;
32
36
  /**
33
37
  * Disable the switch. Bound automatically from the field's disabled state
@@ -36,6 +40,20 @@ declare class WrSwitch implements FormCheckboxControl {
36
40
  * @default false
37
41
  */
38
42
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
43
+ /**
44
+ * Refuse edits while staying focusable and submittable. Bound automatically
45
+ * from the field's readonly state when used with `[formField]`.
46
+ *
47
+ * A native checkbox ignores the `readonly` attribute, so this cancels the
48
+ * click's activation behaviour instead — which covers Space too, since the key
49
+ * arrives as a click — and mirrors the state as `aria-readonly`, which role
50
+ * `switch` supports.
51
+ *
52
+ * @default false
53
+ */
54
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
55
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
56
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
39
57
  /**
40
58
  * Control size — shares the `--wr-control-*` contract. Unset falls back to the
41
59
  * `switch.size` app default from `provideWrConfig()`. @default 'md'
@@ -48,10 +66,16 @@ declare class WrSwitch implements FormCheckboxControl {
48
66
  /** Emitted on blur so a bound field can mark itself touched. */
49
67
  readonly touch: _angular_core.OutputEmitterRef<void>;
50
68
  protected readonly classes: _angular_core.Signal<string>;
69
+ /**
70
+ * Cancel the toggle while readonly. `change` never fires for a click whose
71
+ * default was prevented, so this is the only guard the pointer and Space paths
72
+ * need; `onInputChange` keeps its own for a synthetic `change`.
73
+ */
74
+ protected onInputClick(event: Event): void;
51
75
  protected onInputChange(event: Event): void;
52
76
  protected onInputBlur(): void;
53
77
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSwitch, never>;
54
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSwitch, "wr-switch", never, { "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "touch": "touch"; }, never, ["*"], true, never>;
78
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSwitch, "wr-switch", never, { "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "touch": "touch"; }, never, ["*"], true, never>;
55
79
  }
56
80
 
57
81
  export { WrSwitch };
@@ -1,3 +1,4 @@
1
+ import * as ngwr_form from 'ngwr/form';
1
2
  import * as _angular_core from '@angular/core';
2
3
  import { ElementRef } from '@angular/core';
3
4
  import { FormValueControl } from '@angular/forms/signals';
@@ -68,6 +69,8 @@ declare class WrTextarea implements FormValueControl<string> {
68
69
  protected readonly native: _angular_core.Signal<ElementRef<HTMLTextAreaElement>>;
69
70
  /** Resize direction, gated by `resizable` (false → 'none'). */
70
71
  protected readonly effectiveResize: _angular_core.Signal<WrTextareaResize>;
72
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
73
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
71
74
  protected readonly classes: _angular_core.Signal<string>;
72
75
  /** Show the corner grip (hidden when direction is 'none' / autosize / disabled). */
73
76
  protected readonly showHandle: _angular_core.Signal<boolean>;
@@ -159,6 +159,11 @@ declare const WR_THEME_CONFIG: InjectionToken<WrThemeConfig>;
159
159
  * - Persists the selected mode via {@link WrStorage} (defaults to
160
160
  * `localStorage`; swap the storage engine globally to change where).
161
161
  *
162
+ * A configured `attribute` has to be given to the STYLESHEET too — a CSS
163
+ * selector cannot read a provider value — so pair it with
164
+ * `@use 'ngwr' with ($theme-attribute: '...')`. In dev mode the service compares
165
+ * the two and warns when they disagree.
166
+ *
162
167
  * @example
163
168
  * ```ts
164
169
  * const theme = inject(WrTheme);
@@ -183,6 +188,25 @@ declare class WrTheme {
183
188
  set(mode: WrThemeMode): void;
184
189
  /** Cycle: light → dark → light (skips auto). */
185
190
  toggle(): void;
191
+ /**
192
+ * Dev-mode check that the STYLESHEET keys on the same attribute this service
193
+ * writes.
194
+ *
195
+ * `attribute` is a runtime value and a CSS selector cannot read one, so the
196
+ * dark block is keyed on a Sass variable (`$theme-attribute`) the consumer
197
+ * configures separately. That makes disagreement possible, and disagreement is
198
+ * silent in the worst way: the service resolves `dark`, writes the attribute,
199
+ * reports success — and the page stays light forever, because nothing matches.
200
+ *
201
+ * The compiled theme publishes the name it keys on as `--wr-theme-attribute`,
202
+ * which is what this reads. An empty value means no ngwr stylesheet is loaded
203
+ * (a unit test, a consumer bundling their own CSS) or that it predates v13, so
204
+ * the check stays quiet — it can only fire on a real mismatch, never on an
205
+ * absence it cannot interpret.
206
+ *
207
+ * Production builds drop the call entirely via `isDevMode()` tree-shaking.
208
+ */
209
+ private warnOnAttributeMismatch;
186
210
  private readPersisted;
187
211
  private persist;
188
212
  static ɵfac: i0.ɵɵFactoryDeclaration<WrTheme, never>;
@@ -1,4 +1,5 @@
1
1
  import * as ngwr_i18n from 'ngwr/i18n';
2
+ import * as ngwr_form from 'ngwr/form';
2
3
  import * as _angular_core from '@angular/core';
3
4
  import { FormValueControl } from '@angular/forms/signals';
4
5
 
@@ -74,6 +75,21 @@ declare class WrTransfer implements FormValueControl<readonly unknown[]> {
74
75
  readonly touch: _angular_core.OutputEmitterRef<void>;
75
76
  /** Disable the whole control. @default false */
76
77
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
78
+ /**
79
+ * Refuse changes to the value while both panes stay focusable and readable.
80
+ * Bound automatically from the field's readonly state when used with
81
+ * `[formField]`.
82
+ *
83
+ * The move buttons go inert and the row checkboxes go read-only; SEARCH keeps
84
+ * working, because filtering a pane changes what is shown and not what is
85
+ * chosen. No `aria-readonly` on the host: role `group` does not support the
86
+ * state, so each row's checkbox mirrors its own instead.
87
+ *
88
+ * @default false
89
+ */
90
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
91
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
92
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
77
93
  /** Show a filter box above each pane. @default false */
78
94
  readonly searchable: _angular_core.InputSignalWithTransform<boolean, any>;
79
95
  /** Heading above the left pane. Falls back to `transfer.source`. */
@@ -126,7 +142,7 @@ declare class WrTransfer implements FormValueControl<readonly unknown[]> {
126
142
  /** Filter, then derive the header state from what survived. */
127
143
  private pane;
128
144
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrTransfer, never>;
129
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTransfer, "wr-transfer", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "sourceTitle": { "alias": "sourceTitle"; "required": false; "isSignal": true; }; "targetTitle": { "alias": "targetTitle"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "selectAllLabel": { "alias": "selectAllLabel"; "required": false; "isSignal": true; }; "toTargetLabel": { "alias": "toTargetLabel"; "required": false; "isSignal": true; }; "toSourceLabel": { "alias": "toSourceLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
145
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTransfer, "wr-transfer", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "sourceTitle": { "alias": "sourceTitle"; "required": false; "isSignal": true; }; "targetTitle": { "alias": "targetTitle"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "selectAllLabel": { "alias": "selectAllLabel"; "required": false; "isSignal": true; }; "toTargetLabel": { "alias": "toTargetLabel"; "required": false; "isSignal": true; }; "toSourceLabel": { "alias": "toSourceLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
130
146
  }
131
147
 
132
148
  export { WrTransfer };
@@ -1,4 +1,5 @@
1
1
  import * as ngwr_i18n from 'ngwr/i18n';
2
+ import * as ngwr_form from 'ngwr/form';
2
3
  import * as _angular_core from '@angular/core';
3
4
  import { TemplateRef } from '@angular/core';
4
5
  import { FormValueControl } from '@angular/forms/signals';
@@ -89,6 +90,25 @@ declare class WrTree<TId = string> implements FormValueControl<unknown> {
89
90
  * @default false
90
91
  */
91
92
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
93
+ /**
94
+ * Refuse selection changes while the tree stays focusable and the value still
95
+ * submits. Bound automatically from the field's readonly state when used with
96
+ * `[formField]`.
97
+ *
98
+ * Expanding and collapsing keep working: a branch is NAVIGATION, not a value,
99
+ * so a read-only tree is still browsable — it is picking and un-picking that
100
+ * stops. In `overlay` mode the trigger additionally refuses to open, because
101
+ * there the panel exists only to choose from and it already shows what is
102
+ * chosen.
103
+ *
104
+ * `aria-readonly` rides on the combobox trigger only; role `tree` does not
105
+ * support the state, so the inline shape has nothing valid to mirror it onto.
106
+ *
107
+ * @default false
108
+ */
109
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
110
+ /** The surrounding `<wr-form-field>`'s error state. @internal */
111
+ protected readonly fieldAria: ngwr_form.WrFormFieldAria;
92
112
  /** Render shape. @default 'inline' */
93
113
  readonly openOn: _angular_core.InputSignal<"inline" | "overlay">;
94
114
  /** Placeholder shown on the trigger when no node is selected. */
@@ -274,7 +294,7 @@ declare class WrTree<TId = string> implements FormValueControl<unknown> {
274
294
  private openOverlay;
275
295
  private closeOverlay;
276
296
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrTree<any>, never>;
277
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTree<any>, "wr-tree", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "openOn": { "alias": "openOn"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "maxTagCount": { "alias": "maxTagCount"; "required": false; "isSignal": true; }; "defaultExpandAll": { "alias": "defaultExpandAll"; "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; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "expanded": "expandedChange"; "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
297
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTree<any>, "wr-tree", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "openOn": { "alias": "openOn"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "maxTagCount": { "alias": "maxTagCount"; "required": false; "isSignal": true; }; "defaultExpandAll": { "alias": "defaultExpandAll"; "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; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "expanded": "expandedChange"; "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
278
298
  }
279
299
 
280
300
  export { WrTree };
@@ -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 = "12.1.0";
19
+ declare const NGWR_VERSION = "13.0.0";
20
20
 
21
21
  /**
22
22
  * @license
@@ -1,38 +1,15 @@
1
- // Pull the whole theme so a standalone `@use 'ngwr/<name>'` brings in every
2
- // design token this stylesheet references. Sass deduplicates `@use` per
3
- // compilation, so the umbrella sheet still emits the theme only once.
4
- @use '../../theme/styles' as theme;
5
-
6
- .wr-typewriter {
7
- --wr-typewriter-cursor-blink: 0.5s;
8
-
9
- display: inline-flex;
10
- align-items: baseline;
11
-
12
- &__content {
13
- white-space: pre;
14
- }
15
-
16
- &__cursor {
17
- display: inline-block;
18
- margin-inline-start: 1px;
19
- animation: wr-typewriter-blink var(--wr-typewriter-cursor-blink) ease-in-out infinite alternate;
20
- }
21
- }
22
-
23
- @keyframes wr-typewriter-blink {
24
- from {
25
- opacity: 1;
26
- }
27
- to {
28
- opacity: 0;
29
- }
30
- }
31
-
32
- // Reduced motion: solid cursor — the blink is decorative.
33
- @media (prefers-reduced-motion: reduce) {
34
- .wr-typewriter__cursor {
35
- animation: none;
36
- opacity: 1;
37
- }
38
- }
1
+ // Public Sass entry for `@use 'ngwr/typewriter'`.
2
+ //
3
+ // Pulls the whole theme so a standalone import still brings in every design
4
+ // token these rules reference, then loads the rules themselves from `_rules`.
5
+ //
6
+ // The split is what keeps the token layer out of the JavaScript bundle.
7
+ // `typewriter.scss` is the component's `styleUrl`, and a component stylesheet is
8
+ // its OWN Sass compilation — `@use` only deduplicates within one. So while the
9
+ // umbrella sheet emits the theme once, forwarding it from here would inline a
10
+ // second, byte-identical copy of `:root`, `[data-theme='dark']` and the
11
+ // box-sizing reset into the compiled component styles, which ng-packagr then
12
+ // embeds in the FESM bundle as a string. `typewriter.scss` forwards `_rules`
13
+ // instead, so it carries this component's own CSS and nothing else.
14
+ @use '../../theme/styles';
15
+ @forward 'rules';
@@ -0,0 +1,33 @@
1
+ .wr-typewriter {
2
+ --wr-typewriter-cursor-blink: 0.5s;
3
+
4
+ display: inline-flex;
5
+ align-items: baseline;
6
+
7
+ &__content {
8
+ white-space: pre;
9
+ }
10
+
11
+ &__cursor {
12
+ display: inline-block;
13
+ margin-inline-start: 1px;
14
+ animation: wr-typewriter-blink var(--wr-typewriter-cursor-blink) ease-in-out infinite alternate;
15
+ }
16
+ }
17
+
18
+ @keyframes wr-typewriter-blink {
19
+ from {
20
+ opacity: 1;
21
+ }
22
+ to {
23
+ opacity: 0;
24
+ }
25
+ }
26
+
27
+ // Reduced motion: solid cursor — the blink is decorative.
28
+ @media (prefers-reduced-motion: reduce) {
29
+ .wr-typewriter__cursor {
30
+ animation: none;
31
+ opacity: 1;
32
+ }
33
+ }
@@ -1 +1 @@
1
- @forward './styles';
1
+ @forward './styles/rules';
@@ -1,32 +1,15 @@
1
- // Pull the whole theme so a standalone `@use 'ngwr/<name>'` brings in every
2
- // design token this stylesheet references. Sass deduplicates `@use` per
3
- // compilation, so the umbrella sheet still emits the theme only once.
4
- @use '../../theme/styles' as theme;
5
-
6
- // Fixed-size virtual scroll wrapper. Most of the layout work is done by
7
- // CDK's `<cdk-virtual-scroll-viewport>`; this stylesheet just makes the
8
- // host a block-level container and tames default overflow behaviour.
9
-
10
- .wr-virtual-scroll {
11
- display: block;
12
- width: 100%;
13
- overflow: hidden;
14
-
15
- &__viewport {
16
- width: 100%;
17
- height: 100%;
18
- // CDK already sets `overflow: auto`; just add a discreet scrollbar
19
- // skin via the platform defaults — a discreet custom thumb that still matches the
20
- // host application's chrome.
21
- scrollbar-width: thin;
22
-
23
- &::-webkit-scrollbar {
24
- width: 0.5rem;
25
- height: 0.5rem;
26
- }
27
- &::-webkit-scrollbar-thumb {
28
- background: rgba(var(--wr-color-on-surface-rgb), 0.2);
29
- border-radius: 999px;
30
- }
31
- }
32
- }
1
+ // Public Sass entry for `@use 'ngwr/virtual-scroll'`.
2
+ //
3
+ // Pulls the whole theme so a standalone import still brings in every design
4
+ // token these rules reference, then loads the rules themselves from `_rules`.
5
+ //
6
+ // The split is what keeps the token layer out of the JavaScript bundle.
7
+ // `virtual-scroll.scss` is the component's `styleUrl`, and a component stylesheet is
8
+ // its OWN Sass compilation — `@use` only deduplicates within one. So while the
9
+ // umbrella sheet emits the theme once, forwarding it from here would inline a
10
+ // second, byte-identical copy of `:root`, `[data-theme='dark']` and the
11
+ // box-sizing reset into the compiled component styles, which ng-packagr then
12
+ // embeds in the FESM bundle as a string. `virtual-scroll.scss` forwards `_rules`
13
+ // instead, so it carries this component's own CSS and nothing else.
14
+ @use '../../theme/styles';
15
+ @forward 'rules';