@radix-ng/primitives 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/fesm2022/radix-ng-primitives-autocomplete.mjs +43 -9
  2. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
  3. package/fesm2022/radix-ng-primitives-checkbox.mjs +89 -8
  4. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-combobox.mjs +43 -9
  6. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-core.mjs +208 -2
  8. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  9. package/fesm2022/radix-ng-primitives-date-field.mjs +50 -9
  10. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  11. package/fesm2022/radix-ng-primitives-editable.mjs +31 -5
  12. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-field.mjs +265 -46
  14. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-form.mjs +110 -26
  16. package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-input.mjs +16 -6
  18. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-number-field.mjs +32 -7
  20. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-radio.mjs +18 -4
  22. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-select.mjs +26 -8
  24. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-signal-forms.mjs +184 -0
  26. package/fesm2022/radix-ng-primitives-signal-forms.mjs.map +1 -0
  27. package/fesm2022/radix-ng-primitives-slider.mjs +24 -8
  28. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-switch.mjs +29 -5
  30. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  31. package/fesm2022/radix-ng-primitives-time-field.mjs +49 -9
  32. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  33. package/fesm2022/radix-ng-primitives-toggle-group.mjs +23 -12
  34. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  35. package/package.json +11 -1
  36. package/types/radix-ng-primitives-autocomplete.d.ts +21 -2
  37. package/types/radix-ng-primitives-checkbox.d.ts +53 -4
  38. package/types/radix-ng-primitives-combobox.d.ts +51 -2
  39. package/types/radix-ng-primitives-core.d.ts +206 -3
  40. package/types/radix-ng-primitives-date-field.d.ts +27 -2
  41. package/types/radix-ng-primitives-editable.d.ts +15 -2
  42. package/types/radix-ng-primitives-field.d.ts +136 -33
  43. package/types/radix-ng-primitives-form.d.ts +115 -21
  44. package/types/radix-ng-primitives-input.d.ts +8 -1
  45. package/types/radix-ng-primitives-number-field.d.ts +14 -3
  46. package/types/radix-ng-primitives-radio.d.ts +7 -2
  47. package/types/radix-ng-primitives-select.d.ts +11 -3
  48. package/types/radix-ng-primitives-signal-forms.d.ts +97 -0
  49. package/types/radix-ng-primitives-slider.d.ts +9 -7
  50. package/types/radix-ng-primitives-switch.d.ts +15 -2
  51. package/types/radix-ng-primitives-time-field.d.ts +26 -2
  52. package/types/radix-ng-primitives-toggle-group.d.ts +6 -4
@@ -4,7 +4,7 @@ import * as i1 from '@radix-ng/primitives/popper';
4
4
  import { RdxPopperAnchor, RdxPopperArrow, RdxPopper, RdxPopperContentWrapper, provideRdxPopperContentWrapper, provideRdxPopperContentConfig, injectPopperContentWrapperContext, RdxPopperContent } from '@radix-ng/primitives/popper';
5
5
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
6
  import * as i2 from '@radix-ng/primitives/core';
7
- import { useFilter, injectId, useListHighlight, useTransitionStatus, createContext, createFloatingRootContext, isItemEqualToValue, isNullish, createCancelableChangeEventDetails, itemToStringLabel, provideFloatingTree, provideFloatingRootContext, setupInternalBackdrop, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useAnchoredScrollLock, RdxFloatingNodeRegistration, rdxDevError } from '@radix-ng/primitives/core';
7
+ import { useFilter, injectId, useListHighlight, useTransitionStatus, createContext, RdxFormUiControlBase, createFloatingRootContext, isItemEqualToValue, isNullish, createCancelableChangeEventDetails, itemToStringLabel, provideFloatingTree, provideFloatingRootContext, setupInternalBackdrop, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useAnchoredScrollLock, RdxFloatingNodeRegistration, rdxDevError } from '@radix-ng/primitives/core';
8
8
  import { injectDirection } from '@radix-ng/primitives/direction-provider';
9
9
  import * as i1$1 from '@radix-ng/primitives/dismissable-layer';
