@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.
- package/aspect-ratio/README.md +1 -1
- package/fesm2022/radix-ng-primitives-accordion.mjs +6 -1
- package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-aspect-ratio.mjs +9 -34
- package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +43 -9
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-avatar.mjs +69 -18
- package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +93 -16
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-collapsible.mjs +4 -3
- package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +43 -9
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +208 -2
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +50 -9
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs +31 -5
- package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +276 -58
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-form.mjs +111 -27
- package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-input.mjs +16 -6
- package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-label.mjs +5 -4
- package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +39 -10
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-progress.mjs +37 -22
- package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +18 -9
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +4 -4
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +26 -8
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-separator.mjs +7 -13
- package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-signal-forms.mjs +184 -0
- package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-slider.mjs +25 -10
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +32 -8
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs +4 -4
- package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +49 -9
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +33 -16
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle.mjs +24 -29
- package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toolbar.mjs +15 -2
- package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
- package/package.json +11 -1
- package/types/radix-ng-primitives-accordion.d.ts +1 -0
- package/types/radix-ng-primitives-aspect-ratio.d.ts +10 -23
- package/types/radix-ng-primitives-autocomplete.d.ts +21 -2
- package/types/radix-ng-primitives-avatar.d.ts +51 -25
- package/types/radix-ng-primitives-checkbox.d.ts +78 -101
- package/types/radix-ng-primitives-combobox.d.ts +51 -2
- package/types/radix-ng-primitives-core.d.ts +206 -3
- package/types/radix-ng-primitives-date-field.d.ts +27 -2
- package/types/radix-ng-primitives-editable.d.ts +15 -2
- package/types/radix-ng-primitives-field.d.ts +165 -236
- package/types/radix-ng-primitives-form.d.ts +122 -37
- package/types/radix-ng-primitives-input.d.ts +8 -1
- package/types/radix-ng-primitives-label.d.ts +3 -2
- package/types/radix-ng-primitives-number-field.d.ts +15 -4
- package/types/radix-ng-primitives-progress.d.ts +59 -121
- package/types/radix-ng-primitives-radio.d.ts +7 -3
- package/types/radix-ng-primitives-select.d.ts +11 -3
- package/types/radix-ng-primitives-separator.d.ts +0 -7
- package/types/radix-ng-primitives-signal-forms.d.ts +97 -0
- package/types/radix-ng-primitives-slider.d.ts +9 -7
- package/types/radix-ng-primitives-switch.d.ts +15 -2
- package/types/radix-ng-primitives-time-field.d.ts +26 -2
- package/types/radix-ng-primitives-toggle-group.d.ts +13 -7
- package/types/radix-ng-primitives-toggle.d.ts +8 -8
- package/types/radix-ng-primitives-toolbar.d.ts +2 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, booleanAttribute, signal, computed, inject, ElementRef, DestroyRef, Directive, effect, afterNextRender } from '@angular/core';
|
|
3
|
-
import { createContext, rdxCheckLabelElement } from '@radix-ng/primitives/core';
|
|
3
|
+
import { createContext, injectId, RDX_DEFAULT_VALIDATION_MODE, isValidationRevealed, RDX_FIELD_VALIDITY, rdxCheckLabelElement } from '@radix-ng/primitives/core';
|
|
4
4
|
import { injectFormRootContext } from '@radix-ng/primitives/form';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const removeId = (ids, id) => ids.filter((item) => item !== id);
|
|
6
|
+
const attr$5 = (value) => (value ? '' : undefined);
|
|
7
|
+
const addId$1 = (ids, id) => (ids.includes(id) ? ids : [...ids, id]);
|
|
8
|
+
const removeId$1 = (ids, id) => ids.filter((item) => item !== id);
|
|
10
9
|
const fieldRootContext = () => {
|
|
11
10
|
const root = injectFieldRoot();
|
|
12
11
|
return {
|
|
@@ -14,10 +13,13 @@ const fieldRootContext = () => {
|
|
|
14
13
|
name: root.name,
|
|
15
14
|
descriptionIds: root.descriptionIds,
|
|
16
15
|
errorIds: root.errorIds,
|
|
17
|
-
/** Combined
|
|
16
|
+
/** Combined messages for `RdxFieldError`: client (provider + form name-routing, when revealed) then
|
|
17
|
+
* server (`errors` input, always). */
|
|
18
18
|
messages: root.messages,
|
|
19
19
|
/** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
|
|
20
20
|
notifyEdited: () => root.notifyEdited(),
|
|
21
|
+
validState: root.validState,
|
|
22
|
+
formSubmitAttempted: root.formSubmitAttempted,
|
|
21
23
|
invalidState: root.invalidState,
|
|
22
24
|
disabledState: root.disabledState,
|
|
23
25
|
requiredState: root.requiredState,
|
|
@@ -26,10 +28,10 @@ const fieldRootContext = () => {
|
|
|
26
28
|
filledState: root.filledState,
|
|
27
29
|
focusedState: root.focusedState,
|
|
28
30
|
setControlId: (id) => root.controlId.set(id),
|
|
29
|
-
addDescriptionId: (id) => root.descriptionIds.update((ids) => addId(ids, id)),
|
|
30
|
-
removeDescriptionId: (id) => root.descriptionIds.update((ids) => removeId(ids, id)),
|
|
31
|
-
addErrorId: (id) => root.errorIds.update((ids) => addId(ids, id)),
|
|
32
|
-
removeErrorId: (id) => root.errorIds.update((ids) => removeId(ids, id)),
|
|
31
|
+
addDescriptionId: (id) => root.descriptionIds.update((ids) => addId$1(ids, id)),
|
|
32
|
+
removeDescriptionId: (id) => root.descriptionIds.update((ids) => removeId$1(ids, id)),
|
|
33
|
+
addErrorId: (id) => root.errorIds.update((ids) => addId$1(ids, id)),
|
|
34
|
+
removeErrorId: (id) => root.errorIds.update((ids) => removeId$1(ids, id)),
|
|
33
35
|
setFocused: (value) => root.focusedValue.set(value),
|
|
34
36
|
setFilled: (value) => root.filledValue.set(value),
|
|
35
37
|
setDirty: (value) => root.dirtyValue.set(value),
|
|
@@ -41,6 +43,7 @@ const fieldRootContext = () => {
|
|
|
41
43
|
* provider so adapters can restore it on teardown.
|
|
42
44
|
*/
|
|
43
45
|
setStateProvider: (provider) => root.setStateProvider(provider),
|
|
46
|
+
clearStateProvider: (provider, previous) => root.clearStateProvider(provider, previous),
|
|
44
47
|
hasStateProvider: root.hasStateProvider
|
|
45
48
|
};
|
|
46
49
|
};
|
|
@@ -109,9 +112,17 @@ class RdxFieldRoot {
|
|
|
109
112
|
*/
|
|
110
113
|
this.name = input(/* @ts-ignore */
|
|
111
114
|
...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ []));
|
|
115
|
+
/**
|
|
116
|
+
* Overrides when this field reveals its validity (error styling + message). Falls back to the
|
|
117
|
+
* enclosing `rdxFormRoot`'s `validationMode`, then `'onBlur'`. Server errors always show regardless.
|
|
118
|
+
*
|
|
119
|
+
* @group Props
|
|
120
|
+
*/
|
|
121
|
+
this.validationMode = input(/* @ts-ignore */
|
|
122
|
+
...(ngDevMode ? [undefined, { debugName: "validationMode" }] : /* istanbul ignore next */ []));
|
|
112
123
|
/** The enclosing Form, if any. All Form-related behavior is a no-op when this is `null`. */
|
|
113
124
|
this.formContext = injectFormRootContext(true);
|
|
114
|
-
this.controlId = signal(
|
|
125
|
+
this.controlId = signal(injectId('rdx-field-control-'), /* @ts-ignore */
|
|
115
126
|
...(ngDevMode ? [{ debugName: "controlId" }] : /* istanbul ignore next */ []));
|
|
116
127
|
this.descriptionIds = signal([], /* @ts-ignore */
|
|
117
128
|
...(ngDevMode ? [{ debugName: "descriptionIds" }] : /* istanbul ignore next */ []));
|
|
@@ -134,37 +145,108 @@ class RdxFieldRoot {
|
|
|
134
145
|
/** Error content from a registered state provider (e.g. a Signal Forms adapter). */
|
|
135
146
|
this.providerErrors = computed(() => this.stateProvider()?.errors?.() ?? [], /* @ts-ignore */
|
|
136
147
|
...(ngDevMode ? [{ debugName: "providerErrors" }] : /* istanbul ignore next */ []));
|
|
137
|
-
/**
|
|
138
|
-
this.
|
|
139
|
-
...(ngDevMode ? [{ debugName: "
|
|
140
|
-
/**
|
|
141
|
-
this.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
/** **Client** validation errors routed by a form-level provider (`rdxSignalForm`) — gated by `validationMode`. */
|
|
149
|
+
this.clientErrors = computed(() => this.formContext?.clientErrorsFor(this.name()) ?? [], /* @ts-ignore */
|
|
150
|
+
...(ngDevMode ? [{ debugName: "clientErrors" }] : /* istanbul ignore next */ []));
|
|
151
|
+
/** **Server/external** errors from the Form's `errors` input — shown eagerly (never gated). */
|
|
152
|
+
this.serverErrors = computed(() => this.formContext?.externalErrorsFor(this.name()) ?? [], /* @ts-ignore */
|
|
153
|
+
...(ngDevMode ? [{ debugName: "serverErrors" }] : /* istanbul ignore next */ []));
|
|
154
|
+
/** Whether the enclosing Form has had a submit attempted; `false` when standalone. A presentation
|
|
155
|
+
* seam an adapter can read to reveal errors after a submit attempt (Base UI's submit-attempt state). */
|
|
156
|
+
this.formSubmitAttempted = computed(() => this.formContext?.submitAttempted() ?? false, /* @ts-ignore */
|
|
157
|
+
...(ngDevMode ? [{ debugName: "formSubmitAttempted" }] : /* istanbul ignore next */ []));
|
|
158
|
+
/**
|
|
159
|
+
* Client messages first (per-field `rdxSignalField` provider, then form-level `rdxSignalForm`
|
|
160
|
+
* name-routing) — only once `validationMode` reveals client validity — then the Form's **server**
|
|
161
|
+
* messages (the `errors` input), which always show. **Deduped by text**: a field can receive the same
|
|
162
|
+
* Signal Forms error from both a per-field provider and the form-level routing (they read the same
|
|
163
|
+
* field state), so deduping renders it once while still surfacing distinct messages from each source.
|
|
164
|
+
*/
|
|
165
|
+
this.messages = computed(() => {
|
|
166
|
+
// **Client** messages (per-field `rdxSignalField` provider + form-level `rdxSignalForm` routing)
|
|
167
|
+
// surface only once the field's `validationMode` reveals them; **server** messages (the `errors`
|
|
168
|
+
// input) always show. So a neutral field stays empty and the polite live region announces on reveal.
|
|
169
|
+
const client = this.validationRevealed()
|
|
170
|
+
? [...this.providerErrors().map((error) => error.message ?? error.kind), ...this.clientErrors()]
|
|
171
|
+
: [];
|
|
172
|
+
const seen = new Set();
|
|
173
|
+
const result = [];
|
|
174
|
+
for (const message of [...client, ...this.serverErrors()]) {
|
|
175
|
+
if (message && !seen.has(message)) {
|
|
176
|
+
seen.add(message);
|
|
177
|
+
result.push(message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}, /* @ts-ignore */
|
|
145
182
|
...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
183
|
+
/** Effective validation-display mode: this field's override → the enclosing Form's → the default. */
|
|
184
|
+
this.effectiveValidationMode = computed(() => this.validationMode() ?? this.formContext?.validationMode() ?? RDX_DEFAULT_VALIDATION_MODE, /* @ts-ignore */
|
|
185
|
+
...(ngDevMode ? [{ debugName: "effectiveValidationMode" }] : /* istanbul ignore next */ []));
|
|
186
|
+
/** Whether client-side validity is revealed yet, per {@link effectiveValidationMode} + interaction. */
|
|
187
|
+
this.validationRevealed = computed(() => isValidationRevealed(this.effectiveValidationMode(), {
|
|
188
|
+
touched: this.touchedState(),
|
|
189
|
+
dirty: this.dirtyState(),
|
|
190
|
+
submitAttempted: this.formSubmitAttempted()
|
|
191
|
+
}), /* @ts-ignore */
|
|
192
|
+
...(ngDevMode ? [{ debugName: "validationRevealed" }] : /* istanbul ignore next */ []));
|
|
193
|
+
/**
|
|
194
|
+
* Client-side invalidity (gated by `validationMode`): the per-field provider's error content / `invalid`
|
|
195
|
+
* (`rdxSignalField`), a form-level provider's name-routed errors (`rdxSignalForm`), or the `[invalid]`
|
|
196
|
+
* input. Excludes server errors (which are eager).
|
|
197
|
+
*/
|
|
198
|
+
this.clientInvalidState = computed(() => this.providerErrors().length > 0 ||
|
|
199
|
+
this.clientErrors().length > 0 ||
|
|
200
|
+
this.resolve('invalid', () => this.invalid()), /* @ts-ignore */
|
|
201
|
+
...(ngDevMode ? [{ debugName: "clientInvalidState" }] : /* istanbul ignore next */ []));
|
|
202
|
+
/**
|
|
203
|
+
* Tri-state *displayed* validity (`boolean | null`) — the source for `data-valid` / `data-invalid`.
|
|
204
|
+
* Server errors show immediately; client-side validity (including `rdxSignalForm` name-routing) stays
|
|
205
|
+
* **neutral** (`null`) until the field's {@link effectiveValidationMode} reveals it, then `false`/`true`.
|
|
206
|
+
*/
|
|
207
|
+
this.validState = computed(() => {
|
|
208
|
+
if (this.serverErrors().length > 0) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
if (!this.validationRevealed()) {
|
|
212
|
+
return null;
|
|
151
213
|
}
|
|
152
|
-
return this.
|
|
214
|
+
return this.clientInvalidState() ? false : true;
|
|
153
215
|
}, /* @ts-ignore */
|
|
216
|
+
...(ngDevMode ? [{ debugName: "validState" }] : /* istanbul ignore next */ []));
|
|
217
|
+
/**
|
|
218
|
+
* Boolean **displayed** invalidity (= `validState() === false`), used by `rdxFieldError` (hidden) and
|
|
219
|
+
* `rdxFieldControl`'s `aria-describedby` error linking. A neutral (`null`) `validState` reads as not
|
|
220
|
+
* invalid here, so the error region stays hidden until the field's mode reveals it.
|
|
221
|
+
*/
|
|
222
|
+
this.invalidState = computed(() => this.validState() === false, /* @ts-ignore */
|
|
154
223
|
...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
|
|
224
|
+
/**
|
|
225
|
+
* Boolean **actual** invalidity — ungated by the display mode. The enclosing Form aggregates this into
|
|
226
|
+
* `anyInvalid` (→ submit-block / focus-first-invalid), so a field that is really invalid but displayed
|
|
227
|
+
* neutral still blocks submit. The form's presentation `data-invalid` comes from the *displayed*
|
|
228
|
+
* aggregate (`anyDisplayedInvalid`) instead — not from this. Server errors + provider error content +
|
|
229
|
+
* the provider/input `invalid`.
|
|
230
|
+
*/
|
|
231
|
+
this.actualInvalidState = computed(() => this.serverErrors().length > 0 || this.clientInvalidState(), /* @ts-ignore */
|
|
232
|
+
...(ngDevMode ? [{ debugName: "actualInvalidState" }] : /* istanbul ignore next */ []));
|
|
155
233
|
this.disabledState = computed(() => this.resolve('disabled', () => this.disabled()), /* @ts-ignore */
|
|
156
234
|
...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
|
|
157
235
|
this.requiredState = computed(() => this.resolve('required', () => this.required()), /* @ts-ignore */
|
|
158
236
|
...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
|
|
159
|
-
|
|
237
|
+
// `touched`/`dirty` also OR in the enclosing Form's per-name state (`rdxSignalForm` name-routing), so a
|
|
238
|
+
// field with only a bare `[formField]` (no `rdxSignalField`/`rdxFieldControl`) still reveals on blur.
|
|
239
|
+
this.dirtyState = computed(() => this.resolve('dirty', () => this.dirty() || this.dirtyValue()) ||
|
|
240
|
+
(this.formContext?.dirtyFor(this.name()) ?? false), /* @ts-ignore */
|
|
160
241
|
...(ngDevMode ? [{ debugName: "dirtyState" }] : /* istanbul ignore next */ []));
|
|
161
|
-
this.touchedState = computed(() => this.resolve('touched', () => this.touched() || this.touchedValue())
|
|
242
|
+
this.touchedState = computed(() => this.resolve('touched', () => this.touched() || this.touchedValue()) ||
|
|
243
|
+
(this.formContext?.touchedFor(this.name()) ?? false), /* @ts-ignore */
|
|
162
244
|
...(ngDevMode ? [{ debugName: "touchedState" }] : /* istanbul ignore next */ []));
|
|
163
245
|
this.filledState = computed(() => this.resolve('filled', () => this.filled() ?? this.filledValue()), /* @ts-ignore */
|
|
164
246
|
...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
|
|
165
247
|
this.focusedState = computed(() => this.resolve('focused', () => this.focused() ?? this.focusedValue()), /* @ts-ignore */
|
|
166
248
|
...(ngDevMode ? [{ debugName: "focusedState" }] : /* istanbul ignore next */ []));
|
|
167
|
-
this.dataAttr = attr$
|
|
249
|
+
this.dataAttr = attr$5;
|
|
168
250
|
this.host = inject(ElementRef).nativeElement;
|
|
169
251
|
// Register with an enclosing Form (if any) for aggregate state, submit guard, and reset; a
|
|
170
252
|
// standalone field never enters this branch and behaves exactly as before.
|
|
@@ -172,7 +254,11 @@ class RdxFieldRoot {
|
|
|
172
254
|
if (formContext) {
|
|
173
255
|
const registration = {
|
|
174
256
|
name: () => this.name(),
|
|
175
|
-
invalid
|
|
257
|
+
// `invalid` reports *actual* validity (ungated) — `form.anyInvalid` + the submit guard must
|
|
258
|
+
// reflect real state even before a field reveals it. `displayValid` reports the *gated*
|
|
259
|
+
// tri-state so the form's presentation `data-invalid` stays neutral on load.
|
|
260
|
+
invalid: () => this.actualInvalidState(),
|
|
261
|
+
displayValid: () => this.validState(),
|
|
176
262
|
dirty: () => this.dirtyState(),
|
|
177
263
|
touched: () => this.touchedState(),
|
|
178
264
|
focus: () => this.focusControl(),
|
|
@@ -216,26 +302,47 @@ class RdxFieldRoot {
|
|
|
216
302
|
this.stateProvider.set(provider);
|
|
217
303
|
return previous;
|
|
218
304
|
}
|
|
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, previous) {
|
|
311
|
+
if (this.stateProvider() === provider) {
|
|
312
|
+
this.stateProvider.set(previous);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
219
315
|
/**
|
|
220
316
|
* Prefer the registered provider's value for `key` when it exposes one,
|
|
221
|
-
* otherwise fall back to the root inputs / DOM-derived signals.
|
|
317
|
+
* otherwise fall back to the root inputs / DOM-derived signals. `errors` (content) and `valid`
|
|
318
|
+
* (tri-state `boolean | null`) are resolved separately, so they're excluded from this boolean key.
|
|
222
319
|
*/
|
|
223
320
|
resolve(key, fallback) {
|
|
224
321
|
const accessor = this.stateProvider()?.[key];
|
|
225
322
|
return accessor ? accessor() : fallback();
|
|
226
323
|
}
|
|
227
324
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
228
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldRoot, isStandalone: true, selector: "[rdxFieldRoot]", inputs: { invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, filled: { classPropertyName: "filled", publicName: "filled", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "notifyEdited()", "change": "notifyEdited()" }, properties: { "attr.data-invalid": "dataAttr(
|
|
325
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldRoot, isStandalone: true, selector: "[rdxFieldRoot]", inputs: { invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, filled: { classPropertyName: "filled", publicName: "filled", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, validationMode: { classPropertyName: "validationMode", publicName: "validationMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "notifyEdited()", "change": "notifyEdited()" }, properties: { "attr.data-invalid": "dataAttr(validState() === false)", "attr.data-valid": "dataAttr(validState() === true)", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-dirty": "dataAttr(dirtyState())", "attr.data-touched": "dataAttr(touchedState())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())" } }, providers: [
|
|
326
|
+
provideFieldRootContext(fieldRootContext),
|
|
327
|
+
// Expose the tri-state display validity so controls inside the field reflect it (single source).
|
|
328
|
+
{ provide: RDX_FIELD_VALIDITY, useFactory: () => inject(RdxFieldRoot).validState }
|
|
329
|
+
], exportAs: ["rdxFieldRoot"], ngImport: i0 }); }
|
|
229
330
|
}
|
|
230
331
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldRoot, decorators: [{
|
|
231
332
|
type: Directive,
|
|
232
333
|
args: [{
|
|
233
334
|
selector: '[rdxFieldRoot]',
|
|
234
335
|
exportAs: 'rdxFieldRoot',
|
|
235
|
-
providers: [
|
|
336
|
+
providers: [
|
|
337
|
+
provideFieldRootContext(fieldRootContext),
|
|
338
|
+
// Expose the tri-state display validity so controls inside the field reflect it (single source).
|
|
339
|
+
{ provide: RDX_FIELD_VALIDITY, useFactory: () => inject(RdxFieldRoot).validState }
|
|
340
|
+
],
|
|
236
341
|
host: {
|
|
237
|
-
|
|
238
|
-
|
|
342
|
+
// Tri-state: `data-invalid` when displayed-invalid, `data-valid` only when displayed-valid,
|
|
343
|
+
// and **neither** when neutral (`validState()` is `null`).
|
|
344
|
+
'[attr.data-invalid]': 'dataAttr(validState() === false)',
|
|
345
|
+
'[attr.data-valid]': 'dataAttr(validState() === true)',
|
|
239
346
|
'[attr.data-disabled]': 'dataAttr(disabledState())',
|
|
240
347
|
'[attr.data-required]': 'dataAttr(requiredState())',
|
|
241
348
|
'[attr.data-dirty]': 'dataAttr(dirtyState())',
|
|
@@ -246,13 +353,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
246
353
|
'(change)': 'notifyEdited()'
|
|
247
354
|
}
|
|
248
355
|
}]
|
|
249
|
-
}], ctorParameters: () => [], propDecorators: { invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], filled: [{ type: i0.Input, args: [{ isSignal: true, alias: "filled", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }] } });
|
|
356
|
+
}], ctorParameters: () => [], propDecorators: { invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], filled: [{ type: i0.Input, args: [{ isSignal: true, alias: "filled", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }] } });
|
|
250
357
|
function injectFieldRoot() {
|
|
251
358
|
return inject(RdxFieldRoot);
|
|
252
359
|
}
|
|
253
360
|
|
|
254
|
-
|
|
255
|
-
const attr$3 = (value) => (value ? '' : undefined);
|
|
361
|
+
const attr$4 = (value) => (value ? '' : undefined);
|
|
256
362
|
/**
|
|
257
363
|
* Connects a form control to the field label, description, error, and state.
|
|
258
364
|
*
|
|
@@ -268,7 +374,7 @@ class RdxFieldControl {
|
|
|
268
374
|
*
|
|
269
375
|
* @group Props
|
|
270
376
|
*/
|
|
271
|
-
this.id = input(
|
|
377
|
+
this.id = input(injectId('rdx-field-control-'), /* @ts-ignore */
|
|
272
378
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
273
379
|
this.describedBy = computed(() => {
|
|
274
380
|
const ids = [
|
|
@@ -278,7 +384,7 @@ class RdxFieldControl {
|
|
|
278
384
|
return ids.length ? ids.join(' ') : undefined;
|
|
279
385
|
}, /* @ts-ignore */
|
|
280
386
|
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
281
|
-
this.dataAttr = attr$
|
|
387
|
+
this.dataAttr = attr$4;
|
|
282
388
|
effect(() => {
|
|
283
389
|
this.rootContext.setControlId(this.id());
|
|
284
390
|
});
|
|
@@ -307,7 +413,7 @@ class RdxFieldControl {
|
|
|
307
413
|
return element.value ?? '';
|
|
308
414
|
}
|
|
309
415
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldControl, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
310
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldControl, isStandalone: true, selector: "[rdxFieldControl]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "input": "syncFilled()", "change": "syncFilled()" }, properties: { "attr.id": "id()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "rootContext.
|
|
416
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldControl, isStandalone: true, selector: "[rdxFieldControl]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "input": "syncFilled()", "change": "syncFilled()" }, properties: { "attr.id": "id()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "rootContext.validState() === false ? \"true\" : undefined", "attr.aria-required": "!isNativeFormControl() && rootContext.requiredState() ? \"true\" : undefined", "attr.aria-disabled": "!isNativeFormControl() && rootContext.disabledState() ? \"true\" : undefined", "attr.disabled": "isNativeFormControl() && rootContext.disabledState() ? \"\" : undefined", "attr.required": "isNativeFormControl() && rootContext.requiredState() ? \"\" : undefined", "attr.data-invalid": "dataAttr(rootContext.validState() === false)", "attr.data-valid": "dataAttr(rootContext.validState() === true)", "attr.data-disabled": "dataAttr(rootContext.disabledState())", "attr.data-required": "dataAttr(rootContext.requiredState())", "attr.data-dirty": "dataAttr(rootContext.dirtyState())", "attr.data-touched": "dataAttr(rootContext.touchedState())", "attr.data-filled": "dataAttr(rootContext.filledState())", "attr.data-focused": "dataAttr(rootContext.focusedState())" } }, exportAs: ["rdxFieldControl"], ngImport: i0 }); }
|
|
311
417
|
}
|
|
312
418
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldControl, decorators: [{
|
|
313
419
|
type: Directive,
|
|
@@ -317,15 +423,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
317
423
|
host: {
|
|
318
424
|
'[attr.id]': 'id()',
|
|
319
425
|
'[attr.aria-describedby]': 'describedBy()',
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
426
|
+
// `aria-invalid`/`data-*` follow the field's tri-state `validState`: while it is neutral (`null`,
|
|
427
|
+
// e.g. a field whose `validationMode` defers display (e.g. `onBlur`) before interaction) the control emits no `aria-invalid`
|
|
428
|
+
// and neither `data-valid` nor `data-invalid`, matching the field root.
|
|
429
|
+
'[attr.aria-invalid]': 'rootContext.validState() === false ? "true" : undefined',
|
|
430
|
+
// On a native control the native `required`/`disabled` attributes already convey the state, so
|
|
431
|
+
// `aria-required`/`aria-disabled` are only emitted on non-native (custom) controls.
|
|
432
|
+
'[attr.aria-required]': '!isNativeFormControl() && rootContext.requiredState() ? "true" : undefined',
|
|
433
|
+
'[attr.aria-disabled]': '!isNativeFormControl() && rootContext.disabledState() ? "true" : undefined',
|
|
323
434
|
'[attr.disabled]': 'isNativeFormControl() && rootContext.disabledState() ? "" : undefined',
|
|
324
435
|
'[attr.required]': 'isNativeFormControl() && rootContext.requiredState() ? "" : undefined',
|
|
325
|
-
'[attr.data-invalid]': 'dataAttr(rootContext.
|
|
326
|
-
'[attr.data-valid]': 'dataAttr(
|
|
436
|
+
'[attr.data-invalid]': 'dataAttr(rootContext.validState() === false)',
|
|
437
|
+
'[attr.data-valid]': 'dataAttr(rootContext.validState() === true)',
|
|
327
438
|
'[attr.data-disabled]': 'dataAttr(rootContext.disabledState())',
|
|
328
439
|
'[attr.data-required]': 'dataAttr(rootContext.requiredState())',
|
|
440
|
+
'[attr.data-dirty]': 'dataAttr(rootContext.dirtyState())',
|
|
441
|
+
'[attr.data-touched]': 'dataAttr(rootContext.touchedState())',
|
|
329
442
|
'[attr.data-filled]': 'dataAttr(rootContext.filledState())',
|
|
330
443
|
'[attr.data-focused]': 'dataAttr(rootContext.focusedState())',
|
|
331
444
|
'(focus)': 'onFocus()',
|
|
@@ -336,8 +449,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
336
449
|
}]
|
|
337
450
|
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
338
451
|
|
|
339
|
-
|
|
340
|
-
const attr$2 = (value) => (value ? '' : undefined);
|
|
452
|
+
const attr$3 = (value) => (value ? '' : undefined);
|
|
341
453
|
/**
|
|
342
454
|
* Describes the field control.
|
|
343
455
|
*
|
|
@@ -351,9 +463,9 @@ class RdxFieldDescription {
|
|
|
351
463
|
*
|
|
352
464
|
* @group Props
|
|
353
465
|
*/
|
|
354
|
-
this.id = input(
|
|
466
|
+
this.id = input(injectId('rdx-field-description-'), /* @ts-ignore */
|
|
355
467
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
356
|
-
this.dataAttr = attr$
|
|
468
|
+
this.dataAttr = attr$3;
|
|
357
469
|
effect((onCleanup) => {
|
|
358
470
|
const id = this.id();
|
|
359
471
|
this.rootContext.addDescriptionId(id);
|
|
@@ -376,8 +488,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
376
488
|
}]
|
|
377
489
|
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
378
490
|
|
|
379
|
-
|
|
380
|
-
const attr$1 = (value) => (value ? '' : undefined);
|
|
491
|
+
const attr$2 = (value) => (value ? '' : undefined);
|
|
381
492
|
/**
|
|
382
493
|
* Describes an invalid field control.
|
|
383
494
|
*
|
|
@@ -391,15 +502,16 @@ class RdxFieldError {
|
|
|
391
502
|
*
|
|
392
503
|
* @group Props
|
|
393
504
|
*/
|
|
394
|
-
this.id = input(
|
|
505
|
+
this.id = input(injectId('rdx-field-error-'), /* @ts-ignore */
|
|
395
506
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
396
507
|
/**
|
|
397
|
-
* The field's
|
|
398
|
-
* them
|
|
508
|
+
* The field's validation messages — client (provider / form name-routing, once `validationMode`
|
|
509
|
+
* reveals them) then server (the Form's `errors` input, always); `[]` when none. Render them
|
|
510
|
+
* explicitly via the `exportAs` reference — the directive never injects text content itself:
|
|
399
511
|
* `<p rdxFieldError #err="rdxFieldError">{{ err.messages().join(' ') }}</p>`.
|
|
400
512
|
*/
|
|
401
513
|
this.messages = this.rootContext.messages;
|
|
402
|
-
this.dataAttr = attr$
|
|
514
|
+
this.dataAttr = attr$2;
|
|
403
515
|
effect((onCleanup) => {
|
|
404
516
|
const id = this.id();
|
|
405
517
|
this.rootContext.addErrorId(id);
|
|
@@ -424,7 +536,113 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
424
536
|
}]
|
|
425
537
|
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
426
538
|
|
|
427
|
-
|
|
539
|
+
const attr$1 = (value) => (value ? '' : undefined);
|
|
540
|
+
const addId = (ids, id) => (ids.includes(id) ? ids : [...ids, id]);
|
|
541
|
+
const removeId = (ids, id) => ids.filter((item) => item !== id);
|
|
542
|
+
/**
|
|
543
|
+
* The field item context **re-provides** {@link RdxFieldRootContext} so a label, description, and control
|
|
544
|
+
* placed inside the item associate with the **item's** control (own `controlId` / `descriptionIds`),
|
|
545
|
+
* while all validation state (`invalidState` / `dirtyState` / `touchedState` / `filledState` /
|
|
546
|
+
* `focusedState` / `requiredState`, errors and messages) is **delegated to the enclosing `rdxFieldRoot`**.
|
|
547
|
+
* `disabledState` is the item's `disabled` OR'd with the root's. The enclosing root is reached with
|
|
548
|
+
* `skipSelf` (the item provides the same token), so there is no circular injection.
|
|
549
|
+
*/
|
|
550
|
+
const fieldItemContext = () => {
|
|
551
|
+
const item = inject(RdxFieldItem);
|
|
552
|
+
const root = item.root;
|
|
553
|
+
return {
|
|
554
|
+
controlId: item.controlId,
|
|
555
|
+
name: root.name,
|
|
556
|
+
descriptionIds: item.descriptionIds,
|
|
557
|
+
errorIds: root.errorIds,
|
|
558
|
+
messages: root.messages,
|
|
559
|
+
notifyEdited: () => root.notifyEdited(),
|
|
560
|
+
validState: root.validState,
|
|
561
|
+
formSubmitAttempted: root.formSubmitAttempted,
|
|
562
|
+
invalidState: root.invalidState,
|
|
563
|
+
disabledState: item.disabledState,
|
|
564
|
+
requiredState: root.requiredState,
|
|
565
|
+
dirtyState: root.dirtyState,
|
|
566
|
+
touchedState: root.touchedState,
|
|
567
|
+
filledState: root.filledState,
|
|
568
|
+
focusedState: root.focusedState,
|
|
569
|
+
setControlId: (id) => item.controlId.set(id),
|
|
570
|
+
addDescriptionId: (id) => item.descriptionIds.update((ids) => addId(ids, id)),
|
|
571
|
+
removeDescriptionId: (id) => item.descriptionIds.update((ids) => removeId(ids, id)),
|
|
572
|
+
addErrorId: (id) => root.errorIds.update((ids) => addId(ids, id)),
|
|
573
|
+
removeErrorId: (id) => root.errorIds.update((ids) => removeId(ids, id)),
|
|
574
|
+
setFocused: (value) => root.focusedValue.set(value),
|
|
575
|
+
setFilled: (value) => root.filledValue.set(value),
|
|
576
|
+
setDirty: (value) => root.dirtyValue.set(value),
|
|
577
|
+
setTouched: (value) => root.touchedValue.set(value),
|
|
578
|
+
setStateProvider: (provider) => root.setStateProvider(provider),
|
|
579
|
+
clearStateProvider: (provider, previous) => root.clearStateProvider(provider, previous),
|
|
580
|
+
hasStateProvider: root.hasStateProvider
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
/**
|
|
584
|
+
* Groups an individual item in a checkbox group or radio group with its own label and description.
|
|
585
|
+
*
|
|
586
|
+
* Use inside a `rdxFieldRoot` (typically wrapping a group) when each control needs its own label /
|
|
587
|
+
* description: the item scopes those associations to its control while reflecting the field's validation
|
|
588
|
+
* state. Mirrors Base UI's `Field.Item`.
|
|
589
|
+
*
|
|
590
|
+
* @group Components
|
|
591
|
+
*/
|
|
592
|
+
class RdxFieldItem {
|
|
593
|
+
constructor() {
|
|
594
|
+
/** The enclosing field root (items are leaves under the root, so `skipSelf` reaches it). */
|
|
595
|
+
this.root = inject(RdxFieldRoot, { skipSelf: true });
|
|
596
|
+
/**
|
|
597
|
+
* Whether the wrapped control should ignore user interaction. The `disabled` on `rdxFieldRoot` takes
|
|
598
|
+
* precedence (it is OR'd in).
|
|
599
|
+
*
|
|
600
|
+
* @group Props
|
|
601
|
+
* @defaultValue false
|
|
602
|
+
*/
|
|
603
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
604
|
+
/** This item's control id — label / description / control inside the item associate with it. */
|
|
605
|
+
this.controlId = signal(injectId('rdx-field-item-control-'), /* @ts-ignore */
|
|
606
|
+
...(ngDevMode ? [{ debugName: "controlId" }] : /* istanbul ignore next */ []));
|
|
607
|
+
/** Description ids for this item's control `aria-describedby`. */
|
|
608
|
+
this.descriptionIds = signal([], /* @ts-ignore */
|
|
609
|
+
...(ngDevMode ? [{ debugName: "descriptionIds" }] : /* istanbul ignore next */ []));
|
|
610
|
+
/** The item's effective disabled state: the root's disabled OR the item's. */
|
|
611
|
+
this.disabledState = computed(() => this.root.disabledState() || this.disabled(), /* @ts-ignore */
|
|
612
|
+
...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
|
|
613
|
+
this.dataAttr = attr$1;
|
|
614
|
+
}
|
|
615
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
616
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldItem, isStandalone: true, selector: "[rdxFieldItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-invalid": "dataAttr(root.validState() === false)", "attr.data-valid": "dataAttr(root.validState() === true)", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(root.requiredState())", "attr.data-dirty": "dataAttr(root.dirtyState())", "attr.data-touched": "dataAttr(root.touchedState())", "attr.data-filled": "dataAttr(root.filledState())", "attr.data-focused": "dataAttr(root.focusedState())" } }, providers: [
|
|
617
|
+
provideFieldRootContext(fieldItemContext),
|
|
618
|
+
// Items delegate validity to the root; expose the root's tri-state to controls inside the item.
|
|
619
|
+
{ provide: RDX_FIELD_VALIDITY, useFactory: () => inject(RdxFieldItem).root.validState }
|
|
620
|
+
], exportAs: ["rdxFieldItem"], ngImport: i0 }); }
|
|
621
|
+
}
|
|
622
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldItem, decorators: [{
|
|
623
|
+
type: Directive,
|
|
624
|
+
args: [{
|
|
625
|
+
selector: '[rdxFieldItem]',
|
|
626
|
+
exportAs: 'rdxFieldItem',
|
|
627
|
+
providers: [
|
|
628
|
+
provideFieldRootContext(fieldItemContext),
|
|
629
|
+
// Items delegate validity to the root; expose the root's tri-state to controls inside the item.
|
|
630
|
+
{ provide: RDX_FIELD_VALIDITY, useFactory: () => inject(RdxFieldItem).root.validState }
|
|
631
|
+
],
|
|
632
|
+
host: {
|
|
633
|
+
// Tri-state, mirroring the root: neither attribute while the root's `validState` is neutral.
|
|
634
|
+
'[attr.data-invalid]': 'dataAttr(root.validState() === false)',
|
|
635
|
+
'[attr.data-valid]': 'dataAttr(root.validState() === true)',
|
|
636
|
+
'[attr.data-disabled]': 'dataAttr(disabledState())',
|
|
637
|
+
'[attr.data-required]': 'dataAttr(root.requiredState())',
|
|
638
|
+
'[attr.data-dirty]': 'dataAttr(root.dirtyState())',
|
|
639
|
+
'[attr.data-touched]': 'dataAttr(root.touchedState())',
|
|
640
|
+
'[attr.data-filled]': 'dataAttr(root.filledState())',
|
|
641
|
+
'[attr.data-focused]': 'dataAttr(root.focusedState())'
|
|
642
|
+
}
|
|
643
|
+
}]
|
|
644
|
+
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
645
|
+
|
|
428
646
|
const attr = (value) => (value ? '' : undefined);
|
|
429
647
|
/**
|
|
430
648
|
* Labels the field control.
|
|
@@ -439,7 +657,7 @@ class RdxFieldLabel {
|
|
|
439
657
|
*
|
|
440
658
|
* @group Props
|
|
441
659
|
*/
|
|
442
|
-
this.id = input(
|
|
660
|
+
this.id = input(injectId('rdx-field-label-'), /* @ts-ignore */
|
|
443
661
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
444
662
|
this.htmlFor = () => this.rootContext.controlId();
|
|
445
663
|
this.dataAttr = attr;
|
|
@@ -467,5 +685,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
467
685
|
* Generated bundle index. Do not edit.
|
|
468
686
|
*/
|
|
469
687
|
|
|
470
|
-
export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
|
|
688
|
+
export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldItem, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
|
|
471
689
|
//# sourceMappingURL=radix-ng-primitives-field.mjs.map
|