@radix-ng/primitives 1.0.6 → 1.0.8

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 (83) hide show
  1. package/aspect-ratio/README.md +1 -1
  2. package/fesm2022/radix-ng-primitives-accordion.mjs +6 -1
  3. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  4. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs +9 -34
  5. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
  6. package/fesm2022/radix-ng-primitives-autocomplete.mjs +43 -9
  7. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-avatar.mjs +69 -18
  9. package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-checkbox.mjs +93 -16
  11. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-collapsible.mjs +4 -3
  13. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-combobox.mjs +43 -9
  15. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-core.mjs +208 -2
  17. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-date-field.mjs +50 -9
  19. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-editable.mjs +31 -5
  21. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-field.mjs +276 -58
  23. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-form.mjs +111 -27
  25. package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-input.mjs +16 -6
  27. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-label.mjs +5 -4
  29. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-number-field.mjs +39 -10
  31. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-progress.mjs +37 -22
  33. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  34. package/fesm2022/radix-ng-primitives-radio.mjs +18 -9
  35. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  36. package/fesm2022/radix-ng-primitives-scroll-area.mjs +4 -4
  37. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-select.mjs +26 -8
  39. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  40. package/fesm2022/radix-ng-primitives-separator.mjs +7 -13
  41. package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
  42. package/fesm2022/radix-ng-primitives-signal-forms.mjs +184 -0
  43. package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -0
  44. package/fesm2022/radix-ng-primitives-slider.mjs +25 -10
  45. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  46. package/fesm2022/radix-ng-primitives-switch.mjs +32 -8
  47. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  48. package/fesm2022/radix-ng-primitives-tabs.mjs +4 -4
  49. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  50. package/fesm2022/radix-ng-primitives-time-field.mjs +49 -9
  51. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  52. package/fesm2022/radix-ng-primitives-toggle-group.mjs +33 -16
  53. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  54. package/fesm2022/radix-ng-primitives-toggle.mjs +24 -29
  55. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  56. package/fesm2022/radix-ng-primitives-toolbar.mjs +15 -2
  57. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  58. package/package.json +11 -1
  59. package/types/radix-ng-primitives-accordion.d.ts +1 -0
  60. package/types/radix-ng-primitives-aspect-ratio.d.ts +10 -23
  61. package/types/radix-ng-primitives-autocomplete.d.ts +21 -2
  62. package/types/radix-ng-primitives-avatar.d.ts +51 -25
  63. package/types/radix-ng-primitives-checkbox.d.ts +78 -101
  64. package/types/radix-ng-primitives-combobox.d.ts +51 -2
  65. package/types/radix-ng-primitives-core.d.ts +206 -3
  66. package/types/radix-ng-primitives-date-field.d.ts +27 -2
  67. package/types/radix-ng-primitives-editable.d.ts +15 -2
  68. package/types/radix-ng-primitives-field.d.ts +165 -236
  69. package/types/radix-ng-primitives-form.d.ts +122 -37
  70. package/types/radix-ng-primitives-input.d.ts +8 -1
  71. package/types/radix-ng-primitives-label.d.ts +3 -2
  72. package/types/radix-ng-primitives-number-field.d.ts +15 -4
  73. package/types/radix-ng-primitives-progress.d.ts +59 -121
  74. package/types/radix-ng-primitives-radio.d.ts +7 -3
  75. package/types/radix-ng-primitives-select.d.ts +11 -3
  76. package/types/radix-ng-primitives-separator.d.ts +0 -7
  77. package/types/radix-ng-primitives-signal-forms.d.ts +97 -0
  78. package/types/radix-ng-primitives-slider.d.ts +9 -7
  79. package/types/radix-ng-primitives-switch.d.ts +15 -2
  80. package/types/radix-ng-primitives-time-field.d.ts +26 -2
  81. package/types/radix-ng-primitives-toggle-group.d.ts +13 -7
  82. package/types/radix-ng-primitives-toggle.d.ts +8 -8
  83. package/types/radix-ng-primitives-toolbar.d.ts +2 -0
