@radix-ng/primitives 1.0.10 → 1.1.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.
- package/README.md +26 -5
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +88 -21
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +199 -129
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +203 -52
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-composite.mjs +221 -36
- package/fesm2022/radix-ng-primitives-composite.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +352 -24
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +11 -5
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +127 -23
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-form.mjs +35 -4
- package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-input.mjs +87 -15
- package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menu.mjs +34 -7
- package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +38 -7
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs +80 -11
- package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +49 -2
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +6 -3
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +70 -14
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-signal-forms.mjs +27 -11
- package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +17 -2
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +60 -7
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +12 -6
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +25 -3
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/package.json +8 -3
- package/types/radix-ng-primitives-autocomplete.d.ts +16 -2
- package/types/radix-ng-primitives-checkbox.d.ts +66 -44
- package/types/radix-ng-primitives-combobox.d.ts +74 -3
- package/types/radix-ng-primitives-composite.d.ts +48 -2
- package/types/radix-ng-primitives-core.d.ts +212 -96
- package/types/radix-ng-primitives-date-field.d.ts +7 -4
- package/types/radix-ng-primitives-field.d.ts +55 -8
- package/types/radix-ng-primitives-form.d.ts +9 -0
- package/types/radix-ng-primitives-input.d.ts +10 -2
- package/types/radix-ng-primitives-menu.d.ts +45 -4
- package/types/radix-ng-primitives-navigation-menu.d.ts +2 -2
- package/types/radix-ng-primitives-number-field.d.ts +12 -5
- package/types/radix-ng-primitives-popover.d.ts +2 -2
- package/types/radix-ng-primitives-popper.d.ts +60 -15
- package/types/radix-ng-primitives-preview-card.d.ts +2 -2
- package/types/radix-ng-primitives-radio.d.ts +6 -1
- package/types/radix-ng-primitives-select.d.ts +25 -4
- package/types/radix-ng-primitives-signal-forms.d.ts +22 -8
- package/types/radix-ng-primitives-slider.d.ts +2 -1
- package/types/radix-ng-primitives-switch.d.ts +19 -3
- package/types/radix-ng-primitives-time-field.d.ts +9 -6
- package/types/radix-ng-primitives-toggle-group.d.ts +5 -1
- package/types/radix-ng-primitives-tooltip.d.ts +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { InputSignal, InputSignalWithTransform, ModelSignal, OutputRef, Signal, Type, Provider, WritableSignal, ProviderToken, InjectionToken, OutputEmitterRef, Injector, ElementRef, EffectRef, EffectCleanupRegisterFn, CreateEffectOptions } from '@angular/core';
|
|
3
3
|
import { ControlValueAccessor } from '@angular/forms';
|
|
4
4
|
import { DateValue, Time, CalendarDateTime, ZonedDateTime } from '@internationalized/date';
|
|
5
5
|
import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
|
|
@@ -101,6 +101,116 @@ declare class RdxControlValueAccessor<T> implements ControlValueAccessor {
|
|
|
101
101
|
*/
|
|
102
102
|
declare function injectControlValueAccessor<T>(): RdxControlValueAccessor<T>;
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Local mirror of Angular Signal Forms' control contracts
|
|
106
|
+
* (`@angular/forms/signals`, stable in Angular 22).
|
|
107
|
+
*
|
|
108
|
+
* These interfaces intentionally do **not** import from `@angular/forms/signals`,
|
|
109
|
+
* so control entries do not pull that optional integration into their public
|
|
110
|
+
* dependency graph. Primitives can still declare `implements RdxFormValueControl<T>` /
|
|
111
|
+
* `implements RdxFormCheckboxControl`; the mirror locks the public surface (the
|
|
112
|
+
* required `value` / `checked` signal) and catches naming regressions on CI — e.g.
|
|
113
|
+
* a rewrite renaming `value` → `modelValue` (as the slider once had) would no
|
|
114
|
+
* longer type-check.
|
|
115
|
+
*
|
|
116
|
+
* Optional state types are widened only where Radix NG controls legitimately
|
|
117
|
+
* differ from Angular's exact types (e.g. `input<string>()` produces
|
|
118
|
+
* `string | undefined`, and boolean inputs carry a coercion transform).
|
|
119
|
+
*
|
|
120
|
+
* The real Angular types stay isolated in `@radix-ng/primitives/signal-forms`.
|
|
121
|
+
* See ADR 0018 and `.claude/skills/project-knowledge/references/signal-forms-readiness.md`.
|
|
122
|
+
*/
|
|
123
|
+
/** An optional control-state member exposed as an Angular input signal (with or without a coercion transform). */
|
|
124
|
+
type RdxFormStateInput<T> = InputSignal<T> | InputSignalWithTransform<T, any>;
|
|
125
|
+
/**
|
|
126
|
+
* Minimal stand-in for Angular's `ValidationError`. The real type is a tagged
|
|
127
|
+
* union (`RequiredValidationError`, `PatternValidationError`, …); this keeps a
|
|
128
|
+
* shared shape until the v22 type is available.
|
|
129
|
+
*/
|
|
130
|
+
interface RdxValidationError {
|
|
131
|
+
readonly kind: string;
|
|
132
|
+
readonly message?: string;
|
|
133
|
+
}
|
|
134
|
+
/** Optional state shared by value and checkbox controls (mirror of Angular's `FormUiControl`). */
|
|
135
|
+
interface RdxFormUiControl {
|
|
136
|
+
readonly disabled?: RdxFormStateInput<boolean>;
|
|
137
|
+
readonly readonly?: RdxFormStateInput<boolean>;
|
|
138
|
+
readonly required?: RdxFormStateInput<boolean>;
|
|
139
|
+
readonly invalid?: RdxFormStateInput<boolean>;
|
|
140
|
+
readonly hidden?: RdxFormStateInput<boolean>;
|
|
141
|
+
readonly pending?: RdxFormStateInput<boolean>;
|
|
142
|
+
/**
|
|
143
|
+
* Touched status the form writes into the control.
|
|
144
|
+
*
|
|
145
|
+
* The two API generations disagree on the notification half: the 21.x
|
|
146
|
+
* experimental implementation listens to a `touched` **model**'s
|
|
147
|
+
* `touchedChange` output, while stable Angular 22 reverted to a plain
|
|
148
|
+
* `touched` input plus a separate {@link touch} output. A `model()` set on
|
|
149
|
+
* blur **plus** an emitted `touch` output satisfies both (`ModelSignal`
|
|
150
|
+
* extends `InputSignalWithTransform`, so it type-checks as the 22 input).
|
|
151
|
+
*/
|
|
152
|
+
readonly touched?: ModelSignal<boolean> | RdxFormStateInput<boolean> | OutputRef<boolean>;
|
|
153
|
+
readonly dirty?: RdxFormStateInput<boolean>;
|
|
154
|
+
readonly name?: RdxFormStateInput<string | undefined>;
|
|
155
|
+
readonly errors?: RdxFormStateInput<readonly RdxValidationError[]>;
|
|
156
|
+
readonly minLength?: RdxFormStateInput<number | undefined>;
|
|
157
|
+
readonly maxLength?: RdxFormStateInput<number | undefined>;
|
|
158
|
+
readonly pattern?: RdxFormStateInput<readonly RegExp[]>;
|
|
159
|
+
/** Notifies the form the control was touched (stable Angular 22 contract; ignored by 21.x). */
|
|
160
|
+
readonly touch?: OutputRef<void>;
|
|
161
|
+
/** Resets the control's UI state (optional method added in stable Angular 22). */
|
|
162
|
+
reset?(): void;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Mirror of `FormValueControl<TValue>` — a control that edits a single value via
|
|
166
|
+
* `value = model<TValue>()`. It must **not** expose `checked`.
|
|
167
|
+
*/
|
|
168
|
+
interface RdxFormValueControl<TValue> extends RdxFormUiControl {
|
|
169
|
+
readonly value: ModelSignal<TValue>;
|
|
170
|
+
readonly checked?: undefined;
|
|
171
|
+
readonly min?: RdxFormStateInput<NonNullable<TValue> | undefined>;
|
|
172
|
+
readonly max?: RdxFormStateInput<NonNullable<TValue> | undefined>;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Mirror of `FormCheckboxControl` — a control that toggles via
|
|
176
|
+
* `checked = model<boolean>()`. It must **not** expose `value`.
|
|
177
|
+
*/
|
|
178
|
+
interface RdxFormCheckboxControl extends RdxFormUiControl {
|
|
179
|
+
readonly checked: ModelSignal<boolean>;
|
|
180
|
+
readonly value?: undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Form state owned by an Angular Reactive Forms or template-driven `NgControl` on the same host
|
|
185
|
+
* element. `connected` stays false for standalone and Signal Forms controls.
|
|
186
|
+
*
|
|
187
|
+
* @ignore
|
|
188
|
+
*/
|
|
189
|
+
interface RdxNgControlState {
|
|
190
|
+
readonly connected: Signal<boolean>;
|
|
191
|
+
readonly name: Signal<string | undefined>;
|
|
192
|
+
readonly value: Signal<unknown>;
|
|
193
|
+
readonly valid: Signal<boolean>;
|
|
194
|
+
readonly invalid: Signal<boolean>;
|
|
195
|
+
readonly pending: Signal<boolean>;
|
|
196
|
+
readonly disabled: Signal<boolean>;
|
|
197
|
+
readonly errors: Signal<readonly RdxValidationError[]>;
|
|
198
|
+
readonly dirty: Signal<boolean>;
|
|
199
|
+
readonly touched: Signal<boolean>;
|
|
200
|
+
/** Resets a connected Reactive/template-driven control; returns whether one was connected. */
|
|
201
|
+
reset(value: unknown): boolean;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Lazily connects to the same-host `NgControl` without creating a circular dependency while Angular
|
|
205
|
+
* is resolving its `ControlValueAccessor`. The unified `AbstractControl.events` stream mirrors
|
|
206
|
+
* programmatic value, status, validation, and interaction-state changes as well as user-driven ones.
|
|
207
|
+
*
|
|
208
|
+
* Must be called in an injection context.
|
|
209
|
+
*
|
|
210
|
+
* @ignore
|
|
211
|
+
*/
|
|
212
|
+
declare function injectNgControlState(): RdxNgControlState;
|
|
213
|
+
|
|
104
214
|
/**
|
|
105
215
|
* Include in the providers section of a component which utilizes ControlValueAccessor to redundant code.
|
|
106
216
|
*
|
|
@@ -461,7 +571,7 @@ type UseDateFieldProps = {
|
|
|
461
571
|
disabled: Signal<boolean>;
|
|
462
572
|
readonly: Signal<boolean>;
|
|
463
573
|
part: SegmentPart;
|
|
464
|
-
modelValue: ModelSignal<DateValue |
|
|
574
|
+
modelValue: ModelSignal<DateValue | null> | WritableSignal<DateValue | null>;
|
|
465
575
|
focusNext: () => void;
|
|
466
576
|
};
|
|
467
577
|
type SegmentAttrProps = {
|
|
@@ -665,8 +775,9 @@ type ItemValueComparator<T = unknown> = ((a: T, b: T) => boolean) | string;
|
|
|
665
775
|
*/
|
|
666
776
|
declare function itemToStringLabel(value: unknown): string;
|
|
667
777
|
/**
|
|
668
|
-
* Converts an item value to the string used for form serialization.
|
|
669
|
-
*
|
|
778
|
+
* Converts an item value to the string used for form serialization. A conventional `{ value, label }`
|
|
779
|
+
* item serializes its `value` member; other non-string values use Base UI-compatible JSON serialization
|
|
780
|
+
* with `String()` as a fallback. Kept separate so a primitive can diverge label vs. value.
|
|
670
781
|
*/
|
|
671
782
|
declare function itemToStringValue(value: unknown): string;
|
|
672
783
|
/**
|
|
@@ -784,86 +895,7 @@ declare function isEqual(a: any, b: any): boolean;
|
|
|
784
895
|
declare function provideExistingToken<T>(token: ProviderToken<T>, type: Type<T>): Provider;
|
|
785
896
|
|
|
786
897
|
/**
|
|
787
|
-
*
|
|
788
|
-
* (`@angular/forms/signals`, stable in Angular 22).
|
|
789
|
-
*
|
|
790
|
-
* These interfaces intentionally do **not** import from `@angular/forms/signals`
|
|
791
|
-
* so primitives can declare `implements RdxFormValueControl<T>` /
|
|
792
|
-
* `implements RdxFormCheckboxControl` while the library baseline is still on
|
|
793
|
-
* Angular 21, where the real API is experimental. They mirror Angular's contract
|
|
794
|
-
* closely enough to lock the public surface (the required `value` / `checked`
|
|
795
|
-
* signal) and catch naming regressions on CI — e.g. a rewrite renaming
|
|
796
|
-
* `value` → `modelValue` (as the slider once had) would no longer type-check.
|
|
797
|
-
*
|
|
798
|
-
* Optional state types are widened only where Radix NG controls legitimately
|
|
799
|
-
* differ from Angular's exact types (e.g. `input<string>()` produces
|
|
800
|
-
* `string | undefined`, and boolean inputs carry a coercion transform).
|
|
801
|
-
*
|
|
802
|
-
* Replace with the real imports once the baseline moves to Angular 22.
|
|
803
|
-
* See `.claude/skills/project-knowledge/references/signal-forms-readiness.md`.
|
|
804
|
-
*/
|
|
805
|
-
/** An optional control-state member exposed as an Angular input signal (with or without a coercion transform). */
|
|
806
|
-
type RdxFormStateInput<T> = InputSignal<T> | InputSignalWithTransform<T, any>;
|
|
807
|
-
/**
|
|
808
|
-
* Minimal stand-in for Angular's `ValidationError`. The real type is a tagged
|
|
809
|
-
* union (`RequiredValidationError`, `PatternValidationError`, …); this keeps a
|
|
810
|
-
* shared shape until the v22 type is available.
|
|
811
|
-
*/
|
|
812
|
-
interface RdxValidationError {
|
|
813
|
-
readonly kind: string;
|
|
814
|
-
readonly message?: string;
|
|
815
|
-
}
|
|
816
|
-
/** Optional state shared by value and checkbox controls (mirror of Angular's `FormUiControl`). */
|
|
817
|
-
interface RdxFormUiControl {
|
|
818
|
-
readonly disabled?: RdxFormStateInput<boolean>;
|
|
819
|
-
readonly readonly?: RdxFormStateInput<boolean>;
|
|
820
|
-
readonly required?: RdxFormStateInput<boolean>;
|
|
821
|
-
readonly invalid?: RdxFormStateInput<boolean>;
|
|
822
|
-
readonly hidden?: RdxFormStateInput<boolean>;
|
|
823
|
-
readonly pending?: RdxFormStateInput<boolean>;
|
|
824
|
-
/**
|
|
825
|
-
* Touched status the form writes into the control.
|
|
826
|
-
*
|
|
827
|
-
* The two API generations disagree on the notification half: the 21.x
|
|
828
|
-
* experimental implementation listens to a `touched` **model**'s
|
|
829
|
-
* `touchedChange` output, while stable Angular 22 reverted to a plain
|
|
830
|
-
* `touched` input plus a separate {@link touch} output. A `model()` set on
|
|
831
|
-
* blur **plus** an emitted `touch` output satisfies both (`ModelSignal`
|
|
832
|
-
* extends `InputSignalWithTransform`, so it type-checks as the 22 input).
|
|
833
|
-
*/
|
|
834
|
-
readonly touched?: ModelSignal<boolean> | RdxFormStateInput<boolean> | OutputRef<boolean>;
|
|
835
|
-
readonly dirty?: RdxFormStateInput<boolean>;
|
|
836
|
-
readonly name?: RdxFormStateInput<string | undefined>;
|
|
837
|
-
readonly errors?: RdxFormStateInput<readonly RdxValidationError[]>;
|
|
838
|
-
readonly minLength?: RdxFormStateInput<number | undefined>;
|
|
839
|
-
readonly maxLength?: RdxFormStateInput<number | undefined>;
|
|
840
|
-
readonly pattern?: RdxFormStateInput<readonly RegExp[]>;
|
|
841
|
-
/** Notifies the form the control was touched (stable Angular 22 contract; ignored by 21.x). */
|
|
842
|
-
readonly touch?: OutputRef<void>;
|
|
843
|
-
/** Resets the control's UI state (optional method added in stable Angular 22). */
|
|
844
|
-
reset?(): void;
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* Mirror of `FormValueControl<TValue>` — a control that edits a single value via
|
|
848
|
-
* `value = model<TValue>()`. It must **not** expose `checked`.
|
|
849
|
-
*/
|
|
850
|
-
interface RdxFormValueControl<TValue> extends RdxFormUiControl {
|
|
851
|
-
readonly value: ModelSignal<TValue>;
|
|
852
|
-
readonly checked?: undefined;
|
|
853
|
-
readonly min?: RdxFormStateInput<NonNullable<TValue> | undefined>;
|
|
854
|
-
readonly max?: RdxFormStateInput<NonNullable<TValue> | undefined>;
|
|
855
|
-
}
|
|
856
|
-
/**
|
|
857
|
-
* Mirror of `FormCheckboxControl` — a control that toggles via
|
|
858
|
-
* `checked = model<boolean>()`. It must **not** expose `value`.
|
|
859
|
-
*/
|
|
860
|
-
interface RdxFormCheckboxControl extends RdxFormUiControl {
|
|
861
|
-
readonly checked: ModelSignal<boolean>;
|
|
862
|
-
readonly value?: undefined;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
/**
|
|
866
|
-
* Optional form-control UI state derived from a control's `invalid`/`errors`/`touched`/`dirty`
|
|
898
|
+
* Optional form-control UI state derived from a control's `invalid`/`pending`/`errors`/`touched`/`dirty`
|
|
867
899
|
* inputs (the optional members of Signal Forms' `FormUiControl`), plus the two mutators every
|
|
868
900
|
* control needs.
|
|
869
901
|
*
|
|
@@ -872,6 +904,12 @@ interface RdxFormCheckboxControl extends RdxFormUiControl {
|
|
|
872
904
|
interface RdxFormUiState {
|
|
873
905
|
/** Invalid when the `invalid` input is set or the `errors` list is non-empty. */
|
|
874
906
|
readonly invalidState: Signal<boolean>;
|
|
907
|
+
/** Whether asynchronous validation is still settling. Pending is neither valid nor invalid. */
|
|
908
|
+
readonly pendingState: Signal<boolean>;
|
|
909
|
+
/** Tri-state validity: valid / invalid / neutral while pending or disabled. */
|
|
910
|
+
readonly validState: Signal<boolean | null>;
|
|
911
|
+
/** Explicit control errors merged with same-host Angular Forms errors. */
|
|
912
|
+
readonly errorsState: Signal<readonly RdxValidationError[]>;
|
|
875
913
|
/** Whether the control has been touched (reflects the `touched` model). */
|
|
876
914
|
readonly touchedState: Signal<boolean>;
|
|
877
915
|
/** Whether the value changed from its initial value — external `dirty` OR internal tracking. */
|
|
@@ -880,6 +918,10 @@ interface RdxFormUiState {
|
|
|
880
918
|
markAsTouched(): void;
|
|
881
919
|
/** Flag the control dirty after a value change (feeds {@link dirtyState}). */
|
|
882
920
|
markDirty(): void;
|
|
921
|
+
/** Clear control-owned touched/dirty state when a form resets it. */
|
|
922
|
+
resetInteractionState?(): void;
|
|
923
|
+
/** Clear only control-owned dirty state when the form marks the field pristine. */
|
|
924
|
+
resetDirtyState?(): void;
|
|
883
925
|
}
|
|
884
926
|
/** Minimal `ControlValueAccessor` surface the form-UI state bridges for the dual (Reactive/template) path. */
|
|
885
927
|
interface RdxFormUiTouchTarget {
|
|
@@ -888,20 +930,24 @@ interface RdxFormUiTouchTarget {
|
|
|
888
930
|
/** Inputs a control passes to {@link createFormUiState} — its own `FormUiControl` signals. */
|
|
889
931
|
interface RdxFormUiStateOptions {
|
|
890
932
|
readonly invalid: Signal<boolean>;
|
|
933
|
+
/** Optional for backwards compatibility with custom controls authored before pending support. */
|
|
934
|
+
readonly pending?: Signal<boolean>;
|
|
891
935
|
readonly errors: Signal<readonly RdxValidationError[]>;
|
|
892
936
|
readonly touched: ModelSignal<boolean>;
|
|
893
937
|
readonly touch: OutputEmitterRef<void>;
|
|
894
938
|
readonly dirty: Signal<boolean>;
|
|
939
|
+
/** Same-host Reactive/template-driven form interaction state, when one is present. */
|
|
940
|
+
readonly ngControlState?: RdxNgControlState | null;
|
|
895
941
|
/**
|
|
896
942
|
* The control's `ControlValueAccessor`, if it has one (dual controls — switch, number-field, …).
|
|
897
|
-
* Omit or pass `null` for Signal-Forms-only controls without a CVA (e.g.
|
|
943
|
+
* Omit or pass `null` for Signal-Forms-only controls without a CVA (e.g. date-field).
|
|
898
944
|
*/
|
|
899
945
|
readonly cva?: RdxFormUiTouchTarget | null;
|
|
900
946
|
}
|
|
901
947
|
/**
|
|
902
948
|
* Builds the shared form-UI state and its mutators from a control's input signals, removing the
|
|
903
|
-
* per-control copy-paste of the
|
|
904
|
-
*
|
|
949
|
+
* per-control copy-paste of the validation/interaction computeds and the `markAsTouched`/`markDirty`
|
|
950
|
+
* logic.
|
|
905
951
|
*
|
|
906
952
|
* **Why the inputs stay on the control (not in here):** Angular's compiler only discovers
|
|
907
953
|
* `input()`/`model()` declared as field initializers, and Signal Forms binds form-written state
|
|
@@ -919,6 +965,8 @@ declare function createFormUiState(options: RdxFormUiStateOptions): RdxFormUiSta
|
|
|
919
965
|
*/
|
|
920
966
|
interface RdxFormUiStateContext {
|
|
921
967
|
invalidState: Signal<boolean>;
|
|
968
|
+
pendingState: Signal<boolean>;
|
|
969
|
+
validState: Signal<boolean | null>;
|
|
922
970
|
touchedState: Signal<boolean>;
|
|
923
971
|
dirtyState: Signal<boolean>;
|
|
924
972
|
markAsTouched: () => void;
|
|
@@ -939,14 +987,14 @@ declare const RDX_FIELD_VALIDITY: InjectionToken<Signal<boolean | null>>;
|
|
|
939
987
|
/**
|
|
940
988
|
* Tri-state display validity: when inside a `Field` the field's gated `validState` is the **single
|
|
941
989
|
* source** (the control reflects it, including its `validationMode` neutral state); standalone, the
|
|
942
|
-
* control's own
|
|
990
|
+
* control's own tri-state validity (pending is neutral).
|
|
943
991
|
*
|
|
944
992
|
* **Contract:** inside a `Field` a control's own `invalid` / `errors` inputs are **not** displayed — the
|
|
945
993
|
* Field owns displayed validity. Drive validity through the Field instead: bind `rdxSignalField`
|
|
946
994
|
* (Signal Forms), or set `[invalid]` on `rdxFieldRoot`. The control's own `invalid`/`errors` are for
|
|
947
995
|
* standalone use.
|
|
948
996
|
*/
|
|
949
|
-
declare function resolveDisplayValid(fieldValidity: Signal<boolean | null> | null, ownInvalid: Signal<boolean>): boolean | null;
|
|
997
|
+
declare function resolveDisplayValid(fieldValidity: Signal<boolean | null> | null, ownInvalid: Signal<boolean>, ownPending?: Signal<boolean>): boolean | null;
|
|
950
998
|
/**
|
|
951
999
|
* Provide a control's {@link RdxFormUiState} on its host element so {@link RdxFormUiStateHost} can
|
|
952
1000
|
* reflect it. Pair with `hostDirectives: [RdxFormUiStateHost]`:
|
|
@@ -985,7 +1033,7 @@ declare class RdxFormUiStateHost {
|
|
|
985
1033
|
}
|
|
986
1034
|
/**
|
|
987
1035
|
* Abstract base that declares the optional `FormUiControl` state inputs
|
|
988
|
-
* (`invalid`/`errors`/`touched`/`dirty` + the `touch` output) once and builds the control's
|
|
1036
|
+
* (`invalid`/`pending`/`errors`/`touched`/`dirty` + the `touch` output) once and builds the control's
|
|
989
1037
|
* {@link RdxFormUiState} from them, so a control directive can inherit the whole surface with a
|
|
990
1038
|
* single `extends` instead of re-declaring it.
|
|
991
1039
|
*
|
|
@@ -1002,6 +1050,8 @@ declare class RdxFormUiStateHost {
|
|
|
1002
1050
|
declare abstract class RdxFormUiControlBase {
|
|
1003
1051
|
/** Whether the control is invalid. A non-empty {@link errors} list also marks it invalid. */
|
|
1004
1052
|
readonly invalid: i0.InputSignalWithTransform<boolean, BooleanInput>;
|
|
1053
|
+
/** Whether async validation is pending. Pending controls publish neither `data-valid` nor `data-invalid`. */
|
|
1054
|
+
readonly pending: i0.InputSignalWithTransform<boolean, BooleanInput>;
|
|
1005
1055
|
/** Whether the control has been touched. A `model()` so Signal Forms can write it; set on blur/focus-out. */
|
|
1006
1056
|
readonly touched: ModelSignal<boolean>;
|
|
1007
1057
|
/** Whether the value changed from its initial value. Merged with internal tracking. */
|
|
@@ -1010,8 +1060,12 @@ declare abstract class RdxFormUiControlBase {
|
|
|
1010
1060
|
readonly errors: i0.InputSignal<readonly RdxValidationError[]>;
|
|
1011
1061
|
/** Emits when the control is touched, notifying Signal Forms (stable Angular 22 contract). */
|
|
1012
1062
|
readonly touch: OutputEmitterRef<void>;
|
|
1063
|
+
private readonly ngControlState;
|
|
1013
1064
|
/** The shared form-UI state derived from the inputs above. Call `formUi.markDirty()` on value change. */
|
|
1014
1065
|
readonly formUi: RdxFormUiState;
|
|
1066
|
+
/** Validation errors from the control inputs and a same-host Reactive/template-driven form control. */
|
|
1067
|
+
readonly validationErrors: Signal<readonly RdxValidationError[]>;
|
|
1068
|
+
constructor();
|
|
1015
1069
|
/** The enclosing Field's tri-state display validity, if any. `protected` so a control whose own
|
|
1016
1070
|
* invalidity is richer than `formUi.invalidState` (e.g. date/time-field add a parse check) can build
|
|
1017
1071
|
* its own `displayValid` from it. */
|
|
@@ -1019,19 +1073,32 @@ declare abstract class RdxFormUiControlBase {
|
|
|
1019
1073
|
/**
|
|
1020
1074
|
* Tri-state *displayed* validity for controls that bind their own host attributes (radio, switch,
|
|
1021
1075
|
* number-field): the enclosing Field's gated state when inside a `rdxFieldRoot`, else this control's
|
|
1022
|
-
* own
|
|
1076
|
+
* own validity (`formUi.pendingState` is neutral; otherwise `formUi.invalidState` is binary). Bind
|
|
1077
|
+
* `data-valid`/`data-invalid`/`aria-invalid` to
|
|
1023
1078
|
* this so a neutral field shows neither. Controls whose `invalidState` is richer than
|
|
1024
|
-
* `formUi.invalidState` override this with
|
|
1079
|
+
* `formUi.invalidState` override this with
|
|
1080
|
+
* `resolveDisplayValid(this.fieldValidity, this.invalidState, this.formUi.pendingState)`.
|
|
1025
1081
|
*/
|
|
1026
1082
|
readonly displayValid: Signal<boolean | null>;
|
|
1027
1083
|
/**
|
|
1028
1084
|
* Override to bridge the control's `ControlValueAccessor` into `markAsTouched` (dual controls —
|
|
1029
1085
|
* return `injectControlValueAccessor()` or a `{ markAsTouched }` adapter). Default: no CVA
|
|
1030
|
-
* (Signal-Forms-only controls such as
|
|
1086
|
+
* (Signal-Forms-only controls such as date-field).
|
|
1031
1087
|
*/
|
|
1032
1088
|
protected formUiTouchTarget(): RdxFormUiTouchTarget | null;
|
|
1089
|
+
/**
|
|
1090
|
+
* Resets a same-host Reactive/template-driven control without reporting the reset as a user edit.
|
|
1091
|
+
* Returns `false` when no Angular `NgControl` is connected, so a control can fall back to its CVA
|
|
1092
|
+
* change callback for an unusually early native reset.
|
|
1093
|
+
*/
|
|
1094
|
+
protected resetNgControl(value: unknown): boolean;
|
|
1095
|
+
/**
|
|
1096
|
+
* Reset control-owned interaction state. Angular Signal Forms calls this optional custom-control
|
|
1097
|
+
* hook from `FieldState.reset()` after restoring the field value.
|
|
1098
|
+
*/
|
|
1099
|
+
reset(): void;
|
|
1033
1100
|
static ɵfac: i0.ɵɵFactoryDeclaration<RdxFormUiControlBase, never>;
|
|
1034
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<RdxFormUiControlBase, never, never, { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; }, { "touched": "touchedChange"; "touch": "touch"; }, never, never, true, never>;
|
|
1101
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<RdxFormUiControlBase, never, never, { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; }, { "touched": "touchedChange"; "touch": "touch"; }, never, never, true, never>;
|
|
1035
1102
|
}
|
|
1036
1103
|
|
|
1037
1104
|
/**
|
|
@@ -1737,6 +1804,55 @@ declare function elementSize({ elementRef, injector }: {
|
|
|
1737
1804
|
*/
|
|
1738
1805
|
declare function getActiveElement(root?: DocumentOrShadowRoot): Element | null;
|
|
1739
1806
|
|
|
1807
|
+
/** Configuration for a composite control that participates in a native HTML form. */
|
|
1808
|
+
interface RdxNativeFormControlOptions<T> {
|
|
1809
|
+
/** Form-field name. No value is contributed while it is absent. */
|
|
1810
|
+
readonly name: Signal<string | undefined>;
|
|
1811
|
+
/** Optional id of an external owning form. */
|
|
1812
|
+
readonly form: Signal<string | undefined>;
|
|
1813
|
+
/** Disabled controls are excluded from successful form controls. */
|
|
1814
|
+
readonly disabled: Signal<boolean>;
|
|
1815
|
+
/** Current control value, used when the form constructs `FormData`. */
|
|
1816
|
+
readonly value?: Signal<T>;
|
|
1817
|
+
/** Converts a value to one or more form entries. Omit for controls with their own native inputs. */
|
|
1818
|
+
readonly serialize?: (value: T) => readonly string[];
|
|
1819
|
+
/** Whether a consumer-rendered native input currently owns serialization. */
|
|
1820
|
+
readonly hasNativeControl?: Signal<boolean>;
|
|
1821
|
+
/** Synchronizes a consumer-rendered native control immediately before an imperative submit. */
|
|
1822
|
+
readonly syncNativeControl?: () => void;
|
|
1823
|
+
/** Value restored by a native form reset. Captured once after inputs bind. */
|
|
1824
|
+
readonly defaultValue?: () => T;
|
|
1825
|
+
/** Applies the captured default value after a native form reset. */
|
|
1826
|
+
readonly onReset?: (value: T) => void;
|
|
1827
|
+
}
|
|
1828
|
+
/** Imperative operations needed by controls that submit immediately after a value change. */
|
|
1829
|
+
interface RdxNativeFormControl {
|
|
1830
|
+
/** The current owning form, including an external form selected by the `form` input. */
|
|
1831
|
+
ownerForm(): HTMLFormElement | null;
|
|
1832
|
+
/** Synchronizes generated/native controls with the current signals. */
|
|
1833
|
+
sync(): void;
|
|
1834
|
+
/** Synchronizes the value and requests submission from the owning form. */
|
|
1835
|
+
requestSubmit(): void;
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Converts a scalar or array model to HTML form values. `null` and `undefined` represent no
|
|
1839
|
+
* successful control; arrays deliberately become repeated entries under the same field name.
|
|
1840
|
+
*/
|
|
1841
|
+
declare function serializeNativeFormValue(value: unknown, itemToStringValue?: (entry: unknown) => string): readonly string[];
|
|
1842
|
+
/**
|
|
1843
|
+
* Adds native form semantics to a composite control, rendering hidden inputs only when the control
|
|
1844
|
+
* has no native successful control of its own.
|
|
1845
|
+
*
|
|
1846
|
+
* A hidden input is necessary for a headless root to enter the platform's successful-controls tree
|
|
1847
|
+
* (including older engines that do not dispatch `formdata` for `new FormData(form)`). One input is
|
|
1848
|
+
* created per serialized value, preserving repeated-field semantics; controls with their own native
|
|
1849
|
+
* input use this solely for reset and imperative-submit coordination.
|
|
1850
|
+
*
|
|
1851
|
+
* Generated inputs are browser-only. Rendering imperative sibling nodes on the server would put DOM
|
|
1852
|
+
* outside Angular's hydration graph; the client creates them after its view has been claimed instead.
|
|
1853
|
+
*/
|
|
1854
|
+
declare function useNativeFormControl<T>(options: RdxNativeFormControlOptions<T>): RdxNativeFormControl;
|
|
1855
|
+
|
|
1740
1856
|
/**
|
|
1741
1857
|
* Creates a resize observer effect for element
|
|
1742
1858
|
*
|
|
@@ -2056,5 +2172,5 @@ declare enum RdxPositionAlign {
|
|
|
2056
2172
|
End = "end"
|
|
2057
2173
|
}
|
|
2058
2174
|
|
|
2059
|
-
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, DOCS_BASE_URL, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_DEFAULT_VALIDATION_MODE, RDX_FIELD_VALIDITY, RDX_FLOATING_REGISTRATION, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_TREE, RDX_FORM_UI_STATE, RDX_INTERNAL_BACKDROP_ATTR, RDX_SCROLL_LOCKED_ATTR, RdxControlValueAccessor, RdxFloatingNode, RdxFloatingNodeRegistration, RdxFloatingRegistrationContext, RdxFloatingRootContext, RdxFloatingTree, RdxFormUiControlBase, RdxFormUiStateHost, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, RdxTriggerRegistry, SHIFT, SPACE, SPACE_CODE, TAB, TIME_GRANULARITIES, a, areAllDaysBetweenValid, clamp, createCancelableChangeEventDetails, createContent, createContext, createFloatingEvents, createFloatingRootContext, createFormUiState, createFormatter, createMonth, createMonths, docsUrl, elementSize, formUiStateContext, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectFloatingRootContext, injectId, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isItemEqualToValue, isNullish, isNumberString, isSegmentNavigationKey, isValidationRevealed, isZonedDateTime, itemToStringLabel, itemToStringValue, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideExistingToken, provideFloatingRegistration, provideFloatingRootContext, provideFloatingTree, provideFormUiState, provideValueAccessor, rdxCheckLabelElement, rdxCheckTriggerElement, rdxDevError, rdxDevWarning, resetRdxDevWarnings, resizeEffect, resolveDisplayValid, resolveFloatingTree, roundToStepPrecision, segmentBuilders, setupInternalBackdrop, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useAnchoredScrollLock, useArrowNavigation, useDateField, useFilter, useGraceArea, useListHighlight, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
2060
|
-
export type { AcceptableValue, AnyExceptLiteral, AriaLivePoliteness, BooleanInput, CreateMonthProps, DataOrientation, DateAndTimeSegmentObj, DateFormatterOptions, DateMatcher, DateRange, DateSegmentObj, DateSegmentPart, DateStep, DayPeriod, Direction, EditableSegmentPart, FilterPredicates, Formatter, Granularity, HourCycle, InjectContext, ItemValueComparator, ListHighlight, Month, NonEditableSegmentPart, Nullable, NumberInput, PlaceholderMap, RdxAnchoredScrollLockOptions, RdxCancelableChangeEventDetails, RdxCancelableChangeEventTransaction, RdxFloatingEventMap, RdxFloatingEvents, RdxFloatingLifecycle, RdxFloatingNodeInit, RdxFloatingParentOverride, RdxFloatingRegistrationReader, RdxFloatingRegistrationStatus, RdxFloatingRootContextEventMap, RdxFloatingRootContextInit, RdxFormCheckboxControl, RdxFormStateInput, RdxFormUiControl, RdxFormUiState, RdxFormUiStateContext, RdxFormUiStateOptions, RdxFormUiTouchTarget, RdxFormValueControl, RdxInternalBackdropOptions, RdxPointerDragHandlers, RdxScrollLockOptions, RdxTransitionStatus, RdxTransitionStatusRef, RdxValidationError, RdxValidationInteraction, RdxValidationMode, SafeFunction, SegmentContentObj, SegmentPart, SegmentValueObj, TimeGranularity, TimeSegmentObj, TimeSegmentPart, TimeValue, UseDateFieldProps, UseFilterOptions, UseListHighlightOptions };
|
|
2175
|
+
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, DOCS_BASE_URL, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_DEFAULT_VALIDATION_MODE, RDX_FIELD_VALIDITY, RDX_FLOATING_REGISTRATION, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_TREE, RDX_FORM_UI_STATE, RDX_INTERNAL_BACKDROP_ATTR, RDX_SCROLL_LOCKED_ATTR, RdxControlValueAccessor, RdxFloatingNode, RdxFloatingNodeRegistration, RdxFloatingRegistrationContext, RdxFloatingRootContext, RdxFloatingTree, RdxFormUiControlBase, RdxFormUiStateHost, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, RdxTriggerRegistry, SHIFT, SPACE, SPACE_CODE, TAB, TIME_GRANULARITIES, a, areAllDaysBetweenValid, clamp, createCancelableChangeEventDetails, createContent, createContext, createFloatingEvents, createFloatingRootContext, createFormUiState, createFormatter, createMonth, createMonths, docsUrl, elementSize, formUiStateContext, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectFloatingRootContext, injectId, injectNgControlState, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isItemEqualToValue, isNullish, isNumberString, isSegmentNavigationKey, isValidationRevealed, isZonedDateTime, itemToStringLabel, itemToStringValue, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideExistingToken, provideFloatingRegistration, provideFloatingRootContext, provideFloatingTree, provideFormUiState, provideValueAccessor, rdxCheckLabelElement, rdxCheckTriggerElement, rdxDevError, rdxDevWarning, resetRdxDevWarnings, resizeEffect, resolveDisplayValid, resolveFloatingTree, roundToStepPrecision, segmentBuilders, serializeNativeFormValue, setupInternalBackdrop, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useAnchoredScrollLock, useArrowNavigation, useDateField, useFilter, useGraceArea, useListHighlight, useNativeFormControl, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
2176
|
+
export type { AcceptableValue, AnyExceptLiteral, AriaLivePoliteness, BooleanInput, CreateMonthProps, DataOrientation, DateAndTimeSegmentObj, DateFormatterOptions, DateMatcher, DateRange, DateSegmentObj, DateSegmentPart, DateStep, DayPeriod, Direction, EditableSegmentPart, FilterPredicates, Formatter, Granularity, HourCycle, InjectContext, ItemValueComparator, ListHighlight, Month, NonEditableSegmentPart, Nullable, NumberInput, PlaceholderMap, RdxAnchoredScrollLockOptions, RdxCancelableChangeEventDetails, RdxCancelableChangeEventTransaction, RdxFloatingEventMap, RdxFloatingEvents, RdxFloatingLifecycle, RdxFloatingNodeInit, RdxFloatingParentOverride, RdxFloatingRegistrationReader, RdxFloatingRegistrationStatus, RdxFloatingRootContextEventMap, RdxFloatingRootContextInit, RdxFormCheckboxControl, RdxFormStateInput, RdxFormUiControl, RdxFormUiState, RdxFormUiStateContext, RdxFormUiStateOptions, RdxFormUiTouchTarget, RdxFormValueControl, RdxInternalBackdropOptions, RdxNativeFormControl, RdxNativeFormControlOptions, RdxNgControlState, RdxPointerDragHandlers, RdxScrollLockOptions, RdxTransitionStatus, RdxTransitionStatusRef, RdxValidationError, RdxValidationInteraction, RdxValidationMode, SafeFunction, SegmentContentObj, SegmentPart, SegmentValueObj, TimeGranularity, TimeSegmentObj, TimeSegmentPart, TimeValue, UseDateFieldProps, UseFilterOptions, UseListHighlightOptions };
|
|
@@ -4,11 +4,12 @@ import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
|
|
|
4
4
|
import { RdxFormUiControlBase, RdxFormValueControl, DateMatcher, HourCycle, Granularity, Direction, BooleanInput, DateStep, Formatter, SegmentValueObj, SegmentPart } from '@radix-ng/primitives/core';
|
|
5
5
|
import { DateValue } from '@internationalized/date';
|
|
6
6
|
|
|
7
|
-
declare class RdxDateFieldRootDirective extends RdxFormUiControlBase implements RdxFormValueControl<DateValue |
|
|
7
|
+
declare class RdxDateFieldRootDirective extends RdxFormUiControlBase implements RdxFormValueControl<DateValue | null> {
|
|
8
8
|
/**
|
|
9
|
-
* The controlled value of the date field.
|
|
9
|
+
* The controlled value of the date field. `null` represents an empty field and keeps the value
|
|
10
|
+
* addressable as an Angular Signal Forms child field (`undefined` denotes an absent optional path).
|
|
10
11
|
*/
|
|
11
|
-
readonly value: _angular_core.ModelSignal<DateValue |
|
|
12
|
+
readonly value: _angular_core.ModelSignal<DateValue | null>;
|
|
12
13
|
/**
|
|
13
14
|
* A matcher that marks specific dates as unavailable; a matched value makes the field invalid.
|
|
14
15
|
*/
|
|
@@ -122,6 +123,8 @@ declare class RdxDateFieldRootDirective extends RdxFormUiControlBase implements
|
|
|
122
123
|
private readonly userInteracted;
|
|
123
124
|
/** @ignore Mark the field touched (model + `touch` output) for Signal Forms. Called on segment blur. */
|
|
124
125
|
markAsTouched(): void;
|
|
126
|
+
/** Reset segment interaction so the form-owned value write remains pristine. */
|
|
127
|
+
reset(): void;
|
|
125
128
|
/**
|
|
126
129
|
* @ignore
|
|
127
130
|
*/
|
|
@@ -235,7 +238,7 @@ declare class RdxDateFieldInputDirective {
|
|
|
235
238
|
|
|
236
239
|
interface DateFieldContextToken {
|
|
237
240
|
locale: InputSignal<string>;
|
|
238
|
-
value: ModelSignal<DateValue |
|
|
241
|
+
value: ModelSignal<DateValue | null>;
|
|
239
242
|
disabled: Signal<boolean>;
|
|
240
243
|
readonly: Signal<boolean>;
|
|
241
244
|
isInvalid: Signal<boolean>;
|
|
@@ -63,6 +63,15 @@ declare class RdxFieldError {
|
|
|
63
63
|
* @group Props
|
|
64
64
|
*/
|
|
65
65
|
readonly id: _angular_core.InputSignal<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Shows this error only for a matching validation-error key. Bind `true` to keep it visible under
|
|
68
|
+
* external control; omit it for the field's default error behavior.
|
|
69
|
+
*
|
|
70
|
+
* @group Props
|
|
71
|
+
*/
|
|
72
|
+
readonly match: _angular_core.InputSignal<string | boolean | undefined>;
|
|
73
|
+
/** Whether this error part is currently presented. */
|
|
74
|
+
readonly visible: _angular_core.Signal<boolean>;
|
|
66
75
|
/**
|
|
67
76
|
* The field's validation messages — client (provider / form name-routing, once `validationMode`
|
|
68
77
|
* reveals them) then server (the Form's `errors` input, always); `[]` when none. Render them
|
|
@@ -73,12 +82,11 @@ declare class RdxFieldError {
|
|
|
73
82
|
constructor();
|
|
74
83
|
protected readonly dataAttr: (value: boolean) => "" | undefined;
|
|
75
84
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldError, never>;
|
|
76
|
-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldError, "[rdxFieldError]", ["rdxFieldError"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
85
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldError, "[rdxFieldError]", ["rdxFieldError"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "match": { "alias": "match"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
/**
|
|
80
|
-
* External owner of field state. An adapter (
|
|
81
|
-
* `[rdxSignalField]` directive, or a Reactive Forms bridge) registers one via
|
|
89
|
+
* External owner of field state. An adapter (`rdxSignalField` or `rdxNgControlField`) registers one via
|
|
82
90
|
* `setStateProvider` so Field reads authoritative form state instead of
|
|
83
91
|
* self-computing it from the DOM. Each member is an optional signal-like
|
|
84
92
|
* accessor; only the states the adapter owns need to be provided — the rest
|
|
@@ -86,15 +94,19 @@ declare class RdxFieldError {
|
|
|
86
94
|
* `() => boolean` accessors keeps Field framework-agnostic (no dependency on
|
|
87
95
|
* `@angular/forms/signals`).
|
|
88
96
|
*
|
|
89
|
-
* See ADR 0004 and `signal-forms-readiness.md` (prep #4).
|
|
97
|
+
* See ADR 0004, ADR 0021, and `signal-forms-readiness.md` (prep #4).
|
|
90
98
|
*/
|
|
91
99
|
interface RdxFieldState {
|
|
100
|
+
/** Field name inferred by an adapter. An explicit `rdxFieldRoot[name]` always wins. */
|
|
101
|
+
name?: () => string | undefined;
|
|
92
102
|
/**
|
|
93
103
|
* The control's **actual** invalidity (ungated). The Field decides *when* to display it from its
|
|
94
104
|
* `validationMode` (e.g. only after blur) — the adapter just reports the real state. A non-empty
|
|
95
105
|
* `errors()` also counts as invalid.
|
|
96
106
|
*/
|
|
97
107
|
invalid?: () => boolean;
|
|
108
|
+
/** Whether async validation is pending. Pending validity remains neutral, never falsely valid. */
|
|
109
|
+
pending?: () => boolean;
|
|
98
110
|
disabled?: () => boolean;
|
|
99
111
|
required?: () => boolean;
|
|
100
112
|
dirty?: () => boolean;
|
|
@@ -108,7 +120,7 @@ interface RdxFieldState {
|
|
|
108
120
|
* any enclosing Form's server messages. Uses `core`'s framework-free shim type so the seam stays free of
|
|
109
121
|
* `@angular/forms/signals` (ADR 0004 amendment).
|
|
110
122
|
*/
|
|
111
|
-
errors?: () => RdxValidationError[];
|
|
123
|
+
errors?: () => readonly RdxValidationError[];
|
|
112
124
|
}
|
|
113
125
|
interface RdxFieldRootContext {
|
|
114
126
|
controlId: Signal<string>;
|
|
@@ -116,6 +128,8 @@ interface RdxFieldRootContext {
|
|
|
116
128
|
descriptionIds: Signal<string[]>;
|
|
117
129
|
errorIds: Signal<string[]>;
|
|
118
130
|
messages: Signal<string[]>;
|
|
131
|
+
/** Whether the currently displayed client errors contain this validation kind. */
|
|
132
|
+
matchesError: (kind: string) => boolean;
|
|
119
133
|
notifyEdited: () => void;
|
|
120
134
|
/** Tri-state *displayed* validity (`true` valid / `false` invalid / `null` neutral), gated by the
|
|
121
135
|
* field's `validationMode`. The source for `data-valid` / `data-invalid` on the field and its controls. */
|
|
@@ -229,6 +243,8 @@ declare class RdxFieldRoot {
|
|
|
229
243
|
private readonly stateProvider;
|
|
230
244
|
/** Whether an external adapter currently owns field state. */
|
|
231
245
|
readonly hasStateProvider: Signal<boolean>;
|
|
246
|
+
/** Explicit field name wins; an adapter may infer one from its form-control binding. */
|
|
247
|
+
readonly effectiveName: Signal<string | undefined>;
|
|
232
248
|
/** Error content from a registered state provider (e.g. a Signal Forms adapter). */
|
|
233
249
|
private readonly providerErrors;
|
|
234
250
|
/** **Client** validation errors routed by a form-level provider (`rdxSignalForm`) — gated by `validationMode`. */
|
|
@@ -246,6 +262,8 @@ declare class RdxFieldRoot {
|
|
|
246
262
|
* field state), so deduping renders it once while still surfacing distinct messages from each source.
|
|
247
263
|
*/
|
|
248
264
|
readonly messages: Signal<string[]>;
|
|
265
|
+
/** Whether a client validation error of `kind` is currently revealed by the field. */
|
|
266
|
+
matchesError(kind: string): boolean;
|
|
249
267
|
/** Effective validation-display mode: this field's override → the enclosing Form's → the default. */
|
|
250
268
|
readonly effectiveValidationMode: Signal<RdxValidationMode>;
|
|
251
269
|
/** Whether client-side validity is revealed yet, per {@link effectiveValidationMode} + interaction. */
|
|
@@ -276,6 +294,7 @@ declare class RdxFieldRoot {
|
|
|
276
294
|
* the provider/input `invalid`.
|
|
277
295
|
*/
|
|
278
296
|
readonly actualInvalidState: Signal<boolean>;
|
|
297
|
+
readonly pendingState: Signal<boolean>;
|
|
279
298
|
readonly disabledState: Signal<boolean>;
|
|
280
299
|
readonly requiredState: Signal<boolean>;
|
|
281
300
|
readonly dirtyState: Signal<boolean>;
|
|
@@ -310,8 +329,8 @@ declare class RdxFieldRoot {
|
|
|
310
329
|
clearStateProvider(provider: RdxFieldState | null, previous: RdxFieldState | null): void;
|
|
311
330
|
/**
|
|
312
331
|
* Prefer the registered provider's value for `key` when it exposes one,
|
|
313
|
-
* otherwise fall back to the root inputs / DOM-derived signals. `
|
|
314
|
-
*
|
|
332
|
+
* otherwise fall back to the root inputs / DOM-derived signals. `name` and `errors` are resolved
|
|
333
|
+
* separately, so they're excluded from this boolean key.
|
|
315
334
|
*/
|
|
316
335
|
private resolve;
|
|
317
336
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldRoot, never>;
|
|
@@ -369,5 +388,33 @@ declare class RdxFieldLabel {
|
|
|
369
388
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldLabel, "[rdxFieldLabel]", ["rdxFieldLabel"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
370
389
|
}
|
|
371
390
|
|
|
372
|
-
|
|
391
|
+
/**
|
|
392
|
+
* Bridges a same-host Reactive Forms or template-driven `NgControl` into an enclosing `rdxFieldRoot`.
|
|
393
|
+
* Place it next to `formControl`, `formControlName`, or `ngModel`; Angular remains the source of value,
|
|
394
|
+
* validation, and interaction state while Field owns when that state is displayed.
|
|
395
|
+
*
|
|
396
|
+
* ```html
|
|
397
|
+
* <div rdxFieldRoot>
|
|
398
|
+
* <label rdxFieldLabel>Email</label>
|
|
399
|
+
* <input formControlName="email" rdxFieldControl rdxNgControlField />
|
|
400
|
+
* <p match="required" rdxFieldError>Email is required.</p>
|
|
401
|
+
* </div>
|
|
402
|
+
* ```
|
|
403
|
+
*
|
|
404
|
+
* The adapter also infers the Field name from `formControlName` / `ngModel` for Form-level server-error
|
|
405
|
+
* routing. An explicit `name` on `rdxFieldRoot` takes precedence (useful for nested or remapped keys).
|
|
406
|
+
*
|
|
407
|
+
* @group Components
|
|
408
|
+
*/
|
|
409
|
+
declare class RdxNgControlField {
|
|
410
|
+
private readonly ngControlState;
|
|
411
|
+
private readonly fieldContext;
|
|
412
|
+
/** Normalized Angular validation errors (`{ kind, message? }[]`). */
|
|
413
|
+
readonly validationErrors: _angular_core.Signal<readonly _radix_ng_primitives_core.RdxValidationError[]>;
|
|
414
|
+
constructor();
|
|
415
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNgControlField, never>;
|
|
416
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNgControlField, "[formControl][rdxNgControlField], [formControlName][rdxNgControlField], [ngModel][rdxNgControlField]", ["rdxNgControlField"], {}, {}, never, never, true, never>;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldItem, RdxFieldLabel, RdxFieldRoot, RdxNgControlField, injectFieldRootContext, provideFieldRootContext };
|
|
373
420
|
export type { RdxFieldRootContext, RdxFieldState };
|
|
@@ -49,6 +49,13 @@ interface RdxFormState {
|
|
|
49
49
|
dirty?: () => boolean;
|
|
50
50
|
touched?: () => boolean;
|
|
51
51
|
submitting?: () => boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Optional Angular-owned submission lifecycle. Returning `undefined` keeps the Form's Base UI-style
|
|
54
|
+
* synchronous submit path; returning a Promise delegates this submit to the adapter. Signal Forms
|
|
55
|
+
* uses this only when its opt-in `rdxSignalSubmit` input is present, and calls Angular's public
|
|
56
|
+
* `submit()` API so validation, touched state, concurrency, and submission errors stay Angular-owned.
|
|
57
|
+
*/
|
|
58
|
+
submit?: () => Promise<boolean> | undefined;
|
|
52
59
|
/**
|
|
53
60
|
* Per-name **client** validation errors (e.g. `rdxSignalForm`'s Signal Forms name-routing). Surfaced
|
|
54
61
|
* through the Form's `clientErrorsFor` channel and gated by `validationMode` like any client validity.
|
|
@@ -190,6 +197,8 @@ declare class RdxFormRoot {
|
|
|
190
197
|
*/
|
|
191
198
|
clearStateProvider(provider: RdxFormState | null, previous: RdxFormState | null): void;
|
|
192
199
|
onSubmit(event: SubmitEvent): void;
|
|
200
|
+
private finishDelegatedSubmit;
|
|
201
|
+
private focusFirstInvalidField;
|
|
193
202
|
onReset(): void;
|
|
194
203
|
private readonly resetTimers;
|
|
195
204
|
constructor();
|