@radix-ng/primitives 1.0.10 → 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 (50) hide show
  1. package/README.md +26 -5
  2. package/fesm2022/radix-ng-primitives-autocomplete.mjs +24 -16
  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 +35 -18
  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 +181 -21
  11. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-date-field.mjs +11 -5
  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-form.mjs +35 -4
  17. package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-input.mjs +87 -15
  19. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-menu.mjs +34 -7
  21. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-popper.mjs +80 -11
  23. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-scroll-area.mjs +6 -3
  25. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-select.mjs +36 -12
  27. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-signal-forms.mjs +27 -11
  29. package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-time-field.mjs +12 -6
  31. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  32. package/package.json +8 -3
  33. package/types/radix-ng-primitives-autocomplete.d.ts +7 -2
  34. package/types/radix-ng-primitives-checkbox.d.ts +10 -1
  35. package/types/radix-ng-primitives-combobox.d.ts +29 -2
  36. package/types/radix-ng-primitives-composite.d.ts +48 -2
  37. package/types/radix-ng-primitives-core.d.ts +152 -94
  38. package/types/radix-ng-primitives-date-field.d.ts +7 -4
  39. package/types/radix-ng-primitives-field.d.ts +55 -8
  40. package/types/radix-ng-primitives-form.d.ts +9 -0
  41. package/types/radix-ng-primitives-input.d.ts +10 -2
  42. package/types/radix-ng-primitives-menu.d.ts +45 -4
  43. package/types/radix-ng-primitives-navigation-menu.d.ts +2 -2
  44. package/types/radix-ng-primitives-popover.d.ts +2 -2
  45. package/types/radix-ng-primitives-popper.d.ts +60 -15
  46. package/types/radix-ng-primitives-preview-card.d.ts +2 -2
  47. package/types/radix-ng-primitives-select.d.ts +17 -3
  48. package/types/radix-ng-primitives-signal-forms.d.ts +22 -8
  49. package/types/radix-ng-primitives-time-field.d.ts +9 -6
  50. package/types/radix-ng-primitives-tooltip.d.ts +2 -2
