@radix-ng/primitives 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +26 -5
  2. package/fesm2022/radix-ng-primitives-autocomplete.mjs +35 -19
  3. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
  4. package/fesm2022/radix-ng-primitives-checkbox.mjs +55 -7
  5. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  6. package/fesm2022/radix-ng-primitives-combobox.mjs +46 -21
  7. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-composite.mjs +221 -36
  9. package/fesm2022/radix-ng-primitives-composite.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-core.mjs +189 -26
  11. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-date-field.mjs +29 -13
  13. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-field.mjs +127 -23
  15. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +9 -0
  17. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-focus-scope.mjs +241 -95
  19. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-form.mjs +35 -4
  21. package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-input.mjs +87 -15
  23. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-menu.mjs +131 -16
  25. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +17 -3
  27. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-popper.mjs +223 -29
  29. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-portal.mjs +16 -5
  31. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-scroll-area.mjs +6 -3
  33. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  34. package/fesm2022/radix-ng-primitives-select.mjs +49 -17
  35. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  36. package/fesm2022/radix-ng-primitives-signal-forms.mjs +27 -11
  37. package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-time-field.mjs +24 -10
  39. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  40. package/package.json +8 -7
  41. package/types/radix-ng-primitives-autocomplete.d.ts +7 -2
  42. package/types/radix-ng-primitives-checkbox.d.ts +10 -1
  43. package/types/radix-ng-primitives-combobox.d.ts +29 -2
  44. package/types/radix-ng-primitives-composite.d.ts +48 -2
  45. package/types/radix-ng-primitives-core.d.ts +165 -104
  46. package/types/radix-ng-primitives-date-field.d.ts +21 -8
  47. package/types/radix-ng-primitives-field.d.ts +55 -8
  48. package/types/radix-ng-primitives-floating-focus-manager.d.ts +7 -0
  49. package/types/radix-ng-primitives-focus-scope.d.ts +61 -44
  50. package/types/radix-ng-primitives-form.d.ts +9 -0
  51. package/types/radix-ng-primitives-input.d.ts +10 -2
  52. package/types/radix-ng-primitives-menu.d.ts +59 -7
  53. package/types/radix-ng-primitives-navigation-menu.d.ts +2 -2
  54. package/types/radix-ng-primitives-popover.d.ts +2 -2
  55. package/types/radix-ng-primitives-popper.d.ts +186 -48
  56. package/types/radix-ng-primitives-portal.d.ts +18 -8
  57. package/types/radix-ng-primitives-preview-card.d.ts +2 -2
  58. package/types/radix-ng-primitives-select.d.ts +17 -3
  59. package/types/radix-ng-primitives-signal-forms.d.ts +22 -8
  60. package/types/radix-ng-primitives-time-field.d.ts +21 -10
  61. package/types/radix-ng-primitives-tooltip.d.ts +2 -2
  62. package/fesm2022/radix-ng-primitives-focus-guards.mjs +0 -53
  63. package/fesm2022/radix-ng-primitives-focus-guards.mjs.map +0 -1
  64. package/focus-guards/README.md +0 -1
  65. package/types/radix-ng-primitives-focus-guards.d.ts +0 -15
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DestroyRef, Directive, input, NgModule } from '@angular/core';
3
- import { FormField } from '@angular/forms/signals';
2
+ import { inject, DestroyRef, Directive, input, booleanAttribute, NgModule } from '@angular/core';
3
+ import { FormField, submit } from '@angular/forms/signals';
4
4
  import { injectFieldRootContext } from '@radix-ng/primitives/field';
5
5
  import { injectFormRootContext } from '@radix-ng/primitives/form';
6
6
 
@@ -19,9 +19,9 @@ import { injectFormRootContext } from '@radix-ng/primitives/form';
19
19
  *
20
20
  * It owns no model and runs no validation — Signal Forms remains the source of truth. It only registers
21
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).
22
+ * `required` / `dirty` / `touched` data-attributes, tri-state pending validity, and the error *content*
23
+ * (`rdxFieldError.messages()`) read authoritative Signal Forms state. `filled` / `focused` stay on
24
+ * Field's DOM heuristic (partial ownership — the seam supports it).
25
25
  *
26
26
  * It reports the **actual** Signal Forms state only; the `Field` decides *when* to display it from its
27
27
  * `validationMode` (default `'onBlur'` — neutral until the field is touched or the form submitted). So an
@@ -42,6 +42,7 @@ class RdxSignalField {
42
42
  // adapter reports authoritative *actual* state; the Field gates the *display* by its validationMode.
43
43
  const state = {
44
44
  invalid: () => this.state().invalid(),
45
+ pending: () => this.state().pending(),
45
46
  disabled: () => this.state().disabled(),
46
47
  required: () => this.state().required(),
47
48
  dirty: () => this.state().dirty(),
@@ -81,9 +82,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
81
82
  *
82
83
  * Registers an {@link RdxFormState} provider so the Form's aggregate `data-invalid` / `data-dirty` /
83
84
  * `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.
85
+ * state. By default this adapter owns only client-side state and `name`-routing; server errors stay a
86
+ * separate eager channel applied through `rdxFormRoot[errors]`. Add `rdxSignalSubmit` to delegate native
87
+ * submission to Signal Forms' own `submit()` lifecycle instead of `rdxFormRoot.onFormSubmit`:
88
+ *
89
+ * ```html
90
+ * <form rdxFormRoot [rdxSignalForm]="loginForm" rdxSignalSubmit>…</form>
91
+ * ```
87
92
  *
88
93
  * `errorsFor(name)` routes a field's errors to a `rdxFieldRoot` by its `name`, walking the `FieldTree`
89
94
  * so dotted paths into nested object/array fields resolve too (`address.street`, `items.0.name`). A
@@ -92,7 +97,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
92
97
  * a field carries both, `rdxFieldError.messages()` deduplicates by text so the shared message is not
93
98
  * shown twice.
94
99
  *
95
- * See ADR 0018.
100
+ * See ADR 0018 and ADR 0020.
96
101
  *
97
102
  * @group Components
98
103
  */
@@ -100,12 +105,23 @@ class RdxSignalForm {
100
105
  constructor() {
101
106
  /** The Signal Forms root field (from `form(...)`) whose aggregate state drives the enclosing Form. */
102
107
  this.form = input.required({ ...(ngDevMode ? { debugName: "form" } : /* istanbul ignore next */ {}), alias: 'rdxSignalForm' });
108
+ /**
109
+ * Delegate native submission to Angular Signal Forms' `submit()` lifecycle. Opt-in so adding the
110
+ * state adapter to an existing 1.x form cannot silently replace its `(onFormSubmit)` side effects.
111
+ * The bound `form()` must define `submission.action`; Angular reports a descriptive error otherwise.
112
+ *
113
+ * @group Props
114
+ * @defaultValue false
115
+ */
116
+ this.signalSubmit = input(false, { ...(ngDevMode ? { debugName: "signalSubmit" } : /* istanbul ignore next */ {}), alias: 'rdxSignalSubmit',
117
+ transform: booleanAttribute });
103
118
  this.formContext = injectFormRootContext();
104
119
  const state = {
105
120
  invalid: () => this.state().invalid(),
106
121
  dirty: () => this.state().dirty(),
107
122
  touched: () => this.state().touched(),
108
123
  submitting: () => this.state().submitting(),
124
+ submit: () => (this.signalSubmit() ? submit(this.form()) : undefined),
109
125
  errorsFor: (name) => this.errorsFor(name),
110
126
  // Per-name interaction state so a name-routed field (bare `[formField]`, no `rdxSignalField`)
111
127
  // can reveal its error on blur/change under `validationMode="onBlur"`/`"onChange"`.
@@ -152,7 +168,7 @@ class RdxSignalForm {
152
168
  return this.form()();
153
169
  }
154
170
  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 }); }
171
+ 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 }, signalSubmit: { classPropertyName: "signalSubmit", publicName: "rdxSignalSubmit", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["rdxSignalForm"], ngImport: i0 }); }
156
172
  }
157
173
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxSignalForm, decorators: [{
158
174
  type: Directive,
@@ -160,7 +176,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
160
176
  selector: 'form[rdxFormRoot][rdxSignalForm]',
161
177
  exportAs: 'rdxSignalForm'
162
178
  }]
163
- }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxSignalForm", required: true }] }] } });
179
+ }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxSignalForm", required: true }] }], signalSubmit: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxSignalSubmit", required: false }] }] } });
164
180
 
165
181
  const _importsSignalForms = [RdxSignalField, RdxSignalForm];
166
182
  class RdxSignalFormsModule {
@@ -1 +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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"}
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, tri-state pending validity, and the error *content*\n * (`rdxFieldError.messages()`) read authoritative Signal Forms state. `filled` / `focused` stay on\n * Field's DOM heuristic (partial 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 pending: () => this.state().pending(),\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 { booleanAttribute, DestroyRef, Directive, inject, input } from '@angular/core';\nimport { submit, type FieldTree } from '@angular/forms/signals';\nimport { BooleanInput } from '@radix-ng/primitives/core';\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. By default this adapter owns only client-side state and `name`-routing; server errors stay a\n * separate eager channel applied through `rdxFormRoot[errors]`. Add `rdxSignalSubmit` to delegate native\n * submission to Signal Forms' own `submit()` lifecycle instead of `rdxFormRoot.onFormSubmit`:\n *\n * ```html\n * <form rdxFormRoot [rdxSignalForm]=\"loginForm\" rdxSignalSubmit>…</form>\n * ```\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 and ADR 0020.\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 /**\n * Delegate native submission to Angular Signal Forms' `submit()` lifecycle. Opt-in so adding the\n * state adapter to an existing 1.x form cannot silently replace its `(onFormSubmit)` side effects.\n * The bound `form()` must define `submission.action`; Angular reports a descriptive error otherwise.\n *\n * @group Props\n * @defaultValue false\n */\n readonly signalSubmit = input<boolean, BooleanInput>(false, {\n alias: 'rdxSignalSubmit',\n transform: booleanAttribute\n });\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 submit: () => (this.signalSubmit() ? submit(this.form()) : undefined),\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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"}
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, ElementRef, input, computed, signal, effect, Directive, model, booleanAttribute, contentChildren, linkedSignal, NgModule } from '@angular/core';
3
- import { useDateField, isNullish, RdxFormUiControlBase, normalizeDateStep, createFormatter, normalizeHourCycle, getDefaultTime, syncSegmentValues, initializeSegmentValues, isBefore, resolveDisplayValid, createContent, watch, isSegmentNavigationKey, ARROW_LEFT, ARROW_RIGHT, provideToken } from '@radix-ng/primitives/core';
3
+ import { useDateField, isNullish, RdxFormUiControlBase, normalizeDateStep, createFormatter, normalizeHourCycle, getDefaultTime, syncSegmentValues, initializeSegmentValues, isBefore, resolveDisplayValid, createContent, watch, isSegmentNavigationKey, ARROW_LEFT, ARROW_RIGHT, provideExistingToken } from '@radix-ng/primitives/core';
4
4
  import { toCalendarDateTime, today, getLocalTimeZone, Time, isEqualDay } from '@internationalized/date';