@@ -1,7 +1,8 @@
1
- import * as _radix_ng_primitives_field from '@radix-ng/primitives/field';
2
1
  import * as _angular_core from '@angular/core';
2
+ import { Signal } from '@angular/core';
3
+ import * as _radix_ng_primitives_field from '@radix-ng/primitives/field';
3
4
  import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
4
- import { BooleanInput, RdxValidationError } from '@radix-ng/primitives/core';
5
+ import { BooleanInput, RdxValidationMode, RdxValidationError } from '@radix-ng/primitives/core';
5
6
 
6
7
  /**
7
8
  * Connects a form control to the field label, description, error, and state.
@@ -9,32 +10,7 @@ import { BooleanInput, RdxValidationError } from '@radix-ng/primitives/core';
9
10
  * @group Components
10
11
  */
11
12
  declare class RdxFieldControl {
12
- protected readonly rootContext: {
13
- controlId: _angular_core.WritableSignal<string>;
14
- name: _angular_core.InputSignal<string | undefined>;
15
- descriptionIds: _angular_core.WritableSignal<string[]>;
16
- errorIds: _angular_core.WritableSignal<string[]>;
17
- messages: _angular_core.Signal<string[]>;
18
- notifyEdited: () => void;
19
- invalidState: _angular_core.Signal<boolean>;
20
- disabledState: _angular_core.Signal<boolean>;
21
- requiredState: _angular_core.Signal<boolean>;
22
- dirtyState: _angular_core.Signal<boolean>;
23
- touchedState: _angular_core.Signal<boolean>;
24
- filledState: _angular_core.Signal<boolean>;
25
- focusedState: _angular_core.Signal<boolean>;
26
- setControlId: (id: string) => void;
27
- addDescriptionId: (id: string) => void;
28
- removeDescriptionId: (id: string) => void;
29
- addErrorId: (id: string) => void;
30
- removeErrorId: (id: string) => void;
31
- setFocused: (value: boolean) => void;
32
- setFilled: (value: boolean) => void;
33
- setDirty: (value: boolean) => void;
34
- setTouched: (value: boolean) => void;
35
- setStateProvider: (provider: _radix_ng_primitives_field.RdxFieldState | null) => _radix_ng_primitives_field.RdxFieldState | null;
36
- hasStateProvider: _angular_core.Signal<boolean>;
37
- };
13
+ protected readonly rootContext: _radix_ng_primitives_field.RdxFieldRootContext;
38
14
  private readonly elementRef;
39
15
  private initialValue;
40
16
  /**
@@ -61,32 +37,7 @@ declare class RdxFieldControl {
61
37
  * @group Components
62
38
  */
63
39
  declare class RdxFieldDescription {
64
- protected readonly rootContext: {
65
- controlId: _angular_core.WritableSignal<string>;
66
- name: _angular_core.InputSignal<string | undefined>;
67
- descriptionIds: _angular_core.WritableSignal<string[]>;
68
- errorIds: _angular_core.WritableSignal<string[]>;
69
- messages: _angular_core.Signal<string[]>;
70
- notifyEdited: () => void;
71
- invalidState: _angular_core.Signal<boolean>;
72
- disabledState: _angular_core.Signal<boolean>;
73
- requiredState: _angular_core.Signal<boolean>;
74
- dirtyState: _angular_core.Signal<boolean>;
75
- touchedState: _angular_core.Signal<boolean>;
76
- filledState: _angular_core.Signal<boolean>;
77
- focusedState: _angular_core.Signal<boolean>;
78
- setControlId: (id: string) => void;
79
- addDescriptionId: (id: string) => void;
80
- removeDescriptionId: (id: string) => void;
81
- addErrorId: (id: string) => void;
82
- removeErrorId: (id: string) => void;
83
- setFocused: (value: boolean) => void;
84
- setFilled: (value: boolean) => void;
85
- setDirty: (value: boolean) => void;
86
- setTouched: (value: boolean) => void;
87
- setStateProvider: (provider: _radix_ng_primitives_field.RdxFieldState | null) => _radix_ng_primitives_field.RdxFieldState | null;
88
- hasStateProvider: _angular_core.Signal<boolean>;
89
- };
40
+ protected readonly rootContext: _radix_ng_primitives_field.RdxFieldRootContext;
90
41
  /**
91
42
  * Description id.
92
43
  *
@@ -105,32 +56,7 @@ declare class RdxFieldDescription {
105
56
  * @group Components
106
57
  */
107
58
  declare class RdxFieldError {
108
- protected readonly rootContext: {
109
- controlId: _angular_core.WritableSignal<string>;
110
- name: _angular_core.InputSignal<string | undefined>;
111
- descriptionIds: _angular_core.WritableSignal<string[]>;
112
- errorIds: _angular_core.WritableSignal<string[]>;
113
- messages: _angular_core.Signal<string[]>;
114
- notifyEdited: () => void;
115
- invalidState: _angular_core.Signal<boolean>;
116
- disabledState: _angular_core.Signal<boolean>;
117
- requiredState: _angular_core.Signal<boolean>;
118
- dirtyState: _angular_core.Signal<boolean>;
119
- touchedState: _angular_core.Signal<boolean>;
120
- filledState: _angular_core.Signal<boolean>;
121
- focusedState: _angular_core.Signal<boolean>;
122
- setControlId: (id: string) => void;
123
- addDescriptionId: (id: string) => void;
124
- removeDescriptionId: (id: string) => void;
125
- addErrorId: (id: string) => void;
126
- removeErrorId: (id: string) => void;
127
- setFocused: (value: boolean) => void;
128
- setFilled: (value: boolean) => void;
129
- setDirty: (value: boolean) => void;
130
- setTouched: (value: boolean) => void;
131
- setStateProvider: (provider: _radix_ng_primitives_field.RdxFieldState | null) => _radix_ng_primitives_field.RdxFieldState | null;
132
- hasStateProvider: _angular_core.Signal<boolean>;
133
- };
59
+ protected readonly rootContext: _radix_ng_primitives_field.RdxFieldRootContext;
134
60
  /**
135
61
  * Error message id.
136
62
  *
@@ -138,8 +64,9 @@ declare class RdxFieldError {
138
64
  */
139
65
  readonly id: _angular_core.InputSignal<string>;
140
66
  /**
141
- * The field's external messages (state provider's, then enclosing Form's), `[]` when none. Render
142
- * them explicitly via the `exportAs` reference the directive never injects text content itself:
67
+ * The field's validation messages — client (provider / form name-routing, once `validationMode`
68
+ * reveals them) then server (the Form's `errors` input, always); `[]` when none. Render them
69
+ * explicitly via the `exportAs` reference — the directive never injects text content itself:
143
70
  * `<p rdxFieldError #err="rdxFieldError">{{ err.messages().join(' ') }}</p>`.
144
71
  */
145
72
  readonly messages: _angular_core.Signal<string[]>;
@@ -149,51 +76,6 @@ declare class RdxFieldError {
149
76
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldError, "[rdxFieldError]", ["rdxFieldError"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
150
77
  }
151
78
 
152
- /**
153
- * Labels the field control.
154
- *
155
- * @group Components
156
- */
157
- declare class RdxFieldLabel {
158
- protected readonly rootContext: {
159
- controlId: _angular_core.WritableSignal<string>;
160
- name: _angular_core.InputSignal<string | undefined>;
161
- descriptionIds: _angular_core.WritableSignal<string[]>;
162
- errorIds: _angular_core.WritableSignal<string[]>;
163
- messages: _angular_core.Signal<string[]>;
164
- notifyEdited: () => void;
165
- invalidState: _angular_core.Signal<boolean>;
166
- disabledState: _angular_core.Signal<boolean>;
167
- requiredState: _angular_core.Signal<boolean>;
168
- dirtyState: _angular_core.Signal<boolean>;
169
- touchedState: _angular_core.Signal<boolean>;
170
- filledState: _angular_core.Signal<boolean>;
171
- focusedState: _angular_core.Signal<boolean>;
172
- setControlId: (id: string) => void;
173
- addDescriptionId: (id: string) => void;
174
- removeDescriptionId: (id: string) => void;
175
- addErrorId: (id: string) => void;
176
- removeErrorId: (id: string) => void;
177
- setFocused: (value: boolean) => void;
178
- setFilled: (value: boolean) => void;
179
- setDirty: (value: boolean) => void;
180
- setTouched: (value: boolean) => void;
181
- setStateProvider: (provider: _radix_ng_primitives_field.RdxFieldState | null) => _radix_ng_primitives_field.RdxFieldState | null;
182
- hasStateProvider: _angular_core.Signal<boolean>;
183
- };
184
- /**
185
- * Label id.
186
- *
187
- * @group Props
188
- */
189
- readonly id: _angular_core.InputSignal<string>;
190
- readonly htmlFor: () => string;
191
- constructor();
192
- protected readonly dataAttr: (value: boolean) => "" | undefined;
193
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldLabel, never>;
194
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldLabel, "[rdxFieldLabel]", ["rdxFieldLabel"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
195
- }
196
-
197
79
  /**
198
80
  * External owner of field state. An adapter (e.g. a future Signal Forms
199
81
  * `[rdxSignalField]` directive, or a Reactive Forms bridge) registers one via
@@ -207,6 +89,11 @@ declare class RdxFieldLabel {
207
89
  * See ADR 0004 and `signal-forms-readiness.md` (prep #4).
208
90
  */
209
91
  interface RdxFieldState {
92
+ /**
93
+ * The control's **actual** invalidity (ungated). The Field decides *when* to display it from its
94
+ * `validationMode` (e.g. only after blur) — the adapter just reports the real state. A non-empty
95
+ * `errors()` also counts as invalid.
96
+ */
210
97
  invalid?: () => boolean;
211
98
  disabled?: () => boolean;
212
99
  required?: () => boolean;
@@ -215,64 +102,33 @@ interface RdxFieldState {
215
102
  filled?: () => boolean;
216
103
  focused?: () => boolean;
217
104
  /**
218
- * Optional source of error *content* (not just the invalid boolean). When provided and non-empty
219
- * it forces `invalidState` true, and its messages (`message ?? kind` per error) surface through
220
- * `RdxFieldError.messages()` ahead of any enclosing Form's external messages. Uses `core`'s
221
- * framework-free shim type so the seam stays free of `@angular/forms/signals` (ADR 0004 amendment).
105
+ * Optional source of error *content* (not just the invalid boolean). A non-empty list marks the field
106
+ * **actually** invalid (client validation) and its messages (`message ?? kind` per error) surface
107
+ * through `RdxFieldError.messages()` once the field's `validationMode` reveals client validity, ahead of
108
+ * any enclosing Form's server messages. Uses `core`'s framework-free shim type so the seam stays free of
109
+ * `@angular/forms/signals` (ADR 0004 amendment).
222
110
  */
223
111
  errors?: () => RdxValidationError[];
224
112
  }
225
- declare const fieldRootContext: () => {
226
- controlId: _angular_core.WritableSignal<string>;
227
- name: _angular_core.InputSignal<string | undefined>;
228
- descriptionIds: _angular_core.WritableSignal<string[]>;
229
- errorIds: _angular_core.WritableSignal<string[]>;
230
- /** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
231
- messages: _angular_core.Signal<string[]>;
232
- /** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
233
- notifyEdited: () => void;
234
- invalidState: _angular_core.Signal<boolean>;
235
- disabledState: _angular_core.Signal<boolean>;
236
- requiredState: _angular_core.Signal<boolean>;
237
- dirtyState: _angular_core.Signal<boolean>;
238
- touchedState: _angular_core.Signal<boolean>;
239
- filledState: _angular_core.Signal<boolean>;
240
- focusedState: _angular_core.Signal<boolean>;
241
- setControlId: (id: string) => void;
242
- addDescriptionId: (id: string) => void;
243
- removeDescriptionId: (id: string) => void;
244
- addErrorId: (id: string) => void;
245
- removeErrorId: (id: string) => void;
246
- setFocused: (value: boolean) => void;
247
- setFilled: (value: boolean) => void;
248
- setDirty: (value: boolean) => void;
249
- setTouched: (value: boolean) => void;
250
- /**
251
- * Register (or clear with `null`) an external owner of field state.
252
- * While a provider is registered, any state it exposes takes precedence
253
- * over the root inputs and the DOM-derived values. Returns the previous
254
- * provider so adapters can restore it on teardown.
255
- */
256
- setStateProvider: (provider: RdxFieldState | null) => RdxFieldState | null;
257
- hasStateProvider: _angular_core.Signal<boolean>;
258
- };
259
- type RdxFieldRootContext = ReturnType<typeof fieldRootContext>;
260
- declare const injectFieldRootContext: _radix_ng_primitives_core.InjectContext<{
261
- controlId: _angular_core.WritableSignal<string>;
262
- name: _angular_core.InputSignal<string | undefined>;
263
- descriptionIds: _angular_core.WritableSignal<string[]>;
264
- errorIds: _angular_core.WritableSignal<string[]>;
265
- /** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
266
- messages: _angular_core.Signal<string[]>;
267
- /** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
113
+ interface RdxFieldRootContext {
114
+ controlId: Signal<string>;
115
+ name: Signal<string | undefined>;
116
+ descriptionIds: Signal<string[]>;
117
+ errorIds: Signal<string[]>;
118
+ messages: Signal<string[]>;
268
119
  notifyEdited: () => void;
269
- invalidState: _angular_core.Signal<boolean>;
270
- disabledState: _angular_core.Signal<boolean>;
271
- requiredState: _angular_core.Signal<boolean>;
272
- dirtyState: _angular_core.Signal<boolean>;
273
- touchedState: _angular_core.Signal<boolean>;
274
- filledState: _angular_core.Signal<boolean>;
275
- focusedState: _angular_core.Signal<boolean>;
120
+ /** Tri-state *displayed* validity (`true` valid / `false` invalid / `null` neutral), gated by the
121
+ * field's `validationMode`. The source for `data-valid` / `data-invalid` on the field and its controls. */
122
+ validState: Signal<boolean | null>;
123
+ /** Whether the enclosing Form has had a submit attempted (always `false` with no Form). */
124
+ formSubmitAttempted: Signal<boolean>;
125
+ invalidState: Signal<boolean>;
126
+ disabledState: Signal<boolean>;
127
+ requiredState: Signal<boolean>;
128
+ dirtyState: Signal<boolean>;
129
+ touchedState: Signal<boolean>;
130
+ filledState: Signal<boolean>;
131
+ focusedState: Signal<boolean>;
276
132
  setControlId: (id: string) => void;
277
133
  addDescriptionId: (id: string) => void;
278
134
  removeDescriptionId: (id: string) => void;
@@ -282,49 +138,17 @@ declare const injectFieldRootContext: _radix_ng_primitives_core.InjectContext<{
282
138
  setFilled: (value: boolean) => void;
283
139
  setDirty: (value: boolean) => void;
284
140
  setTouched: (value: boolean) => void;
285
- /**
286
- * Register (or clear with `null`) an external owner of field state.
287
- * While a provider is registered, any state it exposes takes precedence
288
- * over the root inputs and the DOM-derived values. Returns the previous
289
- * provider so adapters can restore it on teardown.
290
- */
291
141
  setStateProvider: (provider: RdxFieldState | null) => RdxFieldState | null;
292
- hasStateProvider: _angular_core.Signal<boolean>;
293
- }>;
294
- declare const provideFieldRootContext: (useFactory: () => {
295
- controlId: _angular_core.WritableSignal<string>;
296
- name: _angular_core.InputSignal<string | undefined>;
297
- descriptionIds: _angular_core.WritableSignal<string[]>;
298
- errorIds: _angular_core.WritableSignal<string[]>;
299
- /** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
300
- messages: _angular_core.Signal<string[]>;
301
- /** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
302
- notifyEdited: () => void;
303
- invalidState: _angular_core.Signal<boolean>;
304
- disabledState: _angular_core.Signal<boolean>;
305
- requiredState: _angular_core.Signal<boolean>;
306
- dirtyState: _angular_core.Signal<boolean>;
307
- touchedState: _angular_core.Signal<boolean>;
308
- filledState: _angular_core.Signal<boolean>;
309
- focusedState: _angular_core.Signal<boolean>;
310
- setControlId: (id: string) => void;
311
- addDescriptionId: (id: string) => void;
312
- removeDescriptionId: (id: string) => void;
313
- addErrorId: (id: string) => void;
314
- removeErrorId: (id: string) => void;
315
- setFocused: (value: boolean) => void;
316
- setFilled: (value: boolean) => void;
317
- setDirty: (value: boolean) => void;
318
- setTouched: (value: boolean) => void;
319
142
  /**
320
- * Register (or clear with `null`) an external owner of field state.
321
- * While a provider is registered, any state it exposes takes precedence
322
- * over the root inputs and the DOM-derived values. Returns the previous
323
- * provider so adapters can restore it on teardown.
143
+ * Identity-checked teardown: roll the slot back to `previous` only if `provider` is still the
144
+ * active one. A newer adapter that registered after `provider` (create-before-destroy during a
145
+ * view swap) owns the slot and must not be clobbered by the old adapter's destroy.
324
146
  */
325
- setStateProvider: (provider: RdxFieldState | null) => RdxFieldState | null;
326
- hasStateProvider: _angular_core.Signal<boolean>;
327
- }) => _angular_core.Provider;
147
+ clearStateProvider: (provider: RdxFieldState | null, previous: RdxFieldState | null) => void;
148
+ hasStateProvider: Signal<boolean>;
149
+ }
150
+ declare const injectFieldRootContext: _radix_ng_primitives_core.InjectContext<RdxFieldRootContext>;
151
+ declare const provideFieldRootContext: (useFactory: () => RdxFieldRootContext) => _angular_core.Provider;
328
152
  /**
329
153
  * Groups a form control with its label, description, error message, and field state.
330
154
  *
@@ -385,6 +209,13 @@ declare class RdxFieldRoot {
385
209
  * @group Props
386
210
  */
387
211
  readonly name: _angular_core.InputSignal<string | undefined>;
212
+ /**
213
+ * Overrides when this field reveals its validity (error styling + message). Falls back to the
214
+ * enclosing `rdxFormRoot`'s `validationMode`, then `'onBlur'`. Server errors always show regardless.
215
+ *
216
+ * @group Props
217
+ */
218
+ readonly validationMode: _angular_core.InputSignal<RdxValidationMode | undefined>;
388
219
  /** The enclosing Form, if any. All Form-related behavior is a no-op when this is `null`. */
389
220
  private readonly formContext;
390
221
  readonly controlId: _angular_core.WritableSignal<string>;
@@ -397,20 +228,60 @@ declare class RdxFieldRoot {
397
228
  /** External state owner registered through the context; `null` when Field self-computes. */
398
229
  private readonly stateProvider;
399
230
  /** Whether an external adapter currently owns field state. */
400
- readonly hasStateProvider: _angular_core.Signal<boolean>;
231
+ readonly hasStateProvider: Signal<boolean>;
401
232
  /** Error content from a registered state provider (e.g. a Signal Forms adapter). */
402
233
  private readonly providerErrors;
403
- /** External messages from the enclosing Form matched by this field's `name`. */
404
- readonly externalErrors: _angular_core.Signal<string[]>;
405
- /** Provider messages first (`message ?? kind`), then the Form's external messages. */
406
- readonly messages: _angular_core.Signal<string[]>;
407
- readonly invalidState: _angular_core.Signal<boolean>;
408
- readonly disabledState: _angular_core.Signal<boolean>;
409
- readonly requiredState: _angular_core.Signal<boolean>;
410
- readonly dirtyState: _angular_core.Signal<boolean>;
411
- readonly touchedState: _angular_core.Signal<boolean>;
412
- readonly filledState: _angular_core.Signal<boolean>;
413
- readonly focusedState: _angular_core.Signal<boolean>;
234
+ /** **Client** validation errors routed by a form-level provider (`rdxSignalForm`) gated by `validationMode`. */
235
+ private readonly clientErrors;
236
+ /** **Server/external** errors from the Form's `errors` input shown eagerly (never gated). */
237
+ private readonly serverErrors;
238
+ /** Whether the enclosing Form has had a submit attempted; `false` when standalone. A presentation
239
+ * seam an adapter can read to reveal errors after a submit attempt (Base UI's submit-attempt state). */
240
+ readonly formSubmitAttempted: Signal<boolean>;
241
+ /**
242
+ * Client messages first (per-field `rdxSignalField` provider, then form-level `rdxSignalForm`
243
+ * name-routing) — only once `validationMode` reveals client validity — then the Form's **server**
244
+ * messages (the `errors` input), which always show. **Deduped by text**: a field can receive the same
245
+ * Signal Forms error from both a per-field provider and the form-level routing (they read the same
246
+ * field state), so deduping renders it once while still surfacing distinct messages from each source.
247
+ */
248
+ readonly messages: Signal<string[]>;
249
+ /** Effective validation-display mode: this field's override → the enclosing Form's → the default. */
250
+ readonly effectiveValidationMode: Signal<RdxValidationMode>;
251
+ /** Whether client-side validity is revealed yet, per {@link effectiveValidationMode} + interaction. */
252
+ private readonly validationRevealed;
253
+ /**
254
+ * Client-side invalidity (gated by `validationMode`): the per-field provider's error content / `invalid`
255
+ * (`rdxSignalField`), a form-level provider's name-routed errors (`rdxSignalForm`), or the `[invalid]`
256
+ * input. Excludes server errors (which are eager).
257
+ */
258
+ private readonly clientInvalidState;
259
+ /**
260
+ * Tri-state *displayed* validity (`boolean | null`) — the source for `data-valid` / `data-invalid`.
261
+ * Server errors show immediately; client-side validity (including `rdxSignalForm` name-routing) stays
262
+ * **neutral** (`null`) until the field's {@link effectiveValidationMode} reveals it, then `false`/`true`.
263
+ */
264
+ readonly validState: Signal<boolean | null>;
265
+ /**
266
+ * Boolean **displayed** invalidity (= `validState() === false`), used by `rdxFieldError` (hidden) and
267
+ * `rdxFieldControl`'s `aria-describedby` error linking. A neutral (`null`) `validState` reads as not
268
+ * invalid here, so the error region stays hidden until the field's mode reveals it.
269
+ */
270
+ readonly invalidState: Signal<boolean>;
271
+ /**
272
+ * Boolean **actual** invalidity — ungated by the display mode. The enclosing Form aggregates this into
273
+ * `anyInvalid` (→ submit-block / focus-first-invalid), so a field that is really invalid but displayed
274
+ * neutral still blocks submit. The form's presentation `data-invalid` comes from the *displayed*
275
+ * aggregate (`anyDisplayedInvalid`) instead — not from this. Server errors + provider error content +
276
+ * the provider/input `invalid`.
277
+ */
278
+ readonly actualInvalidState: Signal<boolean>;
279
+ readonly disabledState: Signal<boolean>;
280
+ readonly requiredState: Signal<boolean>;
281
+ readonly dirtyState: Signal<boolean>;
282
+ readonly touchedState: Signal<boolean>;
283
+ readonly filledState: Signal<boolean>;
284
+ readonly focusedState: Signal<boolean>;
414
285
  protected readonly dataAttr: (value: boolean) => "" | undefined;
415
286
  constructor();
416
287
  /** Notify the enclosing Form (if any) that this field's control was edited (clear-on-edit). */
@@ -431,14 +302,72 @@ declare class RdxFieldRoot {
431
302
  * @ignore
432
303
  */
433
304
  setStateProvider(provider: RdxFieldState | null): RdxFieldState | null;
305
+ /**
306
+ * Identity-checked teardown — roll back to `previous` only if `provider` is still active. Prevents
307
+ * an old adapter's destroy from clobbering a newer adapter that registered after it (create-before-
308
+ * destroy during a structural view swap).
309
+ */
310
+ clearStateProvider(provider: RdxFieldState | null, previous: RdxFieldState | null): void;
434
311
  /**
435
312
  * Prefer the registered provider's value for `key` when it exposes one,
436
- * otherwise fall back to the root inputs / DOM-derived signals.
313
+ * otherwise fall back to the root inputs / DOM-derived signals. `errors` (content) and `valid`
314
+ * (tri-state `boolean | null`) are resolved separately, so they're excluded from this boolean key.
437
315
  */
438
316
  private resolve;
439
317
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldRoot, never>;
440
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldRoot, "[rdxFieldRoot]", ["rdxFieldRoot"], { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "filled": { "alias": "filled"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
318
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldRoot, "[rdxFieldRoot]", ["rdxFieldRoot"], { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "filled": { "alias": "filled"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "validationMode": { "alias": "validationMode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
319
+ }
320
+
321
+ /**
322
+ * Groups an individual item in a checkbox group or radio group with its own label and description.
323
+ *
324
+ * Use inside a `rdxFieldRoot` (typically wrapping a group) when each control needs its own label /
325
+ * description: the item scopes those associations to its control while reflecting the field's validation
326
+ * state. Mirrors Base UI's `Field.Item`.
327
+ *
328
+ * @group Components
329
+ */
330
+ declare class RdxFieldItem {
331
+ /** The enclosing field root (items are leaves under the root, so `skipSelf` reaches it). */
332
+ readonly root: RdxFieldRoot;
333
+ /**
334
+ * Whether the wrapped control should ignore user interaction. The `disabled` on `rdxFieldRoot` takes
335
+ * precedence (it is OR'd in).
336
+ *
337
+ * @group Props
338
+ * @defaultValue false
339
+ */
340
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
341
+ /** This item's control id — label / description / control inside the item associate with it. */
342
+ readonly controlId: _angular_core.WritableSignal<string>;
343
+ /** Description ids for this item's control `aria-describedby`. */
344
+ readonly descriptionIds: _angular_core.WritableSignal<string[]>;
345
+ /** The item's effective disabled state: the root's disabled OR the item's. */
346
+ readonly disabledState: _angular_core.Signal<boolean>;
347
+ protected readonly dataAttr: (value: boolean) => "" | undefined;
348
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldItem, never>;
349
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldItem, "[rdxFieldItem]", ["rdxFieldItem"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
350
+ }
351
+
352
+ /**
353
+ * Labels the field control.
354
+ *
355
+ * @group Components
356
+ */
357
+ declare class RdxFieldLabel {
358
+ protected readonly rootContext: _radix_ng_primitives_field.RdxFieldRootContext;
359
+ /**
360
+ * Label id.
361
+ *
362
+ * @group Props
363
+ */
364
+ readonly id: _angular_core.InputSignal<string>;
365
+ readonly htmlFor: () => string;
366
+ constructor();
367
+ protected readonly dataAttr: (value: boolean) => "" | undefined;
368
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldLabel, never>;
369
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldLabel, "[rdxFieldLabel]", ["rdxFieldLabel"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
441
370
  }
442
371
 
443
- export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
372
+ export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldItem, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
444
373
  export type { RdxFieldRootContext, RdxFieldState };