@@ -162,13 +162,19 @@ class RdxDateFieldRootDirective extends RdxFormUiControlBase {
162
162
  markAsTouched() {
163
163
  this.formUi.markAsTouched();
164
164
  }
165
+ /** Reset segment interaction so the form-owned value write remains pristine. */
166
+ reset() {
167
+ this.userInteracted.set(false);
168
+ super.reset();
169
+ }
165
170
  constructor() {
166
171
  super();
167
172
  /**
168
- * The controlled value of the date field.
173
+ * The controlled value of the date field. `null` represents an empty field and keeps the value
174
+ * addressable as an Angular Signal Forms child field (`undefined` denotes an absent optional path).
169
175
  */
170
- this.value = model(/* @ts-ignore */
171
- ...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
176
+ this.value = model(null, /* @ts-ignore */
177
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
172
178
  /**
173
179
  * A matcher that marks specific dates as unavailable; a matched value makes the field invalid.
174
180
  */
@@ -233,7 +239,7 @@ class RdxDateFieldRootDirective extends RdxFormUiControlBase {
233
239
  this.defaultDate = computed(() => getDefaultDate({
234
240
  defaultPlaceholder: undefined,
235
241
  granularity: this.granularity(),
236
- defaultValue: this.value(),
242
+ defaultValue: this.value() ?? undefined,
237
243
  locale: this.locale()
238
244
  }), /* @ts-ignore */
239
245
  ...(ngDevMode ? [{ debugName: "defaultDate" }] : /* istanbul ignore next */ []));
@@ -323,7 +329,7 @@ class RdxDateFieldRootDirective extends RdxFormUiControlBase {
323
329
  * else the date-field's own (parse + form) invalidity. Overrides the base (whose default uses only
324
330
  * `formUi.invalidState`) so the standalone path keeps the built-in range/availability check.
325
331
  */
326
- this.displayValid = computed(() => resolveDisplayValid(this.fieldValidity, this.invalidState), /* @ts-ignore */
332
+ this.displayValid = computed(() => resolveDisplayValid(this.fieldValidity, this.invalidState, this.formUi.pendingState), /* @ts-ignore */
327
333
  ...(ngDevMode ? [{ debugName: "displayValid" }] : /* istanbul ignore next */ []));
328
334
  /** @ignore */
329
335
  this.touchedState = this.formUi.touchedState;
@@ -1 +1 @@
1
- {"version":3,"file":"radix-ng-primitives-date-field.mjs","sources":["../../../packages/primitives/date-field/src/date-field-context.token.ts","../../../packages/primitives/date-field/src/date-field-input.directive.ts","../../../packages/primitives/date-field/src/date-field-root.directive.ts","../../../packages/primitives/date-field/index.ts","../../../packages/primitives/date-field/radix-ng-primitives-date-field.ts"],"sourcesContent":["import { inject, InjectionToken, InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';\nimport { DateValue } from '@internationalized/date';\nimport { DateStep, Formatter, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';\n\nexport interface DateFieldContextToken {\n locale: InputSignal<string>;\n value: ModelSignal<DateValue | undefined>;\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 isInvalid: Signal<boolean>;\n /** Effective invalid: the built-in range/availability 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 /** The controlled placeholder; may be `undefined`. Use `effectivePlaceholder` for segment math. */\n placeholder: Signal<DateValue | undefined>;\n /** Always-defined placeholder (falls back to the default date) for segment attributes/key handlers. */\n effectivePlaceholder: Signal<DateValue>;\n hourCycle: Signal<HourCycle | undefined>;\n step$: Signal<DateStep>;\n formatter: Signal<Formatter>;\n segmentValues: WritableSignal<SegmentValueObj>;\n focusNext: () => void;\n setFocusedElement: (el: HTMLElement) => void;\n}\n\nexport const DATE_FIELDS_ROOT_CONTEXT = new InjectionToken<DateFieldContextToken>('DATE_FIELDS_ROOT_CONTEXT');\n\nexport function injectDateFieldsRootContext(): DateFieldContextToken {\n return inject(DATE_FIELDS_ROOT_CONTEXT);\n}\n","import { computed, Directive, effect, ElementRef, inject, input, signal } from '@angular/core';\nimport { isNullish, SegmentPart, useDateField } from '@radix-ng/primitives/core';\nimport { injectDateFieldsRootContext } from './date-field-context.token';\n\n/**\n * Attribute keys produced by `useDateField().attributes()` that are instead owned by host\n * bindings. Writing them imperatively would clobber the host value — re-enabling a disabled\n * segment via `contenteditable`, or overwriting a consumer's inline `style`.\n */\nconst hostManagedAttrs = new Set(['contenteditable', 'style']);\n\n@Directive({\n selector: '[rdxDateFieldInput]',\n host: {\n '[attr.contenteditable]': 'disabled() || readonly() ? false : part() !== \"literal\"',\n '[style.caret-color]': 'part() !== \"literal\" ? \"transparent\" : undefined',\n '[attr.data-rdx-date-field-segment]': 'part()',\n '[attr.aria-disabled]': 'disabled() ? \"true\" : 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 RdxDateFieldInputDirective {\n private readonly elementRef = 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.elementRef.nativeElement;\n\n private readonly rootContext = injectDateFieldsRootContext();\n\n /**\n * The part of the date to render\n * `'day' | 'month' | 'year' | '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.effectivePlaceholder,\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 step: this.rootContext.step$,\n modelValue: this.rootContext.value,\n focusNext: this.rootContext.focusNext\n });\n });\n\n private readonly attributes = computed(() => this.fieldData().attributes());\n\n /**\n * Attribute keys applied imperatively on the previous effect run, so keys that\n * disappear from `attributes()` are removed instead of lingering as stale state.\n * @ignore\n */\n private appliedAttrs = new Set<string>();\n\n constructor() {\n effect(() => {\n const element = this.elementRef.nativeElement as HTMLElement;\n const attrs = this.attributes();\n const next = new Set<string>();\n\n for (const [attr, value] of Object.entries(attrs)) {\n // Skip keys a host binding already owns, so this effect never fights it.\n if (hostManagedAttrs.has(attr)) {\n continue;\n }\n\n // A nullish value means the attribute should be absent (e.g. `data-placeholder`\n // once a segment is filled); removing it avoids a literal `\"undefined\"` string.\n if (isNullish(value)) {\n element.removeAttribute(attr);\n } else {\n element.setAttribute(attr, String(value));\n next.add(attr);\n }\n }\n\n for (const attr of this.appliedAttrs) {\n if (!next.has(attr)) {\n element.removeAttribute(attr);\n }\n }\n\n this.appliedAttrs = next;\n });\n }\n\n /**\n * @ignore\n */\n handleSegmentClick(event: Event) {\n this.fieldData().handleSegmentClick(event as MouseEvent);\n }\n\n /**\n * @ignore\n */\n handleSegmentKeydown(event: Event) {\n this.fieldData().handleSegmentKeydown(event as KeyboardEvent);\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 } from '@internationalized/date';\nimport {\n ARROW_LEFT,\n ARROW_RIGHT,\n BooleanInput,\n createContent,\n createFormatter,\n DateMatcher,\n DateStep,\n Direction,\n Formatter,\n getDefaultDate,\n Granularity,\n hasTime,\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 watch\n} from '@radix-ng/primitives/core';\nimport { injectDirection } from '@radix-ng/primitives/direction-provider';\nimport { DATE_FIELDS_ROOT_CONTEXT } from './date-field-context.token';\nimport { RdxDateFieldInputDirective } from './date-field-input.directive';\n\n@Directive({\n selector: '[rdxDateFieldRoot]',\n exportAs: 'rdxDateFieldRoot',\n providers: [provideExistingToken(DATE_FIELDS_ROOT_CONTEXT, RdxDateFieldRootDirective)],\n host: {\n role: 'group',\n '[attr.aria-disabled]': 'disabled() ? \"true\" : 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 RdxDateFieldRootDirective\n extends RdxFormUiControlBase\n implements RdxFormValueControl<DateValue | undefined>\n{\n /**\n * The controlled value of the date field.\n */\n readonly value = model<DateValue | undefined>();\n\n /**\n * A matcher that marks specific dates as unavailable; a matched value makes the field invalid.\n */\n readonly isDateUnavailable = input<DateMatcher | undefined>(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<DateValue>();\n\n /**\n * The maximum valid date that can be entered.\n */\n readonly maxValue = input<DateValue>();\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 getDefaultDate({\n defaultPlaceholder: undefined,\n granularity: this.granularity(),\n defaultValue: this.value(),\n locale: this.locale()\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<DateValue | 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 date so segment attributes and key handlers never\n * dereference `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(RdxDateFieldInputDirective);\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(() => {\n // Use the always-defined placeholder: a controlled `[placeholder]` reset to `undefined` while\n // `value` is a date-time must still infer 'minute' (from the default's shape), not drop to 'day'.\n const placeholder = this.effectivePlaceholder();\n\n if (this.granularity()) return !hasTime(placeholder) ? 'day' : this.granularity();\n\n return hasTime(placeholder) ? 'minute' : 'day';\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: DateValue | undefined; granularity: Granularity; formatter: Formatter },\n SegmentValueObj\n >({\n source: () => ({\n value: this.value(),\n granularity: <Granularity>this.inferredGranularity(),\n formatter: this.formatter()\n }),\n computation: ({ value, granularity, formatter }) =>\n value ? { ...syncSegmentValues({ value, formatter }) } : { ...initializeSegmentValues(granularity) }\n });\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => {\n if (!this.value()) return false;\n\n if (this.isDateUnavailable()?.(<DateValue>this.value())) return true;\n\n if (this.minValue() && isBefore(<DateValue>this.value(), <DateValue>this.minValue())) return true;\n\n if (this.maxValue() && isBefore(<DateValue>this.maxValue(), <DateValue>this.value())) return true;\n\n return false;\n });\n\n /**\n * @ignore Effective invalid: the built-in range/availability check OR the form-driven\n * `invalid` / `errors` (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 date-field's own (parse + form) invalidity. Overrides the base (whose default uses only\n * `formUi.invalidState`) so the standalone path keeps the built-in range/availability check.\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: <Granularity>this.inferredGranularity(),\n dateRef: this.effectivePlaceholder(),\n formatter: this.formatter(),\n hideTimeZone: this.hideTimeZone(),\n hourCycle: this.hourCycle(),\n segmentValues: this.segmentValues(),\n locale: this.locale\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.value], ([modelValue]) => {\n if (!isNullish(modelValue) && this.placeholder()?.compare(modelValue) !== 0) {\n this.placeholder.set(modelValue.copy());\n }\n });\n\n // The placeholder is seeded once at construction, before `locale` binds. When the locale\n // selects a different calendar system (e.g. Buddhist, Japanese) and the field is still\n // empty, re-seed it so segments and `getDaysInMonth` use that calendar.\n watch([this.locale], () => {\n if (!isNullish(this.value())) return;\n const next = this.defaultDate();\n if (this.placeholder()?.calendar.identifier !== next.calendar.identifier) {\n this.placeholder.set(next.copy());\n }\n });\n }\n\n /**\n * @ignore\n */\n onKeydown(event: Event) {\n const keyEvent = event as KeyboardEvent;\n const code = keyEvent.code;\n if ([ARROW_LEFT, ARROW_RIGHT].includes(code)) {\n if (!isSegmentNavigationKey(keyEvent.key)) return;\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 /**\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 { RdxDateFieldInputDirective } from './src/date-field-input.directive';\nimport { RdxDateFieldRootDirective } from './src/date-field-root.directive';\n\nexport * from './src/date-field-context.token';\nexport * from './src/date-field-input.directive';\nexport * from './src/date-field-root.directive';\n\nconst _imports = [RdxDateFieldRootDirective, RdxDateFieldInputDirective];\n\n@NgModule({\n imports: [..._imports],\n exports: [..._imports]\n})\nexport class RdxDateFieldModule {}\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-date-field.mjs","sources":["../../../packages/primitives/date-field/src/date-field-context.token.ts","../../../packages/primitives/date-field/src/date-field-input.directive.ts","../../../packages/primitives/date-field/src/date-field-root.directive.ts","../../../packages/primitives/date-field/index.ts","../../../packages/primitives/date-field/radix-ng-primitives-date-field.ts"],"sourcesContent":["import { inject, InjectionToken, InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';\nimport { DateValue } from '@internationalized/date';\nimport { DateStep, Formatter, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';\n\nexport interface DateFieldContextToken {\n locale: InputSignal<string>;\n value: ModelSignal<DateValue | 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 isInvalid: Signal<boolean>;\n /** Effective invalid: the built-in range/availability 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 /** The controlled placeholder; may be `undefined`. Use `effectivePlaceholder` for segment math. */\n placeholder: Signal<DateValue | undefined>;\n /** Always-defined placeholder (falls back to the default date) for segment attributes/key handlers. */\n effectivePlaceholder: Signal<DateValue>;\n hourCycle: Signal<HourCycle | undefined>;\n step$: Signal<DateStep>;\n formatter: Signal<Formatter>;\n segmentValues: WritableSignal<SegmentValueObj>;\n focusNext: () => void;\n setFocusedElement: (el: HTMLElement) => void;\n}\n\nexport const DATE_FIELDS_ROOT_CONTEXT = new InjectionToken<DateFieldContextToken>('DATE_FIELDS_ROOT_CONTEXT');\n\nexport function injectDateFieldsRootContext(): DateFieldContextToken {\n return inject(DATE_FIELDS_ROOT_CONTEXT);\n}\n","import { computed, Directive, effect, ElementRef, inject, input, signal } from '@angular/core';\nimport { isNullish, SegmentPart, useDateField } from '@radix-ng/primitives/core';\nimport { injectDateFieldsRootContext } from './date-field-context.token';\n\n/**\n * Attribute keys produced by `useDateField().attributes()` that are instead owned by host\n * bindings. Writing them imperatively would clobber the host value — re-enabling a disabled\n * segment via `contenteditable`, or overwriting a consumer's inline `style`.\n */\nconst hostManagedAttrs = new Set(['contenteditable', 'style']);\n\n@Directive({\n selector: '[rdxDateFieldInput]',\n host: {\n '[attr.contenteditable]': 'disabled() || readonly() ? false : part() !== \"literal\"',\n '[style.caret-color]': 'part() !== \"literal\" ? \"transparent\" : undefined',\n '[attr.data-rdx-date-field-segment]': 'part()',\n '[attr.aria-disabled]': 'disabled() ? \"true\" : 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 RdxDateFieldInputDirective {\n private readonly elementRef = 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.elementRef.nativeElement;\n\n private readonly rootContext = injectDateFieldsRootContext();\n\n /**\n * The part of the date to render\n * `'day' | 'month' | 'year' | '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.effectivePlaceholder,\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 step: this.rootContext.step$,\n modelValue: this.rootContext.value,\n focusNext: this.rootContext.focusNext\n });\n });\n\n private readonly attributes = computed(() => this.fieldData().attributes());\n\n /**\n * Attribute keys applied imperatively on the previous effect run, so keys that\n * disappear from `attributes()` are removed instead of lingering as stale state.\n * @ignore\n */\n private appliedAttrs = new Set<string>();\n\n constructor() {\n effect(() => {\n const element = this.elementRef.nativeElement as HTMLElement;\n const attrs = this.attributes();\n const next = new Set<string>();\n\n for (const [attr, value] of Object.entries(attrs)) {\n // Skip keys a host binding already owns, so this effect never fights it.\n if (hostManagedAttrs.has(attr)) {\n continue;\n }\n\n // A nullish value means the attribute should be absent (e.g. `data-placeholder`\n // once a segment is filled); removing it avoids a literal `\"undefined\"` string.\n if (isNullish(value)) {\n element.removeAttribute(attr);\n } else {\n element.setAttribute(attr, String(value));\n next.add(attr);\n }\n }\n\n for (const attr of this.appliedAttrs) {\n if (!next.has(attr)) {\n element.removeAttribute(attr);\n }\n }\n\n this.appliedAttrs = next;\n });\n }\n\n /**\n * @ignore\n */\n handleSegmentClick(event: Event) {\n this.fieldData().handleSegmentClick(event as MouseEvent);\n }\n\n /**\n * @ignore\n */\n handleSegmentKeydown(event: Event) {\n this.fieldData().handleSegmentKeydown(event as KeyboardEvent);\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 } from '@internationalized/date';\nimport {\n ARROW_LEFT,\n ARROW_RIGHT,\n BooleanInput,\n createContent,\n createFormatter,\n DateMatcher,\n DateStep,\n Direction,\n Formatter,\n getDefaultDate,\n Granularity,\n hasTime,\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 watch\n} from '@radix-ng/primitives/core';\nimport { injectDirection } from '@radix-ng/primitives/direction-provider';\nimport { DATE_FIELDS_ROOT_CONTEXT } from './date-field-context.token';\nimport { RdxDateFieldInputDirective } from './date-field-input.directive';\n\n@Directive({\n selector: '[rdxDateFieldRoot]',\n exportAs: 'rdxDateFieldRoot',\n providers: [provideExistingToken(DATE_FIELDS_ROOT_CONTEXT, RdxDateFieldRootDirective)],\n host: {\n role: 'group',\n '[attr.aria-disabled]': 'disabled() ? \"true\" : 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 RdxDateFieldRootDirective extends RdxFormUiControlBase implements RdxFormValueControl<DateValue | null> {\n /**\n * The controlled value of the date field. `null` represents an empty field and keeps the value\n * addressable as an Angular Signal Forms child field (`undefined` denotes an absent optional path).\n */\n readonly value = model<DateValue | null>(null);\n\n /**\n * A matcher that marks specific dates as unavailable; a matched value makes the field invalid.\n */\n readonly isDateUnavailable = input<DateMatcher | undefined>(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<DateValue>();\n\n /**\n * The maximum valid date that can be entered.\n */\n readonly maxValue = input<DateValue>();\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 getDefaultDate({\n defaultPlaceholder: undefined,\n granularity: this.granularity(),\n defaultValue: this.value() ?? undefined,\n locale: this.locale()\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<DateValue | 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 date so segment attributes and key handlers never\n * dereference `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(RdxDateFieldInputDirective);\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(() => {\n // Use the always-defined placeholder: a controlled `[placeholder]` reset to `undefined` while\n // `value` is a date-time must still infer 'minute' (from the default's shape), not drop to 'day'.\n const placeholder = this.effectivePlaceholder();\n\n if (this.granularity()) return !hasTime(placeholder) ? 'day' : this.granularity();\n\n return hasTime(placeholder) ? 'minute' : 'day';\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: DateValue | null; granularity: Granularity; formatter: Formatter },\n SegmentValueObj\n >({\n source: () => ({\n value: this.value(),\n granularity: <Granularity>this.inferredGranularity(),\n formatter: this.formatter()\n }),\n computation: ({ value, granularity, formatter }) =>\n value ? { ...syncSegmentValues({ value, formatter }) } : { ...initializeSegmentValues(granularity) }\n });\n\n /**\n * @ignore\n */\n readonly isInvalid = computed(() => {\n if (!this.value()) return false;\n\n if (this.isDateUnavailable()?.(<DateValue>this.value())) return true;\n\n if (this.minValue() && isBefore(<DateValue>this.value(), <DateValue>this.minValue())) return true;\n\n if (this.maxValue() && isBefore(<DateValue>this.maxValue(), <DateValue>this.value())) return true;\n\n return false;\n });\n\n /**\n * @ignore Effective invalid: the built-in range/availability check OR the form-driven\n * `invalid` / `errors` (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 date-field's own (parse + form) invalidity. Overrides the base (whose default uses only\n * `formUi.invalidState`) so the standalone path keeps the built-in range/availability check.\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: <Granularity>this.inferredGranularity(),\n dateRef: this.effectivePlaceholder(),\n formatter: this.formatter(),\n hideTimeZone: this.hideTimeZone(),\n hourCycle: this.hourCycle(),\n segmentValues: this.segmentValues(),\n locale: this.locale\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.value], ([modelValue]) => {\n if (!isNullish(modelValue) && this.placeholder()?.compare(modelValue) !== 0) {\n this.placeholder.set(modelValue.copy());\n }\n });\n\n // The placeholder is seeded once at construction, before `locale` binds. When the locale\n // selects a different calendar system (e.g. Buddhist, Japanese) and the field is still\n // empty, re-seed it so segments and `getDaysInMonth` use that calendar.\n watch([this.locale], () => {\n if (!isNullish(this.value())) return;\n const next = this.defaultDate();\n if (this.placeholder()?.calendar.identifier !== next.calendar.identifier) {\n this.placeholder.set(next.copy());\n }\n });\n }\n\n /**\n * @ignore\n */\n onKeydown(event: Event) {\n const keyEvent = event as KeyboardEvent;\n const code = keyEvent.code;\n if ([ARROW_LEFT, ARROW_RIGHT].includes(code)) {\n if (!isSegmentNavigationKey(keyEvent.key)) return;\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 /**\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 { RdxDateFieldInputDirective } from './src/date-field-input.directive';\nimport { RdxDateFieldRootDirective } from './src/date-field-root.directive';\n\nexport * from './src/date-field-context.token';\nexport * from './src/date-field-input.directive';\nexport * from './src/date-field-root.directive';\n\nconst _imports = [RdxDateFieldRootDirective, RdxDateFieldInputDirective];\n\n@NgModule({\n imports: [..._imports],\n exports: [..._imports]\n})\nexport class RdxDateFieldModule {}\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
- import { input, booleanAttribute, signal, computed, inject, ElementRef, DestroyRef, Directive, effect, afterNextRender } from '@angular/core';
3
- import { createContext, injectId, RDX_DEFAULT_VALIDATION_MODE, isValidationRevealed, RDX_FIELD_VALIDITY, rdxCheckLabelElement } from '@radix-ng/primitives/core';
2
+ import { input, booleanAttribute, signal, computed, inject, ElementRef, DestroyRef, Directive, effect, afterNextRender, untracked } from '@angular/core';
3
+ import { createContext, injectId, RDX_DEFAULT_VALIDATION_MODE, isValidationRevealed, RDX_FIELD_VALIDITY, rdxCheckLabelElement, injectNgControlState } from '@radix-ng/primitives/core';
4
4
  import { injectFormRootContext } from '@radix-ng/primitives/form';
5
5
 
6
6
  const attr$5 = (value) => (value ? '' : undefined);
@@ -10,12 +10,13 @@ const fieldRootContext = () => {
10
10
  const root = injectFieldRoot();
11
11
  return {
12
12
  controlId: root.controlId,
13
- name: root.name,
13
+ name: root.effectiveName,
14
14
  descriptionIds: root.descriptionIds,
15
15
  errorIds: root.errorIds,
16
16
  /** Combined messages for `RdxFieldError`: client (provider + form name-routing, when revealed) then
17
17
  * server (`errors` input, always). */
18
18
  messages: root.messages,
19
+ matchesError: (kind) => root.matchesError(kind),
19
20
  /** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
20
21
  notifyEdited: () => root.notifyEdited(),
21
22
  validState: root.validState,
@@ -54,6 +55,10 @@ const [injectFieldRootContext, provideFieldRootContext] = createContext('RdxFiel
54
55
  * @group Components
55
56
  */
56
57
  class RdxFieldRoot {
58
+ /** Whether a client validation error of `kind` is currently revealed by the field. */
59
+ matchesError(kind) {
60
+ return this.validationRevealed() && this.providerErrors().some((error) => error.kind === kind);
61
+ }
57
62
  constructor() {
58
63
  /**
59
64
  * Whether the field is invalid.
@@ -142,14 +147,17 @@ class RdxFieldRoot {
142
147
  /** Whether an external adapter currently owns field state. */
143
148
  this.hasStateProvider = computed(() => this.stateProvider() !== null, /* @ts-ignore */
144
149
  ...(ngDevMode ? [{ debugName: "hasStateProvider" }] : /* istanbul ignore next */ []));
150
+ /** Explicit field name wins; an adapter may infer one from its form-control binding. */
151
+ this.effectiveName = computed(() => this.name() ?? this.stateProvider()?.name?.(), /* @ts-ignore */
152
+ ...(ngDevMode ? [{ debugName: "effectiveName" }] : /* istanbul ignore next */ []));
145
153
  /** Error content from a registered state provider (e.g. a Signal Forms adapter). */
146
154
  this.providerErrors = computed(() => this.stateProvider()?.errors?.() ?? [], /* @ts-ignore */
147
155
  ...(ngDevMode ? [{ debugName: "providerErrors" }] : /* istanbul ignore next */ []));
148
156
  /** **Client** validation errors routed by a form-level provider (`rdxSignalForm`) — gated by `validationMode`. */
149
- this.clientErrors = computed(() => this.formContext?.clientErrorsFor(this.name()) ?? [], /* @ts-ignore */
157
+ this.clientErrors = computed(() => this.formContext?.clientErrorsFor(this.effectiveName()) ?? [], /* @ts-ignore */
150
158
  ...(ngDevMode ? [{ debugName: "clientErrors" }] : /* istanbul ignore next */ []));
151
159
  /** **Server/external** errors from the Form's `errors` input — shown eagerly (never gated). */
152
- this.serverErrors = computed(() => this.formContext?.externalErrorsFor(this.name()) ?? [], /* @ts-ignore */
160
+ this.serverErrors = computed(() => this.formContext?.externalErrorsFor(this.effectiveName()) ?? [], /* @ts-ignore */
153
161
  ...(ngDevMode ? [{ debugName: "serverErrors" }] : /* istanbul ignore next */ []));
154
162
  /** Whether the enclosing Form has had a submit attempted; `false` when standalone. A presentation
155
163
  * seam an adapter can read to reveal errors after a submit attempt (Base UI's submit-attempt state). */
@@ -208,6 +216,17 @@ class RdxFieldRoot {
208
216
  if (this.serverErrors().length > 0) {
209
217
  return false;
210
218
  }
219
+ // Angular Forms distinguishes pending from both valid and invalid. Preserve Base UI's
220
+ // tri-state presentation by publishing neither validity attribute while validation settles.
221
+ if (this.pendingState()) {
222
+ return null;
223
+ }
224
+ // A disabled Angular control does not participate in validation. Keep it neutral unless an
225
+ // explicit invalid/error source still marks it invalid (matching Base UI's controlled-invalid
226
+ // precedence over computed disabled validity).
227
+ if (this.disabledState() && !this.clientInvalidState()) {
228
+ return null;
229
+ }
211
230
  if (!this.validationRevealed()) {
212
231
  return null;
213
232
  }
@@ -230,6 +249,8 @@ class RdxFieldRoot {
230
249
  */
231
250
  this.actualInvalidState = computed(() => this.serverErrors().length > 0 || this.clientInvalidState(), /* @ts-ignore */
232
251
  ...(ngDevMode ? [{ debugName: "actualInvalidState" }] : /* istanbul ignore next */ []));
252
+ this.pendingState = computed(() => this.resolve('pending', () => false), /* @ts-ignore */
253
+ ...(ngDevMode ? [{ debugName: "pendingState" }] : /* istanbul ignore next */ []));
233
254
  this.disabledState = computed(() => this.resolve('disabled', () => this.disabled()), /* @ts-ignore */
234
255
  ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
235
256
  this.requiredState = computed(() => this.resolve('required', () => this.required()), /* @ts-ignore */
@@ -237,10 +258,10 @@ class RdxFieldRoot {
237
258
  // `touched`/`dirty` also OR in the enclosing Form's per-name state (`rdxSignalForm` name-routing), so a
238
259
  // field with only a bare `[formField]` (no `rdxSignalField`/`rdxFieldControl`) still reveals on blur.
239
260
  this.dirtyState = computed(() => this.resolve('dirty', () => this.dirty() || this.dirtyValue()) ||
240
- (this.formContext?.dirtyFor(this.name()) ?? false), /* @ts-ignore */
261
+ (this.formContext?.dirtyFor(this.effectiveName()) ?? false), /* @ts-ignore */
241
262
  ...(ngDevMode ? [{ debugName: "dirtyState" }] : /* istanbul ignore next */ []));
242
263
  this.touchedState = computed(() => this.resolve('touched', () => this.touched() || this.touchedValue()) ||
243
- (this.formContext?.touchedFor(this.name()) ?? false), /* @ts-ignore */
264
+ (this.formContext?.touchedFor(this.effectiveName()) ?? false), /* @ts-ignore */
244
265
  ...(ngDevMode ? [{ debugName: "touchedState" }] : /* istanbul ignore next */ []));
245
266
  this.filledState = computed(() => this.resolve('filled', () => this.filled() ?? this.filledValue()), /* @ts-ignore */
246
267
  ...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
@@ -253,7 +274,7 @@ class RdxFieldRoot {
253
274
  const formContext = this.formContext;
254
275
  if (formContext) {
255
276
  const registration = {
256
- name: () => this.name(),
277
+ name: () => this.effectiveName(),
257
278
  // `invalid` reports *actual* validity (ungated) — `form.anyInvalid` + the submit guard must
258
279
  // reflect real state even before a field reveals it. `displayValid` reports the *gated*
259
280
  // tri-state so the form's presentation `data-invalid` stays neutral on load.
@@ -270,7 +291,7 @@ class RdxFieldRoot {
270
291
  }
271
292
  /** Notify the enclosing Form (if any) that this field's control was edited (clear-on-edit). */
272
293
  notifyEdited() {
273
- this.formContext?.notifyEdited(this.name());
294
+ this.formContext?.notifyEdited(this.effectiveName());
274
295
  }
275
296
  /** Reset interaction state on native form reset: touched/dirty/focused → false, filled re-synced. */
276
297
  resetState() {
@@ -278,12 +299,20 @@ class RdxFieldRoot {
278
299
  this.dirtyValue.set(false);
279
300
  this.focusedValue.set(false);
280
301
  const control = this.controlElement();
281
- const value = control?.value ?? '';
302
+ const value = control && 'value' in control ? control.value : '';
282
303
  this.filledValue.set(value != null && value !== '');
283
304
  }
284
305
  /** Focus the field's control (used by the Form's first-invalid-focus on blocked submit). */
285
306
  focusControl() {
286
- this.controlElement()?.focus();
307
+ const control = this.controlElement();
308
+ if (!control) {
309
+ return;
310
+ }
311
+ control.focus();
312
+ // Base UI selects text after focusing an invalid input so the user can replace it immediately.
313
+ if (control.tagName === 'INPUT') {
314
+ control.select();
315
+ }
287
316
  }
288
317
  /**
289
318
  * The field's control element, found by `controlId` but scoped to this field's own subtree — a
@@ -314,8 +343,8 @@ class RdxFieldRoot {
314
343
  }
315
344
  /**
316
345
  * Prefer the registered provider's value for `key` when it exposes one,
317
- * otherwise fall back to the root inputs / DOM-derived signals. `errors` (content) and `valid`
318
- * (tri-state `boolean | null`) are resolved separately, so they're excluded from this boolean key.
346
+ * otherwise fall back to the root inputs / DOM-derived signals. `name` and `errors` are resolved
347
+ * separately, so they're excluded from this boolean key.
319
348
  */
320
349
  resolve(key, fallback) {
321
350
  const accessor = this.stateProvider()?.[key];
@@ -377,10 +406,7 @@ class RdxFieldControl {
377
406
  this.id = input(injectId('rdx-field-control-'), /* @ts-ignore */
378
407
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
379
408
  this.describedBy = computed(() => {
380
- const ids = [
381
- ...this.rootContext.descriptionIds(),
382
- ...(this.rootContext.invalidState() ? this.rootContext.errorIds() : [])
383
- ];
409
+ const ids = [...this.rootContext.descriptionIds(), ...this.rootContext.errorIds()];
384
410
  return ids.length ? ids.join(' ') : undefined;
385
411
  }, /* @ts-ignore */
386
412
  ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
@@ -504,6 +530,26 @@ class RdxFieldError {
504
530
  */
505
531
  this.id = input(injectId('rdx-field-error-'), /* @ts-ignore */
506
532
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
533
+ /**
534
+ * Shows this error only for a matching validation-error key. Bind `true` to keep it visible under
535
+ * external control; omit it for the field's default error behavior.
536
+ *
537
+ * @group Props
538
+ */
539
+ this.match = input(/* @ts-ignore */
540
+ ...(ngDevMode ? [undefined, { debugName: "match" }] : /* istanbul ignore next */ []));
541
+ /** Whether this error part is currently presented. */
542
+ this.visible = computed(() => {
543
+ const match = this.match();
544
+ if (match === true) {
545
+ return true;
546
+ }
547
+ if (typeof match === 'string') {
548
+ return this.rootContext.matchesError(match);
549
+ }
550
+ return this.rootContext.invalidState();
551
+ }, /* @ts-ignore */
552
+ ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
507
553
  /**
508
554
  * The field's validation messages — client (provider / form name-routing, once `validationMode`
509
555
  * reveals them) then server (the Form's `errors` input, always); `[]` when none. Render them
@@ -514,12 +560,15 @@ class RdxFieldError {
514
560
  this.dataAttr = attr$2;
515
561
  effect((onCleanup) => {
516
562
  const id = this.id();
563
+ if (!this.visible()) {
564
+ return;
565
+ }
517
566
  this.rootContext.addErrorId(id);
518
567
  onCleanup(() => this.rootContext.removeErrorId(id));
519
568
  });
520
569
  }
521
570
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldError, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
522
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldError, isStandalone: true, selector: "[rdxFieldError]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "id()", "attr.hidden": "rootContext.invalidState() ? undefined : \"\"", "attr.aria-live": "\"polite\"", "attr.data-invalid": "dataAttr(rootContext.invalidState())", "attr.data-disabled": "dataAttr(rootContext.disabledState())" } }, exportAs: ["rdxFieldError"], ngImport: i0 }); }
571
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFieldError, isStandalone: true, selector: "[rdxFieldError]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, match: { classPropertyName: "match", publicName: "match", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "id()", "attr.hidden": "visible() ? undefined : \"\"", "attr.aria-live": "\"polite\"", "attr.data-invalid": "dataAttr(visible() && rootContext.invalidState())", "attr.data-disabled": "dataAttr(rootContext.disabledState())" } }, exportAs: ["rdxFieldError"], ngImport: i0 }); }
523
572
  }
524
573
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFieldError, decorators: [{
525
574
  type: Directive,
@@ -528,13 +577,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
528
577
  exportAs: 'rdxFieldError',
529
578
  host: {
530
579
  '[attr.id]': 'id()',
531
- '[attr.hidden]': 'rootContext.invalidState() ? undefined : ""',
580
+ '[attr.hidden]': 'visible() ? undefined : ""',
532
581
  '[attr.aria-live]': '"polite"',
533
- '[attr.data-invalid]': 'dataAttr(rootContext.invalidState())',
582
+ '[attr.data-invalid]': 'dataAttr(visible() && rootContext.invalidState())',
534
583
  '[attr.data-disabled]': 'dataAttr(rootContext.disabledState())'
535
584
  }
536
585
  }]
537
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
586
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], match: [{ type: i0.Input, args: [{ isSignal: true, alias: "match", required: false }] }] } });
538
587
 
539
588
  const attr$1 = (value) => (value ? '' : undefined);
540
589
  const addId = (ids, id) => (ids.includes(id) ? ids : [...ids, id]);
@@ -552,10 +601,11 @@ const fieldItemContext = () => {
552
601
  const root = item.root;
553
602
  return {
554
603
  controlId: item.controlId,
555
- name: root.name,
604
+ name: root.effectiveName,
556
605
  descriptionIds: item.descriptionIds,
557
606
  errorIds: root.errorIds,
558
607
  messages: root.messages,
608
+ matchesError: (kind) => root.matchesError(kind),
559
609
  notifyEdited: () => root.notifyEdited(),
560
610
  validState: root.validState,
561
611
  formSubmitAttempted: root.formSubmitAttempted,
@@ -681,9 +731,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
681
731
  }]
682
732
  }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
683
733
 
734
+ /**
735
+ * Bridges a same-host Reactive Forms or template-driven `NgControl` into an enclosing `rdxFieldRoot`.
736
+ * Place it next to `formControl`, `formControlName`, or `ngModel`; Angular remains the source of value,
737
+ * validation, and interaction state while Field owns when that state is displayed.
738
+ *
739
+ * ```html
740
+ * <div rdxFieldRoot>
741
+ * <label rdxFieldLabel>Email</label>
742
+ * <input formControlName="email" rdxFieldControl rdxNgControlField />
743
+ * <p match="required" rdxFieldError>Email is required.</p>
744
+ * </div>
745
+ * ```
746
+ *
747
+ * The adapter also infers the Field name from `formControlName` / `ngModel` for Form-level server-error
748
+ * routing. An explicit `name` on `rdxFieldRoot` takes precedence (useful for nested or remapped keys).
749
+ *
750
+ * @group Components
751
+ */
752
+ class RdxNgControlField {
753
+ constructor() {
754
+ this.ngControlState = injectNgControlState();
755
+ this.fieldContext = injectFieldRootContext();
756
+ /** Normalized Angular validation errors (`{ kind, message? }[]`). */
757
+ this.validationErrors = this.ngControlState.errors;
758
+ effect((onCleanup) => {
759
+ if (!this.ngControlState.connected()) {
760
+ return;
761
+ }
762
+ const state = {
763
+ name: () => this.ngControlState.name(),
764
+ invalid: () => this.ngControlState.invalid(),
765
+ pending: () => this.ngControlState.pending(),
766
+ disabled: () => this.ngControlState.disabled(),
767
+ dirty: () => this.ngControlState.dirty(),
768
+ touched: () => this.ngControlState.touched(),
769
+ errors: () => this.ngControlState.errors()
770
+ };
771
+ // Registration reads the previous provider internally. Keep that bookkeeping outside
772
+ // this effect's dependency graph or replacing the provider would retrigger itself.
773
+ const previous = untracked(() => this.fieldContext.setStateProvider(state));
774
+ onCleanup(() => untracked(() => this.fieldContext.clearStateProvider(state, previous)));
775
+ }, { debugName: 'RdxNgControlField.connect' });
776
+ }
777
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxNgControlField, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
778
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: RdxNgControlField, isStandalone: true, selector: "[formControl][rdxNgControlField], [formControlName][rdxNgControlField], [ngModel][rdxNgControlField]", exportAs: ["rdxNgControlField"], ngImport: i0 }); }
779
+ }
780
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxNgControlField, decorators: [{
781
+ type: Directive,
782
+ args: [{
783
+ selector: '[formControl][rdxNgControlField], [formControlName][rdxNgControlField], [ngModel][rdxNgControlField]',
784
+ exportAs: 'rdxNgControlField'
785
+ }]
786
+ }], ctorParameters: () => [] });
787
+
684
788
  /**
685
789
  * Generated bundle index. Do not edit.
686
790
  */
687
791
 
688
- export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldItem, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
792
+ export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldItem, RdxFieldLabel, RdxFieldRoot, RdxNgControlField, injectFieldRootContext, provideFieldRootContext };
689
793
  //# sourceMappingURL=radix-ng-primitives-field.mjs.map