5
5
  import { injectDirection } from '@radix-ng/primitives/direction-provider';
6
6
 
@@ -145,13 +145,19 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
145
145
  markAsTouched() {
146
146
  this.formUi.markAsTouched();
147
147
  }
148
+ /** Reset segment interaction so the form-owned value write remains pristine. */
149
+ reset() {
150
+ this.userInteracted.set(false);
151
+ super.reset();
152
+ }
148
153
  constructor() {
149
154
  super();
150
155
  /**
151
- * The controlled checked state of the calendar.
156
+ * The controlled time value. `null` represents an empty field and keeps the value addressable as
157
+ * an Angular Signal Forms child field (`undefined` denotes an absent optional path).
152
158
  */
153
- this.value = model(/* @ts-ignore */
154
- ...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
159
+ this.value = model(null, /* @ts-ignore */
160
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
155
161
  /**
156
162
  * The hour cycle to use for formatting times. Defaults to the locale preference
157
163
  */
@@ -210,7 +216,7 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
210
216
  */
211
217
  this.defaultDate = computed(() => getDefaultTime({
212
218
  defaultPlaceholder: undefined,
213
- defaultValue: this.value()
219
+ defaultValue: this.value() ?? undefined
214
220
  }), /* @ts-ignore */
215
221
  ...(ngDevMode ? [{ debugName: "defaultDate" }] : /* istanbul ignore next */ []));
216
222
  /**
@@ -218,6 +224,14 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
218
224
  */
219
225
  this.placeholder = model(this.defaultDate().copy(), /* @ts-ignore */
220
226
  ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
227
+ /**
228
+ * Always-defined placeholder used for segment math. A controlled `[placeholder]` can be reset to
229
+ * `undefined`; fall back to the default time so the converted placeholder is never built from
230
+ * `undefined`.
231
+ * @ignore
232
+ */
233
+ this.effectivePlaceholder = computed(() => this.placeholder() ?? this.defaultDate().copy(), /* @ts-ignore */
234
+ ...(ngDevMode ? [{ debugName: "effectivePlaceholder" }] : /* istanbul ignore next */ []));
221
235
  // Internal state
222
236
  /**
223
237
  * Segment input parts, collected from the projected content in DOM order. This
@@ -258,7 +272,7 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
258
272
  return value;
259
273
  } });
260
274
  this.convertedPlaceholder = linkedSignal({ ...(ngDevMode ? { debugName: "convertedPlaceholder" } : /* istanbul ignore next */ {}), source: () => {
261
- return convertValue(this.placeholder());
275
+ return convertValue(this.effectivePlaceholder());
262
276
  },
263
277
  computation: (value) => {
264
278
  return value;
@@ -303,7 +317,7 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
303
317
  * @ignore Tri-state display validity: the enclosing Field's gated state when inside a `rdxFieldRoot`,
304
318
  * else the time-field's own (parse + form) invalidity. Overrides the base default (`formUi` only).
305
319
  */
306
- this.displayValid = computed(() => resolveDisplayValid(this.fieldValidity, this.invalidState), /* @ts-ignore */
320
+ this.displayValid = computed(() => resolveDisplayValid(this.fieldValidity, this.invalidState, this.formUi.pendingState), /* @ts-ignore */
307
321
  ...(ngDevMode ? [{ debugName: "displayValid" }] : /* istanbul ignore next */ []));
308
322
  /** @ignore */
309
323
  this.touchedState = this.formUi.touchedState;
@@ -386,7 +400,7 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
386
400
  // buffer; mirror it back onto the public `value` model so two-way binding and
387
401
  // `valueChange` fire. The guard keeps this idempotent and breaks the feedback loop
388
402
  // (`value` → `convertedModelValue` source → here) once the values agree.
389
- const next = isNullish(value) ? undefined : toModelValue(value, this.value());
403
+ const next = isNullish(value) ? null : toModelValue(value, this.value());
390
404
  if (!isSameTimeValue(this.value(), next)) {
391
405
  this.value.set(next);
392
406
  }
@@ -415,14 +429,14 @@ class RdxTimeFieldRootDirective extends RdxFormUiControlBase {
415
429
  this.userInteracted.set(true);
416
430
  }
417
431
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxTimeFieldRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
418
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.2", type: RdxTimeFieldRootDirective, isStandalone: true, selector: "[rdxTimeFieldRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hourCycle: { classPropertyName: "hourCycle", publicName: "hourCycle", isSignal: true, isRequired: false, transformFunction: null }, granularity: { classPropertyName: "granularity", publicName: "granularity", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirInput: { classPropertyName: "dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, hideTimeZone: { classPropertyName: "hideTimeZone", publicName: "hideTimeZone", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", placeholder: "placeholderChange" }, host: { attributes: { "role": "group" }, listeners: { "keydown": "onKeydown($event)", "focusout": "markAsTouched()" }, properties: { "attr.aria-disabled": "disabled() ? \"\" : undefined", "attr.data-disabled": "disabled() ? \"\" : undefined", "attr.data-readonly": "readonly() ? \"\" : undefined", "attr.aria-invalid": "displayValid() === false ? \"true\" : undefined", "attr.data-invalid": "displayValid() === false ? \"\" : undefined", "attr.data-valid": "displayValid() === true ? \"\" : undefined", "attr.data-touched": "touchedState() ? \"\" : undefined", "attr.data-dirty": "dirtyState() ? \"\" : undefined", "attr.dir": "dir()" } }, providers: [provideToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)], queries: [{ propertyName: "segmentInputs", predicate: RdxTimeFieldInputDirective, isSignal: true }], exportAs: ["rdxTimeFieldRoot"], usesInheritance: true, ngImport: i0 }); }
432
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.2", type: RdxTimeFieldRootDirective, isStandalone: true, selector: "[rdxTimeFieldRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hourCycle: { classPropertyName: "hourCycle", publicName: "hourCycle", isSignal: true, isRequired: false, transformFunction: null }, granularity: { classPropertyName: "granularity", publicName: "granularity", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirInput: { classPropertyName: "dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, hideTimeZone: { classPropertyName: "hideTimeZone", publicName: "hideTimeZone", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", placeholder: "placeholderChange" }, host: { attributes: { "role": "group" }, listeners: { "keydown": "onKeydown($event)", "focusout": "markAsTouched()" }, properties: { "attr.aria-disabled": "disabled() ? \"\" : undefined", "attr.data-disabled": "disabled() ? \"\" : undefined", "attr.data-readonly": "readonly() ? \"\" : undefined", "attr.aria-invalid": "displayValid() === false ? \"true\" : undefined", "attr.data-invalid": "displayValid() === false ? \"\" : undefined", "attr.data-valid": "displayValid() === true ? \"\" : undefined", "attr.data-touched": "touchedState() ? \"\" : undefined", "attr.data-dirty": "dirtyState() ? \"\" : undefined", "attr.dir": "dir()" } }, providers: [provideExistingToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)], queries: [{ propertyName: "segmentInputs", predicate: RdxTimeFieldInputDirective, isSignal: true }], exportAs: ["rdxTimeFieldRoot"], usesInheritance: true, ngImport: i0 }); }
419
433
  }
