@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,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, linkedSignal,
|
|
2
|
+
import { input, linkedSignal, Directive } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
const DEFAULT_ORIENTATION = 'horizontal';
|
|
5
5
|
/**
|
|
@@ -18,22 +18,14 @@ class RdxSeparatorRootDirective {
|
|
|
18
18
|
*/
|
|
19
19
|
this.orientation = input(DEFAULT_ORIENTATION, /* @ts-ignore */
|
|
20
20
|
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
21
|
-
this.orientationState = linkedSignal(
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Computes the `aria-orientation` attribute. It is set to "vertical" only when
|
|
25
|
-
* the separator orientation is vertical. Horizontal is the implicit ARIA default.
|
|
26
|
-
*
|
|
27
|
-
* @ignore
|
|
28
|
-
*/
|
|
29
|
-
this.computedAriaOrientation = computed(() => this.orientationState() === 'vertical' ? 'vertical' : undefined, /* @ts-ignore */
|
|
30
|
-
...(ngDevMode ? [{ debugName: "computedAriaOrientation" }] : /* istanbul ignore next */ []));
|
|
21
|
+
this.orientationState = linkedSignal(this.orientation, /* @ts-ignore */
|
|
22
|
+
...(ngDevMode ? [{ debugName: "orientationState" }] : /* istanbul ignore next */ []));
|
|
31
23
|
}
|
|
32
24
|
updateOrientation(value) {
|
|
33
25
|
this.orientationState.set(value);
|
|
34
26
|
}
|
|
35
27
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSeparatorRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
36
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSeparatorRootDirective, isStandalone: true, selector: "[rdxSeparatorRoot]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "attr.aria-orientation": "
|
|
28
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSeparatorRootDirective, isStandalone: true, selector: "[rdxSeparatorRoot]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "attr.aria-orientation": "orientationState()", "attr.data-orientation": "orientationState()" } }, ngImport: i0 }); }
|
|
37
29
|
}
|
|
38
30
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSeparatorRootDirective, decorators: [{
|
|
39
31
|
type: Directive,
|
|
@@ -41,7 +33,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
41
33
|
selector: '[rdxSeparatorRoot]',
|
|
42
34
|
host: {
|
|
43
35
|
role: 'separator',
|
|
44
|
-
|
|
36
|
+
// Base UI emits `aria-orientation` for both orientations (matching this repo's
|
|
37
|
+
// menu/combobox separators), not just the vertical override.
|
|
38
|
+
'[attr.aria-orientation]': 'orientationState()',
|
|
45
39
|
'[attr.data-orientation]': 'orientationState()'
|
|
46
40
|
}
|
|
47
41
|
}]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radix-ng-primitives-separator.mjs","sources":["../../../packages/primitives/separator/src/separator.directive.ts","../../../packages/primitives/separator/radix-ng-primitives-separator.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"radix-ng-primitives-separator.mjs","sources":["../../../packages/primitives/separator/src/separator.directive.ts","../../../packages/primitives/separator/radix-ng-primitives-separator.ts"],"sourcesContent":["import { Directive, input, linkedSignal } from '@angular/core';\n\nconst DEFAULT_ORIENTATION = 'horizontal';\n\nexport type Orientation = 'horizontal' | 'vertical';\n\nexport interface SeparatorProps {\n /**\n * Either `vertical` or `horizontal`. Defaults to `horizontal`.\n */\n orientation?: Orientation;\n}\n\n/**\n * Directive that adds accessible and configurable separator element to the DOM.\n * This can be either horizontal or vertical.\n *\n * @group Components\n */\n@Directive({\n selector: '[rdxSeparatorRoot]',\n host: {\n role: 'separator',\n // Base UI emits `aria-orientation` for both orientations (matching this repo's\n // menu/combobox separators), not just the vertical override.\n '[attr.aria-orientation]': 'orientationState()',\n '[attr.data-orientation]': 'orientationState()'\n }\n})\nexport class RdxSeparatorRootDirective {\n /**\n * Orientation of the separator, can be either 'horizontal' or 'vertical'.\n *\n * @defaultValue 'horizontal'\n * @group Props\n */\n readonly orientation = input<Orientation>(DEFAULT_ORIENTATION);\n\n protected readonly orientationState = linkedSignal(this.orientation);\n\n updateOrientation(value: Orientation) {\n this.orientationState.set(value);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAEA,MAAM,mBAAmB,GAAG,YAAY;AAWxC;;;;;AAKG;MAWU,yBAAyB,CAAA;AAVtC,IAAA,WAAA,GAAA;AAWI;;;;;AAKG;QACM,IAAA,CAAA,WAAW,GAAG,KAAK,CAAc,mBAAmB;wFAAC;AAE3C,QAAA,IAAA,CAAA,gBAAgB,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW;6FAAC;AAKvE,IAAA;AAHG,IAAA,iBAAiB,CAAC,KAAkB,EAAA;AAChC,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;IACpC;8GAbS,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAAzB,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,WAAA,EAAA,EAAA,UAAA,EAAA,EAAA,uBAAA,EAAA,oBAAA,EAAA,uBAAA,EAAA,oBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAAzB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAVrC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACP,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,IAAI,EAAE;AACF,wBAAA,IAAI,EAAE,WAAW;;;AAGjB,wBAAA,yBAAyB,EAAE,oBAAoB;AAC/C,wBAAA,yBAAyB,EAAE;AAC9B;AACJ,iBAAA;;;AC5BD;;AAEG;;;;"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, DestroyRef, Directive, input, NgModule } from '@angular/core';
|
|
3
|
+
import { FormField } from '@angular/forms/signals';
|
|
4
|
+
import { injectFieldRootContext } from '@radix-ng/primitives/field';
|
|
5
|
+
import { injectFormRootContext } from '@radix-ng/primitives/form';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Bridges an Angular **Signal Forms** field into an enclosing `rdxFieldRoot` — with **no duplicate
|
|
9
|
+
* binding**. Place it on the control that already carries `[formField]`; it reads the bound field's
|
|
10
|
+
* state from that directive, so the field expression is written exactly once:
|
|
11
|
+
*
|
|
12
|
+
* ```html
|
|
13
|
+
* <div rdxFieldRoot>
|
|
14
|
+
* <label rdxFieldLabel>Email</label>
|
|
15
|
+
* <input rdxInput [formField]="loginForm.email" rdxSignalField />
|
|
16
|
+
* <p rdxFieldError>Email is required.</p>
|
|
17
|
+
* </div>
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* It owns no model and runs no validation — Signal Forms remains the source of truth. It only registers
|
|
21
|
+
* an {@link RdxFieldState} provider on the ancestor Field context so the field's `invalid` / `disabled` /
|
|
22
|
+
* `required` / `dirty` / `touched` data-attributes and the error *content* (`rdxFieldError.messages()`)
|
|
23
|
+
* read authoritative Signal Forms state. `filled` / `focused` stay on Field's DOM heuristic (partial
|
|
24
|
+
* ownership — the seam supports it).
|
|
25
|
+
*
|
|
26
|
+
* It reports the **actual** Signal Forms state only; the `Field` decides *when* to display it from its
|
|
27
|
+
* `validationMode` (default `'onBlur'` — neutral until the field is touched or the form submitted). So an
|
|
28
|
+
* empty required field is neutral on load with no manual `[invalid]`/`[touched]` wiring, and a pristine
|
|
29
|
+
* submit reveals the errors (the `Form` records the submit attempt before checking validity and blocks).
|
|
30
|
+
*
|
|
31
|
+
* See ADR 0018.
|
|
32
|
+
*
|
|
33
|
+
* @group Components
|
|
34
|
+
*/
|
|
35
|
+
class RdxSignalField {
|
|
36
|
+
constructor() {
|
|
37
|
+
/** The co-located `[formField]` directive — the single source of the bound field's state. */
|
|
38
|
+
this.formField = inject(FormField);
|
|
39
|
+
this.fieldContext = injectFieldRootContext();
|
|
40
|
+
// The accessors are evaluated lazily by Field's `*State` computeds during change detection (after
|
|
41
|
+
// the `[formField]` binding resolves), so reading `state()` inside these closures is safe. The
|
|
42
|
+
// adapter reports authoritative *actual* state; the Field gates the *display* by its validationMode.
|
|
43
|
+
const state = {
|
|
44
|
+
invalid: () => this.state().invalid(),
|
|
45
|
+
disabled: () => this.state().disabled(),
|
|
46
|
+
required: () => this.state().required(),
|
|
47
|
+
dirty: () => this.state().dirty(),
|
|
48
|
+
touched: () => this.state().touched(),
|
|
49
|
+
errors: () => this.state()
|
|
50
|
+
.errors()
|
|
51
|
+
.map((error) => ({ kind: error.kind, message: error.message }))
|
|
52
|
+
};
|
|
53
|
+
const previous = this.fieldContext.setStateProvider(state);
|
|
54
|
+
// Identity-checked teardown: only roll back if our provider is still active, so a newer adapter
|
|
55
|
+
// mounted during a view swap (create-before-destroy) is not clobbered by this destroy.
|
|
56
|
+
inject(DestroyRef).onDestroy(() => this.fieldContext.clearStateProvider(state, previous));
|
|
57
|
+
}
|
|
58
|
+
/** Current Signal Forms field state, read from the co-located `[formField]` directive. */
|
|
59
|
+
state() {
|
|
60
|
+
return this.formField.state();
|
|
61
|
+
}
|
|
62
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalField, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
63
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: RdxSignalField, isStandalone: true, selector: "[formField][rdxSignalField]", exportAs: ["rdxSignalField"], ngImport: i0 }); }
|
|
64
|
+
}
|
|
65
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalField, decorators: [{
|
|
66
|
+
type: Directive,
|
|
67
|
+
args: [{
|
|
68
|
+
selector: '[formField][rdxSignalField]',
|
|
69
|
+
exportAs: 'rdxSignalField'
|
|
70
|
+
}]
|
|
71
|
+
}], ctorParameters: () => [] });
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Bridges an Angular **Signal Forms** form into an enclosing `form[rdxFormRoot]`.
|
|
75
|
+
*
|
|
76
|
+
* ```html
|
|
77
|
+
* <form rdxFormRoot [rdxSignalForm]="loginForm">
|
|
78
|
+
* <!-- fields bound with [formField] (+ rdxSignalField) -->
|
|
79
|
+
* </form>
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* Registers an {@link RdxFormState} provider so the Form's aggregate `data-invalid` / `data-dirty` /
|
|
83
|
+
* `data-touched` / `data-submitting` attributes and the submit guard read authoritative Signal Forms
|
|
84
|
+
* state. This adapter owns only client-side state and `name`-routing; server errors stay a separate
|
|
85
|
+
* eager channel applied through `rdxFormRoot[errors]`, and Signal Forms' own `submit()` owns the
|
|
86
|
+
* submit lifecycle.
|
|
87
|
+
*
|
|
88
|
+
* `errorsFor(name)` routes a field's errors to a `rdxFieldRoot` by its `name`, walking the `FieldTree`
|
|
89
|
+
* so dotted paths into nested object/array fields resolve too (`address.street`, `items.0.name`). A
|
|
90
|
+
* field can surface messages from the form alone — no per-field `rdxSignalField` needed for errors.
|
|
91
|
+
* These are the **two modes** (per-field adapter vs form-level name routing) — prefer one per field; if
|
|
92
|
+
* a field carries both, `rdxFieldError.messages()` deduplicates by text so the shared message is not
|
|
93
|
+
* shown twice.
|
|
94
|
+
*
|
|
95
|
+
* See ADR 0018.
|
|
96
|
+
*
|
|
97
|
+
* @group Components
|
|
98
|
+
*/
|
|
99
|
+
class RdxSignalForm {
|
|
100
|
+
constructor() {
|
|
101
|
+
/** The Signal Forms root field (from `form(...)`) whose aggregate state drives the enclosing Form. */
|
|
102
|
+
this.form = input.required({ ...(ngDevMode ? { debugName: "form" } : /* istanbul ignore next */ {}), alias: 'rdxSignalForm' });
|
|
103
|
+
this.formContext = injectFormRootContext();
|
|
104
|
+
const state = {
|
|
105
|
+
invalid: () => this.state().invalid(),
|
|
106
|
+
dirty: () => this.state().dirty(),
|
|
107
|
+
touched: () => this.state().touched(),
|
|
108
|
+
submitting: () => this.state().submitting(),
|
|
109
|
+
errorsFor: (name) => this.errorsFor(name),
|
|
110
|
+
// Per-name interaction state so a name-routed field (bare `[formField]`, no `rdxSignalField`)
|
|
111
|
+
// can reveal its error on blur/change under `validationMode="onBlur"`/`"onChange"`.
|
|
112
|
+
touchedFor: (name) => this.fieldState(name)?.touched() ?? false,
|
|
113
|
+
dirtyFor: (name) => this.fieldState(name)?.dirty() ?? false
|
|
114
|
+
};
|
|
115
|
+
const previous = this.formContext.setStateProvider(state);
|
|
116
|
+
// Identity-checked teardown: only roll back if our provider is still active, so a newer adapter
|
|
117
|
+
// mounted during a view swap (create-before-destroy) is not clobbered by this destroy.
|
|
118
|
+
inject(DestroyRef).onDestroy(() => this.formContext.clearStateProvider(state, previous));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Messages for the field at the dotted `name` path (`message ?? kind` per error). Walks the
|
|
122
|
+
* `FieldTree` so nested object/array fields resolve too — e.g. `address.street`, `items.0.name`.
|
|
123
|
+
*/
|
|
124
|
+
errorsFor(name) {
|
|
125
|
+
return (this.fieldState(name)
|
|
126
|
+
?.errors()
|
|
127
|
+
.map((error) => error.message ?? error.kind) ?? []);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The Signal Forms field *state* at the dotted `name` path, or `null` if it doesn't resolve. Walks the
|
|
131
|
+
* `FieldTree` so nested object/array fields work (`address.street`, `items.0.name`).
|
|
132
|
+
*/
|
|
133
|
+
fieldState(name) {
|
|
134
|
+
let node = this.form();
|
|
135
|
+
for (const segment of name.split('.')) {
|
|
136
|
+
if (node == null || (typeof node !== 'object' && typeof node !== 'function')) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
// Only walk into own properties: a `FieldTree` exposes its subfields as own keys, so a
|
|
140
|
+
// segment that is not one (`constructor`, `__proto__`, `toString`, …) is not a real field.
|
|
141
|
+
// Reading it would resolve to an inherited member — and a function one would then be called
|
|
142
|
+
// below — so reject it instead.
|
|
143
|
+
if (!Object.hasOwn(node, segment)) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
node = node[segment];
|
|
147
|
+
}
|
|
148
|
+
return typeof node === 'function' ? node() : null;
|
|
149
|
+
}
|
|
150
|
+
/** The current Signal Forms root field state (a `FieldTree` is callable). */
|
|
151
|
+
state() {
|
|
152
|
+
return this.form()();
|
|
153
|
+
}
|
|
154
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalForm, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
155
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSignalForm, isStandalone: true, selector: "form[rdxFormRoot][rdxSignalForm]", inputs: { form: { classPropertyName: "form", publicName: "rdxSignalForm", isSignal: true, isRequired: true, transformFunction: null } }, exportAs: ["rdxSignalForm"], ngImport: i0 }); }
|
|
156
|
+
}
|
|
157
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalForm, decorators: [{
|
|
158
|
+
type: Directive,
|
|
159
|
+
args: [{
|
|
160
|
+
selector: 'form[rdxFormRoot][rdxSignalForm]',
|
|
161
|
+
exportAs: 'rdxSignalForm'
|
|
162
|
+
}]
|
|
163
|
+
}], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxSignalForm", required: true }] }] } });
|
|
164
|
+
|
|
165
|
+
const _importsSignalForms = [RdxSignalField, RdxSignalForm];
|
|
166
|
+
class RdxSignalFormsModule {
|
|
167
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
168
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalFormsModule, imports: [RdxSignalField, RdxSignalForm], exports: [RdxSignalField, RdxSignalForm] }); }
|
|
169
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalFormsModule }); }
|
|
170
|
+
}
|
|
171
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalFormsModule, decorators: [{
|
|
172
|
+
type: NgModule,
|
|
173
|
+
args: [{
|
|
174
|
+
imports: [..._importsSignalForms],
|
|
175
|
+
exports: [..._importsSignalForms]
|
|
176
|
+
}]
|
|
177
|
+
}] });
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Generated bundle index. Do not edit.
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
export { RdxSignalField, RdxSignalForm, RdxSignalFormsModule, _importsSignalForms };
|
|
184
|
+
//# sourceMappingURL=radix-ng-primitives-signal-forms.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radix-ng-primitives-signal-forms.mjs","sources":["../../../packages/primitives/signal-forms/src/signal-field.ts","../../../packages/primitives/signal-forms/src/signal-form.ts","../../../packages/primitives/signal-forms/index.ts","../../../packages/primitives/signal-forms/radix-ng-primitives-signal-forms.ts"],"sourcesContent":["import { DestroyRef, Directive, inject } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { injectFieldRootContext, RdxFieldState } from '@radix-ng/primitives/field';\n\n/**\n * Bridges an Angular **Signal Forms** field into an enclosing `rdxFieldRoot` — with **no duplicate\n * binding**. Place it on the control that already carries `[formField]`; it reads the bound field's\n * state from that directive, so the field expression is written exactly once:\n *\n * ```html\n * <div rdxFieldRoot>\n * <label rdxFieldLabel>Email</label>\n * <input rdxInput [formField]=\"loginForm.email\" rdxSignalField />\n * <p rdxFieldError>Email is required.</p>\n * </div>\n * ```\n *\n * It owns no model and runs no validation — Signal Forms remains the source of truth. It only registers\n * an {@link RdxFieldState} provider on the ancestor Field context so the field's `invalid` / `disabled` /\n * `required` / `dirty` / `touched` data-attributes and the error *content* (`rdxFieldError.messages()`)\n * read authoritative Signal Forms state. `filled` / `focused` stay on Field's DOM heuristic (partial\n * ownership — the seam supports it).\n *\n * It reports the **actual** Signal Forms state only; the `Field` decides *when* to display it from its\n * `validationMode` (default `'onBlur'` — neutral until the field is touched or the form submitted). So an\n * empty required field is neutral on load with no manual `[invalid]`/`[touched]` wiring, and a pristine\n * submit reveals the errors (the `Form` records the submit attempt before checking validity and blocks).\n *\n * See ADR 0018.\n *\n * @group Components\n */\n@Directive({\n selector: '[formField][rdxSignalField]',\n exportAs: 'rdxSignalField'\n})\nexport class RdxSignalField {\n /** The co-located `[formField]` directive — the single source of the bound field's state. */\n private readonly formField = inject(FormField);\n private readonly fieldContext = injectFieldRootContext();\n\n constructor() {\n // The accessors are evaluated lazily by Field's `*State` computeds during change detection (after\n // the `[formField]` binding resolves), so reading `state()` inside these closures is safe. The\n // adapter reports authoritative *actual* state; the Field gates the *display* by its validationMode.\n const state: RdxFieldState = {\n invalid: () => this.state().invalid(),\n disabled: () => this.state().disabled(),\n required: () => this.state().required(),\n dirty: () => this.state().dirty(),\n touched: () => this.state().touched(),\n errors: () =>\n this.state()\n .errors()\n .map((error) => ({ kind: error.kind, message: error.message }))\n };\n\n const previous = this.fieldContext.setStateProvider(state);\n // Identity-checked teardown: only roll back if our provider is still active, so a newer adapter\n // mounted during a view swap (create-before-destroy) is not clobbered by this destroy.\n inject(DestroyRef).onDestroy(() => this.fieldContext.clearStateProvider(state, previous));\n }\n\n /** Current Signal Forms field state, read from the co-located `[formField]` directive. */\n private state() {\n return this.formField.state();\n }\n}\n","import { DestroyRef, Directive, inject, input } from '@angular/core';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { injectFormRootContext, RdxFormState } from '@radix-ng/primitives/form';\n\n/** A Signal Forms subfield read structurally — callable to its state (`errors()` / `touched()` / `dirty()`). */\ntype NamedField = () => {\n errors: () => readonly { kind: string; message?: string }[];\n touched: () => boolean;\n dirty: () => boolean;\n};\n\n/**\n * Bridges an Angular **Signal Forms** form into an enclosing `form[rdxFormRoot]`.\n *\n * ```html\n * <form rdxFormRoot [rdxSignalForm]=\"loginForm\">\n * <!-- fields bound with [formField] (+ rdxSignalField) -->\n * </form>\n * ```\n *\n * Registers an {@link RdxFormState} provider so the Form's aggregate `data-invalid` / `data-dirty` /\n * `data-touched` / `data-submitting` attributes and the submit guard read authoritative Signal Forms\n * state. This adapter owns only client-side state and `name`-routing; server errors stay a separate\n * eager channel applied through `rdxFormRoot[errors]`, and Signal Forms' own `submit()` owns the\n * submit lifecycle.\n *\n * `errorsFor(name)` routes a field's errors to a `rdxFieldRoot` by its `name`, walking the `FieldTree`\n * so dotted paths into nested object/array fields resolve too (`address.street`, `items.0.name`). A\n * field can surface messages from the form alone — no per-field `rdxSignalField` needed for errors.\n * These are the **two modes** (per-field adapter vs form-level name routing) — prefer one per field; if\n * a field carries both, `rdxFieldError.messages()` deduplicates by text so the shared message is not\n * shown twice.\n *\n * See ADR 0018.\n *\n * @group Components\n */\n@Directive({\n selector: 'form[rdxFormRoot][rdxSignalForm]',\n exportAs: 'rdxSignalForm'\n})\nexport class RdxSignalForm {\n /** The Signal Forms root field (from `form(...)`) whose aggregate state drives the enclosing Form. */\n readonly form = input.required<FieldTree<unknown>>({ alias: 'rdxSignalForm' });\n\n private readonly formContext = injectFormRootContext();\n\n constructor() {\n const state: RdxFormState = {\n invalid: () => this.state().invalid(),\n dirty: () => this.state().dirty(),\n touched: () => this.state().touched(),\n submitting: () => this.state().submitting(),\n errorsFor: (name) => this.errorsFor(name),\n // Per-name interaction state so a name-routed field (bare `[formField]`, no `rdxSignalField`)\n // can reveal its error on blur/change under `validationMode=\"onBlur\"`/`\"onChange\"`.\n touchedFor: (name) => this.fieldState(name)?.touched() ?? false,\n dirtyFor: (name) => this.fieldState(name)?.dirty() ?? false\n };\n\n const previous = this.formContext.setStateProvider(state);\n // Identity-checked teardown: only roll back if our provider is still active, so a newer adapter\n // mounted during a view swap (create-before-destroy) is not clobbered by this destroy.\n inject(DestroyRef).onDestroy(() => this.formContext.clearStateProvider(state, previous));\n }\n\n /**\n * Messages for the field at the dotted `name` path (`message ?? kind` per error). Walks the\n * `FieldTree` so nested object/array fields resolve too — e.g. `address.street`, `items.0.name`.\n */\n private errorsFor(name: string): string[] {\n return (\n this.fieldState(name)\n ?.errors()\n .map((error) => error.message ?? error.kind) ?? []\n );\n }\n\n /**\n * The Signal Forms field *state* at the dotted `name` path, or `null` if it doesn't resolve. Walks the\n * `FieldTree` so nested object/array fields work (`address.street`, `items.0.name`).\n */\n private fieldState(name: string): ReturnType<NamedField> | null {\n let node: unknown = this.form();\n for (const segment of name.split('.')) {\n if (node == null || (typeof node !== 'object' && typeof node !== 'function')) {\n return null;\n }\n // Only walk into own properties: a `FieldTree` exposes its subfields as own keys, so a\n // segment that is not one (`constructor`, `__proto__`, `toString`, …) is not a real field.\n // Reading it would resolve to an inherited member — and a function one would then be called\n // below — so reject it instead.\n if (!Object.hasOwn(node, segment)) {\n return null;\n }\n node = (node as Record<string, unknown>)[segment];\n }\n return typeof node === 'function' ? (node as NamedField)() : null;\n }\n\n /** The current Signal Forms root field state (a `FieldTree` is callable). */\n private state() {\n return this.form()();\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RdxSignalField } from './src/signal-field';\nimport { RdxSignalForm } from './src/signal-form';\n\nexport * from './src/signal-field';\nexport * from './src/signal-form';\n\nexport const _importsSignalForms = [RdxSignalField, RdxSignalForm];\n\n@NgModule({\n imports: [..._importsSignalForms],\n exports: [..._importsSignalForms]\n})\nexport class RdxSignalFormsModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, ElementRef, DestroyRef, Directive, computed, input, numberAttribute, booleanAttribute, model, output, signal, effect, afterNextRender, afterRenderEffect, untracked, NgModule } from '@angular/core';
|
|
3
3
|
import { DOCUMENT } from '@angular/common';
|
|
4
4
|
import * as i2 from '@radix-ng/primitives/core';
|
|
5
|
-
import { createContext, clamp, injectControlValueAccessor, injectDocument, injectId, createCancelableChangeEventDetails, RdxControlValueAccessor } from '@radix-ng/primitives/core';
|
|
5
|
+
import { createContext, clamp, RdxFormUiControlBase, injectControlValueAccessor, injectDocument, injectId, createCancelableChangeEventDetails, provideFormUiState, RdxFormUiStateHost, RdxControlValueAccessor } from '@radix-ng/primitives/core';
|
|
6
6
|
export { clamp } from '@radix-ng/primitives/core';
|
|
7
7
|
import * as i1 from '@radix-ng/primitives/composite';
|
|
8
8
|
import { RdxCompositeList, RdxCompositeListItem } from '@radix-ng/primitives/composite';
|
|
@@ -718,8 +718,12 @@ function cloneChangeEventWithTarget(event, value, name) {
|
|
|
718
718
|
*
|
|
719
719
|
* @see https://base-ui.com/react/components/slider
|
|
720
720
|
*/
|
|
721
|
-
|
|
721
|
+
// NOTE: does not `implements RdxFormValueControl` — the slider value is a `number | number[]` union,
|
|
722
|
+
// while `min`/`max` are scalar `number`s; the shim ties `min`/`max` to `NonNullable<TValue>`, which the
|
|
723
|
+
// union can't satisfy. The runtime contract (value model + the inherited `FormUiControl` state) holds.
|
|
724
|
+
class RdxSliderRoot extends RdxFormUiControlBase {
|
|
722
725
|
constructor() {
|
|
726
|
+
super(...arguments);
|
|
723
727
|
/** @ignore */
|
|
724
728
|
this.cva = injectControlValueAccessor();
|
|
725
729
|
this.document = injectDocument();
|
|
@@ -935,6 +939,7 @@ class RdxSliderRoot {
|
|
|
935
939
|
this.lastChangeEvent = eventDetails.event;
|
|
936
940
|
this.value.set(next);
|
|
937
941
|
this.cva.setValue(next);
|
|
942
|
+
this.formUi.markDirty();
|
|
938
943
|
return true;
|
|
939
944
|
}
|
|
940
945
|
/** @ignore Keyboard / native input path: clamps to neighbours, commits immediately. */
|
|
@@ -948,7 +953,7 @@ class RdxSliderRoot {
|
|
|
948
953
|
}
|
|
949
954
|
const arr = Array.isArray(result) ? result : [result];
|
|
950
955
|
const applied = this.setValue(arr, reason, event, index);
|
|
951
|
-
this.
|
|
956
|
+
this.markAsTouched();
|
|
952
957
|
if (applied) {
|
|
953
958
|
this.commitValue(event, reason);
|
|
954
959
|
}
|
|
@@ -966,9 +971,13 @@ class RdxSliderRoot {
|
|
|
966
971
|
}
|
|
967
972
|
});
|
|
968
973
|
}
|
|
969
|
-
/** @ignore */
|
|
974
|
+
/** @ignore Bridge the CVA into `markAsTouched` (dual). */
|
|
975
|
+
formUiTouchTarget() {
|
|
976
|
+
return injectControlValueAccessor();
|
|
977
|
+
}
|
|
978
|
+
/** @ignore Mark touched: CVA (Reactive/template) + `touched` model + `touch` (Signal Forms). */
|
|
970
979
|
markAsTouched() {
|
|
971
|
-
this.
|
|
980
|
+
this.formUi.markAsTouched();
|
|
972
981
|
}
|
|
973
982
|
/** @ignore */
|
|
974
983
|
setDragging(dragging) {
|
|
@@ -984,17 +993,24 @@ class RdxSliderRoot {
|
|
|
984
993
|
getOwnerWindow() {
|
|
985
994
|
return this.document.defaultView ?? undefined;
|
|
986
995
|
}
|
|
987
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSliderRoot, deps:
|
|
988
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSliderRoot, isStandalone: true, selector: "div[rdxSliderRoot]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, largeStep: { classPropertyName: "largeStep", publicName: "largeStep", isSignal: true, isRequired: false, transformFunction: null }, minStepsBetweenValues: { classPropertyName: "minStepsBetweenValues", publicName: "minStepsBetweenValues", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, dirInput: { classPropertyName: "dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, thumbCollisionBehavior: { classPropertyName: "thumbCollisionBehavior", publicName: "thumbCollisionBehavior", isSignal: true, isRequired: false, transformFunction: null }, thumbAlignment: { classPropertyName: "thumbAlignment", publicName: "thumbAlignment", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onValueChange: "onValueChange", onValueCommitted: "onValueCommitted" }, host: { attributes: { "role": "group" }, properties: { "id": "id()", "attr.aria-labelledby": "ariaLabelledBy()", "attr.dir": "dir()", "attr.data-orientation": "orientation()", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-dragging": "dragging() ? \"\" : undefined" } }, providers: [
|
|
996
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSliderRoot, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
997
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSliderRoot, isStandalone: true, selector: "div[rdxSliderRoot]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, largeStep: { classPropertyName: "largeStep", publicName: "largeStep", isSignal: true, isRequired: false, transformFunction: null }, minStepsBetweenValues: { classPropertyName: "minStepsBetweenValues", publicName: "minStepsBetweenValues", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, dirInput: { classPropertyName: "dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, thumbCollisionBehavior: { classPropertyName: "thumbCollisionBehavior", publicName: "thumbCollisionBehavior", isSignal: true, isRequired: false, transformFunction: null }, thumbAlignment: { classPropertyName: "thumbAlignment", publicName: "thumbAlignment", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onValueChange: "onValueChange", onValueCommitted: "onValueCommitted" }, host: { attributes: { "role": "group" }, properties: { "id": "id()", "attr.aria-labelledby": "ariaLabelledBy()", "attr.dir": "dir()", "attr.data-orientation": "orientation()", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-dragging": "dragging() ? \"\" : undefined" } }, providers: [
|
|
998
|
+
provideSliderRootContext(() => inject(RdxSliderRoot)),
|
|
999
|
+
provideFormUiState(() => inject(RdxSliderRoot).formUi)
|
|
1000
|
+
], exportAs: ["rdxSliderRoot"], usesInheritance: true, hostDirectives: [{ directive: i1.RdxCompositeList }, { directive: i2.RdxFormUiStateHost }, { directive: i2.RdxControlValueAccessor, inputs: ["value", "value", "disabled", "disabled"] }], ngImport: i0 }); }
|
|
989
1001
|
}
|
|
990
1002
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSliderRoot, decorators: [{
|
|
991
1003
|
type: Directive,
|
|
992
1004
|
args: [{
|
|
993
1005
|
selector: 'div[rdxSliderRoot]',
|
|
994
1006
|
exportAs: 'rdxSliderRoot',
|
|
995
|
-
providers: [
|
|
1007
|
+
providers: [
|
|
1008
|
+
provideSliderRootContext(() => inject(RdxSliderRoot)),
|
|
1009
|
+
provideFormUiState(() => inject(RdxSliderRoot).formUi)
|
|
1010
|
+
],
|
|
996
1011
|
hostDirectives: [
|
|
997
1012
|
RdxCompositeList,
|
|
1013
|
+
RdxFormUiStateHost,
|
|
998
1014
|
{
|
|
999
1015
|
directive: RdxControlValueAccessor,
|
|
1000
1016
|
inputs: ['value: value', 'disabled']
|
|
@@ -1292,7 +1308,7 @@ class RdxSliderThumbInput {
|
|
|
1292
1308
|
}
|
|
1293
1309
|
}
|
|
1294
1310
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSliderThumbInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1295
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSliderThumbInput, isStandalone: true, selector: "input[rdxSliderThumbInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaValueTextInput: { classPropertyName: "ariaValueTextInput", publicName: "aria-valuetext", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "range" }, listeners: { "keydown": "onKeyDown($event)", "change": "onChange($event)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "id": "id()", "style.writing-mode": "writingMode()", "attr.min": "root.min()", "attr.max": "root.max()", "attr.step": "root.step()", "value": "thumb.value() ?? \"\"", "disabled": "thumb.disabled()", "attr.name": "root.name()", "attr.form": "root.form()", "attr.aria-orientation": "root.orientation()", "attr.aria-valuenow": "thumb.value()", "attr.aria-valuetext": "valueText()", "attr.aria-label": "ariaLabel()", "attr.aria-labelledby": "ariaLabelledBy()"
|
|
1311
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxSliderThumbInput, isStandalone: true, selector: "input[rdxSliderThumbInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaValueTextInput: { classPropertyName: "ariaValueTextInput", publicName: "aria-valuetext", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "range" }, listeners: { "keydown": "onKeyDown($event)", "change": "onChange($event)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "id": "id()", "style.writing-mode": "writingMode()", "attr.min": "root.min()", "attr.max": "root.max()", "attr.step": "root.step()", "value": "thumb.value() ?? \"\"", "disabled": "thumb.disabled()", "attr.name": "root.name()", "attr.form": "root.form()", "attr.aria-orientation": "root.orientation()", "attr.aria-valuenow": "thumb.value()", "attr.aria-valuetext": "valueText()", "attr.aria-label": "ariaLabel()", "attr.aria-labelledby": "ariaLabelledBy()" }, styleAttribute: "position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; opacity: 0; cursor: inherit;" }, exportAs: ["rdxSliderThumbInput"], ngImport: i0 }); }
|
|
1296
1312
|
}
|
|
1297
1313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSliderThumbInput, decorators: [{
|
|
1298
1314
|
type: Directive,
|
|
@@ -1316,7 +1332,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1316
1332
|
'[attr.aria-valuetext]': 'valueText()',
|
|
1317
1333
|
'[attr.aria-label]': 'ariaLabel()',
|
|
1318
1334
|
'[attr.aria-labelledby]': 'ariaLabelledBy()',
|
|
1319
|
-
'[attr.data-index]': 'thumb.index()',
|
|
1320
1335
|
'(keydown)': 'onKeyDown($event)',
|
|
1321
1336
|
'(change)': 'onChange($event)',
|
|
1322
1337
|
'(focus)': 'onFocus()',
|