10
10
  import { RdxFloatingInsideElement, RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
@@ -621,6 +621,9 @@ const context = () => {
621
621
  disabledState: root.disabledState,
622
622
  readonly: root.readOnly,
623
623
  requiredState: root.requiredState,
624
+ invalidState: root.invalidState,
625
+ touchedState: root.touchedState,
626
+ dirtyState: root.dirtyState,
624
627
  openOnInputClick: root.openOnInputClick,
625
628
  modal: root.modal,
626
629
  virtualized: root.virtualized,
@@ -699,7 +702,7 @@ function coerceAutoHighlight(value) {
699
702
  *
700
703
  * @group Components
701
704
  */
702
- class RdxComboboxRoot {
705
+ class RdxComboboxRoot extends RdxFormUiControlBase {
703
706
  /** The list element id referenced by `aria-controls` / `aria-activedescendant` (engine-backed). */
704
707
  get listId() {
705
708
  return this.engine.listId;
@@ -725,6 +728,7 @@ class RdxComboboxRoot {
725
728
  return this.engine.activeId;
726
729
  }
727
730
  constructor() {
731
+ super();
728
732
  this.injector = inject(Injector);
729
733
  /** Per-popup floating root context (ADR 0015) — `open` / `triggers` / reference for the dismissal engine. */
730
734
  this.floatingContext = createFloatingRootContext({
@@ -864,6 +868,12 @@ class RdxComboboxRoot {
864
868
  ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
865
869
  this.requiredState = computed(() => this.required(), /* @ts-ignore */
866
870
  ...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
871
+ /** @ignore */
872
+ this.invalidState = this.formUi.invalidState;
873
+ /** @ignore */
874
+ this.touchedState = this.formUi.touchedState;
875
+ /** @ignore */
876
+ this.dirtyState = this.formUi.dirtyState;
867
877
  this.preventUnmountOnClose = signal(false, /* @ts-ignore */
868
878
  ...(ngDevMode ? [{ debugName: "preventUnmountOnClose" }] : /* istanbul ignore next */ []));
869
879
  this.present = computed(() => this.open() || this.preventUnmountOnClose(), /* @ts-ignore */
@@ -1193,8 +1203,12 @@ class RdxComboboxRoot {
1193
1203
  focusLastChip() {
1194
1204
  return this.chipsFocusLast?.() ?? false;
1195
1205
  }
1206
+ /** @ignore Bridge the CVA `onTouched` so `markAsTouched()` also notifies Reactive/template forms. */
1207
+ formUiTouchTarget() {
1208
+ return { markAsTouched: () => this.onTouched?.() };
1209
+ }
1196
1210
  markAsTouched() {
1197
- this.onTouched?.();
1211
+ this.formUi.markAsTouched();
1198
1212
  }
1199
1213
  /**
1200
1214
  * The single guarded value-mutation point for all user-driven changes (selection toggle, Clear,
@@ -1211,6 +1225,7 @@ class RdxComboboxRoot {
1211
1225
  return false;
1212
1226
  }
1213
1227
  this.value.set(value);
1228
+ this.formUi.markDirty();
1214
1229
  this.onChange?.(value);
1215
1230
  return true;
1216
1231
  }
@@ -1255,7 +1270,7 @@ class RdxComboboxRoot {
1255
1270
  // New floating foundation (ADR 0015/0017) — the dismissal capability reads this shared context.
1256
1271
  provideFloatingTree(),
1257
1272
  provideFloatingRootContext(() => inject(RdxComboboxRoot).floatingContext)
1258
- ], exportAs: ["rdxComboboxRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
1273
+ ], exportAs: ["rdxComboboxRoot"], usesInheritance: true, hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
1259
1274
  }
1260
1275
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxComboboxRoot, decorators: [{
1261
1276
  type: Directive,
@@ -1746,12 +1761,27 @@ class RdxComboboxInput {
1746
1761
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
1747
1762
  /** Marks the input as invalid independently of any Field state. */
1748
1763
  this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1749
- this.invalidState = computed(() => this.invalid() || Boolean(this.fieldRootContext?.invalidState()), /* @ts-ignore */
1764
+ this.invalidState = computed(() => this.invalid() || this.rootContext.invalidState() || Boolean(this.fieldRootContext?.invalidState()), /* @ts-ignore */
1750
1765
  ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
1766
+ /**
1767
+ * Tri-state *displayed* validity: the enclosing Field's gated `validState` when inside a `rdxFieldRoot`
1768
+ * (so a field whose `validationMode` defers display (e.g. `onBlur`) keeps the input neutral until revealed), else the input's
1769
+ * own binary invalidity.
1770
+ */
1771
+ this.displayValid = computed(() => this.fieldRootContext
1772
+ ? this.fieldRootContext.validState()
1773
+ : this.invalid() || this.rootContext.invalidState()
1774
+ ? false
1775
+ : true, /* @ts-ignore */
1776
+ ...(ngDevMode ? [{ debugName: "displayValid" }] : /* istanbul ignore next */ []));
1751
1777
  this.disabledState = computed(() => this.rootContext.disabledState() || Boolean(this.fieldRootContext?.disabledState()), /* @ts-ignore */
1752
1778
  ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
1753
1779
  this.requiredState = computed(() => this.rootContext.requiredState() || Boolean(this.fieldRootContext?.requiredState()), /* @ts-ignore */
1754
1780
  ...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
1781
+ this.touchedState = computed(() => this.rootContext.touchedState() || Boolean(this.fieldRootContext?.touchedState()), /* @ts-ignore */
1782
+ ...(ngDevMode ? [{ debugName: "touchedState" }] : /* istanbul ignore next */ []));
1783
+ this.dirtyState = computed(() => this.rootContext.dirtyState() || Boolean(this.fieldRootContext?.dirtyState()), /* @ts-ignore */
1784
+ ...(ngDevMode ? [{ debugName: "dirtyState" }] : /* istanbul ignore next */ []));
1755
1785
  this.filledState = computed(() => !this.isEmptyValue() || Boolean(this.fieldRootContext?.filledState()), /* @ts-ignore */
1756
1786
  ...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
1757
1787
  this.focusedState = computed(() => Boolean(this.fieldRootContext?.focusedState()), /* @ts-ignore */
@@ -1830,6 +1860,8 @@ class RdxComboboxInput {
1830
1860
  onBlur() {
1831
1861
  this.fieldRootContext?.setFocused(false);
1832
1862
  this.fieldRootContext?.setTouched(true);
1863
+ // Notify Signal Forms (touched model + touch output) the control was touched.
1864
+ this.rootContext.markAsTouched();
1833
1865
  }
1834
1866
  onKeydown(event) {
1835
1867
  // Don't interfere with IME composition or text-editing shortcuts / range selection. Shift+Arrows
@@ -1946,7 +1978,7 @@ class RdxComboboxInput {
1946
1978
  }
1947
1979
  }
1948
1980
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxComboboxInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1949
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxComboboxInput, isStandalone: true, selector: "input[rdxComboboxInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "combobox", "autocomplete": "off", "aria-autocomplete": "list" }, listeners: { "input": "onInput($event)", "click": "onClick($event)", "focus": "onFocus()", "blur": "onBlur()", "keydown": "onKeydown($event)", "compositionstart": "composing = true", "compositionend": "onCompositionEnd($event)" }, properties: { "attr.id": "id()", "attr.aria-haspopup": "rootContext.grid() ? \"grid\" : \"listbox\"", "attr.aria-expanded": "rootContext.open()", "attr.aria-controls": "rootContext.listId", "attr.aria-labelledby": "rootContext.labelId()", "attr.aria-activedescendant": "rootContext.activeId()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "invalidState() ? \"true\" : undefined", "attr.aria-required": "requiredState() ? \"true\" : undefined", "attr.aria-disabled": "disabledState() ? \"true\" : undefined", "attr.disabled": "disabledState() ? \"\" : undefined", "attr.readonly": "rootContext.readonly() ? \"\" : undefined", "attr.required": "requiredState() ? \"\" : undefined", "value": "rootContext.inputValue()", "attr.data-popup-open": "dataAttr(rootContext.open())", "attr.data-list-empty": "dataAttr(rootContext.visibleCount() === 0)", "attr.data-placeholder": "dataAttr(isEmptyValue())", "attr.data-invalid": "dataAttr(invalidState())", "attr.data-valid": "dataAttr(!invalidState())", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())" } }, exportAs: ["rdxComboboxInput"], hostDirectives: [{ directive: i1.RdxPopperAnchor }, { directive: i1$1.RdxFloatingInsideElement }], ngImport: i0 }); }
1981
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxComboboxInput, isStandalone: true, selector: "input[rdxComboboxInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "combobox", "autocomplete": "off", "aria-autocomplete": "list" }, listeners: { "input": "onInput($event)", "click": "onClick($event)", "focus": "onFocus()", "blur": "onBlur()", "keydown": "onKeydown($event)", "compositionstart": "composing = true", "compositionend": "onCompositionEnd($event)" }, properties: { "attr.id": "id()", "attr.aria-haspopup": "rootContext.grid() ? \"grid\" : \"listbox\"", "attr.aria-expanded": "rootContext.open()", "attr.aria-controls": "rootContext.listId", "attr.aria-labelledby": "rootContext.labelId()", "attr.aria-activedescendant": "rootContext.activeId()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "displayValid() === false ? \"true\" : undefined", "attr.aria-required": "requiredState() ? \"true\" : undefined", "attr.aria-disabled": "disabledState() ? \"true\" : undefined", "attr.disabled": "disabledState() ? \"\" : undefined", "attr.readonly": "rootContext.readonly() ? \"\" : undefined", "attr.required": "requiredState() ? \"\" : undefined", "value": "rootContext.inputValue()", "attr.data-popup-open": "dataAttr(rootContext.open())", "attr.data-list-empty": "dataAttr(rootContext.visibleCount() === 0)", "attr.data-placeholder": "dataAttr(isEmptyValue())", "attr.data-invalid": "dataAttr(displayValid() === false)", "attr.data-valid": "dataAttr(displayValid() === true)", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-touched": "dataAttr(touchedState())", "attr.data-dirty": "dataAttr(dirtyState())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())" } }, exportAs: ["rdxComboboxInput"], hostDirectives: [{ directive: i1.RdxPopperAnchor }, { directive: i1$1.RdxFloatingInsideElement }], ngImport: i0 }); }
1950
1982
  }
1951
1983
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxComboboxInput, decorators: [{
1952
1984
  type: Directive,
@@ -1965,7 +1997,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
1965
1997
  '[attr.aria-labelledby]': 'rootContext.labelId()',
1966
1998
  '[attr.aria-activedescendant]': 'rootContext.activeId()',
1967
1999
  '[attr.aria-describedby]': 'describedBy()',
1968
- '[attr.aria-invalid]': 'invalidState() ? "true" : undefined',
2000
+ '[attr.aria-invalid]': 'displayValid() === false ? "true" : undefined',
1969
2001
  '[attr.aria-required]': 'requiredState() ? "true" : undefined',
1970
2002
  '[attr.aria-disabled]': 'disabledState() ? "true" : undefined',
1971
2003
  '[attr.disabled]': 'disabledState() ? "" : undefined',
@@ -1975,10 +2007,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
1975
2007
  '[attr.data-popup-open]': 'dataAttr(rootContext.open())',
1976
2008
  '[attr.data-list-empty]': 'dataAttr(rootContext.visibleCount() === 0)',
1977
2009
  '[attr.data-placeholder]': 'dataAttr(isEmptyValue())',
1978
- '[attr.data-invalid]': 'dataAttr(invalidState())',
1979
- '[attr.data-valid]': 'dataAttr(!invalidState())',
2010
+ '[attr.data-invalid]': 'dataAttr(displayValid() === false)',
2011
+ '[attr.data-valid]': 'dataAttr(displayValid() === true)',
1980
2012
  '[attr.data-disabled]': 'dataAttr(disabledState())',
1981
2013
  '[attr.data-required]': 'dataAttr(requiredState())',
2014
+ '[attr.data-touched]': 'dataAttr(touchedState())',
2015
+ '[attr.data-dirty]': 'dataAttr(dirtyState())',
1982
2016
  '[attr.data-filled]': 'dataAttr(filledState())',
1983
2017
  '[attr.data-focused]': 'dataAttr(focusedState())',
1984
2018
  '(input)': 'onInput($event)',