420
434
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxTimeFieldRootDirective, decorators: [{
421
435
  type: Directive,
422
436
  args: [{
423
437
  selector: '[rdxTimeFieldRoot]',
424
438
  exportAs: 'rdxTimeFieldRoot',
425
- providers: [provideToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)],
439
+ providers: [provideExistingToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)],
426
440
  host: {
427
441
  role: 'group',
428
442
  '[attr.aria-disabled]': 'disabled() ? "" : undefined',
@@ -1 +1 @@
1
- {"version":3,"file":"radix-ng-primitives-time-field.mjs","sources":["../../../packages/primitives/time-field/src/time-field-context.token.ts","../../../packages/primitives/time-field/src/time-field-input.directive.ts","../../../packages/primitives/time-field/src/time-field-root.directive.ts","../../../packages/primitives/time-field/index.ts","../../../packages/primitives/time-field/radix-ng-primitives-time-field.ts"],"sourcesContent":["import { inject, InjectionToken, InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';\nimport { DateStep, Formatter, HourCycle, SegmentValueObj, TimeValue } from '@radix-ng/primitives/core';\n\nexport interface TimeFieldContextToken {\n locale: InputSignal<string>;\n value: ModelSignal<TimeValue | undefined>;\n placeholder: ModelSignal<TimeValue>;\n isInvalid: Signal<boolean>;\n /** Effective invalid: the built-in range check OR the form-driven invalid state. */\n invalidState: Signal<boolean>;\n /** Tri-state displayed validity (`true`/`false`/`null`): the field's gated state inside a Field, else own. */\n displayValid: Signal<boolean | null>;\n disabled: InputSignal<boolean>;\n readonly: InputSignal<boolean>;\n formatter: Signal<Formatter>;\n hourCycle: InputSignal<HourCycle>;\n segmentValues: WritableSignal<SegmentValueObj>;\n focusNext: () => void;\n setFocusedElement: (el: HTMLElement) => void;\n convertedModelValue: WritableSignal<TimeValue | undefined>;\n convertedPlaceholder: WritableSignal<TimeValue>;\n step$: Signal<DateStep>;\n}\n\nexport const TIME_FIELDS_ROOT_CONTEXT = new InjectionToken<TimeFieldContextToken>('TIME_FIELDS_ROOT_CONTEXT');\n\nexport function injectTimeFieldsRootContext(): TimeFieldContextToken {\n return inject(TIME_FIELDS_ROOT_CONTEXT);\n}\n","import { computed, Directive, effect, ElementRef, inject, input, signal, WritableSignal } from '@angular/core';\nimport { DateValue } from '@internationalized/date';\nimport { SegmentPart, useDateField } from '@radix-ng/primitives/core';\nimport { injectTimeFieldsRootContext } from './time-field-context.token';\n\n@Directive({\n selector: '[rdxTimeFieldInput]',\n host: {\n '[attr.contenteditable]': 'disabled() || readonly() ? false : part() !== \"literal\"',\n '[attr.data-rdx-date-field-segment]': 'part()',\n '[attr.aria-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-invalid]': 'displayValid() === false ? \"\" : undefined',\n '[attr.aria-invalid]': 'displayValid() === false ? true : undefined',\n\n '(mousedown)': 'part() !== \"literal\" && handleSegmentClick($event)',\n '(keydown)': 'part() !== \"literal\" && handleSegmentKeydown($event)',\n '(focus)': 'part() !== \"literal\" && onFocus($event)',\n '(focusout)': 'part() !== \"literal\" && onFocusOut()'\n }\n})\nexport class RdxTimeFieldInputDirective {\n private readonly el = inject(ElementRef);\n\n /**\n * The host element of this segment. Consumed by the root to collect focusable\n * segments in DOM order.\n * @ignore\n */\n readonly element: HTMLElement = this.el.nativeElement;\n\n private readonly rootContext = injectTimeFieldsRootContext();\n\n /**\n * The part of the date to render\n * `'hour' | 'minute' | 'second' | 'dayPeriod' | 'literal' | 'timeZoneName'`\n */\n readonly part = input<SegmentPart>();\n\n /**\n * @ignore\n */\n readonly disabled = computed(() => this.rootContext.disabled());\n\n /**\n * @ignore\n */\n readonly readonly = computed(() => this.rootContext.readonly());\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => this.rootContext.invalidState());\n\n /** @ignore Tri-state display validity from the root (gated by an enclosing Field). */\n readonly displayValid = computed(() => this.rootContext.displayValid());\n\n /**\n * @ignore\n */\n readonly hasLeftFocus = signal<boolean>(true);\n\n /**\n * @ignore\n */\n readonly lastKeyZero = signal<boolean>(false);\n\n private readonly fieldData = computed(() => {\n return useDateField({\n hasLeftFocus: this.hasLeftFocus,\n lastKeyZero: this.lastKeyZero,\n placeholder: this.rootContext.convertedPlaceholder as unknown as WritableSignal<DateValue>,\n hourCycle: this.rootContext.hourCycle(),\n segmentValues: this.rootContext.segmentValues,\n formatter: this.rootContext.formatter(),\n part: <SegmentPart>this.part(),\n disabled: this.rootContext.disabled,\n readonly: this.rootContext.readonly,\n modelValue: this.rootContext.convertedModelValue as unknown as WritableSignal<DateValue>,\n focusNext: this.rootContext.focusNext,\n step: this.rootContext.step$\n });\n });\n\n private readonly attributes = computed(() => this.fieldData().attributes());\n\n /**\n * @ignore\n */\n handleSegmentClick: (e: Event) => void;\n\n /**\n * @ignore\n */\n handleSegmentKeydown: (e: Event) => void;\n\n constructor() {\n effect(() => {\n const { handleSegmentClick, handleSegmentKeydown } = this.fieldData();\n this.handleSegmentKeydown = handleSegmentKeydown as (e: Event) => void;\n this.handleSegmentClick = handleSegmentClick as (e: Event) => void;\n });\n\n effect(() => {\n const attrs = this.attributes();\n Object.entries(attrs).forEach(([attr, value]) => {\n this.el.nativeElement.setAttribute(attr, String(value));\n });\n });\n }\n\n /**\n * @ignore\n */\n onFocus(e: Event) {\n this.rootContext.setFocusedElement(e.target as HTMLElement);\n }\n\n /**\n * @ignore\n */\n onFocusOut() {\n this.hasLeftFocus.set(true);\n }\n}\n","import {\n booleanAttribute,\n computed,\n contentChildren,\n Directive,\n input,\n linkedSignal,\n model,\n Signal,\n signal\n} from '@angular/core';\nimport { DateValue, getLocalTimeZone, isEqualDay, Time, toCalendarDateTime, today } from '@internationalized/date';\nimport {\n ARROW_LEFT,\n ARROW_RIGHT,\n BooleanInput,\n createContent,\n createFormatter,\n DateStep,\n Direction,\n Formatter,\n getDefaultTime,\n Granularity,\n HourCycle,\n initializeSegmentValues,\n isBefore,\n isNullish,\n isSegmentNavigationKey,\n normalizeDateStep,\n normalizeHourCycle,\n provideToken,\n RdxFormUiControlBase,\n RdxFormValueControl,\n resolveDisplayValid,\n SegmentValueObj,\n syncSegmentValues,\n TimeValue,\n watch\n} from '@radix-ng/primitives/core';\nimport { injectDirection } from '@radix-ng/primitives/direction-provider';\nimport { TIME_FIELDS_ROOT_CONTEXT } from './time-field-context.token';\nimport { RdxTimeFieldInputDirective } from './time-field-input.directive';\n\nfunction convertValue(value: TimeValue, date: DateValue = today(getLocalTimeZone())) {\n if (value && 'day' in value) {\n return value;\n }\n\n return toCalendarDateTime(date, value);\n}\n\n/**\n * Map the internal edit buffer (`convertedModelValue`, always a date-bearing value\n * so the segment editor has a date context) back onto the public `value` model.\n * A date-bearing model keeps its shape; a time-only model is exposed as a plain `Time`.\n */\nfunction toModelValue(value: TimeValue, current: TimeValue | undefined): TimeValue {\n if (current && 'day' in current) {\n return value;\n }\n\n return new Time(value.hour, value.minute, value.second, value.millisecond);\n}\n\nfunction isSameTimeValue(a: TimeValue | undefined, b: TimeValue | undefined): boolean {\n if (isNullish(a) || isNullish(b)) return a === b;\n return (a as { compare(other: TimeValue): number }).compare(b) === 0;\n}\n\n@Directive({\n selector: '[rdxTimeFieldRoot]',\n exportAs: 'rdxTimeFieldRoot',\n providers: [provideToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)],\n host: {\n role: 'group',\n '[attr.aria-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-readonly]': 'readonly() ? \"\" : undefined',\n '[attr.aria-invalid]': 'displayValid() === false ? \"true\" : undefined',\n '[attr.data-invalid]': 'displayValid() === false ? \"\" : undefined',\n '[attr.data-valid]': 'displayValid() === true ? \"\" : undefined',\n '[attr.data-touched]': 'touchedState() ? \"\" : undefined',\n '[attr.data-dirty]': 'dirtyState() ? \"\" : undefined',\n '[attr.dir]': 'dir()',\n\n '(keydown)': 'onKeydown($event)',\n '(focusout)': 'markAsTouched()'\n }\n})\nexport class RdxTimeFieldRootDirective\n extends RdxFormUiControlBase\n implements RdxFormValueControl<TimeValue | undefined>\n{\n /**\n * The controlled checked state of the calendar.\n */\n readonly value = model<TimeValue | undefined>();\n\n /**\n * The hour cycle to use for formatting times. Defaults to the locale preference\n */\n readonly hourCycle = input<HourCycle>();\n\n /**\n * The granularity to use for formatting the field. Defaults to 'day' if a CalendarDate is provided, otherwise defaults to 'minute'.\n * The field will render segments for each part of the date up to and including the specified granularity.\n */\n readonly granularity = input<Granularity>();\n\n /**\n * The locale to use for formatting dates.\n */\n readonly locale = input<string>('en');\n\n readonly dirInput = input<Direction | undefined>(undefined, { alias: 'dir' });\n readonly dir = injectDirection(this.dirInput);\n\n /**\n * The minimum valid date that can be entered.\n */\n readonly minValue = input<TimeValue>();\n\n /**\n * The maximum valid date that can be entered.\n */\n readonly maxValue = input<TimeValue>();\n\n /**\n * Whether or not to hide the time zone segment of the field.\n */\n readonly hideTimeZone = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * Whether or not the field is readonly.\n */\n readonly readonly = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * The stepping interval for the time fields. Defaults to 1\n */\n readonly step = input<DateStep>();\n\n readonly step$ = computed(() => normalizeDateStep(this.step()));\n\n /**\n * Locale- and hour-cycle-aware formatter. Recomputed whenever `locale` or\n * `hourCycle` change so segments always render with the current settings.\n * @ignore\n */\n readonly formatter: Signal<Formatter> = computed(() =>\n createFormatter(this.locale(), {\n hourCycle: normalizeHourCycle(this.hourCycle())\n })\n );\n\n /**\n * @ignore\n */\n readonly defaultDate = computed(() =>\n getDefaultTime({\n defaultPlaceholder: undefined,\n defaultValue: this.value()\n })\n );\n\n /**\n * The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view\n */\n readonly placeholder = model<TimeValue | undefined>(this.defaultDate().copy());\n\n // Internal state\n\n /**\n * Segment input parts, collected from the projected content in DOM order. This\n * stays in sync with `segmentContents()` (granularity / locale / value changes\n * add or remove segments) instead of being captured once after view init.\n * @ignore\n */\n private readonly segmentInputs = contentChildren(RdxTimeFieldInputDirective);\n\n /**\n * The focusable (non-literal) segment elements, in DOM order.\n * @ignore\n */\n readonly segmentElements = computed(() =>\n this.segmentInputs()\n .filter((seg) => seg.part() !== 'literal')\n .map((seg) => seg.element)\n );\n\n /**\n * @ignore\n */\n readonly currentFocusedElement = signal<HTMLElement | null>(null);\n\n /**\n * @ignore\n */\n readonly inferredGranularity = computed(() => this.granularity() ?? 'minute');\n\n readonly convertedMinValue = computed(() => (this.minValue() ? convertValue(this.minValue()!) : undefined));\n readonly convertedMaxValue = computed(() => (this.maxValue() ? convertValue(this.maxValue()!) : undefined));\n\n readonly convertedModelValue = linkedSignal({\n source: () => {\n if (isNullish(this.value())) return this.value();\n\n return convertValue(this.value()!);\n },\n computation: (value: TimeValue | undefined) => {\n return value;\n }\n });\n\n readonly convertedPlaceholder = linkedSignal({\n source: () => {\n return convertValue(<TimeValue>this.placeholder());\n },\n computation: (value: TimeValue) => {\n return value;\n }\n });\n\n /**\n * The per-segment values. Writable so segment editing (via `useDateField`) can\n * update individual parts, but re-synced from the model whenever the value,\n * granularity or formatter change — so a controlled `value` set after init is\n * reflected, and an empty field re-initializes when granularity changes.\n * @ignore\n */\n readonly segmentValues = linkedSignal<\n { value: TimeValue | undefined; granularity: Granularity; formatter: Formatter },\n SegmentValueObj\n >({\n source: () => ({\n value: this.convertedModelValue(),\n granularity: this.inferredGranularity(),\n formatter: this.formatter()\n }),\n computation: ({ value, granularity, formatter }) =>\n value\n ? { ...syncSegmentValues({ value: <DateValue>value, formatter }) }\n : { ...initializeSegmentValues(granularity, true) }\n });\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => {\n if (!this.value()) return false;\n\n if (\n this.convertedMinValue() &&\n isBefore(<DateValue>this.convertedModelValue(), <DateValue>this.convertedMinValue())\n )\n return true;\n\n if (\n this.convertedMaxValue() &&\n isBefore(<DateValue>this.convertedMaxValue(), <DateValue>this.convertedModelValue())\n )\n return true;\n\n return false;\n });\n\n /**\n * @ignore Effective invalid: the built-in range check OR the form-driven `invalid` / `errors`\n * (Signal Forms). Reflected on the root and segments.\n */\n readonly invalidState = computed(() => this.isInvalid() || this.formUi.invalidState());\n /**\n * @ignore Tri-state display validity: the enclosing Field's gated state when inside a `rdxFieldRoot`,\n * else the time-field's own (parse + form) invalidity. Overrides the base default (`formUi` only).\n */\n override readonly displayValid = computed(() => resolveDisplayValid(this.fieldValidity, this.invalidState));\n /** @ignore */\n readonly touchedState = this.formUi.touchedState;\n /** @ignore */\n readonly dirtyState = this.formUi.dirtyState;\n\n /** @ignore Whether the user has focused a segment — gates dirty tracking so a form/initial seed of `value` doesn't mark dirty. */\n private readonly userInteracted = signal(false);\n\n /** @ignore Mark the field touched (model + `touch` output) for Signal Forms. Called on segment blur. */\n markAsTouched(): void {\n this.formUi.markAsTouched();\n }\n\n /**\n * @ignore\n */\n readonly allSegmentContent = computed(() =>\n createContent({\n granularity: this.inferredGranularity(),\n dateRef: <DateValue>this.convertedPlaceholder(),\n formatter: this.formatter(),\n hideTimeZone: this.hideTimeZone(),\n hourCycle: this.hourCycle(),\n segmentValues: this.segmentValues(),\n locale: this.locale,\n isTimeValue: true\n })\n );\n\n /**\n * An array of segments that should be readonly, which prevent user input on them.\n */\n readonly segmentContents = computed(() => this.allSegmentContent().arr);\n\n /**\n * @ignore\n */\n readonly currentSegmentIndex = computed(() =>\n this.segmentElements().findIndex((el) => el === this.currentFocusedElement())\n );\n\n /**\n * @ignore\n */\n readonly prevFocusableSegment = computed(() => {\n const sign = this.dir() === 'rtl' ? -1 : 1;\n const elements = this.segmentElements();\n const index = this.currentSegmentIndex();\n const prevCondition = sign > 0 ? index < 0 : index > elements.length - 1;\n if (prevCondition) return null;\n\n return elements[index - sign];\n });\n\n /**\n * @ignore\n */\n readonly nextFocusableSegment = computed(() => {\n const sign = this.dir() === 'rtl' ? -1 : 1;\n const elements = this.segmentElements();\n const index = this.currentSegmentIndex();\n const nextCondition = sign < 0 ? index < 0 : index > elements.length - 1;\n if (nextCondition) return null;\n\n return elements[index + sign];\n });\n\n /**\n * @ignore\n */\n readonly focusNext = () => {\n this.nextFocusableSegment()?.focus();\n };\n\n constructor() {\n super();\n\n // Mark dirty when the value changes after the user has interacted (a form/initial seed of\n // `value` lands before any segment focus, so it is excluded).\n watch([this.value], () => {\n if (this.userInteracted()) {\n this.formUi.markDirty();\n }\n });\n\n watch([this.convertedModelValue], ([value]) => {\n if (\n !isNullish(value) &&\n (!isEqualDay(<DateValue>this.convertedPlaceholder(), <DateValue>value) ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n this.convertedPlaceholder().compare(value) !== 0)\n )\n this.placeholder.set(value.copy());\n\n // Segment editing (via `useDateField`) writes the internal `convertedModelValue`\n // buffer; mirror it back onto the public `value` model so two-way binding and\n // `valueChange` fire. The guard keeps this idempotent and breaks the feedback loop\n // (`value` → `convertedModelValue` source → here) once the values agree.\n const next = isNullish(value) ? undefined : toModelValue(value, this.value());\n if (!isSameTimeValue(this.value(), next)) {\n this.value.set(next);\n }\n });\n }\n\n /**\n * @ignore\n */\n onKeydown(event: Event) {\n const keyEvent = event as KeyboardEvent;\n if (!isSegmentNavigationKey(keyEvent.key)) return;\n const code = keyEvent.code;\n\n if (code === ARROW_LEFT) {\n this.prevFocusableSegment()?.focus();\n }\n\n if (code === ARROW_RIGHT) {\n this.nextFocusableSegment()?.focus();\n }\n }\n\n /**\n * @ignore\n */\n setFocusedElement(el: HTMLElement) {\n this.currentFocusedElement.set(el);\n this.userInteracted.set(true);\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RdxTimeFieldInputDirective } from './src/time-field-input.directive';\nimport { RdxTimeFieldRootDirective } from './src/time-field-root.directive';\n\nexport * from './src/time-field-context.token';\nexport * from './src/time-field-input.directive';\nexport * from './src/time-field-root.directive';\n\nconst _imports = [RdxTimeFieldRootDirective, RdxTimeFieldInputDirective];\n\n@NgModule({\n imports: [..._imports],\n exports: [..._imports]\n})\nexport class RdxTimeFieldModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"radix-ng-primitives-time-field.mjs","sources":["../../../packages/primitives/time-field/src/time-field-context.token.ts","../../../packages/primitives/time-field/src/time-field-input.directive.ts","../../../packages/primitives/time-field/src/time-field-root.directive.ts","../../../packages/primitives/time-field/index.ts","../../../packages/primitives/time-field/radix-ng-primitives-time-field.ts"],"sourcesContent":["import { inject, InjectionToken, InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';\nimport { DateStep, Formatter, HourCycle, SegmentValueObj, TimeValue } from '@radix-ng/primitives/core';\n\nexport interface TimeFieldContextToken {\n locale: InputSignal<string>;\n value: ModelSignal<TimeValue | null>;\n /** The controlled placeholder; may be `undefined`. Use `convertedPlaceholder` for segment math. */\n placeholder: Signal<TimeValue | undefined>;\n isInvalid: Signal<boolean>;\n /** Effective invalid: the built-in range check OR the form-driven invalid state. */\n invalidState: Signal<boolean>;\n /** Tri-state displayed validity (`true`/`false`/`null`): the field's gated state inside a Field, else own. */\n displayValid: Signal<boolean | null>;\n // Read-only views: consumers only read these. Typed as `Signal<…>` supertypes so the concrete\n // signal kind (transformed input, model, computed) is an implementation detail and mocks stay simple.\n disabled: Signal<boolean>;\n readonly: Signal<boolean>;\n formatter: Signal<Formatter>;\n hourCycle: Signal<HourCycle | undefined>;\n segmentValues: WritableSignal<SegmentValueObj>;\n focusNext: () => void;\n setFocusedElement: (el: HTMLElement) => void;\n convertedModelValue: WritableSignal<TimeValue | null>;\n convertedPlaceholder: WritableSignal<TimeValue>;\n step$: Signal<DateStep>;\n}\n\nexport const TIME_FIELDS_ROOT_CONTEXT = new InjectionToken<TimeFieldContextToken>('TIME_FIELDS_ROOT_CONTEXT');\n\nexport function injectTimeFieldsRootContext(): TimeFieldContextToken {\n return inject(TIME_FIELDS_ROOT_CONTEXT);\n}\n","import { computed, Directive, effect, ElementRef, inject, input, signal, WritableSignal } from '@angular/core';\nimport { DateValue } from '@internationalized/date';\nimport { SegmentPart, useDateField } from '@radix-ng/primitives/core';\nimport { injectTimeFieldsRootContext } from './time-field-context.token';\n\n@Directive({\n selector: '[rdxTimeFieldInput]',\n host: {\n '[attr.contenteditable]': 'disabled() || readonly() ? false : part() !== \"literal\"',\n '[attr.data-rdx-date-field-segment]': 'part()',\n '[attr.aria-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-invalid]': 'displayValid() === false ? \"\" : undefined',\n '[attr.aria-invalid]': 'displayValid() === false ? true : undefined',\n\n '(mousedown)': 'part() !== \"literal\" && handleSegmentClick($event)',\n '(keydown)': 'part() !== \"literal\" && handleSegmentKeydown($event)',\n '(focus)': 'part() !== \"literal\" && onFocus($event)',\n '(focusout)': 'part() !== \"literal\" && onFocusOut()'\n }\n})\nexport class RdxTimeFieldInputDirective {\n private readonly el = inject(ElementRef);\n\n /**\n * The host element of this segment. Consumed by the root to collect focusable\n * segments in DOM order.\n * @ignore\n */\n readonly element: HTMLElement = this.el.nativeElement;\n\n private readonly rootContext = injectTimeFieldsRootContext();\n\n /**\n * The part of the date to render\n * `'hour' | 'minute' | 'second' | 'dayPeriod' | 'literal' | 'timeZoneName'`\n */\n readonly part = input<SegmentPart>();\n\n /**\n * @ignore\n */\n readonly disabled = computed(() => this.rootContext.disabled());\n\n /**\n * @ignore\n */\n readonly readonly = computed(() => this.rootContext.readonly());\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => this.rootContext.invalidState());\n\n /** @ignore Tri-state display validity from the root (gated by an enclosing Field). */\n readonly displayValid = computed(() => this.rootContext.displayValid());\n\n /**\n * @ignore\n */\n readonly hasLeftFocus = signal<boolean>(true);\n\n /**\n * @ignore\n */\n readonly lastKeyZero = signal<boolean>(false);\n\n private readonly fieldData = computed(() => {\n return useDateField({\n hasLeftFocus: this.hasLeftFocus,\n lastKeyZero: this.lastKeyZero,\n placeholder: this.rootContext.convertedPlaceholder as unknown as WritableSignal<DateValue>,\n hourCycle: this.rootContext.hourCycle(),\n segmentValues: this.rootContext.segmentValues,\n formatter: this.rootContext.formatter(),\n part: <SegmentPart>this.part(),\n disabled: this.rootContext.disabled,\n readonly: this.rootContext.readonly,\n modelValue: this.rootContext.convertedModelValue as unknown as WritableSignal<DateValue>,\n focusNext: this.rootContext.focusNext,\n step: this.rootContext.step$\n });\n });\n\n private readonly attributes = computed(() => this.fieldData().attributes());\n\n /**\n * @ignore\n */\n handleSegmentClick: (e: Event) => void;\n\n /**\n * @ignore\n */\n handleSegmentKeydown: (e: Event) => void;\n\n constructor() {\n effect(() => {\n const { handleSegmentClick, handleSegmentKeydown } = this.fieldData();\n this.handleSegmentKeydown = handleSegmentKeydown as (e: Event) => void;\n this.handleSegmentClick = handleSegmentClick as (e: Event) => void;\n });\n\n effect(() => {\n const attrs = this.attributes();\n Object.entries(attrs).forEach(([attr, value]) => {\n this.el.nativeElement.setAttribute(attr, String(value));\n });\n });\n }\n\n /**\n * @ignore\n */\n onFocus(e: Event) {\n this.rootContext.setFocusedElement(e.target as HTMLElement);\n }\n\n /**\n * @ignore\n */\n onFocusOut() {\n this.hasLeftFocus.set(true);\n }\n}\n","import {\n booleanAttribute,\n computed,\n contentChildren,\n Directive,\n input,\n linkedSignal,\n model,\n Signal,\n signal\n} from '@angular/core';\nimport { DateValue, getLocalTimeZone, isEqualDay, Time, toCalendarDateTime, today } from '@internationalized/date';\nimport {\n ARROW_LEFT,\n ARROW_RIGHT,\n BooleanInput,\n createContent,\n createFormatter,\n DateStep,\n Direction,\n Formatter,\n getDefaultTime,\n Granularity,\n HourCycle,\n initializeSegmentValues,\n isBefore,\n isNullish,\n isSegmentNavigationKey,\n normalizeDateStep,\n normalizeHourCycle,\n provideExistingToken,\n RdxFormUiControlBase,\n RdxFormValueControl,\n resolveDisplayValid,\n SegmentValueObj,\n syncSegmentValues,\n TimeValue,\n watch\n} from '@radix-ng/primitives/core';\nimport { injectDirection } from '@radix-ng/primitives/direction-provider';\nimport { TIME_FIELDS_ROOT_CONTEXT } from './time-field-context.token';\nimport { RdxTimeFieldInputDirective } from './time-field-input.directive';\n\nfunction convertValue(value: TimeValue, date: DateValue = today(getLocalTimeZone())) {\n if (value && 'day' in value) {\n return value;\n }\n\n return toCalendarDateTime(date, value);\n}\n\n/**\n * Map the internal edit buffer (`convertedModelValue`, always a date-bearing value\n * so the segment editor has a date context) back onto the public `value` model.\n * A date-bearing model keeps its shape; a time-only model is exposed as a plain `Time`.\n */\nfunction toModelValue(value: TimeValue, current: TimeValue | null): TimeValue {\n if (current && 'day' in current) {\n return value;\n }\n\n return new Time(value.hour, value.minute, value.second, value.millisecond);\n}\n\nfunction isSameTimeValue(a: TimeValue | null, b: TimeValue | null): boolean {\n if (isNullish(a) || isNullish(b)) return a === b;\n return (a as { compare(other: TimeValue): number }).compare(b) === 0;\n}\n\n@Directive({\n selector: '[rdxTimeFieldRoot]',\n exportAs: 'rdxTimeFieldRoot',\n providers: [provideExistingToken(TIME_FIELDS_ROOT_CONTEXT, RdxTimeFieldRootDirective)],\n host: {\n role: 'group',\n '[attr.aria-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-disabled]': 'disabled() ? \"\" : undefined',\n '[attr.data-readonly]': 'readonly() ? \"\" : undefined',\n '[attr.aria-invalid]': 'displayValid() === false ? \"true\" : undefined',\n '[attr.data-invalid]': 'displayValid() === false ? \"\" : undefined',\n '[attr.data-valid]': 'displayValid() === true ? \"\" : undefined',\n '[attr.data-touched]': 'touchedState() ? \"\" : undefined',\n '[attr.data-dirty]': 'dirtyState() ? \"\" : undefined',\n '[attr.dir]': 'dir()',\n\n '(keydown)': 'onKeydown($event)',\n '(focusout)': 'markAsTouched()'\n }\n})\nexport class RdxTimeFieldRootDirective extends RdxFormUiControlBase implements RdxFormValueControl<TimeValue | null> {\n /**\n * The controlled time value. `null` represents an empty field and keeps the value addressable as\n * an Angular Signal Forms child field (`undefined` denotes an absent optional path).\n */\n readonly value = model<TimeValue | null>(null);\n\n /**\n * The hour cycle to use for formatting times. Defaults to the locale preference\n */\n readonly hourCycle = input<HourCycle>();\n\n /**\n * The granularity to use for formatting the field. Defaults to 'day' if a CalendarDate is provided, otherwise defaults to 'minute'.\n * The field will render segments for each part of the date up to and including the specified granularity.\n */\n readonly granularity = input<Granularity>();\n\n /**\n * The locale to use for formatting dates.\n */\n readonly locale = input<string>('en');\n\n readonly dirInput = input<Direction | undefined>(undefined, { alias: 'dir' });\n readonly dir = injectDirection(this.dirInput);\n\n /**\n * The minimum valid date that can be entered.\n */\n readonly minValue = input<TimeValue>();\n\n /**\n * The maximum valid date that can be entered.\n */\n readonly maxValue = input<TimeValue>();\n\n /**\n * Whether or not to hide the time zone segment of the field.\n */\n readonly hideTimeZone = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * Whether or not the field is readonly.\n */\n readonly readonly = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * The stepping interval for the time fields. Defaults to 1\n */\n readonly step = input<DateStep>();\n\n readonly step$ = computed(() => normalizeDateStep(this.step()));\n\n /**\n * Locale- and hour-cycle-aware formatter. Recomputed whenever `locale` or\n * `hourCycle` change so segments always render with the current settings.\n * @ignore\n */\n readonly formatter: Signal<Formatter> = computed(() =>\n createFormatter(this.locale(), {\n hourCycle: normalizeHourCycle(this.hourCycle())\n })\n );\n\n /**\n * @ignore\n */\n readonly defaultDate = computed(() =>\n getDefaultTime({\n defaultPlaceholder: undefined,\n defaultValue: this.value() ?? undefined\n })\n );\n\n /**\n * The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view\n */\n readonly placeholder = model<TimeValue | undefined>(this.defaultDate().copy());\n\n /**\n * Always-defined placeholder used for segment math. A controlled `[placeholder]` can be reset to\n * `undefined`; fall back to the default time so the converted placeholder is never built from\n * `undefined`.\n * @ignore\n */\n readonly effectivePlaceholder = computed(() => this.placeholder() ?? this.defaultDate().copy());\n\n // Internal state\n\n /**\n * Segment input parts, collected from the projected content in DOM order. This\n * stays in sync with `segmentContents()` (granularity / locale / value changes\n * add or remove segments) instead of being captured once after view init.\n * @ignore\n */\n private readonly segmentInputs = contentChildren(RdxTimeFieldInputDirective);\n\n /**\n * The focusable (non-literal) segment elements, in DOM order.\n * @ignore\n */\n readonly segmentElements = computed(() =>\n this.segmentInputs()\n .filter((seg) => seg.part() !== 'literal')\n .map((seg) => seg.element)\n );\n\n /**\n * @ignore\n */\n readonly currentFocusedElement = signal<HTMLElement | null>(null);\n\n /**\n * @ignore\n */\n readonly inferredGranularity = computed(() => this.granularity() ?? 'minute');\n\n readonly convertedMinValue = computed(() => (this.minValue() ? convertValue(this.minValue()!) : undefined));\n readonly convertedMaxValue = computed(() => (this.maxValue() ? convertValue(this.maxValue()!) : undefined));\n\n readonly convertedModelValue = linkedSignal({\n source: () => {\n if (isNullish(this.value())) return this.value();\n\n return convertValue(this.value()!);\n },\n computation: (value: TimeValue | null) => {\n return value;\n }\n });\n\n readonly convertedPlaceholder = linkedSignal({\n source: () => {\n return convertValue(this.effectivePlaceholder());\n },\n computation: (value: TimeValue) => {\n return value;\n }\n });\n\n /**\n * The per-segment values. Writable so segment editing (via `useDateField`) can\n * update individual parts, but re-synced from the model whenever the value,\n * granularity or formatter change — so a controlled `value` set after init is\n * reflected, and an empty field re-initializes when granularity changes.\n * @ignore\n */\n readonly segmentValues = linkedSignal<\n { value: TimeValue | null; granularity: Granularity; formatter: Formatter },\n SegmentValueObj\n >({\n source: () => ({\n value: this.convertedModelValue(),\n granularity: this.inferredGranularity(),\n formatter: this.formatter()\n }),\n computation: ({ value, granularity, formatter }) =>\n value\n ? { ...syncSegmentValues({ value: <DateValue>value, formatter }) }\n : { ...initializeSegmentValues(granularity, true) }\n });\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => {\n if (!this.value()) return false;\n\n if (\n this.convertedMinValue() &&\n isBefore(<DateValue>this.convertedModelValue(), <DateValue>this.convertedMinValue())\n )\n return true;\n\n if (\n this.convertedMaxValue() &&\n isBefore(<DateValue>this.convertedMaxValue(), <DateValue>this.convertedModelValue())\n )\n return true;\n\n return false;\n });\n\n /**\n * @ignore Effective invalid: the built-in range check OR the form-driven `invalid` / `errors`\n * (Signal Forms). Reflected on the root and segments.\n */\n readonly invalidState = computed(() => this.isInvalid() || this.formUi.invalidState());\n /**\n * @ignore Tri-state display validity: the enclosing Field's gated state when inside a `rdxFieldRoot`,\n * else the time-field's own (parse + form) invalidity. Overrides the base default (`formUi` only).\n */\n override readonly displayValid = computed(() =>\n resolveDisplayValid(this.fieldValidity, this.invalidState, this.formUi.pendingState)\n );\n /** @ignore */\n readonly touchedState = this.formUi.touchedState;\n /** @ignore */\n readonly dirtyState = this.formUi.dirtyState;\n\n /** @ignore Whether the user has focused a segment — gates dirty tracking so a form/initial seed of `value` doesn't mark dirty. */\n private readonly userInteracted = signal(false);\n\n /** @ignore Mark the field touched (model + `touch` output) for Signal Forms. Called on segment blur. */\n markAsTouched(): void {\n this.formUi.markAsTouched();\n }\n\n /** Reset segment interaction so the form-owned value write remains pristine. */\n override reset(): void {\n this.userInteracted.set(false);\n super.reset();\n }\n\n /**\n * @ignore\n */\n readonly allSegmentContent = computed(() =>\n createContent({\n granularity: this.inferredGranularity(),\n dateRef: <DateValue>this.convertedPlaceholder(),\n formatter: this.formatter(),\n hideTimeZone: this.hideTimeZone(),\n hourCycle: this.hourCycle(),\n segmentValues: this.segmentValues(),\n locale: this.locale,\n isTimeValue: true\n })\n );\n\n /**\n * An array of segments that should be readonly, which prevent user input on them.\n */\n readonly segmentContents = computed(() => this.allSegmentContent().arr);\n\n /**\n * @ignore\n */\n readonly currentSegmentIndex = computed(() =>\n this.segmentElements().findIndex((el) => el === this.currentFocusedElement())\n );\n\n /**\n * @ignore\n */\n readonly prevFocusableSegment = computed(() => {\n const sign = this.dir() === 'rtl' ? -1 : 1;\n const elements = this.segmentElements();\n const index = this.currentSegmentIndex();\n const prevCondition = sign > 0 ? index < 0 : index > elements.length - 1;\n if (prevCondition) return null;\n\n return elements[index - sign];\n });\n\n /**\n * @ignore\n */\n readonly nextFocusableSegment = computed(() => {\n const sign = this.dir() === 'rtl' ? -1 : 1;\n const elements = this.segmentElements();\n const index = this.currentSegmentIndex();\n const nextCondition = sign < 0 ? index < 0 : index > elements.length - 1;\n if (nextCondition) return null;\n\n return elements[index + sign];\n });\n\n /**\n * @ignore\n */\n readonly focusNext = () => {\n this.nextFocusableSegment()?.focus();\n };\n\n constructor() {\n super();\n\n // Mark dirty when the value changes after the user has interacted (a form/initial seed of\n // `value` lands before any segment focus, so it is excluded).\n watch([this.value], () => {\n if (this.userInteracted()) {\n this.formUi.markDirty();\n }\n });\n\n watch([this.convertedModelValue], ([value]) => {\n if (\n !isNullish(value) &&\n (!isEqualDay(<DateValue>this.convertedPlaceholder(), <DateValue>value) ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n this.convertedPlaceholder().compare(value) !== 0)\n )\n this.placeholder.set(value.copy());\n\n // Segment editing (via `useDateField`) writes the internal `convertedModelValue`\n // buffer; mirror it back onto the public `value` model so two-way binding and\n // `valueChange` fire. The guard keeps this idempotent and breaks the feedback loop\n // (`value` → `convertedModelValue` source → here) once the values agree.\n const next = isNullish(value) ? null : toModelValue(value, this.value());\n if (!isSameTimeValue(this.value(), next)) {\n this.value.set(next);\n }\n });\n }\n\n /**\n * @ignore\n */\n onKeydown(event: Event) {\n const keyEvent = event as KeyboardEvent;\n if (!isSegmentNavigationKey(keyEvent.key)) return;\n const code = keyEvent.code;\n\n if (code === ARROW_LEFT) {\n this.prevFocusableSegment()?.focus();\n }\n\n if (code === ARROW_RIGHT) {\n this.nextFocusableSegment()?.focus();\n }\n }\n\n /**\n * @ignore\n */\n setFocusedElement(el: HTMLElement) {\n this.currentFocusedElement.set(el);\n this.userInteracted.set(true);\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RdxTimeFieldInputDirective } from './src/time-field-input.directive';\nimport { RdxTimeFieldRootDirective } from './src/time-field-root.directive';\n\nexport * from './src/time-field-context.token';\nexport * from './src/time-field-input.directive';\nexport * from './src/time-field-root.directive';\n\nconst _imports = [RdxTimeFieldRootDirective, RdxTimeFieldInputDirective];\n\n@NgModule({\n imports: [..._imports],\n exports: [..._imports]\n})\nexport class RdxTimeFieldModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@radix-ng/primitives",
3
- "version": "1.0.9",
4
- "description": "Headless, signals-first UI primitives for Angular.",
3
+ "version": "1.1.0",
4
+ "description": "Headless, signals-first UI primitives with first-class Angular Forms support.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -15,8 +15,13 @@
15
15
  "components",
16
16
  "ui",
17
17
  "angular",
18
+ "angular-forms",
19
+ "signal-forms",
18
20
  "radix-ng",
19
- "headless"
21
+ "headless",
22
+ "headless-ui",
23
+ "accessibility",
24
+ "base-ui"
20
25
  ],
21
26
  "peerDependencies": {
22
27
  "@angular/core": "^21.0.0 || ^22.0.0",
@@ -145,10 +150,6 @@
145
150
  "types": "./types/radix-ng-primitives-floating-focus-manager.d.ts",
146
151
  "default": "./fesm2022/radix-ng-primitives-floating-focus-manager.mjs"
147
152
  },
148
- "./focus-guards": {
149
- "types": "./types/radix-ng-primitives-focus-guards.d.ts",
150
- "default": "./fesm2022/radix-ng-primitives-focus-guards.mjs"
151
- },
152
153
  "./focus-scope": {
153
154
  "types": "./types/radix-ng-primitives-focus-scope.d.ts",
154
155
  "default": "./fesm2022/radix-ng-primitives-focus-scope.mjs"
@@ -109,6 +109,8 @@ declare class RdxAutocompleteRoot extends RdxFormUiControlBase implements Contro
109
109
  * built-in filtering disabled.
110
110
  */
111
111
  readonly filter: _angular_core.InputSignal<AutocompleteFilter | null | undefined>;
112
+ /** Locale for the default `contains` filter's string comparison. Defaults to the runtime locale. */
113
+ readonly locale: _angular_core.InputSignal<Intl.LocalesArgument>;
112
114
  /** Maximum number of matching items to show. `-1` (default) means no limit. */
113
115
  readonly limit: _angular_core.InputSignalWithTransform<number, unknown>;
114
116
  /** The full set of item values for {@link virtualized} mode. */
@@ -135,6 +137,8 @@ declare class RdxAutocompleteRoot extends RdxFormUiControlBase implements Contro
135
137
  readonly requiredState: _angular_core.Signal<boolean>;
136
138
  /** @ignore */
137
139
  readonly invalidState: _angular_core.Signal<boolean>;
140
+ readonly pendingState: _angular_core.Signal<boolean>;
141
+ readonly validState: _angular_core.Signal<boolean | null>;
138
142
  /** @ignore */
139
143
  readonly touchedState: _angular_core.Signal<boolean>;
140
144
  /** @ignore */
@@ -227,7 +231,7 @@ declare class RdxAutocompleteRoot extends RdxFormUiControlBase implements Contro
227
231
  registerOnTouched(fn: () => void): void;
228
232
  setDisabledState(isDisabled: boolean): void;
229
233
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxAutocompleteRoot, never>;
230
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxAutocompleteRoot, "[rdxAutocompleteRoot]", ["rdxAutocompleteRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "defaultValue": { "alias": "defaultValue"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "defaultOpen": { "alias": "defaultOpen"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "loopFocus": { "alias": "loopFocus"; "required": false; "isSignal": true; }; "autoHighlight": { "alias": "autoHighlight"; "required": false; "isSignal": true; }; "highlightItemOnHover": { "alias": "highlightItemOnHover"; "required": false; "isSignal": true; }; "keepHighlight": { "alias": "keepHighlight"; "required": false; "isSignal": true; }; "openOnInputClick": { "alias": "openOnInputClick"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "submitOnItemClick": { "alias": "submitOnItemClick"; "required": false; "isSignal": true; }; "grid": { "alias": "grid"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "virtualized": { "alias": "virtualized"; "required": false; "isSignal": true; }; "isItemEqualToValue": { "alias": "isItemEqualToValue"; "required": false; "isSignal": true; }; "itemToStringValue": { "alias": "itemToStringValue"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "open": "openChange"; "onValueChange": "onValueChange"; "onOpenChange": "onOpenChange"; "onItemHighlighted": "onItemHighlighted"; "onOpenChangeComplete": "onOpenChangeComplete"; }, never, never, true, [{ directive: typeof i1.RdxPopper; inputs: {}; outputs: {}; }]>;
234
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxAutocompleteRoot, "[rdxAutocompleteRoot]", ["rdxAutocompleteRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "defaultValue": { "alias": "defaultValue"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "defaultOpen": { "alias": "defaultOpen"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "loopFocus": { "alias": "loopFocus"; "required": false; "isSignal": true; }; "autoHighlight": { "alias": "autoHighlight"; "required": false; "isSignal": true; }; "highlightItemOnHover": { "alias": "highlightItemOnHover"; "required": false; "isSignal": true; }; "keepHighlight": { "alias": "keepHighlight"; "required": false; "isSignal": true; }; "openOnInputClick": { "alias": "openOnInputClick"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "submitOnItemClick": { "alias": "submitOnItemClick"; "required": false; "isSignal": true; }; "grid": { "alias": "grid"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "virtualized": { "alias": "virtualized"; "required": false; "isSignal": true; }; "isItemEqualToValue": { "alias": "isItemEqualToValue"; "required": false; "isSignal": true; }; "itemToStringValue": { "alias": "itemToStringValue"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "open": "openChange"; "onValueChange": "onValueChange"; "onOpenChange": "onOpenChange"; "onItemHighlighted": "onItemHighlighted"; "onOpenChangeComplete": "onOpenChangeComplete"; }, never, never, true, [{ directive: typeof i1.RdxPopper; inputs: {}; outputs: {}; }]>;
231
235
  }
232
236
 
233
237
  /**
@@ -270,7 +274,6 @@ declare class RdxAutocompleteInput {
270
274
  /** Marks the input as invalid independently of any Field state. */
271
275
  readonly invalid: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
272
276
  protected readonly ariaAutocomplete: _angular_core.Signal<_radix_ng_primitives_autocomplete.AutocompleteMode>;
273
- protected readonly invalidState: _angular_core.Signal<boolean>;
274
277
  /**
275
278
  * Tri-state *displayed* validity: the enclosing Field's gated `validState` when inside a `rdxFieldRoot`
276
279
  * (so a field whose `validationMode` defers display (e.g. `onBlur`) keeps the input neutral until revealed), else the input's
@@ -595,6 +598,8 @@ declare class RdxAutocompleteEmpty {
595
598
  readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
596
599
  requiredState: _angular_core.Signal<boolean>;
597
600
  invalidState: _angular_core.Signal<boolean>;
601
+ pendingState: _angular_core.Signal<boolean>;
602
+ validState: _angular_core.Signal<boolean | null>;
598
603
  touchedState: _angular_core.Signal<boolean>;
599
604
  dirtyState: _angular_core.Signal<boolean>;
600
605
  openOnInputClick: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -64,6 +64,7 @@ declare const provideCheckboxRootContext: (useFactory: () => CheckboxRootContext
64
64
  */
65
65
  declare class RdxCheckboxRootDirective implements RdxFormCheckboxControl {
66
66
  private readonly controlValueAccessor;
67
+ private readonly ngControlState;
67
68
  private readonly elementRef;
68
69
  private readonly renderer;
69
70
  private uncheckedInputElement;
@@ -131,6 +132,8 @@ declare class RdxCheckboxRootDirective implements RdxFormCheckboxControl {
131
132
  * @group Props
132
133
  */
133
134
  readonly invalid: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
135
+ /** Whether async validation is pending. Pending checkboxes publish neither valid nor invalid state. */
136
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
134
137
  /**
135
138
  * Whether the checkbox has been touched. A `model()` so Signal Forms can write it; the checkbox
136
139
  * also sets it on toggle (and emits {@link touch}).
@@ -191,8 +194,12 @@ declare class RdxCheckboxRootDirective implements RdxFormCheckboxControl {
191
194
  readonly disabledState: Signal<boolean>;
192
195
  readonly readOnlyState: Signal<boolean>;
193
196
  private readonly dirtyValue;
197
+ /** Validation errors from the checkbox input and a same-host Reactive/template-driven form control. */
198
+ readonly validationErrors: Signal<readonly RdxValidationError[]>;
194
199
  /** @ignore Invalid when the `invalid` input is set or the `errors` list is non-empty. */
195
200
  readonly invalidState: Signal<boolean>;
201
+ /** @ignore Whether explicit or Angular-owned async validation is pending. */
202
+ readonly pendingState: Signal<boolean>;
196
203
  /** Tri-state display validity exposed by an enclosing Field; absent when standalone. */
197
204
  private readonly fieldValidity;
198
205
  /**
@@ -209,13 +216,15 @@ declare class RdxCheckboxRootDirective implements RdxFormCheckboxControl {
209
216
  readonly state: Signal<"indeterminate" | "checked" | "unchecked">;
210
217
  constructor();
211
218
  toggle(event?: Event): void;
219
+ /** Reset control-owned interaction state; Angular Signal Forms calls this from `FieldState.reset()`. */
220
+ reset(): void;
212
221
  private syncUncheckedInput;
213
222
  private ensureUncheckedInput;
214
223
  private removeUncheckedInput;
215
224
  private setOptionalAttribute;
216
225
  private setBooleanAttribute;
217
226
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxCheckboxRootDirective, never>;
218
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxCheckboxRootDirective, "[rdxCheckboxRoot]", never, { "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "defaultChecked": { "alias": "defaultChecked"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "submitValue": { "alias": "value"; "required": false; "isSignal": true; }; "uncheckedValue": { "alias": "uncheckedValue"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "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; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "parent": { "alias": "parent"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "indeterminate": "indeterminateChange"; "touched": "touchedChange"; "onCheckedChange": "onCheckedChange"; "touch": "touch"; }, never, never, true, [{ directive: typeof _radix_ng_primitives_core.RdxControlValueAccessor; inputs: { "value": "checked"; "disabled": "disabled"; }; outputs: {}; }]>;
227
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxCheckboxRootDirective, "[rdxCheckboxRoot]", never, { "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "defaultChecked": { "alias": "defaultChecked"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "submitValue": { "alias": "value"; "required": false; "isSignal": true; }; "uncheckedValue": { "alias": "uncheckedValue"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "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; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "parent": { "alias": "parent"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "indeterminate": "indeterminateChange"; "touched": "touchedChange"; "onCheckedChange": "onCheckedChange"; "touch": "touch"; }, never, never, true, [{ directive: typeof _radix_ng_primitives_core.RdxControlValueAccessor; inputs: { "value": "checked"; "disabled": "disabled"; }; outputs: {}; }]>;
219
228
  }
220
229
 
221
230
  type RdxCheckboxGroupValueChangeReason = 'none';