@radix-ng/primitives 1.0.0-beta.1 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/radix-ng-primitives-accordion.mjs +2 -2
- package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-calendar.mjs +14 -1
- package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +2 -2
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-collapsible.mjs +1 -1
- package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +1923 -0
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-context-menu.mjs +1 -1
- package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +480 -469
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-cropper.mjs +1 -1
- package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +11 -0
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-dialog.mjs +1 -1
- package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-drawer.mjs +1 -1
- package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +86 -6
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-fieldset.mjs +1 -1
- package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-focus-scope.mjs +1 -1
- package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-form.mjs +207 -0
- package/fesm2022/radix-ng-primitives-form.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-input.mjs +85 -4
- package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menu.mjs +4 -4
- package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menubar.mjs +1 -1
- package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-meter.mjs +1 -1
- package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs +1 -1
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +2 -2
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popover.mjs +1 -1
- package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-preview-card.mjs +1 -1
- package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-progress.mjs +1 -1
- package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-roving-focus.mjs +1 -1
- package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +3 -3
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +421 -224
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +3 -2
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +27 -3
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toast.mjs +1 -1
- package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toolbar.mjs +2 -2
- package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tooltip.mjs +2 -2
- package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
- package/package.json +9 -1
- package/schematics/ng-add/index.js +57 -0
- package/schematics/ng-add/index.js.map +1 -1
- package/schematics/ng-add/schema.d.ts +1 -0
- package/schematics/ng-add/schema.json +6 -0
- package/types/radix-ng-primitives-combobox.d.ts +1265 -0
- package/types/radix-ng-primitives-core.d.ts +148 -56
- package/types/radix-ng-primitives-field.d.ts +71 -2
- package/types/radix-ng-primitives-form.d.ts +124 -0
- package/types/radix-ng-primitives-input.d.ts +75 -5
- package/types/radix-ng-primitives-select.d.ts +292 -132
|
@@ -166,11 +166,13 @@ interface InjectContext<T> {
|
|
|
166
166
|
* Creates a context with injector and provider functions for a given type
|
|
167
167
|
* @template T The type of the context value
|
|
168
168
|
* @param description Descriptive string for the context (used in token creation)
|
|
169
|
+
* @param docs Documentation path for the owning primitive (e.g. `'components/accordion'`),
|
|
170
|
+
* appended to the missing-context error as a link to the required anatomy
|
|
169
171
|
* @returns A tuple containing:
|
|
170
172
|
* - injectContext: Function to retrieve the context value
|
|
171
173
|
* - provideContext: Function to create a provider for the context
|
|
172
174
|
*/
|
|
173
|
-
declare function createContext<T>(description: string): readonly [injectContext: InjectContext<T>, provideContext: (useFactory: () => T) => Provider];
|
|
175
|
+
declare function createContext<T>(description: string, docs?: string): readonly [injectContext: InjectContext<T>, provideContext: (useFactory: () => T) => Provider];
|
|
174
176
|
|
|
175
177
|
declare const DATE_SEGMENT_PARTS: readonly ["day", "month", "year"];
|
|
176
178
|
declare const TIME_SEGMENT_PARTS: readonly ["hour", "minute", "second", "dayPeriod"];
|
|
@@ -343,6 +345,12 @@ declare function areAllDaysBetweenValid(start: DateValue, end: DateValue, isUnav
|
|
|
343
345
|
type TimeValue = Time | CalendarDateTime | ZonedDateTime;
|
|
344
346
|
type Granularity = 'day' | 'hour' | 'minute' | 'second';
|
|
345
347
|
type TimeGranularity = 'hour' | 'minute' | 'second';
|
|
348
|
+
/**
|
|
349
|
+
* The granularities that require a time component (and therefore a `CalendarDateTime`
|
|
350
|
+
* rather than a `CalendarDate`). Single source of truth — used by both the default-date
|
|
351
|
+
* builder and the segment-value initializer.
|
|
352
|
+
*/
|
|
353
|
+
declare const TIME_GRANULARITIES: readonly Granularity[];
|
|
346
354
|
type GetDefaultDateProps = {
|
|
347
355
|
defaultValue?: DateValue | DateValue[] | undefined;
|
|
348
356
|
defaultPlaceholder?: DateValue | undefined;
|
|
@@ -405,7 +413,7 @@ type SyncTimeSegmentValuesProps = {
|
|
|
405
413
|
formatter: Formatter;
|
|
406
414
|
};
|
|
407
415
|
declare function syncTimeSegmentValues(props: SyncTimeSegmentValuesProps): SegmentValueObj;
|
|
408
|
-
declare function initializeSegmentValues(granularity: Granularity): SegmentValueObj;
|
|
416
|
+
declare function initializeSegmentValues(granularity: Granularity, isTimeValue?: boolean): SegmentValueObj;
|
|
409
417
|
type SharedContentProps = {
|
|
410
418
|
granularity: Granularity;
|
|
411
419
|
dateRef: DateValue;
|
|
@@ -462,54 +470,9 @@ type SegmentAttrProps = {
|
|
|
462
470
|
placeholder: DateValue;
|
|
463
471
|
formatter: Formatter;
|
|
464
472
|
};
|
|
465
|
-
declare function daySegmentAttrs(props: SegmentAttrProps): {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
'aria-valuemax': number;
|
|
469
|
-
'aria-valuenow': number;
|
|
470
|
-
'aria-valuetext': string;
|
|
471
|
-
'data-placeholder': string | undefined;
|
|
472
|
-
role: string;
|
|
473
|
-
contenteditable: boolean;
|
|
474
|
-
tabindex: number | undefined;
|
|
475
|
-
spellcheck: boolean;
|
|
476
|
-
inputmode: string;
|
|
477
|
-
autocorrect: string;
|
|
478
|
-
enterkeyhint: string;
|
|
479
|
-
style: string;
|
|
480
|
-
};
|
|
481
|
-
declare function monthSegmentAttrs(props: SegmentAttrProps): {
|
|
482
|
-
'aria-label': string;
|
|
483
|
-
contenteditable: boolean;
|
|
484
|
-
'aria-valuemin': number;
|
|
485
|
-
'aria-valuemax': number;
|
|
486
|
-
'aria-valuenow': number;
|
|
487
|
-
'aria-valuetext': string;
|
|
488
|
-
'data-placeholder': string | undefined;
|
|
489
|
-
role: string;
|
|
490
|
-
tabindex: number | undefined;
|
|
491
|
-
spellcheck: boolean;
|
|
492
|
-
inputmode: string;
|
|
493
|
-
autocorrect: string;
|
|
494
|
-
enterkeyhint: string;
|
|
495
|
-
style: string;
|
|
496
|
-
};
|
|
497
|
-
declare function yearSegmentAttrs(props: SegmentAttrProps): {
|
|
498
|
-
'aria-label': string;
|
|
499
|
-
'aria-valuemin': number;
|
|
500
|
-
'aria-valuemax': number;
|
|
501
|
-
'aria-valuenow': number;
|
|
502
|
-
'aria-valuetext': string;
|
|
503
|
-
'data-placeholder': string | undefined;
|
|
504
|
-
role: string;
|
|
505
|
-
contenteditable: boolean;
|
|
506
|
-
tabindex: number | undefined;
|
|
507
|
-
spellcheck: boolean;
|
|
508
|
-
inputmode: string;
|
|
509
|
-
autocorrect: string;
|
|
510
|
-
enterkeyhint: string;
|
|
511
|
-
style: string;
|
|
512
|
-
};
|
|
473
|
+
declare function daySegmentAttrs(props: SegmentAttrProps): {};
|
|
474
|
+
declare function monthSegmentAttrs(props: SegmentAttrProps): {};
|
|
475
|
+
declare function yearSegmentAttrs(props: SegmentAttrProps): {};
|
|
513
476
|
declare function hourSegmentAttrs(props: SegmentAttrProps): {};
|
|
514
477
|
declare function minuteSegmentAttrs(props: SegmentAttrProps): {};
|
|
515
478
|
declare function secondSegmentAttrs(props: SegmentAttrProps): {};
|
|
@@ -616,6 +579,36 @@ declare class RdxIdGenerator {
|
|
|
616
579
|
*/
|
|
617
580
|
declare function injectId(prefix: string): string;
|
|
618
581
|
|
|
582
|
+
/**
|
|
583
|
+
* A comparator for list-item values, aligned with Base UI's `isItemEqualToValue` naming.
|
|
584
|
+
*
|
|
585
|
+
* - a **function** `(a, b) => boolean` — full control over equality;
|
|
586
|
+
* - a **string** — an object key whose values are compared with {@link isEqual} (Reka-style `by`);
|
|
587
|
+
* - omitted — structural deep equality via {@link isEqual}.
|
|
588
|
+
*/
|
|
589
|
+
type ItemValueComparator<T = unknown> = ((a: T, b: T) => boolean) | string;
|
|
590
|
+
/**
|
|
591
|
+
* Converts an item value to the string shown to the user.
|
|
592
|
+
*
|
|
593
|
+
* Strings pass through unchanged; `null`/`undefined` become an empty string; everything else is
|
|
594
|
+
* coerced with `String()`. Primitives that hold object values (e.g. combobox) typically pass their
|
|
595
|
+
* own `itemToStringLabel` to render a field off the object instead.
|
|
596
|
+
*/
|
|
597
|
+
declare function itemToStringLabel(value: unknown): string;
|
|
598
|
+
/**
|
|
599
|
+
* Converts an item value to the string used for form serialization. Defaults to the same rules as
|
|
600
|
+
* {@link itemToStringLabel}; kept as a separate export so a primitive can diverge label vs. value.
|
|
601
|
+
*/
|
|
602
|
+
declare function itemToStringValue(value: unknown): string;
|
|
603
|
+
/**
|
|
604
|
+
* Compares two item values for equality using an optional {@link ItemValueComparator}.
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* isItemEqualToValue({ id: 1 }, { id: 1 }, 'id'); // true — compares the `id` key
|
|
608
|
+
* isItemEqualToValue({ id: 1 }, { id: 1 }); // true — deep equality fallback
|
|
609
|
+
*/
|
|
610
|
+
declare function isItemEqualToValue<T>(a: T, b: T, comparator?: ItemValueComparator<T>): boolean;
|
|
611
|
+
|
|
619
612
|
declare const ALT = "Alt";
|
|
620
613
|
declare const ARROW_DOWN = "ArrowDown";
|
|
621
614
|
declare const ARROW_LEFT = "ArrowLeft";
|
|
@@ -756,15 +749,27 @@ interface RdxFormUiControl {
|
|
|
756
749
|
readonly invalid?: RdxFormStateInput<boolean>;
|
|
757
750
|
readonly hidden?: RdxFormStateInput<boolean>;
|
|
758
751
|
readonly pending?: RdxFormStateInput<boolean>;
|
|
759
|
-
|
|
752
|
+
/**
|
|
753
|
+
* Touched status the form writes into the control.
|
|
754
|
+
*
|
|
755
|
+
* The two API generations disagree on the notification half: the 21.x
|
|
756
|
+
* experimental implementation listens to a `touched` **model**'s
|
|
757
|
+
* `touchedChange` output, while stable Angular 22 reverted to a plain
|
|
758
|
+
* `touched` input plus a separate {@link touch} output. A `model()` set on
|
|
759
|
+
* blur **plus** an emitted `touch` output satisfies both (`ModelSignal`
|
|
760
|
+
* extends `InputSignalWithTransform`, so it type-checks as the 22 input).
|
|
761
|
+
*/
|
|
762
|
+
readonly touched?: ModelSignal<boolean> | RdxFormStateInput<boolean> | OutputRef<boolean>;
|
|
760
763
|
readonly dirty?: RdxFormStateInput<boolean>;
|
|
761
764
|
readonly name?: RdxFormStateInput<string | undefined>;
|
|
762
765
|
readonly errors?: RdxFormStateInput<readonly RdxValidationError[]>;
|
|
763
766
|
readonly minLength?: RdxFormStateInput<number | undefined>;
|
|
764
767
|
readonly maxLength?: RdxFormStateInput<number | undefined>;
|
|
765
768
|
readonly pattern?: RdxFormStateInput<readonly RegExp[]>;
|
|
766
|
-
/** Notifies the form
|
|
769
|
+
/** Notifies the form the control was touched (stable Angular 22 contract; ignored by 21.x). */
|
|
767
770
|
readonly touch?: OutputRef<void>;
|
|
771
|
+
/** Resets the control's UI state (optional method added in stable Angular 22). */
|
|
772
|
+
reset?(): void;
|
|
768
773
|
}
|
|
769
774
|
/**
|
|
770
775
|
* Mirror of `FormValueControl<TValue>` — a control that edits a single value via
|
|
@@ -813,8 +818,13 @@ declare function resizeEffect(options: {
|
|
|
813
818
|
}): EffectRef;
|
|
814
819
|
|
|
815
820
|
/**
|
|
816
|
-
* Locks
|
|
817
|
-
*
|
|
821
|
+
* Locks page scrolling while `active()` is `true`, and restores the original state when it becomes
|
|
822
|
+
* `false` or the calling context is destroyed.
|
|
823
|
+
*
|
|
824
|
+
* Locks **both** `<body>` and `<html>`: a `body { overflow: hidden }` lock alone does *not* stop the
|
|
825
|
+
* page when `<html>` is the scroller (e.g. a global `overflow-y: scroll`, as Storybook sets), because
|
|
826
|
+
* body-overflow only propagates to the viewport when `<html>`'s overflow is `visible`. The width of
|
|
827
|
+
* the removed scrollbar is added as `padding-right` on `<html>` so the page doesn't shift.
|
|
818
828
|
*
|
|
819
829
|
* Lock ownership is shared across all callers via a single module-level counter, so nested or
|
|
820
830
|
* concurrent overlays compose correctly. Must be called in an injection context.
|
|
@@ -885,6 +895,39 @@ interface ArrowNavigationOptions {
|
|
|
885
895
|
*/
|
|
886
896
|
declare function useArrowNavigation(e: KeyboardEvent, currentElement: HTMLElement, parentElement: HTMLElement | undefined, options?: ArrowNavigationOptions): HTMLElement | null;
|
|
887
897
|
|
|
898
|
+
/**
|
|
899
|
+
* Locale-aware string matching backed by `Intl.Collator`, mirroring Base UI's `useFilter`.
|
|
900
|
+
*
|
|
901
|
+
* The collator defaults to `sensitivity: 'base'`, so matching is both case-insensitive and
|
|
902
|
+
* diacritic-insensitive (`"Äpfel"` matches `"ap"`, `"résumé"` matches `"resume"`). Pass `locale`
|
|
903
|
+
* and/or any `Intl.Collator` options to override.
|
|
904
|
+
*/
|
|
905
|
+
interface UseFilterOptions extends Intl.CollatorOptions {
|
|
906
|
+
/** Locale(s) for the collator. Defaults to the runtime's default locale. */
|
|
907
|
+
locale?: Intl.LocalesArgument;
|
|
908
|
+
}
|
|
909
|
+
/** Predicates returned by {@link useFilter}. An empty `query` always matches. */
|
|
910
|
+
interface FilterPredicates {
|
|
911
|
+
/** Whether `text` contains `query`. */
|
|
912
|
+
contains: (text: string, query: string) => boolean;
|
|
913
|
+
/** Whether `text` starts with `query`. */
|
|
914
|
+
startsWith: (text: string, query: string) => boolean;
|
|
915
|
+
/** Whether `text` ends with `query`. */
|
|
916
|
+
endsWith: (text: string, query: string) => boolean;
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Creates locale-aware `contains` / `startsWith` / `endsWith` predicates.
|
|
920
|
+
*
|
|
921
|
+
* Matching uses `Intl.Collator` with `sensitivity: 'base'` and `usage: 'search'` by default, so
|
|
922
|
+
* comparisons ignore case and diacritics. An empty (or whitespace-only) `query` matches everything,
|
|
923
|
+
* which is the natural "no filter applied" state for a combobox.
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* const { contains } = useFilter();
|
|
927
|
+
* contains('Äpfel', 'ap'); // true
|
|
928
|
+
*/
|
|
929
|
+
declare function useFilter(options?: UseFilterOptions): FilterPredicates;
|
|
930
|
+
|
|
888
931
|
/**
|
|
889
932
|
* Keeps hover content open while the pointer crosses the gap between a trigger and a popup.
|
|
890
933
|
*/
|
|
@@ -893,6 +936,55 @@ declare function useGraceArea(triggerEl: Signal<HTMLElement | null | undefined>,
|
|
|
893
936
|
onPointerExit: (callback: (value: void) => void) => () => void;
|
|
894
937
|
};
|
|
895
938
|
|
|
939
|
+
/** Options for {@link useListHighlight}. */
|
|
940
|
+
interface UseListHighlightOptions<T> {
|
|
941
|
+
/** All items in DOM order (e.g. a collection provider's `items()`). */
|
|
942
|
+
items: Signal<readonly T[]>;
|
|
943
|
+
/**
|
|
944
|
+
* Whether an item can be highlighted — must return `false` for hidden (filtered-out) and
|
|
945
|
+
* disabled items. Navigation and self-healing both consult this.
|
|
946
|
+
*/
|
|
947
|
+
isNavigable: (item: T) => boolean;
|
|
948
|
+
/** Resolves the item's element id, exposed as {@link ListHighlight.activeId} for `aria-activedescendant`. */
|
|
949
|
+
getId: (item: T) => string | undefined;
|
|
950
|
+
/** Whether navigation wraps at the boundaries. Defaults to `true`. */
|
|
951
|
+
loop?: Signal<boolean>;
|
|
952
|
+
/** Injector to bind the self-healing effect to when not called in an injection context. */
|
|
953
|
+
injector?: Injector;
|
|
954
|
+
}
|
|
955
|
+
/** Highlight-model navigation API returned by {@link useListHighlight}. */
|
|
956
|
+
interface ListHighlight<T> {
|
|
957
|
+
/** The currently highlighted item, or `null`. DOM focus is never moved by this state. */
|
|
958
|
+
readonly highlightedItem: Signal<T | null>;
|
|
959
|
+
/** The highlighted item's element id, or `undefined`. Bind to `aria-activedescendant`. */
|
|
960
|
+
readonly activeId: Signal<string | undefined>;
|
|
961
|
+
/** Highlight the first navigable item. */
|
|
962
|
+
first(): void;
|
|
963
|
+
/** Highlight the last navigable item. */
|
|
964
|
+
last(): void;
|
|
965
|
+
/** Highlight the next navigable item (wraps when `loop`). */
|
|
966
|
+
next(): void;
|
|
967
|
+
/** Highlight the previous navigable item (wraps when `loop`). */
|
|
968
|
+
previous(): void;
|
|
969
|
+
/** Highlight a specific item (ignored if not navigable); pass `null` to clear. */
|
|
970
|
+
set(item: T | null): void;
|
|
971
|
+
/** Clear the highlight. */
|
|
972
|
+
clear(): void;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Highlight-model list navigation over a set of items, decoupled from DOM focus.
|
|
976
|
+
*
|
|
977
|
+
* Unlike roving `tabindex`, the highlight is pure state: callers move it with the keyboard while DOM
|
|
978
|
+
* focus stays on a single controlling element (e.g. a combobox `<input>`), which exposes
|
|
979
|
+
* {@link ListHighlight.activeId} as `aria-activedescendant`. Navigation only ever lands on items for
|
|
980
|
+
* which `isNavigable` returns `true`, so hidden (filtered-out) and disabled items are skipped. A
|
|
981
|
+
* self-healing effect clears the highlight if its item stops being navigable or leaves the list, so
|
|
982
|
+
* `activeId` never references a detached or hidden element.
|
|
983
|
+
*
|
|
984
|
+
* Must be called in an injection context, or given an `injector`.
|
|
985
|
+
*/
|
|
986
|
+
declare function useListHighlight<T>(options: UseListHighlightOptions<T>): ListHighlight<T>;
|
|
987
|
+
|
|
896
988
|
interface RdxPointerDragHandlers {
|
|
897
989
|
/** Whether a press may begin a drag (e.g. enabled, not on an opt-out element, at a scroll edge). */
|
|
898
990
|
canStart: (event: PointerEvent) => boolean;
|
|
@@ -1008,5 +1100,5 @@ declare enum RdxPositionAlign {
|
|
|
1008
1100
|
End = "end"
|
|
1009
1101
|
}
|
|
1010
1102
|
|
|
1011
|
-
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RdxControlValueAccessor, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, SPACE_CODE, TAB, a, areAllDaysBetweenValid, clamp, createContent, createContext, createFormatter, createMonth, createMonths, elementSize, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectId, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isNullish, isNumberString, isSegmentNavigationKey, isZonedDateTime, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideToken, provideValueAccessor, resizeEffect, roundToStepPrecision, segmentBuilders, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useArrowNavigation, useDateField, useGraceArea, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
1012
|
-
export type { AcceptableValue, AnyExceptLiteral, AriaLivePoliteness, BooleanInput, CreateMonthProps, DataOrientation, DateAndTimeSegmentObj, DateFormatterOptions, DateMatcher, DateRange, DateSegmentObj, DateSegmentPart, DateStep, DayPeriod, Direction, EditableSegmentPart, Formatter, Granularity, HourCycle, InjectContext, Month, NonEditableSegmentPart, Nullable, NumberInput, PlaceholderMap, RdxFormCheckboxControl, RdxFormStateInput, RdxFormUiControl, RdxFormValueControl, RdxPointerDragHandlers, RdxTransitionStatus, RdxTransitionStatusRef, RdxValidationError, SafeFunction, SegmentContentObj, SegmentPart, SegmentValueObj, TimeGranularity, TimeSegmentObj, TimeSegmentPart, TimeValue, UseDateFieldProps };
|
|
1103
|
+
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RdxControlValueAccessor, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, SPACE_CODE, TAB, TIME_GRANULARITIES, a, areAllDaysBetweenValid, clamp, createContent, createContext, createFormatter, createMonth, createMonths, elementSize, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectId, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isItemEqualToValue, isNullish, isNumberString, isSegmentNavigationKey, isZonedDateTime, itemToStringLabel, itemToStringValue, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideToken, provideValueAccessor, resizeEffect, roundToStepPrecision, segmentBuilders, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useArrowNavigation, useDateField, useFilter, useGraceArea, useListHighlight, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
1104
|
+
export type { AcceptableValue, AnyExceptLiteral, AriaLivePoliteness, BooleanInput, CreateMonthProps, DataOrientation, DateAndTimeSegmentObj, DateFormatterOptions, DateMatcher, DateRange, DateSegmentObj, DateSegmentPart, DateStep, DayPeriod, Direction, EditableSegmentPart, FilterPredicates, Formatter, Granularity, HourCycle, InjectContext, ItemValueComparator, ListHighlight, Month, NonEditableSegmentPart, Nullable, NumberInput, PlaceholderMap, RdxFormCheckboxControl, RdxFormStateInput, RdxFormUiControl, RdxFormValueControl, RdxPointerDragHandlers, RdxTransitionStatus, RdxTransitionStatusRef, RdxValidationError, SafeFunction, SegmentContentObj, SegmentPart, SegmentValueObj, TimeGranularity, TimeSegmentObj, TimeSegmentPart, TimeValue, UseDateFieldProps, UseFilterOptions, UseListHighlightOptions };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _radix_ng_primitives_field from '@radix-ng/primitives/field';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
3
|
import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
|
|
4
|
-
import { BooleanInput } from '@radix-ng/primitives/core';
|
|
4
|
+
import { BooleanInput, RdxValidationError } from '@radix-ng/primitives/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Connects a form control to the field label, description, error, and state.
|
|
@@ -11,8 +11,11 @@ import { BooleanInput } from '@radix-ng/primitives/core';
|
|
|
11
11
|
declare class RdxFieldControl {
|
|
12
12
|
protected readonly rootContext: {
|
|
13
13
|
controlId: _angular_core.WritableSignal<string>;
|
|
14
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
14
15
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
15
16
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
17
|
+
messages: _angular_core.Signal<string[]>;
|
|
18
|
+
notifyEdited: () => void;
|
|
16
19
|
invalidState: _angular_core.Signal<boolean>;
|
|
17
20
|
disabledState: _angular_core.Signal<boolean>;
|
|
18
21
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -60,8 +63,11 @@ declare class RdxFieldControl {
|
|
|
60
63
|
declare class RdxFieldDescription {
|
|
61
64
|
protected readonly rootContext: {
|
|
62
65
|
controlId: _angular_core.WritableSignal<string>;
|
|
66
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
63
67
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
64
68
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
69
|
+
messages: _angular_core.Signal<string[]>;
|
|
70
|
+
notifyEdited: () => void;
|
|
65
71
|
invalidState: _angular_core.Signal<boolean>;
|
|
66
72
|
disabledState: _angular_core.Signal<boolean>;
|
|
67
73
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -101,8 +107,11 @@ declare class RdxFieldDescription {
|
|
|
101
107
|
declare class RdxFieldError {
|
|
102
108
|
protected readonly rootContext: {
|
|
103
109
|
controlId: _angular_core.WritableSignal<string>;
|
|
110
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
104
111
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
105
112
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
113
|
+
messages: _angular_core.Signal<string[]>;
|
|
114
|
+
notifyEdited: () => void;
|
|
106
115
|
invalidState: _angular_core.Signal<boolean>;
|
|
107
116
|
disabledState: _angular_core.Signal<boolean>;
|
|
108
117
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -128,6 +137,12 @@ declare class RdxFieldError {
|
|
|
128
137
|
* @group Props
|
|
129
138
|
*/
|
|
130
139
|
readonly id: _angular_core.InputSignal<string>;
|
|
140
|
+
/**
|
|
141
|
+
* The field's external messages (state provider's, then enclosing Form's), `[]` when none. Render
|
|
142
|
+
* them explicitly via the `exportAs` reference — the directive never injects text content itself:
|
|
143
|
+
* `<p rdxFieldError #err="rdxFieldError">{{ err.messages().join(' ') }}</p>`.
|
|
144
|
+
*/
|
|
145
|
+
readonly messages: _angular_core.Signal<string[]>;
|
|
131
146
|
constructor();
|
|
132
147
|
protected readonly dataAttr: (value: boolean) => "" | undefined;
|
|
133
148
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldError, never>;
|
|
@@ -142,8 +157,11 @@ declare class RdxFieldError {
|
|
|
142
157
|
declare class RdxFieldLabel {
|
|
143
158
|
protected readonly rootContext: {
|
|
144
159
|
controlId: _angular_core.WritableSignal<string>;
|
|
160
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
145
161
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
146
162
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
163
|
+
messages: _angular_core.Signal<string[]>;
|
|
164
|
+
notifyEdited: () => void;
|
|
147
165
|
invalidState: _angular_core.Signal<boolean>;
|
|
148
166
|
disabledState: _angular_core.Signal<boolean>;
|
|
149
167
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -195,11 +213,23 @@ interface RdxFieldState {
|
|
|
195
213
|
touched?: () => boolean;
|
|
196
214
|
filled?: () => boolean;
|
|
197
215
|
focused?: () => boolean;
|
|
216
|
+
/**
|
|
217
|
+
* Optional source of error *content* (not just the invalid boolean). When provided and non-empty
|
|
218
|
+
* it forces `invalidState` true, and its messages (`message ?? kind` per error) surface through
|
|
219
|
+
* `RdxFieldError.messages()` ahead of any enclosing Form's external messages. Uses `core`'s
|
|
220
|
+
* framework-free shim type so the seam stays free of `@angular/forms/signals` (ADR 0004 amendment).
|
|
221
|
+
*/
|
|
222
|
+
errors?: () => RdxValidationError[];
|
|
198
223
|
}
|
|
199
224
|
declare const fieldRootContext: () => {
|
|
200
225
|
controlId: _angular_core.WritableSignal<string>;
|
|
226
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
201
227
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
202
228
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
229
|
+
/** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
|
|
230
|
+
messages: _angular_core.Signal<string[]>;
|
|
231
|
+
/** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
|
|
232
|
+
notifyEdited: () => void;
|
|
203
233
|
invalidState: _angular_core.Signal<boolean>;
|
|
204
234
|
disabledState: _angular_core.Signal<boolean>;
|
|
205
235
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -228,8 +258,13 @@ declare const fieldRootContext: () => {
|
|
|
228
258
|
type RdxFieldRootContext = ReturnType<typeof fieldRootContext>;
|
|
229
259
|
declare const injectFieldRootContext: _radix_ng_primitives_core.InjectContext<{
|
|
230
260
|
controlId: _angular_core.WritableSignal<string>;
|
|
261
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
231
262
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
232
263
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
264
|
+
/** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
|
|
265
|
+
messages: _angular_core.Signal<string[]>;
|
|
266
|
+
/** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
|
|
267
|
+
notifyEdited: () => void;
|
|
233
268
|
invalidState: _angular_core.Signal<boolean>;
|
|
234
269
|
disabledState: _angular_core.Signal<boolean>;
|
|
235
270
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -257,8 +292,13 @@ declare const injectFieldRootContext: _radix_ng_primitives_core.InjectContext<{
|
|
|
257
292
|
}>;
|
|
258
293
|
declare const provideFieldRootContext: (useFactory: () => {
|
|
259
294
|
controlId: _angular_core.WritableSignal<string>;
|
|
295
|
+
name: _angular_core.InputSignal<string | undefined>;
|
|
260
296
|
descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
261
297
|
errorIds: _angular_core.WritableSignal<string[]>;
|
|
298
|
+
/** Combined external messages (state provider's, then enclosing Form's), for `RdxFieldError`. */
|
|
299
|
+
messages: _angular_core.Signal<string[]>;
|
|
300
|
+
/** Notify an enclosing Form that this field's control was edited (composite-control opt-in). */
|
|
301
|
+
notifyEdited: () => void;
|
|
262
302
|
invalidState: _angular_core.Signal<boolean>;
|
|
263
303
|
disabledState: _angular_core.Signal<boolean>;
|
|
264
304
|
requiredState: _angular_core.Signal<boolean>;
|
|
@@ -337,6 +377,15 @@ declare class RdxFieldRoot {
|
|
|
337
377
|
* @group Props
|
|
338
378
|
*/
|
|
339
379
|
readonly focused: _angular_core.InputSignal<boolean | undefined>;
|
|
380
|
+
/**
|
|
381
|
+
* Identifies the field to an enclosing Form for external (server) error matching. Fields without a
|
|
382
|
+
* `name` never match external errors.
|
|
383
|
+
*
|
|
384
|
+
* @group Props
|
|
385
|
+
*/
|
|
386
|
+
readonly name: _angular_core.InputSignal<string | undefined>;
|
|
387
|
+
/** The enclosing Form, if any. All Form-related behavior is a no-op when this is `null`. */
|
|
388
|
+
private readonly formContext;
|
|
340
389
|
readonly controlId: _angular_core.WritableSignal<string>;
|
|
341
390
|
readonly descriptionIds: _angular_core.WritableSignal<string[]>;
|
|
342
391
|
readonly errorIds: _angular_core.WritableSignal<string[]>;
|
|
@@ -348,6 +397,12 @@ declare class RdxFieldRoot {
|
|
|
348
397
|
private readonly stateProvider;
|
|
349
398
|
/** Whether an external adapter currently owns field state. */
|
|
350
399
|
readonly hasStateProvider: _angular_core.Signal<boolean>;
|
|
400
|
+
/** Error content from a registered state provider (e.g. a Signal Forms adapter). */
|
|
401
|
+
private readonly providerErrors;
|
|
402
|
+
/** External messages from the enclosing Form matched by this field's `name`. */
|
|
403
|
+
readonly externalErrors: _angular_core.Signal<string[]>;
|
|
404
|
+
/** Provider messages first (`message ?? kind`), then the Form's external messages. */
|
|
405
|
+
readonly messages: _angular_core.Signal<string[]>;
|
|
351
406
|
readonly invalidState: _angular_core.Signal<boolean>;
|
|
352
407
|
readonly disabledState: _angular_core.Signal<boolean>;
|
|
353
408
|
readonly requiredState: _angular_core.Signal<boolean>;
|
|
@@ -356,6 +411,20 @@ declare class RdxFieldRoot {
|
|
|
356
411
|
readonly filledState: _angular_core.Signal<boolean>;
|
|
357
412
|
readonly focusedState: _angular_core.Signal<boolean>;
|
|
358
413
|
protected readonly dataAttr: (value: boolean) => "" | undefined;
|
|
414
|
+
constructor();
|
|
415
|
+
/** Notify the enclosing Form (if any) that this field's control was edited (clear-on-edit). */
|
|
416
|
+
notifyEdited(): void;
|
|
417
|
+
/** Reset interaction state on native form reset: touched/dirty/focused → false, filled re-synced. */
|
|
418
|
+
resetState(): void;
|
|
419
|
+
/** Focus the field's control (used by the Form's first-invalid-focus on blocked submit). */
|
|
420
|
+
private focusControl;
|
|
421
|
+
private readonly host;
|
|
422
|
+
/**
|
|
423
|
+
* The field's control element, found by `controlId` but scoped to this field's own subtree — a
|
|
424
|
+
* duplicate or consumer-reused id elsewhere on the page can't steal focus/reset. The control
|
|
425
|
+
* registers its id through `setControlId`, so this matches the same element the labels point at.
|
|
426
|
+
*/
|
|
427
|
+
private controlElement;
|
|
359
428
|
/**
|
|
360
429
|
* Register an external owner of field state, returning the previous one.
|
|
361
430
|
* @ignore
|
|
@@ -367,7 +436,7 @@ declare class RdxFieldRoot {
|
|
|
367
436
|
*/
|
|
368
437
|
private resolve;
|
|
369
438
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFieldRoot, never>;
|
|
370
|
-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldRoot, "[rdxFieldRoot]", ["rdxFieldRoot"], { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "filled": { "alias": "filled"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
439
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFieldRoot, "[rdxFieldRoot]", ["rdxFieldRoot"], { "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "filled": { "alias": "filled"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
371
440
|
}
|
|
372
441
|
|
|
373
442
|
export { RdxFieldControl, RdxFieldDescription, RdxFieldError, RdxFieldLabel, RdxFieldRoot, injectFieldRootContext, provideFieldRootContext };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/** A normalized external-error map: each field name maps to its message(s) in display order. */
|
|
5
|
+
type RdxFormErrors = Record<string, string | string[]>;
|
|
6
|
+
/** Payload of {@link RdxFormRoot.onFormSubmit}. */
|
|
7
|
+
interface RdxFormSubmitEvent {
|
|
8
|
+
/** The form's values serialized from `FormData` (repeated names collapse into arrays). */
|
|
9
|
+
values: Record<string, FormDataEntryValue | FormDataEntryValue[]>;
|
|
10
|
+
/** The original native submit event (already `preventDefault`-ed). */
|
|
11
|
+
event: SubmitEvent;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* What a {@link RdxFieldRoot} registers with an enclosing Form. Structural `() =>` accessors keep the
|
|
15
|
+
* Form entry free of any import from `field` (acyclic ng-packagr graph: `field` → `form`).
|
|
16
|
+
*/
|
|
17
|
+
interface RdxFormFieldRegistration {
|
|
18
|
+
/** The field's `name` (key external errors match against), or `undefined`. */
|
|
19
|
+
name: () => string | undefined;
|
|
20
|
+
/** The field's merged invalid state (includes external errors). */
|
|
21
|
+
invalid: () => boolean;
|
|
22
|
+
/** Whether the field is dirty. */
|
|
23
|
+
dirty: () => boolean;
|
|
24
|
+
/** Whether the field is touched. */
|
|
25
|
+
touched: () => boolean;
|
|
26
|
+
/** Focus the field's control (by its `controlId`). */
|
|
27
|
+
focus: () => void;
|
|
28
|
+
/** Reset the field's interaction state (touched/dirty/focused → false, filled re-sync). */
|
|
29
|
+
resetState: () => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* External owner of form-level state (e.g. a future Signal Forms `[rdxSignalForm]` adapter). Mirrors
|
|
33
|
+
* Field's `RdxFieldState` seam one level up. Each member is optional: a provided accessor wins over the
|
|
34
|
+
* built-in registry/`errors`-input behavior; absent accessors leave the built-in behavior untouched.
|
|
35
|
+
* Kept as framework-free `() =>` accessors (no `@angular/forms/signals` dependency). See ADR 0004.
|
|
36
|
+
*/
|
|
37
|
+
interface RdxFormState {
|
|
38
|
+
invalid?: () => boolean;
|
|
39
|
+
dirty?: () => boolean;
|
|
40
|
+
touched?: () => boolean;
|
|
41
|
+
submitting?: () => boolean;
|
|
42
|
+
/** Per-name external error source; while provided, the `errors` input + clear-on-edit are inert. */
|
|
43
|
+
errorsFor?: (name: string) => string[];
|
|
44
|
+
}
|
|
45
|
+
declare const formRootContext: () => {
|
|
46
|
+
errorsFor: (name: string | undefined) => string[];
|
|
47
|
+
notifyEdited: (name: string | undefined) => void;
|
|
48
|
+
register: (field: RdxFormFieldRegistration) => () => void;
|
|
49
|
+
setStateProvider: (provider: RdxFormState | null) => RdxFormState | null;
|
|
50
|
+
hasStateProvider: _angular_core.Signal<boolean>;
|
|
51
|
+
};
|
|
52
|
+
type RdxFormRootContext = ReturnType<typeof formRootContext>;
|
|
53
|
+
declare const injectFormRootContext: _radix_ng_primitives_core.InjectContext<{
|
|
54
|
+
errorsFor: (name: string | undefined) => string[];
|
|
55
|
+
notifyEdited: (name: string | undefined) => void;
|
|
56
|
+
register: (field: RdxFormFieldRegistration) => () => void;
|
|
57
|
+
setStateProvider: (provider: RdxFormState | null) => RdxFormState | null;
|
|
58
|
+
hasStateProvider: _angular_core.Signal<boolean>;
|
|
59
|
+
}>;
|
|
60
|
+
declare const provideFormRootContext: (useFactory: () => {
|
|
61
|
+
errorsFor: (name: string | undefined) => string[];
|
|
62
|
+
notifyEdited: (name: string | undefined) => void;
|
|
63
|
+
register: (field: RdxFormFieldRegistration) => () => void;
|
|
64
|
+
setStateProvider: (provider: RdxFormState | null) => RdxFormState | null;
|
|
65
|
+
hasStateProvider: _angular_core.Signal<boolean>;
|
|
66
|
+
}) => _angular_core.Provider;
|
|
67
|
+
/**
|
|
68
|
+
* The top of the forms layer cake: a single directive on the native `<form>` element that aggregates
|
|
69
|
+
* field state, maps external (server) errors onto fields by `name`, intercepts submit (values-as-object,
|
|
70
|
+
* focus the first invalid field), and resets field interaction state on native `reset`. It owns no
|
|
71
|
+
* values and runs no validation — Angular form systems (or Field inputs) remain the source of validity.
|
|
72
|
+
*
|
|
73
|
+
* @group Components
|
|
74
|
+
*/
|
|
75
|
+
declare class RdxFormRoot {
|
|
76
|
+
private readonly form;
|
|
77
|
+
/** External/server validation errors keyed by `Field.Root` `name`. */
|
|
78
|
+
readonly errors: _angular_core.InputSignal<RdxFormErrors | null | undefined>;
|
|
79
|
+
/** Emits the remaining error map after a field's external error is cleared by a user edit (or reset). */
|
|
80
|
+
readonly onClearErrors: _angular_core.OutputEmitterRef<RdxFormErrors>;
|
|
81
|
+
/** Emits the serialized form values when a valid form is submitted. */
|
|
82
|
+
readonly onFormSubmit: _angular_core.OutputEmitterRef<RdxFormSubmitEvent>;
|
|
83
|
+
private readonly fields;
|
|
84
|
+
private readonly stateProvider;
|
|
85
|
+
/** Whether an external adapter currently owns form-level state. */
|
|
86
|
+
readonly hasStateProvider: _angular_core.Signal<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* Names whose external error has been cleared by a user edit. Reset to empty whenever a new `errors`
|
|
89
|
+
* object reference is assigned — the server just spoke, so everything it said is live again.
|
|
90
|
+
*/
|
|
91
|
+
private readonly clearedNames;
|
|
92
|
+
/** The `errors` input minus cleared names, normalized to `string[]`. */
|
|
93
|
+
private readonly effectiveErrors;
|
|
94
|
+
readonly anyInvalid: _angular_core.Signal<boolean>;
|
|
95
|
+
readonly anyDirty: _angular_core.Signal<boolean>;
|
|
96
|
+
readonly anyTouched: _angular_core.Signal<boolean>;
|
|
97
|
+
readonly submitting: _angular_core.Signal<boolean>;
|
|
98
|
+
/** Resolve a boolean aggregate: a registered provider's accessor wins, else OR over the registry. */
|
|
99
|
+
private aggregate;
|
|
100
|
+
/** Resolves the external messages for a field name (provider source wins over the `errors` input). */
|
|
101
|
+
errorsFor(name: string | undefined): string[];
|
|
102
|
+
/** Clears a field's external error after a user edit, emitting the remaining map. */
|
|
103
|
+
notifyEdited(name: string | undefined): void;
|
|
104
|
+
register(field: RdxFormFieldRegistration): () => void;
|
|
105
|
+
/** Register (or clear with `null`) an external owner of form-level state; returns the previous one. */
|
|
106
|
+
setStateProvider(provider: RdxFormState | null): RdxFormState | null;
|
|
107
|
+
onSubmit(event: SubmitEvent): void;
|
|
108
|
+
onReset(): void;
|
|
109
|
+
private readonly resetTimers;
|
|
110
|
+
constructor();
|
|
111
|
+
private remainingErrors;
|
|
112
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFormRoot, never>;
|
|
113
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFormRoot, "form[rdxFormRoot]", ["rdxFormRoot"], { "errors": { "alias": "errors"; "required": false; "isSignal": true; }; }, { "onClearErrors": "onClearErrors"; "onFormSubmit": "onFormSubmit"; }, never, never, true, never>;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
declare const _importsForm: (typeof RdxFormRoot)[];
|
|
117
|
+
declare class RdxFormModule {
|
|
118
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFormModule, never>;
|
|
119
|
+
static ɵmod: _angular_core.ɵɵNgModuleDeclaration<RdxFormModule, never, [typeof RdxFormRoot], [typeof RdxFormRoot]>;
|
|
120
|
+
static ɵinj: _angular_core.ɵɵInjectorDeclaration<RdxFormModule>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { RdxFormModule, RdxFormRoot, _importsForm, injectFormRootContext, provideFormRootContext };
|
|
124
|
+
export type { RdxFormErrors, RdxFormFieldRegistration, RdxFormRootContext, RdxFormState, RdxFormSubmitEvent };
|