@radix-ng/primitives 1.0.4 → 1.0.6
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 +35 -27
- package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-alert-dialog.mjs +34 -34
- package/fesm2022/radix-ng-primitives-arrow.mjs +3 -3
- package/fesm2022/radix-ng-primitives-aspect-ratio.mjs +5 -4
- package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +175 -125
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-avatar.mjs +25 -19
- package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-button.mjs +11 -7
- package/fesm2022/radix-ng-primitives-button.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-calendar.mjs +140 -90
- package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +61 -40
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-collapsible.mjs +35 -24
- package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +278 -177
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-composite.mjs +76 -35
- package/fesm2022/radix-ng-primitives-composite.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-config.mjs +7 -5
- package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-context-menu.mjs +48 -22
- package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +44 -28
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-cropper.mjs +73 -45
- package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +70 -40
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-dialog.mjs +93 -67
- package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-direction-provider.mjs +5 -4
- package/fesm2022/radix-ng-primitives-direction-provider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +20 -16
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-drawer.mjs +107 -81
- package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs +53 -39
- package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +69 -42
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-fieldset.mjs +8 -7
- package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +77 -40
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-focus-guards.mjs +3 -3
- package/fesm2022/radix-ng-primitives-focus-scope.mjs +7 -5
- package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-form.mjs +25 -16
- package/fesm2022/radix-ng-primitives-form.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-input.mjs +41 -22
- package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-label.mjs +7 -5
- package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menu.mjs +274 -154
- package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menubar.mjs +35 -17
- package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-meter.mjs +41 -30
- package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs +220 -183
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +87 -59
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-pagination.mjs +48 -38
- package/fesm2022/radix-ng-primitives-pagination.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popover.mjs +150 -107
- package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs +79 -47
- package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-portal.mjs +20 -13
- package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-presence.mjs +3 -3
- package/fesm2022/radix-ng-primitives-preview-card.mjs +119 -74
- package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-progress.mjs +43 -31
- package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +177 -168
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +54 -38
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +595 -102
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-separator.mjs +7 -5
- package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +101 -63
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-stepper.mjs +53 -39
- package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +44 -25
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs +72 -47
- package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +72 -41
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toast.mjs +75 -56
- package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +29 -19
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle.mjs +16 -11
- package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toolbar.mjs +38 -30
- package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tooltip.mjs +118 -63
- package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-visually-hidden.mjs +31 -20
- package/fesm2022/radix-ng-primitives-visually-hidden.mjs.map +1 -1
- package/package.json +2 -2
- package/types/radix-ng-primitives-autocomplete.d.ts +3 -1
- package/types/radix-ng-primitives-combobox.d.ts +28 -9
- package/types/radix-ng-primitives-composite.d.ts +2 -0
- package/types/radix-ng-primitives-context-menu.d.ts +2 -0
- package/types/radix-ng-primitives-dialog.d.ts +6 -3
- package/types/radix-ng-primitives-floating-focus-manager.d.ts +11 -0
- package/types/radix-ng-primitives-menu.d.ts +47 -15
- package/types/radix-ng-primitives-menubar.d.ts +6 -1
- package/types/radix-ng-primitives-navigation-menu.d.ts +8 -6
- package/types/radix-ng-primitives-popover.d.ts +12 -4
- package/types/radix-ng-primitives-preview-card.d.ts +18 -5
- package/types/radix-ng-primitives-radio.d.ts +100 -65
- package/types/radix-ng-primitives-select.d.ts +186 -391
- package/types/radix-ng-primitives-switch.d.ts +3 -2
- package/types/radix-ng-primitives-tooltip.d.ts +17 -3
|
@@ -389,7 +389,8 @@ class RdxFocusScope {
|
|
|
389
389
|
* @defaultValue false
|
|
390
390
|
*/
|
|
391
391
|
this.trapped = input(undefined, { ...(ngDevMode ? { debugName: "trapped" } : /* istanbul ignore next */ {}), transform: (value) => (value === undefined ? undefined : booleanAttribute(value)) });
|
|
392
|
-
this.isTrapped = computed(() => this.trapped() ?? this.config.trapped(),
|
|
392
|
+
this.isTrapped = computed(() => this.trapped() ?? this.config.trapped(), /* @ts-ignore */
|
|
393
|
+
...(ngDevMode ? [{ debugName: "isTrapped" }] : /* istanbul ignore next */ []));
|
|
393
394
|
/**
|
|
394
395
|
* Event handler called when auto-focusing on mount.
|
|
395
396
|
* Can be prevented.
|
|
@@ -404,7 +405,8 @@ class RdxFocusScope {
|
|
|
404
405
|
* @group Emits
|
|
405
406
|
*/
|
|
406
407
|
this.unmountAutoFocus = output();
|
|
407
|
-
this.lastFocusedElement = signal(null,
|
|
408
|
+
this.lastFocusedElement = signal(null, /* @ts-ignore */
|
|
409
|
+
...(ngDevMode ? [{ debugName: "lastFocusedElement" }] : /* istanbul ignore next */ []));
|
|
408
410
|
this.focusScopesStack = createFocusScopesStack(this.ownerDocument);
|
|
409
411
|
this.focusScope = {
|
|
410
412
|
paused: signal(false),
|
|
@@ -571,10 +573,10 @@ class RdxFocusScope {
|
|
|
571
573
|
}
|
|
572
574
|
}
|
|
573
575
|
}
|
|
574
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
575
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
576
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFocusScope, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
577
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFocusScope, isStandalone: true, selector: "[rdxFocusScope]", inputs: { loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, trapped: { classPropertyName: "trapped", publicName: "trapped", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { mountAutoFocus: "mountAutoFocus", unmountAutoFocus: "unmountAutoFocus" }, host: { attributes: { "tabindex": "-1" }, listeners: { "keydown": "handleKeyDown($event)" } }, providers: [provideFocusScopeContext(rootContext)], ngImport: i0 }); }
|
|
576
578
|
}
|
|
577
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
579
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFocusScope, decorators: [{
|
|
578
580
|
type: Directive,
|
|
579
581
|
args: [{
|
|
580
582
|
selector: '[rdxFocusScope]',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radix-ng-primitives-focus-scope.mjs","sources":["../../../packages/primitives/focus-scope/src/utils.ts","../../../packages/primitives/focus-scope/src/focus-guards.ts","../../../packages/primitives/focus-scope/src/focus-scope.config.ts","../../../packages/primitives/focus-scope/src/stack.ts","../../../packages/primitives/focus-scope/src/focus-scope.ts","../../../packages/primitives/focus-scope/radix-ng-primitives-focus-scope.ts"],"sourcesContent":["import { getActiveElement } from '@radix-ng/primitives/core';\n\nexport const AUTOFOCUS_ON_MOUNT = 'focusScope.autoFocusOnMount';\nexport const AUTOFOCUS_ON_UNMOUNT = 'focusScope.autoFocusOnUnmount';\nexport const EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\ntype FocusableTarget = HTMLElement | { focus: () => void };\n\n/**\n * The real target of a (possibly retargeted) event, piercing shadow boundaries via `composedPath()`.\n * Falls back to `event.target` when `composedPath` is unavailable.\n */\nexport function getEventTarget(event: Event): EventTarget | null {\n return event.composedPath?.()[0] ?? event.target;\n}\n\n/**\n * Shadow-DOM-aware containment: whether `node` is `container` or lives inside it, crossing shadow roots\n * via their `host` (unlike `Node.contains`, which stops at a shadow boundary).\n */\nexport function composedContains(container: Node, node: Node | null): boolean {\n let current: Node | null = node;\n while (current) {\n if (current === container) {\n return true;\n }\n current = current instanceof ShadowRoot ? current.host : current.parentNode;\n }\n return false;\n}\n\n/**\n * Attempts focusing the first element in a list of candidates.\n * Stops when focus has actually moved.\n */\nexport function focusFirst(candidates: HTMLElement[], { select = false } = {}) {\n const previouslyFocusedElement = getActiveElement();\n for (const candidate of candidates) {\n focus(candidate, { select });\n if (getActiveElement() !== previouslyFocusedElement) return true;\n }\n\n return;\n}\n\n/**\n * Returns a list of potential tabbable candidates.\n *\n * NOTE: This is only a close approximation. For example it doesn't take into account cases like when\n * elements are not visible. This cannot be worked out easily by just reading a property, but rather\n * necessitate runtime knowledge (computed styles, etc). We deal with these cases separately.\n *\n * See: https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker\n * Credit: https://github.com/discord/focus-layers/blob/master/src/util/wrapFocus.tsx#L1\n */\nexport function getTabbableCandidates(container: HTMLElement) {\n const nodes: HTMLElement[] = [];\n const walker = container.ownerDocument.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node: any) => {\n const isHiddenInput = node.tagName === 'INPUT' && node.type === 'hidden';\n if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;\n // `.tabIndex` is not the same as the `tabindex` attribute. It works on the\n // runtime's understanding of tabbability, so this automatically accounts\n // for any kind of element that could be tabbed to.\n return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n });\n while (walker.nextNode()) nodes.push(walker.currentNode as HTMLElement);\n // we do not take into account the order of nodes with positive `tabIndex` as it\n // hinders accessibility to have tab order different from visual order.\n return nodes;\n}\n\nexport function isHidden(node: HTMLElement, { upTo }: { upTo?: HTMLElement }) {\n const view = node.ownerDocument.defaultView;\n if (!view) {\n return false; // no view (detached / SSR) — cannot resolve computed styles, treat as visible\n }\n if (view.getComputedStyle(node).visibility === 'hidden') return true;\n while (node) {\n // we stop at `upTo` (excluding it)\n if (upTo !== undefined && node === upTo) return false;\n if (view.getComputedStyle(node).display === 'none') return true;\n node = node.parentElement as HTMLElement;\n }\n return false;\n}\n\n/**\n * Returns the first visible element in a list.\n * NOTE: Only checks visibility up to the `container`.\n */\nexport function findVisible(elements: HTMLElement[], container: HTMLElement): HTMLElement | undefined {\n for (const element of elements) {\n // we stop checking if it's hidden at the `container` level (excluding)\n if (!isHidden(element, { upTo: container })) return element;\n }\n return undefined;\n}\n\n/**\n * Returns the first and last tabbable elements inside a container.\n */\nexport function getTabbableEdges(container: HTMLElement) {\n const candidates = getTabbableCandidates(container);\n const first = findVisible(candidates, container);\n const last = findVisible(candidates.reverse(), container);\n return [first, last] as const;\n}\n\n/** Visible tabbable elements of `root` in document order (the basis for tab-order navigation). */\nfunction visibleTabbablesIn(root: HTMLElement): HTMLElement[] {\n return getTabbableCandidates(root).filter((el) => !isHidden(el, { upTo: root }));\n}\n\n/** The tabbable one step (`dir`) from the document's active element, within `container`. */\nfunction getTabbableIn(container: HTMLElement, dir: 1 | -1): HTMLElement | undefined {\n const list = visibleTabbablesIn(container);\n if (list.length === 0) {\n return undefined;\n }\n const active = getActiveElement(container.ownerDocument) as HTMLElement | null;\n const index = active ? list.indexOf(active) : -1;\n const nextIndex = index === -1 ? (dir === 1 ? 0 : list.length - 1) : index + dir;\n return list[nextIndex];\n}\n\n/**\n * The next tabbable in the document after the current focus (Base UI `getNextTabbable`) — used by the\n * portal-focus bridge's trailing guard to step focus past the popup. Falls back to `reference`.\n */\nexport function getNextTabbable(reference: Element | null): HTMLElement | null {\n const body = (reference?.ownerDocument ?? document).body;\n return getTabbableIn(body, 1) ?? (reference as HTMLElement | null);\n}\n\n/** The previous tabbable in the document before the current focus (Base UI `getPreviousTabbable`). */\nexport function getPreviousTabbable(reference: Element | null): HTMLElement | null {\n const body = (reference?.ownerDocument ?? document).body;\n return getTabbableIn(body, -1) ?? (reference as HTMLElement | null);\n}\n\n/** The tabbable `dir` steps from `reference` in the document, wrapping around. */\nfunction getTabbableNearElement(reference: Element | null, dir: 1 | -1): HTMLElement | null {\n if (!reference) {\n return null;\n }\n const list = visibleTabbablesIn(reference.ownerDocument.body);\n const index = list.indexOf(reference as HTMLElement);\n if (list.length === 0 || index === -1) {\n return null;\n }\n return list[(index + dir + list.length) % list.length];\n}\n\n/** The tabbable immediately after `reference` in the document, wrapping (Base UI `getTabbableAfterElement`). */\nexport function getTabbableAfterElement(reference: Element | null): HTMLElement | null {\n return getTabbableNearElement(reference, 1);\n}\n\n/** The tabbable immediately before `reference` in the document, wrapping (Base UI `getTabbableBeforeElement`). */\nexport function getTabbableBeforeElement(reference: Element | null): HTMLElement | null {\n return getTabbableNearElement(reference, -1);\n}\n\nexport function isSelectableInput(element: any): element is FocusableTarget & { select: () => void } {\n return element instanceof HTMLInputElement && 'select' in element;\n}\n\nexport function focus(element?: FocusableTarget | null, { select = false } = {}) {\n // only focus if that element is focusable\n if (element && element.focus) {\n const previouslyFocusedElement = getActiveElement();\n // NOTE: we prevent scrolling on focus, to minimize jarring transitions for users\n element.focus({ preventScroll: true });\n // only select if its not the same element, it supports selection and we need to select\n if (element !== previouslyFocusedElement && isSelectableInput(element) && select) {\n element.select();\n }\n }\n}\n","import { effect } from '@angular/core';\nimport { composedContains, getTabbableCandidates } from './utils';\n\n/** Marks the leading / trailing focus-guard spans (Base UI `data-base-ui-focus-guard`). */\nexport const FOCUS_GUARD_ATTR = 'data-rdx-focus-guard';\n\n/** Saved-tabindex marker used by {@link disableFocusInside} / {@link enableFocusInside}. */\nconst SAVED_TABINDEX_ATTR = 'data-rdx-tabindex';\n\n/** Visually-hidden, off-flow style for a focus guard / `aria-owns` anchor (Base UI `visuallyHidden`). */\nexport const FOCUS_GUARD_STYLE: Partial<CSSStyleDeclaration> = {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n border: '0'\n};\n\n/**\n * Creates a visually-hidden, **tabbable** focus-guard `<span>` — the Angular counterpart of Base UI's\n * `FocusGuard`. The portal-focus bridge places one before and one after the portal content so a Tab into\n * (or out of) the portal lands on a guard, which then redirects focus to the right boundary.\n */\nexport function createFocusGuard(ownerDocument: Document): HTMLSpanElement {\n const guard = ownerDocument.createElement('span');\n guard.setAttribute('tabindex', '0');\n guard.setAttribute('aria-hidden', 'true');\n guard.setAttribute(FOCUS_GUARD_ATTR, '');\n Object.assign(guard.style, FOCUS_GUARD_STYLE);\n return guard;\n}\n\n/**\n * Creates a visually-hidden `<span aria-owns=\"…\">` that links the portal node into the trigger's tab /\n * AT order (Base UI's single `aria-owns` anchor). The manager places it next to the trigger.\n */\nexport function createAriaOwnsAnchor(ownerDocument: Document, portalId: string): HTMLSpanElement {\n const anchor = ownerDocument.createElement('span');\n anchor.setAttribute('aria-owns', portalId);\n Object.assign(anchor.style, FOCUS_GUARD_STYLE);\n return anchor;\n}\n\n/**\n * Makes every tabbable descendant of `container` **non-tabbable** (`tabindex=\"-1\"`), saving each one's\n * original tabindex so {@link enableFocusInside} can restore it. Base UI `disableFocusInside`: a\n * non-modal portal keeps its content untabbable until focus is actually inside it, so a Tab from the\n * trigger steps onto the guard instead of jumping into the content.\n */\nexport function disableFocusInside(container: HTMLElement): void {\n for (const element of getTabbableCandidates(container)) {\n element.setAttribute(SAVED_TABINDEX_ATTR, element.getAttribute('tabindex') ?? '');\n element.setAttribute('tabindex', '-1');\n }\n}\n\n/** Restores the tabbability that {@link disableFocusInside} suspended. Base UI `enableFocusInside`. */\nexport function enableFocusInside(container: HTMLElement): void {\n container.querySelectorAll<HTMLElement>(`[${SAVED_TABINDEX_ATTR}]`).forEach((element) => {\n const original = element.getAttribute(SAVED_TABINDEX_ATTR);\n element.removeAttribute(SAVED_TABINDEX_ATTR);\n if (original) {\n element.setAttribute('tabindex', original);\n } else {\n element.removeAttribute('tabindex');\n }\n });\n}\n\n/**\n * Whether a focus event crossed the `container` boundary — its `relatedTarget` (the other side of the\n * focus move) is `null` or outside `container` (Base UI `isOutsideEvent`). Shadow-DOM-aware via\n * {@link composedContains}.\n */\nexport function isOutsideEvent(event: FocusEvent, container: Element): boolean {\n const relatedTarget = event.relatedTarget as Node | null;\n return !relatedTarget || !composedContains(container, relatedTarget);\n}\n\n/**\n * The portal-focus bridge's **tabbability toggle** (Base UI `FloatingPortal` capture-phase `onFocus`).\n * While `portalNode` is mounted (and `enabled`), it makes the portal content tabbable **only when focus\n * is inside it**: focus entering from outside re-enables tabbability, focus leaving to outside disables\n * it again. Listens on the **capture** phase so it settles before the focus manager's guards react.\n *\n * Must be called in an injection context. The initial disable-on-mount and the guard-span placement are\n * the manager's responsibility (Phase 1b); this owns only the dynamic in/out toggle.\n */\nexport function useFocusGuardsTabbability(\n portalNode: () => HTMLElement | null,\n options: { enabled?: () => boolean } = {}\n): void {\n const enabled = options.enabled ?? (() => true);\n let focusInsideDisabled = false;\n\n effect((onCleanup) => {\n const node = portalNode();\n if (!node || !enabled()) {\n return;\n }\n const ownerDocument = node.ownerDocument;\n\n const onFocus = (event: FocusEvent): void => {\n // Only react to focus actually crossing the portal boundary.\n if (!event.relatedTarget || !isOutsideEvent(event, node)) {\n return;\n }\n if (event.type === 'focusin') {\n if (focusInsideDisabled) {\n enableFocusInside(node);\n focusInsideDisabled = false;\n }\n } else {\n disableFocusInside(node);\n focusInsideDisabled = true;\n }\n };\n\n if (isOutsideEvent(new FocusEvent('focusin', { relatedTarget: ownerDocument.activeElement }), node)) {\n disableFocusInside(node);\n focusInsideDisabled = true;\n }\n\n node.addEventListener('focusin', onFocus, true);\n node.addEventListener('focusout', onFocus, true);\n onCleanup(() => {\n node.removeEventListener('focusin', onFocus, true);\n node.removeEventListener('focusout', onFocus, true);\n if (focusInsideDisabled) {\n enableFocusInside(node);\n focusInsideDisabled = false;\n }\n });\n });\n}\n","import { InjectionToken, Provider, Signal, signal } from '@angular/core';\n\nexport type RdxFocusScopeConfig = {\n trapped: Signal<boolean>;\n\n /**\n * Optional return-focus policy override (ADR 0017 `returnFocus`), resolved by an enclosing\n * {@link RdxFloatingFocusManager} at **unmount time**. The focus scope owns the *timing* (its queued\n * post-unmount focus); this lets the manager own the *target*:\n * - `false` → do **not** return focus;\n * - an `HTMLElement` → return focus there **explicitly** (bypasses the moved-focus guard, matching\n * Base UI's `hasExplicitReturnFocus`);\n * - `undefined` → default behavior (return to the element focused before mount, with the guard).\n */\n returnFocus?: () => HTMLElement | false | undefined;\n};\n\nexport const RdxFocusScopeConfigToken = new InjectionToken<RdxFocusScopeConfig>('RdxFocusScopeConfig', {\n factory: () => ({\n trapped: signal(false)\n })\n});\n\nexport function provideRdxFocusScopeConfig(factory: () => RdxFocusScopeConfig): Provider {\n return { provide: RdxFocusScopeConfigToken, useFactory: factory };\n}\n","import { signal, WritableSignal } from '@angular/core';\n\nexport interface FocusScopeAPI {\n paused: WritableSignal<boolean>;\n pause(): void;\n resume(): void;\n}\n\n/**\n * The active-scope stack pauses/resumes scopes, so it **is** cross-document coordination state — keyed\n * per owner `Document` (a `WeakMap`) rather than process-global (ADR 0017 Phase 1a): opening a scope in\n * document B must not pause document A's scope.\n */\nconst stacksByDocument = new WeakMap<Document, WritableSignal<FocusScopeAPI[]>>();\n\nfunction getFocusStackState(document: Document): WritableSignal<FocusScopeAPI[]> {\n let state = stacksByDocument.get(document);\n if (!state) {\n state = signal<FocusScopeAPI[]>([]);\n stacksByDocument.set(document, state);\n }\n return state;\n}\n\nexport function createFocusScopesStack(document: Document) {\n /** A stack of focus scopes for this document, with the active one at the top */\n const stack = getFocusStackState(document);\n\n return {\n add(focusScope: FocusScopeAPI) {\n const current = stack();\n const active = current[0];\n if (focusScope !== active) {\n active?.pause();\n }\n const updated = arrayRemove(current, focusScope);\n updated.unshift(focusScope);\n stack.set(updated);\n },\n\n remove(focusScope: FocusScopeAPI) {\n const current = stack();\n const updated = arrayRemove(current, focusScope);\n stack.set(updated);\n // после удаления «возобновляем» новый верхний\n stack()[0]?.resume();\n }\n };\n}\n\nexport function arrayRemove<T>(array: T[], item: T): T[] {\n const copy = [...array];\n const idx = copy.indexOf(item);\n if (idx !== -1) {\n copy.splice(idx, 1);\n }\n return copy;\n}\n\nexport function removeLinks(items: HTMLElement[]): HTMLElement[] {\n return items.filter((el) => el.tagName !== 'A');\n}\n","import {\n afterNextRender,\n booleanAttribute,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n Injector,\n input,\n output,\n Signal,\n signal\n} from '@angular/core';\nimport { BooleanInput, createContext, getActiveElement } from '@radix-ng/primitives/core';\nimport { RdxFocusScopeConfigToken } from './focus-scope.config';\nimport { createFocusScopesStack, FocusScopeAPI, removeLinks } from './stack';\nimport {\n AUTOFOCUS_ON_MOUNT,\n AUTOFOCUS_ON_UNMOUNT,\n composedContains,\n EVENT_OPTIONS,\n focus,\n focusFirst,\n getEventTarget,\n getTabbableCandidates,\n getTabbableEdges\n} from './utils';\n\nexport interface FocusScopeContext {\n loop?: Signal<boolean>;\n\n trapped?: Signal<boolean>;\n}\n\nexport const [injectFocusScopeContext, provideFocusScopeContext] = createContext<FocusScopeContext>(\n 'FocusScope Context',\n 'utils/focus-scope'\n);\n\nconst rootContext = (): FocusScopeContext => {\n const context = inject(RdxFocusScope);\n\n return {\n loop: context.loop,\n trapped: context.isTrapped\n };\n};\n\n/**\n * @group Components\n */\n@Directive({\n selector: '[rdxFocusScope]',\n providers: [provideFocusScopeContext(rootContext)],\n host: {\n tabindex: '-1',\n '(keydown)': 'handleKeyDown($event)'\n }\n})\nexport class RdxFocusScope {\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly config = inject(RdxFocusScopeConfigToken);\n\n /** The host's owner `Document` — all focus listeners / reads are scoped here, never global `document`. */\n private readonly ownerDocument = this.elementRef.nativeElement.ownerDocument ?? document;\n\n /**\n * When `true`, tabbing from last item will focus first tabbable\n * and shift+tab from first item will focus last tababble.\n *\n * @group Props\n * @defaultValue false\n */\n readonly loop = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * When `true`, focus cannot escape the focus scope via keyboard,\n * pointer, or a programmatic focus.\n *\n * @group Props\n * @defaultValue false\n */\n readonly trapped = input<boolean | undefined, BooleanInput | undefined>(undefined, {\n transform: (value) => (value === undefined ? undefined : booleanAttribute(value))\n });\n\n readonly isTrapped = computed(() => this.trapped() ?? this.config.trapped());\n\n /**\n * Event handler called when auto-focusing on mount.\n * Can be prevented.\n *\n * @group Emits\n */\n readonly mountAutoFocus = output<Event>();\n\n /**\n * Event handler called when auto-focusing on unmount.\n * Can be prevented.\n *\n * @group Emits\n */\n readonly unmountAutoFocus = output<Event>();\n\n readonly lastFocusedElement = signal<HTMLElement | null>(null);\n\n private readonly focusScopesStack = createFocusScopesStack(this.ownerDocument);\n\n readonly focusScope: FocusScopeAPI = {\n paused: signal(false),\n pause: () => this.focusScope.paused.set(true),\n resume: () => this.focusScope.paused.set(false)\n };\n\n private alive = true;\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.alive = false;\n });\n\n afterNextRender(() => {\n effect(\n (onCleanup) => {\n const container = this.elementRef.nativeElement;\n\n if (this.isTrapped()) {\n const handleFocusIn = (event: FocusEvent) => {\n if (this.focusScope.paused() || !container) {\n return;\n }\n\n const target = getEventTarget(event) as HTMLElement | null;\n if (composedContains(container, target)) {\n this.lastFocusedElement.set(target);\n } else {\n focus(this.lastFocusedElement(), { select: true });\n }\n };\n\n const handleFocusOut = (event: FocusEvent) => {\n if (this.focusScope.paused() || !container) {\n return;\n }\n const relatedTarget = event.relatedTarget as HTMLElement | null;\n\n // A `focusout` event with a `null` `relatedTarget` will happen in at least two cases:\n //\n // 1. When the user switches app/tabs/windows/the browser itself loses focus.\n // 2. In Google Chrome, when the focused element is removed from the DOM.\n //\n // We let the browser do its thing here because:\n //\n // 1. The browser already keeps a memory of what's focused for when the page gets refocused.\n // 2. In Google Chrome, if we try to focus the deleted focused element (as per below), it\n // throws the CPU to 100%, so we avoid doing anything for this reason here too.\n if (relatedTarget === null) return;\n\n // If the focus has moved to an actual legitimate element (`relatedTarget !== null`)\n // that is outside the container, we move focus to the last valid focused element inside.\n if (!composedContains(container, relatedTarget)) {\n focus(this.lastFocusedElement(), { select: true });\n }\n };\n\n const handleMutations = () => {\n const isLastFocusedElementExist = composedContains(container, this.lastFocusedElement());\n\n if (!isLastFocusedElementExist) {\n focus(container);\n }\n };\n\n const mutationObserver = new MutationObserver(handleMutations);\n if (container) {\n mutationObserver.observe(container, { childList: true, subtree: true });\n }\n\n this.ownerDocument.addEventListener('focusin', handleFocusIn);\n this.ownerDocument.addEventListener('focusout', handleFocusOut);\n\n onCleanup(() => {\n this.ownerDocument.removeEventListener('focusin', handleFocusIn);\n this.ownerDocument.removeEventListener('focusout', handleFocusOut);\n mutationObserver.disconnect();\n });\n }\n },\n { injector: this.injector }\n );\n\n effect(\n async (onCleanup) => {\n const container = this.elementRef.nativeElement;\n\n await Promise.resolve();\n if (!container || !this.alive) {\n return;\n }\n\n this.focusScopesStack.add(this.focusScope);\n\n const previouslyFocusedElement = getActiveElement(this.ownerDocument) as HTMLElement | null;\n const hasFocusedCandidate = composedContains(container, previouslyFocusedElement);\n const mountEventHandler = (ev: Event) => {\n if (this.alive) this.mountAutoFocus.emit(ev);\n };\n\n if (!hasFocusedCandidate) {\n const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS);\n container.addEventListener(AUTOFOCUS_ON_MOUNT, mountEventHandler);\n container.dispatchEvent(mountEvent);\n\n if (!mountEvent.defaultPrevented) {\n focusFirst(removeLinks(getTabbableCandidates(container)), {\n select: true\n });\n if (getActiveElement(this.ownerDocument) === previouslyFocusedElement) focus(container);\n }\n }\n\n const unmountEventHandler = (ev: Event) => {\n if (this.alive) this.unmountAutoFocus.emit(ev);\n };\n container.addEventListener(AUTOFOCUS_ON_UNMOUNT, unmountEventHandler);\n\n onCleanup(() => {\n container.removeEventListener(AUTOFOCUS_ON_MOUNT, mountEventHandler);\n\n const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS);\n container.dispatchEvent(unmountEvent);\n\n // Queue the return-focus on the owner window's animation frame (not `setTimeout`),\n // so it runs after the unmounting paint settles (ADR 0017 Phase 1a queued focus).\n const view = this.ownerDocument.defaultView ?? globalThis;\n view.requestAnimationFrame(() => {\n // An enclosing focus manager can override the return target (ADR 0017\n // `returnFocus`): `false` suppresses it, an element returns there explicitly\n // (bypassing the moved-focus guard), `undefined` keeps the default behavior.\n const override = this.config.returnFocus?.();\n if (override !== false && !unmountEvent.defaultPrevented) {\n if (override) {\n focus(override, { select: true });\n } else if (!this.shouldPreserveMovedFocus()) {\n focus(previouslyFocusedElement ?? this.ownerDocument.body, { select: true });\n }\n }\n\n // we need to remove the listener after we `dispatchEvent`\n container.removeEventListener(AUTOFOCUS_ON_UNMOUNT, unmountEventHandler);\n\n this.focusScopesStack.remove(this.focusScope);\n });\n });\n },\n { injector: this.injector }\n );\n });\n }\n\n /**\n * Whether the interaction that unmounted this scope already moved focus to a legitimate element\n * **outside** it — e.g. an outside press onto an interactive control in a non-modal layer (ADR 0017\n * §2, finding #3). Returning focus to the previously-focused element would then *steal* it back from\n * what the user just acted on. Focus that fell to `<body>` / `null` (a backdrop press, Escape, or the\n * focused element being removed) is **not** \"moved\" — return focus normally so keyboard users land\n * back on the trigger. The page never scroll-jumps either way: {@link focus} uses `preventScroll`.\n */\n private shouldPreserveMovedFocus(): boolean {\n const active = getActiveElement(this.ownerDocument) as HTMLElement | null;\n return (\n !!active && active !== this.ownerDocument.body && !composedContains(this.elementRef.nativeElement, active)\n );\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const isTabKey = event.key === 'Tab' && !event.altKey && !event.ctrlKey && !event.metaKey;\n\n const focusedElement = getActiveElement(this.ownerDocument) as HTMLElement | null;\n\n if (isTabKey && focusedElement) {\n const container = event.currentTarget as HTMLElement;\n\n const [first, last] = getTabbableEdges(container);\n const hasTabbableElementsInside = first && last;\n\n // we can only wrap focus if we have tabbable edges\n if (!hasTabbableElementsInside) {\n if (focusedElement === container) event.preventDefault();\n } else {\n if (!event.shiftKey && focusedElement === last) {\n event.preventDefault();\n if (this.loop()) {\n focus(first, { select: true });\n }\n } else if (event.shiftKey && focusedElement === first) {\n event.preventDefault();\n if (this.loop()) {\n focus(last, { select: true });\n }\n }\n }\n }\n }\n}\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-focus-scope.mjs","sources":["../../../packages/primitives/focus-scope/src/utils.ts","../../../packages/primitives/focus-scope/src/focus-guards.ts","../../../packages/primitives/focus-scope/src/focus-scope.config.ts","../../../packages/primitives/focus-scope/src/stack.ts","../../../packages/primitives/focus-scope/src/focus-scope.ts","../../../packages/primitives/focus-scope/radix-ng-primitives-focus-scope.ts"],"sourcesContent":["import { getActiveElement } from '@radix-ng/primitives/core';\n\nexport const AUTOFOCUS_ON_MOUNT = 'focusScope.autoFocusOnMount';\nexport const AUTOFOCUS_ON_UNMOUNT = 'focusScope.autoFocusOnUnmount';\nexport const EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\ntype FocusableTarget = HTMLElement | { focus: () => void };\n\n/**\n * The real target of a (possibly retargeted) event, piercing shadow boundaries via `composedPath()`.\n * Falls back to `event.target` when `composedPath` is unavailable.\n */\nexport function getEventTarget(event: Event): EventTarget | null {\n return event.composedPath?.()[0] ?? event.target;\n}\n\n/**\n * Shadow-DOM-aware containment: whether `node` is `container` or lives inside it, crossing shadow roots\n * via their `host` (unlike `Node.contains`, which stops at a shadow boundary).\n */\nexport function composedContains(container: Node, node: Node | null): boolean {\n let current: Node | null = node;\n while (current) {\n if (current === container) {\n return true;\n }\n current = current instanceof ShadowRoot ? current.host : current.parentNode;\n }\n return false;\n}\n\n/**\n * Attempts focusing the first element in a list of candidates.\n * Stops when focus has actually moved.\n */\nexport function focusFirst(candidates: HTMLElement[], { select = false } = {}) {\n const previouslyFocusedElement = getActiveElement();\n for (const candidate of candidates) {\n focus(candidate, { select });\n if (getActiveElement() !== previouslyFocusedElement) return true;\n }\n\n return;\n}\n\n/**\n * Returns a list of potential tabbable candidates.\n *\n * NOTE: This is only a close approximation. For example it doesn't take into account cases like when\n * elements are not visible. This cannot be worked out easily by just reading a property, but rather\n * necessitate runtime knowledge (computed styles, etc). We deal with these cases separately.\n *\n * See: https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker\n * Credit: https://github.com/discord/focus-layers/blob/master/src/util/wrapFocus.tsx#L1\n */\nexport function getTabbableCandidates(container: HTMLElement) {\n const nodes: HTMLElement[] = [];\n const walker = container.ownerDocument.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node: any) => {\n const isHiddenInput = node.tagName === 'INPUT' && node.type === 'hidden';\n if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;\n // `.tabIndex` is not the same as the `tabindex` attribute. It works on the\n // runtime's understanding of tabbability, so this automatically accounts\n // for any kind of element that could be tabbed to.\n return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n });\n while (walker.nextNode()) nodes.push(walker.currentNode as HTMLElement);\n // we do not take into account the order of nodes with positive `tabIndex` as it\n // hinders accessibility to have tab order different from visual order.\n return nodes;\n}\n\nexport function isHidden(node: HTMLElement, { upTo }: { upTo?: HTMLElement }) {\n const view = node.ownerDocument.defaultView;\n if (!view) {\n return false; // no view (detached / SSR) — cannot resolve computed styles, treat as visible\n }\n if (view.getComputedStyle(node).visibility === 'hidden') return true;\n while (node) {\n // we stop at `upTo` (excluding it)\n if (upTo !== undefined && node === upTo) return false;\n if (view.getComputedStyle(node).display === 'none') return true;\n node = node.parentElement as HTMLElement;\n }\n return false;\n}\n\n/**\n * Returns the first visible element in a list.\n * NOTE: Only checks visibility up to the `container`.\n */\nexport function findVisible(elements: HTMLElement[], container: HTMLElement): HTMLElement | undefined {\n for (const element of elements) {\n // we stop checking if it's hidden at the `container` level (excluding)\n if (!isHidden(element, { upTo: container })) return element;\n }\n return undefined;\n}\n\n/**\n * Returns the first and last tabbable elements inside a container.\n */\nexport function getTabbableEdges(container: HTMLElement) {\n const candidates = getTabbableCandidates(container);\n const first = findVisible(candidates, container);\n const last = findVisible(candidates.reverse(), container);\n return [first, last] as const;\n}\n\n/** Visible tabbable elements of `root` in document order (the basis for tab-order navigation). */\nfunction visibleTabbablesIn(root: HTMLElement): HTMLElement[] {\n return getTabbableCandidates(root).filter((el) => !isHidden(el, { upTo: root }));\n}\n\n/** The tabbable one step (`dir`) from the document's active element, within `container`. */\nfunction getTabbableIn(container: HTMLElement, dir: 1 | -1): HTMLElement | undefined {\n const list = visibleTabbablesIn(container);\n if (list.length === 0) {\n return undefined;\n }\n const active = getActiveElement(container.ownerDocument) as HTMLElement | null;\n const index = active ? list.indexOf(active) : -1;\n const nextIndex = index === -1 ? (dir === 1 ? 0 : list.length - 1) : index + dir;\n return list[nextIndex];\n}\n\n/**\n * The next tabbable in the document after the current focus (Base UI `getNextTabbable`) — used by the\n * portal-focus bridge's trailing guard to step focus past the popup. Falls back to `reference`.\n */\nexport function getNextTabbable(reference: Element | null): HTMLElement | null {\n const body = (reference?.ownerDocument ?? document).body;\n return getTabbableIn(body, 1) ?? (reference as HTMLElement | null);\n}\n\n/** The previous tabbable in the document before the current focus (Base UI `getPreviousTabbable`). */\nexport function getPreviousTabbable(reference: Element | null): HTMLElement | null {\n const body = (reference?.ownerDocument ?? document).body;\n return getTabbableIn(body, -1) ?? (reference as HTMLElement | null);\n}\n\n/** The tabbable `dir` steps from `reference` in the document, wrapping around. */\nfunction getTabbableNearElement(reference: Element | null, dir: 1 | -1): HTMLElement | null {\n if (!reference) {\n return null;\n }\n const list = visibleTabbablesIn(reference.ownerDocument.body);\n const index = list.indexOf(reference as HTMLElement);\n if (list.length === 0 || index === -1) {\n return null;\n }\n return list[(index + dir + list.length) % list.length];\n}\n\n/** The tabbable immediately after `reference` in the document, wrapping (Base UI `getTabbableAfterElement`). */\nexport function getTabbableAfterElement(reference: Element | null): HTMLElement | null {\n return getTabbableNearElement(reference, 1);\n}\n\n/** The tabbable immediately before `reference` in the document, wrapping (Base UI `getTabbableBeforeElement`). */\nexport function getTabbableBeforeElement(reference: Element | null): HTMLElement | null {\n return getTabbableNearElement(reference, -1);\n}\n\nexport function isSelectableInput(element: any): element is FocusableTarget & { select: () => void } {\n return element instanceof HTMLInputElement && 'select' in element;\n}\n\nexport function focus(element?: FocusableTarget | null, { select = false } = {}) {\n // only focus if that element is focusable\n if (element && element.focus) {\n const previouslyFocusedElement = getActiveElement();\n // NOTE: we prevent scrolling on focus, to minimize jarring transitions for users\n element.focus({ preventScroll: true });\n // only select if its not the same element, it supports selection and we need to select\n if (element !== previouslyFocusedElement && isSelectableInput(element) && select) {\n element.select();\n }\n }\n}\n","import { effect } from '@angular/core';\nimport { composedContains, getTabbableCandidates } from './utils';\n\n/** Marks the leading / trailing focus-guard spans (Base UI `data-base-ui-focus-guard`). */\nexport const FOCUS_GUARD_ATTR = 'data-rdx-focus-guard';\n\n/** Saved-tabindex marker used by {@link disableFocusInside} / {@link enableFocusInside}. */\nconst SAVED_TABINDEX_ATTR = 'data-rdx-tabindex';\n\n/** Visually-hidden, off-flow style for a focus guard / `aria-owns` anchor (Base UI `visuallyHidden`). */\nexport const FOCUS_GUARD_STYLE: Partial<CSSStyleDeclaration> = {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n border: '0'\n};\n\n/**\n * Creates a visually-hidden, **tabbable** focus-guard `<span>` — the Angular counterpart of Base UI's\n * `FocusGuard`. The portal-focus bridge places one before and one after the portal content so a Tab into\n * (or out of) the portal lands on a guard, which then redirects focus to the right boundary.\n */\nexport function createFocusGuard(ownerDocument: Document): HTMLSpanElement {\n const guard = ownerDocument.createElement('span');\n guard.setAttribute('tabindex', '0');\n guard.setAttribute('aria-hidden', 'true');\n guard.setAttribute(FOCUS_GUARD_ATTR, '');\n Object.assign(guard.style, FOCUS_GUARD_STYLE);\n return guard;\n}\n\n/**\n * Creates a visually-hidden `<span aria-owns=\"…\">` that links the portal node into the trigger's tab /\n * AT order (Base UI's single `aria-owns` anchor). The manager places it next to the trigger.\n */\nexport function createAriaOwnsAnchor(ownerDocument: Document, portalId: string): HTMLSpanElement {\n const anchor = ownerDocument.createElement('span');\n anchor.setAttribute('aria-owns', portalId);\n Object.assign(anchor.style, FOCUS_GUARD_STYLE);\n return anchor;\n}\n\n/**\n * Makes every tabbable descendant of `container` **non-tabbable** (`tabindex=\"-1\"`), saving each one's\n * original tabindex so {@link enableFocusInside} can restore it. Base UI `disableFocusInside`: a\n * non-modal portal keeps its content untabbable until focus is actually inside it, so a Tab from the\n * trigger steps onto the guard instead of jumping into the content.\n */\nexport function disableFocusInside(container: HTMLElement): void {\n for (const element of getTabbableCandidates(container)) {\n element.setAttribute(SAVED_TABINDEX_ATTR, element.getAttribute('tabindex') ?? '');\n element.setAttribute('tabindex', '-1');\n }\n}\n\n/** Restores the tabbability that {@link disableFocusInside} suspended. Base UI `enableFocusInside`. */\nexport function enableFocusInside(container: HTMLElement): void {\n container.querySelectorAll<HTMLElement>(`[${SAVED_TABINDEX_ATTR}]`).forEach((element) => {\n const original = element.getAttribute(SAVED_TABINDEX_ATTR);\n element.removeAttribute(SAVED_TABINDEX_ATTR);\n if (original) {\n element.setAttribute('tabindex', original);\n } else {\n element.removeAttribute('tabindex');\n }\n });\n}\n\n/**\n * Whether a focus event crossed the `container` boundary — its `relatedTarget` (the other side of the\n * focus move) is `null` or outside `container` (Base UI `isOutsideEvent`). Shadow-DOM-aware via\n * {@link composedContains}.\n */\nexport function isOutsideEvent(event: FocusEvent, container: Element): boolean {\n const relatedTarget = event.relatedTarget as Node | null;\n return !relatedTarget || !composedContains(container, relatedTarget);\n}\n\n/**\n * The portal-focus bridge's **tabbability toggle** (Base UI `FloatingPortal` capture-phase `onFocus`).\n * While `portalNode` is mounted (and `enabled`), it makes the portal content tabbable **only when focus\n * is inside it**: focus entering from outside re-enables tabbability, focus leaving to outside disables\n * it again. Listens on the **capture** phase so it settles before the focus manager's guards react.\n *\n * Must be called in an injection context. The initial disable-on-mount and the guard-span placement are\n * the manager's responsibility (Phase 1b); this owns only the dynamic in/out toggle.\n */\nexport function useFocusGuardsTabbability(\n portalNode: () => HTMLElement | null,\n options: { enabled?: () => boolean } = {}\n): void {\n const enabled = options.enabled ?? (() => true);\n let focusInsideDisabled = false;\n\n effect((onCleanup) => {\n const node = portalNode();\n if (!node || !enabled()) {\n return;\n }\n const ownerDocument = node.ownerDocument;\n\n const onFocus = (event: FocusEvent): void => {\n // Only react to focus actually crossing the portal boundary.\n if (!event.relatedTarget || !isOutsideEvent(event, node)) {\n return;\n }\n if (event.type === 'focusin') {\n if (focusInsideDisabled) {\n enableFocusInside(node);\n focusInsideDisabled = false;\n }\n } else {\n disableFocusInside(node);\n focusInsideDisabled = true;\n }\n };\n\n if (isOutsideEvent(new FocusEvent('focusin', { relatedTarget: ownerDocument.activeElement }), node)) {\n disableFocusInside(node);\n focusInsideDisabled = true;\n }\n\n node.addEventListener('focusin', onFocus, true);\n node.addEventListener('focusout', onFocus, true);\n onCleanup(() => {\n node.removeEventListener('focusin', onFocus, true);\n node.removeEventListener('focusout', onFocus, true);\n if (focusInsideDisabled) {\n enableFocusInside(node);\n focusInsideDisabled = false;\n }\n });\n });\n}\n","import { InjectionToken, Provider, Signal, signal } from '@angular/core';\n\nexport type RdxFocusScopeConfig = {\n trapped: Signal<boolean>;\n\n /**\n * Optional return-focus policy override (ADR 0017 `returnFocus`), resolved by an enclosing\n * {@link RdxFloatingFocusManager} at **unmount time**. The focus scope owns the *timing* (its queued\n * post-unmount focus); this lets the manager own the *target*:\n * - `false` → do **not** return focus;\n * - an `HTMLElement` → return focus there **explicitly** (bypasses the moved-focus guard, matching\n * Base UI's `hasExplicitReturnFocus`);\n * - `undefined` → default behavior (return to the element focused before mount, with the guard).\n */\n returnFocus?: () => HTMLElement | false | undefined;\n};\n\nexport const RdxFocusScopeConfigToken = new InjectionToken<RdxFocusScopeConfig>('RdxFocusScopeConfig', {\n factory: () => ({\n trapped: signal(false)\n })\n});\n\nexport function provideRdxFocusScopeConfig(factory: () => RdxFocusScopeConfig): Provider {\n return { provide: RdxFocusScopeConfigToken, useFactory: factory };\n}\n","import { signal, WritableSignal } from '@angular/core';\n\nexport interface FocusScopeAPI {\n paused: WritableSignal<boolean>;\n pause(): void;\n resume(): void;\n}\n\n/**\n * The active-scope stack pauses/resumes scopes, so it **is** cross-document coordination state — keyed\n * per owner `Document` (a `WeakMap`) rather than process-global (ADR 0017 Phase 1a): opening a scope in\n * document B must not pause document A's scope.\n */\nconst stacksByDocument = new WeakMap<Document, WritableSignal<FocusScopeAPI[]>>();\n\nfunction getFocusStackState(document: Document): WritableSignal<FocusScopeAPI[]> {\n let state = stacksByDocument.get(document);\n if (!state) {\n state = signal<FocusScopeAPI[]>([]);\n stacksByDocument.set(document, state);\n }\n return state;\n}\n\nexport function createFocusScopesStack(document: Document) {\n /** A stack of focus scopes for this document, with the active one at the top */\n const stack = getFocusStackState(document);\n\n return {\n add(focusScope: FocusScopeAPI) {\n const current = stack();\n const active = current[0];\n if (focusScope !== active) {\n active?.pause();\n }\n const updated = arrayRemove(current, focusScope);\n updated.unshift(focusScope);\n stack.set(updated);\n },\n\n remove(focusScope: FocusScopeAPI) {\n const current = stack();\n const updated = arrayRemove(current, focusScope);\n stack.set(updated);\n // после удаления «возобновляем» новый верхний\n stack()[0]?.resume();\n }\n };\n}\n\nexport function arrayRemove<T>(array: T[], item: T): T[] {\n const copy = [...array];\n const idx = copy.indexOf(item);\n if (idx !== -1) {\n copy.splice(idx, 1);\n }\n return copy;\n}\n\nexport function removeLinks(items: HTMLElement[]): HTMLElement[] {\n return items.filter((el) => el.tagName !== 'A');\n}\n","import {\n afterNextRender,\n booleanAttribute,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n Injector,\n input,\n output,\n Signal,\n signal\n} from '@angular/core';\nimport { BooleanInput, createContext, getActiveElement } from '@radix-ng/primitives/core';\nimport { RdxFocusScopeConfigToken } from './focus-scope.config';\nimport { createFocusScopesStack, FocusScopeAPI, removeLinks } from './stack';\nimport {\n AUTOFOCUS_ON_MOUNT,\n AUTOFOCUS_ON_UNMOUNT,\n composedContains,\n EVENT_OPTIONS,\n focus,\n focusFirst,\n getEventTarget,\n getTabbableCandidates,\n getTabbableEdges\n} from './utils';\n\nexport interface FocusScopeContext {\n loop?: Signal<boolean>;\n\n trapped?: Signal<boolean>;\n}\n\nexport const [injectFocusScopeContext, provideFocusScopeContext] = createContext<FocusScopeContext>(\n 'FocusScope Context',\n 'utils/focus-scope'\n);\n\nconst rootContext = (): FocusScopeContext => {\n const context = inject(RdxFocusScope);\n\n return {\n loop: context.loop,\n trapped: context.isTrapped\n };\n};\n\n/**\n * @group Components\n */\n@Directive({\n selector: '[rdxFocusScope]',\n providers: [provideFocusScopeContext(rootContext)],\n host: {\n tabindex: '-1',\n '(keydown)': 'handleKeyDown($event)'\n }\n})\nexport class RdxFocusScope {\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly config = inject(RdxFocusScopeConfigToken);\n\n /** The host's owner `Document` — all focus listeners / reads are scoped here, never global `document`. */\n private readonly ownerDocument = this.elementRef.nativeElement.ownerDocument ?? document;\n\n /**\n * When `true`, tabbing from last item will focus first tabbable\n * and shift+tab from first item will focus last tababble.\n *\n * @group Props\n * @defaultValue false\n */\n readonly loop = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n /**\n * When `true`, focus cannot escape the focus scope via keyboard,\n * pointer, or a programmatic focus.\n *\n * @group Props\n * @defaultValue false\n */\n readonly trapped = input<boolean | undefined, BooleanInput | undefined>(undefined, {\n transform: (value) => (value === undefined ? undefined : booleanAttribute(value))\n });\n\n readonly isTrapped = computed(() => this.trapped() ?? this.config.trapped());\n\n /**\n * Event handler called when auto-focusing on mount.\n * Can be prevented.\n *\n * @group Emits\n */\n readonly mountAutoFocus = output<Event>();\n\n /**\n * Event handler called when auto-focusing on unmount.\n * Can be prevented.\n *\n * @group Emits\n */\n readonly unmountAutoFocus = output<Event>();\n\n readonly lastFocusedElement = signal<HTMLElement | null>(null);\n\n private readonly focusScopesStack = createFocusScopesStack(this.ownerDocument);\n\n readonly focusScope: FocusScopeAPI = {\n paused: signal(false),\n pause: () => this.focusScope.paused.set(true),\n resume: () => this.focusScope.paused.set(false)\n };\n\n private alive = true;\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.alive = false;\n });\n\n afterNextRender(() => {\n effect(\n (onCleanup) => {\n const container = this.elementRef.nativeElement;\n\n if (this.isTrapped()) {\n const handleFocusIn = (event: FocusEvent) => {\n if (this.focusScope.paused() || !container) {\n return;\n }\n\n const target = getEventTarget(event) as HTMLElement | null;\n if (composedContains(container, target)) {\n this.lastFocusedElement.set(target);\n } else {\n focus(this.lastFocusedElement(), { select: true });\n }\n };\n\n const handleFocusOut = (event: FocusEvent) => {\n if (this.focusScope.paused() || !container) {\n return;\n }\n const relatedTarget = event.relatedTarget as HTMLElement | null;\n\n // A `focusout` event with a `null` `relatedTarget` will happen in at least two cases:\n //\n // 1. When the user switches app/tabs/windows/the browser itself loses focus.\n // 2. In Google Chrome, when the focused element is removed from the DOM.\n //\n // We let the browser do its thing here because:\n //\n // 1. The browser already keeps a memory of what's focused for when the page gets refocused.\n // 2. In Google Chrome, if we try to focus the deleted focused element (as per below), it\n // throws the CPU to 100%, so we avoid doing anything for this reason here too.\n if (relatedTarget === null) return;\n\n // If the focus has moved to an actual legitimate element (`relatedTarget !== null`)\n // that is outside the container, we move focus to the last valid focused element inside.\n if (!composedContains(container, relatedTarget)) {\n focus(this.lastFocusedElement(), { select: true });\n }\n };\n\n const handleMutations = () => {\n const isLastFocusedElementExist = composedContains(container, this.lastFocusedElement());\n\n if (!isLastFocusedElementExist) {\n focus(container);\n }\n };\n\n const mutationObserver = new MutationObserver(handleMutations);\n if (container) {\n mutationObserver.observe(container, { childList: true, subtree: true });\n }\n\n this.ownerDocument.addEventListener('focusin', handleFocusIn);\n this.ownerDocument.addEventListener('focusout', handleFocusOut);\n\n onCleanup(() => {\n this.ownerDocument.removeEventListener('focusin', handleFocusIn);\n this.ownerDocument.removeEventListener('focusout', handleFocusOut);\n mutationObserver.disconnect();\n });\n }\n },\n { injector: this.injector }\n );\n\n effect(\n async (onCleanup) => {\n const container = this.elementRef.nativeElement;\n\n await Promise.resolve();\n if (!container || !this.alive) {\n return;\n }\n\n this.focusScopesStack.add(this.focusScope);\n\n const previouslyFocusedElement = getActiveElement(this.ownerDocument) as HTMLElement | null;\n const hasFocusedCandidate = composedContains(container, previouslyFocusedElement);\n const mountEventHandler = (ev: Event) => {\n if (this.alive) this.mountAutoFocus.emit(ev);\n };\n\n if (!hasFocusedCandidate) {\n const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS);\n container.addEventListener(AUTOFOCUS_ON_MOUNT, mountEventHandler);\n container.dispatchEvent(mountEvent);\n\n if (!mountEvent.defaultPrevented) {\n focusFirst(removeLinks(getTabbableCandidates(container)), {\n select: true\n });\n if (getActiveElement(this.ownerDocument) === previouslyFocusedElement) focus(container);\n }\n }\n\n const unmountEventHandler = (ev: Event) => {\n if (this.alive) this.unmountAutoFocus.emit(ev);\n };\n container.addEventListener(AUTOFOCUS_ON_UNMOUNT, unmountEventHandler);\n\n onCleanup(() => {\n container.removeEventListener(AUTOFOCUS_ON_MOUNT, mountEventHandler);\n\n const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS);\n container.dispatchEvent(unmountEvent);\n\n // Queue the return-focus on the owner window's animation frame (not `setTimeout`),\n // so it runs after the unmounting paint settles (ADR 0017 Phase 1a queued focus).\n const view = this.ownerDocument.defaultView ?? globalThis;\n view.requestAnimationFrame(() => {\n // An enclosing focus manager can override the return target (ADR 0017\n // `returnFocus`): `false` suppresses it, an element returns there explicitly\n // (bypassing the moved-focus guard), `undefined` keeps the default behavior.\n const override = this.config.returnFocus?.();\n if (override !== false && !unmountEvent.defaultPrevented) {\n if (override) {\n focus(override, { select: true });\n } else if (!this.shouldPreserveMovedFocus()) {\n focus(previouslyFocusedElement ?? this.ownerDocument.body, { select: true });\n }\n }\n\n // we need to remove the listener after we `dispatchEvent`\n container.removeEventListener(AUTOFOCUS_ON_UNMOUNT, unmountEventHandler);\n\n this.focusScopesStack.remove(this.focusScope);\n });\n });\n },\n { injector: this.injector }\n );\n });\n }\n\n /**\n * Whether the interaction that unmounted this scope already moved focus to a legitimate element\n * **outside** it — e.g. an outside press onto an interactive control in a non-modal layer (ADR 0017\n * §2, finding #3). Returning focus to the previously-focused element would then *steal* it back from\n * what the user just acted on. Focus that fell to `<body>` / `null` (a backdrop press, Escape, or the\n * focused element being removed) is **not** \"moved\" — return focus normally so keyboard users land\n * back on the trigger. The page never scroll-jumps either way: {@link focus} uses `preventScroll`.\n */\n private shouldPreserveMovedFocus(): boolean {\n const active = getActiveElement(this.ownerDocument) as HTMLElement | null;\n return (\n !!active && active !== this.ownerDocument.body && !composedContains(this.elementRef.nativeElement, active)\n );\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const isTabKey = event.key === 'Tab' && !event.altKey && !event.ctrlKey && !event.metaKey;\n\n const focusedElement = getActiveElement(this.ownerDocument) as HTMLElement | null;\n\n if (isTabKey && focusedElement) {\n const container = event.currentTarget as HTMLElement;\n\n const [first, last] = getTabbableEdges(container);\n const hasTabbableElementsInside = first && last;\n\n // we can only wrap focus if we have tabbable edges\n if (!hasTabbableElementsInside) {\n if (focusedElement === container) event.preventDefault();\n } else {\n if (!event.shiftKey && focusedElement === last) {\n event.preventDefault();\n if (this.loop()) {\n focus(first, { select: true });\n }\n } else if (event.shiftKey && focusedElement === first) {\n event.preventDefault();\n if (this.loop()) {\n focus(last, { select: true });\n }\n }\n }\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -117,15 +117,19 @@ class RdxFormRoot {
|
|
|
117
117
|
constructor() {
|
|
118
118
|
this.form = inject(ElementRef).nativeElement;
|
|
119
119
|
/** External/server validation errors keyed by `Field.Root` `name`. */
|
|
120
|
-
this.errors = input(
|
|
120
|
+
this.errors = input(/* @ts-ignore */
|
|
121
|
+
...(ngDevMode ? [undefined, { debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
121
122
|
/** Emits the remaining error map after a field's external error is cleared by a user edit (or reset). */
|
|
122
123
|
this.onClearErrors = output();
|
|
123
124
|
/** Emits the serialized form values when a valid form is submitted. */
|
|
124
125
|
this.onFormSubmit = output();
|
|
125
|
-
this.fields = signal([],
|
|
126
|
-
|
|
126
|
+
this.fields = signal([], /* @ts-ignore */
|
|
127
|
+
...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
|
|
128
|
+
this.stateProvider = signal(null, /* @ts-ignore */
|
|
129
|
+
...(ngDevMode ? [{ debugName: "stateProvider" }] : /* istanbul ignore next */ []));
|
|
127
130
|
/** Whether an external adapter currently owns form-level state. */
|
|
128
|
-
this.hasStateProvider = computed(() => this.stateProvider() !== null,
|
|
131
|
+
this.hasStateProvider = computed(() => this.stateProvider() !== null, /* @ts-ignore */
|
|
132
|
+
...(ngDevMode ? [{ debugName: "hasStateProvider" }] : /* istanbul ignore next */ []));
|
|
129
133
|
/**
|
|
130
134
|
* Names whose external error has been cleared by a user edit. Reset to empty whenever a new `errors`
|
|
131
135
|
* object reference is assigned — the server just spoke, so everything it said is live again.
|
|
@@ -145,11 +149,16 @@ class RdxFormRoot {
|
|
|
145
149
|
result[key] = Array.isArray(value) ? value : [value];
|
|
146
150
|
}
|
|
147
151
|
return result;
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
this.
|
|
151
|
-
|
|
152
|
-
this.
|
|
152
|
+
}, /* @ts-ignore */
|
|
153
|
+
...(ngDevMode ? [{ debugName: "effectiveErrors" }] : /* istanbul ignore next */ []));
|
|
154
|
+
this.anyInvalid = computed(() => this.aggregate('invalid'), /* @ts-ignore */
|
|
155
|
+
...(ngDevMode ? [{ debugName: "anyInvalid" }] : /* istanbul ignore next */ []));
|
|
156
|
+
this.anyDirty = computed(() => this.aggregate('dirty'), /* @ts-ignore */
|
|
157
|
+
...(ngDevMode ? [{ debugName: "anyDirty" }] : /* istanbul ignore next */ []));
|
|
158
|
+
this.anyTouched = computed(() => this.aggregate('touched'), /* @ts-ignore */
|
|
159
|
+
...(ngDevMode ? [{ debugName: "anyTouched" }] : /* istanbul ignore next */ []));
|
|
160
|
+
this.submitting = computed(() => this.stateProvider()?.submitting?.() ?? false, /* @ts-ignore */
|
|
161
|
+
...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
|
|
153
162
|
this.resetTimers = new Set();
|
|
154
163
|
inject(DestroyRef).onDestroy(() => this.resetTimers.forEach((timer) => clearTimeout(timer)));
|
|
155
164
|
}
|
|
@@ -164,10 +173,10 @@ class RdxFormRoot {
|
|
|
164
173
|
}
|
|
165
174
|
return result;
|
|
166
175
|
}
|
|
167
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
168
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
176
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFormRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
177
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxFormRoot, isStandalone: true, selector: "form[rdxFormRoot]", inputs: { errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClearErrors: "onClearErrors", onFormSubmit: "onFormSubmit" }, host: { attributes: { "novalidate": "" }, listeners: { "submit": "onSubmit($event)", "reset": "onReset()" }, properties: { "attr.data-invalid": "anyInvalid() ? \"\" : undefined", "attr.data-dirty": "anyDirty() ? \"\" : undefined", "attr.data-touched": "anyTouched() ? \"\" : undefined", "attr.data-submitting": "submitting() ? \"\" : undefined" } }, providers: [provideFormRootContext(formRootContext)], exportAs: ["rdxFormRoot"], ngImport: i0 }); }
|
|
169
178
|
}
|
|
170
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
179
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFormRoot, decorators: [{
|
|
171
180
|
type: Directive,
|
|
172
181
|
args: [{
|
|
173
182
|
selector: 'form[rdxFormRoot]',
|
|
@@ -187,11 +196,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
187
196
|
|
|
188
197
|
const _importsForm = [RdxFormRoot];
|
|
189
198
|
class RdxFormModule {
|
|
190
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
191
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
192
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
199
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
200
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.2", ngImport: i0, type: RdxFormModule, imports: [RdxFormRoot], exports: [RdxFormRoot] }); }
|
|
201
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFormModule }); }
|
|
193
202
|
}
|
|
194
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
203
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxFormModule, decorators: [{
|
|
195
204
|
type: NgModule,
|
|
196
205
|
args: [{
|
|
197
206
|
imports: [..._importsForm],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radix-ng-primitives-form.mjs","sources":["../../../packages/primitives/form/src/form-root.ts","../../../packages/primitives/form/index.ts","../../../packages/primitives/form/radix-ng-primitives-form.ts"],"sourcesContent":["import {\n computed,\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n input,\n linkedSignal,\n output,\n signal\n} from '@angular/core';\nimport { createContext } from '@radix-ng/primitives/core';\n\n/** A normalized external-error map: each field name maps to its message(s) in display order. */\nexport type RdxFormErrors = Record<string, string | string[]>;\n\n/** Payload of {@link RdxFormRoot.onFormSubmit}. */\nexport interface RdxFormSubmitEvent {\n /** The form's values serialized from `FormData` (repeated names collapse into arrays). */\n values: Record<string, FormDataEntryValue | FormDataEntryValue[]>;\n /** The original native submit event (already `preventDefault`-ed). */\n event: SubmitEvent;\n}\n\n/**\n * What a {@link RdxFieldRoot} registers with an enclosing Form. Structural `() =>` accessors keep the\n * Form entry free of any import from `field` (acyclic ng-packagr graph: `field` → `form`).\n */\nexport interface RdxFormFieldRegistration {\n /** The field's `name` (key external errors match against), or `undefined`. */\n name: () => string | undefined;\n /** The field's merged invalid state (includes external errors). */\n invalid: () => boolean;\n /** Whether the field is dirty. */\n dirty: () => boolean;\n /** Whether the field is touched. */\n touched: () => boolean;\n /** Focus the field's control (by its `controlId`). */\n focus: () => void;\n /** Reset the field's interaction state (touched/dirty/focused → false, filled re-sync). */\n resetState: () => void;\n}\n\n/**\n * External owner of form-level state (e.g. a future Signal Forms `[rdxSignalForm]` adapter). Mirrors\n * Field's `RdxFieldState` seam one level up. Each member is optional: a provided accessor wins over the\n * built-in registry/`errors`-input behavior; absent accessors leave the built-in behavior untouched.\n * Kept as framework-free `() =>` accessors (no `@angular/forms/signals` dependency). See ADR 0004.\n */\nexport interface RdxFormState {\n invalid?: () => boolean;\n dirty?: () => boolean;\n touched?: () => boolean;\n submitting?: () => boolean;\n /** Per-name external error source; while provided, the `errors` input + clear-on-edit are inert. */\n errorsFor?: (name: string) => string[];\n}\n\nconst formRootContext = () => {\n const root = inject(RdxFormRoot);\n return {\n errorsFor: (name: string | undefined) => root.errorsFor(name),\n notifyEdited: (name: string | undefined) => root.notifyEdited(name),\n register: (field: RdxFormFieldRegistration) => root.register(field),\n setStateProvider: (provider: RdxFormState | null) => root.setStateProvider(provider),\n hasStateProvider: root.hasStateProvider\n };\n};\n\nexport type RdxFormRootContext = ReturnType<typeof formRootContext>;\n\nexport const [injectFormRootContext, provideFormRootContext] = createContext<RdxFormRootContext>(\n 'RdxFormRoot',\n 'components/form'\n);\n\n/** Collapses `FormData` into a plain object; repeated names collapse into arrays. */\nfunction serializeFormData(data: FormData): Record<string, FormDataEntryValue | FormDataEntryValue[]> {\n const values: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};\n data.forEach((value, key) => {\n // `Object.hasOwn`, not `key in values` — a control named after an Object.prototype member\n // (`toString`, `constructor`, …) must not be misread as a duplicate.\n if (Object.hasOwn(values, key)) {\n const existing = values[key];\n values[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];\n } else {\n values[key] = value;\n }\n });\n return values;\n}\n\n/**\n * The top of the forms layer cake: a single directive on the native `<form>` element that aggregates\n * field state, maps external (server) errors onto fields by `name`, intercepts submit (values-as-object,\n * focus the first invalid field), and resets field interaction state on native `reset`. It owns no\n * values and runs no validation — Angular form systems (or Field inputs) remain the source of validity.\n *\n * @group Components\n */\n@Directive({\n selector: 'form[rdxFormRoot]',\n exportAs: 'rdxFormRoot',\n providers: [provideFormRootContext(formRootContext)],\n host: {\n novalidate: '',\n '[attr.data-invalid]': 'anyInvalid() ? \"\" : undefined',\n '[attr.data-dirty]': 'anyDirty() ? \"\" : undefined',\n '[attr.data-touched]': 'anyTouched() ? \"\" : undefined',\n '[attr.data-submitting]': 'submitting() ? \"\" : undefined',\n '(submit)': 'onSubmit($event)',\n '(reset)': 'onReset()'\n }\n})\nexport class RdxFormRoot {\n private readonly form = inject<ElementRef<HTMLFormElement>>(ElementRef).nativeElement;\n\n /** External/server validation errors keyed by `Field.Root` `name`. */\n readonly errors = input<RdxFormErrors | null | undefined>();\n\n /** Emits the remaining error map after a field's external error is cleared by a user edit (or reset). */\n readonly onClearErrors = output<RdxFormErrors>();\n\n /** Emits the serialized form values when a valid form is submitted. */\n readonly onFormSubmit = output<RdxFormSubmitEvent>();\n\n private readonly fields = signal<RdxFormFieldRegistration[]>([]);\n\n private readonly stateProvider = signal<RdxFormState | null>(null);\n\n /** Whether an external adapter currently owns form-level state. */\n readonly hasStateProvider = computed(() => this.stateProvider() !== null);\n\n /**\n * Names whose external error has been cleared by a user edit. Reset to empty whenever a new `errors`\n * object reference is assigned — the server just spoke, so everything it said is live again.\n */\n private readonly clearedNames = linkedSignal<RdxFormErrors | null | undefined, Set<string>>({\n source: this.errors,\n computation: () => new Set<string>()\n });\n\n /** The `errors` input minus cleared names, normalized to `string[]`. */\n private readonly effectiveErrors = computed<Record<string, string[]>>(() => {\n const errors = this.errors() ?? {};\n const cleared = this.clearedNames();\n const result: Record<string, string[]> = {};\n for (const key of Object.keys(errors)) {\n if (cleared.has(key)) {\n continue;\n }\n const value = errors[key];\n result[key] = Array.isArray(value) ? value : [value];\n }\n return result;\n });\n\n readonly anyInvalid = computed(() => this.aggregate('invalid'));\n readonly anyDirty = computed(() => this.aggregate('dirty'));\n readonly anyTouched = computed(() => this.aggregate('touched'));\n readonly submitting = computed(() => this.stateProvider()?.submitting?.() ?? false);\n\n /** Resolve a boolean aggregate: a registered provider's accessor wins, else OR over the registry. */\n private aggregate(key: 'invalid' | 'dirty' | 'touched'): boolean {\n const accessor = this.stateProvider()?.[key];\n return accessor ? accessor() : this.fields().some((field) => field[key]());\n }\n\n /** Resolves the external messages for a field name (provider source wins over the `errors` input). */\n errorsFor(name: string | undefined): string[] {\n if (!name) {\n return [];\n }\n const provider = this.stateProvider();\n if (provider?.errorsFor) {\n return provider.errorsFor(name);\n }\n return this.effectiveErrors()[name] ?? [];\n }\n\n /** Clears a field's external error after a user edit, emitting the remaining map. */\n notifyEdited(name: string | undefined): void {\n if (!name) {\n return;\n }\n // While a provider owns errors, Signal Forms clears/reapplies them itself — stay inert.\n if (this.stateProvider()?.errorsFor) {\n return;\n }\n const errors = this.errors() ?? {};\n if (!Object.hasOwn(errors, name) || this.clearedNames().has(name)) {\n return;\n }\n this.clearedNames.update((set) => new Set(set).add(name));\n this.onClearErrors.emit(this.remainingErrors());\n }\n\n register(field: RdxFormFieldRegistration): () => void {\n this.fields.update((list) => [...list, field]);\n return () => this.fields.update((list) => list.filter((item) => item !== field));\n }\n\n /** Register (or clear with `null`) an external owner of form-level state; returns the previous one. */\n setStateProvider(provider: RdxFormState | null): RdxFormState | null {\n const previous = this.stateProvider();\n this.stateProvider.set(provider);\n return previous;\n }\n\n onSubmit(event: SubmitEvent): void {\n // SPA submits never navigate; never stopPropagation so Reactive Forms `(ngSubmit)` keeps firing.\n event.preventDefault();\n\n if (this.aggregate('invalid')) {\n // Focus the first invalid registered field (DOM order); provider-only invalid has none to focus.\n this.fields()\n .find((field) => field.invalid())\n ?.focus();\n return;\n }\n\n const values = serializeFormData(new FormData(this.form));\n this.onFormSubmit.emit({ values, event });\n }\n\n onReset(): void {\n // Don't prevent the native reset — control values revert on their own.\n if (!this.stateProvider()?.errorsFor) {\n const keys = Object.keys(this.errors() ?? {});\n const hadVisible = keys.some((key) => !this.clearedNames().has(key));\n if (keys.length) {\n this.clearedNames.set(new Set(keys));\n }\n if (hadVisible) {\n this.onClearErrors.emit({});\n }\n }\n // Values revert asynchronously relative to the reset event — re-sync field state next macrotask.\n // Read the registry fresh inside the callback (fields may register/unregister in between), and\n // cancel on destroy so resetState never runs against a torn-down field.\n const timer = setTimeout(() => {\n this.resetTimers.delete(timer);\n this.fields().forEach((field) => field.resetState());\n });\n this.resetTimers.add(timer);\n }\n\n private readonly resetTimers = new Set<ReturnType<typeof setTimeout>>();\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.resetTimers.forEach((timer) => clearTimeout(timer)));\n }\n\n private remainingErrors(): RdxFormErrors {\n const errors = this.errors() ?? {};\n const cleared = this.clearedNames();\n const result: RdxFormErrors = {};\n for (const key of Object.keys(errors)) {\n if (!cleared.has(key)) {\n result[key] = errors[key];\n }\n }\n return result;\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RdxFormRoot } from './src/form-root';\n\nexport * from './src/form-root';\n\nexport const _importsForm = [RdxFormRoot];\n\n@NgModule({\n imports: [..._importsForm],\n exports: [..._importsForm]\n})\nexport class RdxFormModule {}\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-form.mjs","sources":["../../../packages/primitives/form/src/form-root.ts","../../../packages/primitives/form/index.ts","../../../packages/primitives/form/radix-ng-primitives-form.ts"],"sourcesContent":["import {\n computed,\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n input,\n linkedSignal,\n output,\n signal\n} from '@angular/core';\nimport { createContext } from '@radix-ng/primitives/core';\n\n/** A normalized external-error map: each field name maps to its message(s) in display order. */\nexport type RdxFormErrors = Record<string, string | string[]>;\n\n/** Payload of {@link RdxFormRoot.onFormSubmit}. */\nexport interface RdxFormSubmitEvent {\n /** The form's values serialized from `FormData` (repeated names collapse into arrays). */\n values: Record<string, FormDataEntryValue | FormDataEntryValue[]>;\n /** The original native submit event (already `preventDefault`-ed). */\n event: SubmitEvent;\n}\n\n/**\n * What a {@link RdxFieldRoot} registers with an enclosing Form. Structural `() =>` accessors keep the\n * Form entry free of any import from `field` (acyclic ng-packagr graph: `field` → `form`).\n */\nexport interface RdxFormFieldRegistration {\n /** The field's `name` (key external errors match against), or `undefined`. */\n name: () => string | undefined;\n /** The field's merged invalid state (includes external errors). */\n invalid: () => boolean;\n /** Whether the field is dirty. */\n dirty: () => boolean;\n /** Whether the field is touched. */\n touched: () => boolean;\n /** Focus the field's control (by its `controlId`). */\n focus: () => void;\n /** Reset the field's interaction state (touched/dirty/focused → false, filled re-sync). */\n resetState: () => void;\n}\n\n/**\n * External owner of form-level state (e.g. a future Signal Forms `[rdxSignalForm]` adapter). Mirrors\n * Field's `RdxFieldState` seam one level up. Each member is optional: a provided accessor wins over the\n * built-in registry/`errors`-input behavior; absent accessors leave the built-in behavior untouched.\n * Kept as framework-free `() =>` accessors (no `@angular/forms/signals` dependency). See ADR 0004.\n */\nexport interface RdxFormState {\n invalid?: () => boolean;\n dirty?: () => boolean;\n touched?: () => boolean;\n submitting?: () => boolean;\n /** Per-name external error source; while provided, the `errors` input + clear-on-edit are inert. */\n errorsFor?: (name: string) => string[];\n}\n\nconst formRootContext = () => {\n const root = inject(RdxFormRoot);\n return {\n errorsFor: (name: string | undefined) => root.errorsFor(name),\n notifyEdited: (name: string | undefined) => root.notifyEdited(name),\n register: (field: RdxFormFieldRegistration) => root.register(field),\n setStateProvider: (provider: RdxFormState | null) => root.setStateProvider(provider),\n hasStateProvider: root.hasStateProvider\n };\n};\n\nexport type RdxFormRootContext = ReturnType<typeof formRootContext>;\n\nexport const [injectFormRootContext, provideFormRootContext] = createContext<RdxFormRootContext>(\n 'RdxFormRoot',\n 'components/form'\n);\n\n/** Collapses `FormData` into a plain object; repeated names collapse into arrays. */\nfunction serializeFormData(data: FormData): Record<string, FormDataEntryValue | FormDataEntryValue[]> {\n const values: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};\n data.forEach((value, key) => {\n // `Object.hasOwn`, not `key in values` — a control named after an Object.prototype member\n // (`toString`, `constructor`, …) must not be misread as a duplicate.\n if (Object.hasOwn(values, key)) {\n const existing = values[key];\n values[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];\n } else {\n values[key] = value;\n }\n });\n return values;\n}\n\n/**\n * The top of the forms layer cake: a single directive on the native `<form>` element that aggregates\n * field state, maps external (server) errors onto fields by `name`, intercepts submit (values-as-object,\n * focus the first invalid field), and resets field interaction state on native `reset`. It owns no\n * values and runs no validation — Angular form systems (or Field inputs) remain the source of validity.\n *\n * @group Components\n */\n@Directive({\n selector: 'form[rdxFormRoot]',\n exportAs: 'rdxFormRoot',\n providers: [provideFormRootContext(formRootContext)],\n host: {\n novalidate: '',\n '[attr.data-invalid]': 'anyInvalid() ? \"\" : undefined',\n '[attr.data-dirty]': 'anyDirty() ? \"\" : undefined',\n '[attr.data-touched]': 'anyTouched() ? \"\" : undefined',\n '[attr.data-submitting]': 'submitting() ? \"\" : undefined',\n '(submit)': 'onSubmit($event)',\n '(reset)': 'onReset()'\n }\n})\nexport class RdxFormRoot {\n private readonly form = inject<ElementRef<HTMLFormElement>>(ElementRef).nativeElement;\n\n /** External/server validation errors keyed by `Field.Root` `name`. */\n readonly errors = input<RdxFormErrors | null | undefined>();\n\n /** Emits the remaining error map after a field's external error is cleared by a user edit (or reset). */\n readonly onClearErrors = output<RdxFormErrors>();\n\n /** Emits the serialized form values when a valid form is submitted. */\n readonly onFormSubmit = output<RdxFormSubmitEvent>();\n\n private readonly fields = signal<RdxFormFieldRegistration[]>([]);\n\n private readonly stateProvider = signal<RdxFormState | null>(null);\n\n /** Whether an external adapter currently owns form-level state. */\n readonly hasStateProvider = computed(() => this.stateProvider() !== null);\n\n /**\n * Names whose external error has been cleared by a user edit. Reset to empty whenever a new `errors`\n * object reference is assigned — the server just spoke, so everything it said is live again.\n */\n private readonly clearedNames = linkedSignal<RdxFormErrors | null | undefined, Set<string>>({\n source: this.errors,\n computation: () => new Set<string>()\n });\n\n /** The `errors` input minus cleared names, normalized to `string[]`. */\n private readonly effectiveErrors = computed<Record<string, string[]>>(() => {\n const errors = this.errors() ?? {};\n const cleared = this.clearedNames();\n const result: Record<string, string[]> = {};\n for (const key of Object.keys(errors)) {\n if (cleared.has(key)) {\n continue;\n }\n const value = errors[key];\n result[key] = Array.isArray(value) ? value : [value];\n }\n return result;\n });\n\n readonly anyInvalid = computed(() => this.aggregate('invalid'));\n readonly anyDirty = computed(() => this.aggregate('dirty'));\n readonly anyTouched = computed(() => this.aggregate('touched'));\n readonly submitting = computed(() => this.stateProvider()?.submitting?.() ?? false);\n\n /** Resolve a boolean aggregate: a registered provider's accessor wins, else OR over the registry. */\n private aggregate(key: 'invalid' | 'dirty' | 'touched'): boolean {\n const accessor = this.stateProvider()?.[key];\n return accessor ? accessor() : this.fields().some((field) => field[key]());\n }\n\n /** Resolves the external messages for a field name (provider source wins over the `errors` input). */\n errorsFor(name: string | undefined): string[] {\n if (!name) {\n return [];\n }\n const provider = this.stateProvider();\n if (provider?.errorsFor) {\n return provider.errorsFor(name);\n }\n return this.effectiveErrors()[name] ?? [];\n }\n\n /** Clears a field's external error after a user edit, emitting the remaining map. */\n notifyEdited(name: string | undefined): void {\n if (!name) {\n return;\n }\n // While a provider owns errors, Signal Forms clears/reapplies them itself — stay inert.\n if (this.stateProvider()?.errorsFor) {\n return;\n }\n const errors = this.errors() ?? {};\n if (!Object.hasOwn(errors, name) || this.clearedNames().has(name)) {\n return;\n }\n this.clearedNames.update((set) => new Set(set).add(name));\n this.onClearErrors.emit(this.remainingErrors());\n }\n\n register(field: RdxFormFieldRegistration): () => void {\n this.fields.update((list) => [...list, field]);\n return () => this.fields.update((list) => list.filter((item) => item !== field));\n }\n\n /** Register (or clear with `null`) an external owner of form-level state; returns the previous one. */\n setStateProvider(provider: RdxFormState | null): RdxFormState | null {\n const previous = this.stateProvider();\n this.stateProvider.set(provider);\n return previous;\n }\n\n onSubmit(event: SubmitEvent): void {\n // SPA submits never navigate; never stopPropagation so Reactive Forms `(ngSubmit)` keeps firing.\n event.preventDefault();\n\n if (this.aggregate('invalid')) {\n // Focus the first invalid registered field (DOM order); provider-only invalid has none to focus.\n this.fields()\n .find((field) => field.invalid())\n ?.focus();\n return;\n }\n\n const values = serializeFormData(new FormData(this.form));\n this.onFormSubmit.emit({ values, event });\n }\n\n onReset(): void {\n // Don't prevent the native reset — control values revert on their own.\n if (!this.stateProvider()?.errorsFor) {\n const keys = Object.keys(this.errors() ?? {});\n const hadVisible = keys.some((key) => !this.clearedNames().has(key));\n if (keys.length) {\n this.clearedNames.set(new Set(keys));\n }\n if (hadVisible) {\n this.onClearErrors.emit({});\n }\n }\n // Values revert asynchronously relative to the reset event — re-sync field state next macrotask.\n // Read the registry fresh inside the callback (fields may register/unregister in between), and\n // cancel on destroy so resetState never runs against a torn-down field.\n const timer = setTimeout(() => {\n this.resetTimers.delete(timer);\n this.fields().forEach((field) => field.resetState());\n });\n this.resetTimers.add(timer);\n }\n\n private readonly resetTimers = new Set<ReturnType<typeof setTimeout>>();\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.resetTimers.forEach((timer) => clearTimeout(timer)));\n }\n\n private remainingErrors(): RdxFormErrors {\n const errors = this.errors() ?? {};\n const cleared = this.clearedNames();\n const result: RdxFormErrors = {};\n for (const key of Object.keys(errors)) {\n if (!cleared.has(key)) {\n result[key] = errors[key];\n }\n }\n return result;\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RdxFormRoot } from './src/form-root';\n\nexport * from './src/form-root';\n\nexport const _importsForm = [RdxFormRoot];\n\n@NgModule({\n imports: [..._importsForm],\n exports: [..._importsForm]\n})\nexport class RdxFormModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AA0DA,MAAM,eAAe,GAAG,MAAK;AACzB,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;IAChC,OAAO;QACH,SAAS,EAAE,CAAC,IAAwB,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7D,YAAY,EAAE,CAAC,IAAwB,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;QACnE,QAAQ,EAAE,CAAC,KAA+B,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnE,gBAAgB,EAAE,CAAC,QAA6B,KAAK,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;QACpF,gBAAgB,EAAE,IAAI,CAAC;KAC1B;AACL,CAAC;AAIM,MAAM,CAAC,qBAAqB,EAAE,sBAAsB,CAAC,GAAG,aAAa,CACxE,aAAa,EACb,iBAAiB;AAGrB;AACA,SAAS,iBAAiB,CAAC,IAAc,EAAA;IACrC,MAAM,MAAM,GAA8D,EAAE;IAC5E,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,KAAI;;;QAGxB,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;AAC5B,YAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC;YAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;QACpF;aAAO;AACH,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;QACvB;AACJ,IAAA,CAAC,CAAC;AACF,IAAA,OAAO,MAAM;AACjB;AAEA;;;;;;;AAOG;MAeU,WAAW,CAAA;;AAiDZ,IAAA,SAAS,CAAC,GAAoC,EAAA;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,GAAG,CAAC;QAC5C,OAAO,QAAQ,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9E;;AAGA,IAAA,SAAS,CAAC,IAAwB,EAAA;QAC9B,IAAI,CAAC,IAAI,EAAE;AACP,YAAA,OAAO,EAAE;QACb;AACA,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;AACrC,QAAA,IAAI,QAAQ,EAAE,SAAS,EAAE;AACrB,YAAA,OAAO,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QACnC;QACA,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE;IAC7C;;AAGA,IAAA,YAAY,CAAC,IAAwB,EAAA;QACjC,IAAI,CAAC,IAAI,EAAE;YACP;QACJ;;AAEA,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE;YACjC;QACJ;QACA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;QAClC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC/D;QACJ;QACA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;IACnD;AAEA,IAAA,QAAQ,CAAC,KAA+B,EAAA;AACpC,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;AAC9C,QAAA,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC;IACpF;;AAGA,IAAA,gBAAgB,CAAC,QAA6B,EAAA;AAC1C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;AACrC,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;AAChC,QAAA,OAAO,QAAQ;IACnB;AAEA,IAAA,QAAQ,CAAC,KAAkB,EAAA;;QAEvB,KAAK,CAAC,cAAc,EAAE;AAEtB,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;;YAE3B,IAAI,CAAC,MAAM;iBACN,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE;kBAC9B,KAAK,EAAE;YACb;QACJ;AAEA,QAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC7C;IAEA,OAAO,GAAA;;QAEH,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE;AAClC,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACpE,YAAA,IAAI,IAAI,CAAC,MAAM,EAAE;gBACb,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YACxC;YACA,IAAI,UAAU,EAAE;AACZ,gBAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B;QACJ;;;;AAIA,QAAA,MAAM,KAAK,GAAG,UAAU,CAAC,MAAK;AAC1B,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;AAC9B,YAAA,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;AACxD,QAAA,CAAC,CAAC;AACF,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;IAC/B;AAIA,IAAA,WAAA,GAAA;AAtIiB,QAAA,IAAA,CAAA,IAAI,GAAG,MAAM,CAA8B,UAAU,CAAC,CAAC,aAAa;;AAG5E,QAAA,IAAA,CAAA,MAAM,GAAG,KAAK;8FAAoC;;QAGlD,IAAA,CAAA,aAAa,GAAG,MAAM,EAAiB;;QAGvC,IAAA,CAAA,YAAY,GAAG,MAAM,EAAsB;QAEnC,IAAA,CAAA,MAAM,GAAG,MAAM,CAA6B,EAAE;mFAAC;QAE/C,IAAA,CAAA,aAAa,GAAG,MAAM,CAAsB,IAAI;0FAAC;;QAGzD,IAAA,CAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI;6FAAC;AAEzE;;;AAGG;AACc,QAAA,IAAA,CAAA,YAAY,GAAG,YAAY,CAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,cAAA,EAAA,8BAAA,EAAA,CAAA,EACxC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,MAAM,IAAI,GAAG,EAAU,GACtC;;AAGe,QAAA,IAAA,CAAA,eAAe,GAAG,QAAQ,CAA2B,MAAK;YACvE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;AAClC,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE;YACnC,MAAM,MAAM,GAA6B,EAAE;YAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AACnC,gBAAA,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;oBAClB;gBACJ;AACA,gBAAA,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC;gBACzB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC;YACxD;AACA,YAAA,OAAO,MAAM;QACjB,CAAC;4FAAC;QAEO,IAAA,CAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;uFAAC;QACtD,IAAA,CAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;qFAAC;QAClD,IAAA,CAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;uFAAC;AACtD,QAAA,IAAA,CAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,UAAU,IAAI,IAAI,KAAK;uFAAC;AAuFlE,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,GAAG,EAAiC;QAGnE,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAChG;IAEQ,eAAe,GAAA;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;AAClC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE;QACnC,MAAM,MAAM,GAAkB,EAAE;QAChC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBACnB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;YAC7B;QACJ;AACA,QAAA,OAAO,MAAM;IACjB;8GArJS,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAX,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,gnBAXT,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAW3C,WAAW,EAAA,UAAA,EAAA,CAAA;kBAdvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACP,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,SAAS,EAAE,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC;AACpD,oBAAA,IAAI,EAAE;AACF,wBAAA,UAAU,EAAE,EAAE;AACd,wBAAA,qBAAqB,EAAE,+BAA+B;AACtD,wBAAA,mBAAmB,EAAE,6BAA6B;AAClD,wBAAA,qBAAqB,EAAE,+BAA+B;AACtD,wBAAA,wBAAwB,EAAE,+BAA+B;AACzD,wBAAA,UAAU,EAAE,kBAAkB;AAC9B,wBAAA,SAAS,EAAE;AACd;AACJ,iBAAA;;;AC5GM,MAAM,YAAY,GAAG,CAAC,WAAW;MAM3B,aAAa,CAAA;8GAAb,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA,CAAA;+GAAb,aAAa,EAAA,OAAA,EAAA,CANG,WAAW,CAAA,EAAA,OAAA,EAAA,CAAX,WAAW,CAAA,EAAA,CAAA,CAAA;+GAM3B,aAAa,EAAA,CAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBAJzB,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;AACN,oBAAA,OAAO,EAAE,CAAC,GAAG,YAAY,CAAC;AAC1B,oBAAA,OAAO,EAAE,CAAC,GAAG,YAAY;AAC5B,iBAAA;;;ACVD;;AAEG;;;;"}
|
|
@@ -17,34 +17,41 @@ class RdxInputDirective {
|
|
|
17
17
|
this.fieldRootContext = injectFieldRootContext(true);
|
|
18
18
|
this.initialValue = '';
|
|
19
19
|
this.defaultValueApplied = false;
|
|
20
|
-
this.filledValue = signal(false,
|
|
21
|
-
|
|
22
|
-
this.
|
|
20
|
+
this.filledValue = signal(false, /* @ts-ignore */
|
|
21
|
+
...(ngDevMode ? [{ debugName: "filledValue" }] : /* istanbul ignore next */ []));
|
|
22
|
+
this.focusedValue = signal(false, /* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [{ debugName: "focusedValue" }] : /* istanbul ignore next */ []));
|
|
24
|
+
this.dirtyValue = signal(false, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "dirtyValue" }] : /* istanbul ignore next */ []));
|
|
23
26
|
/**
|
|
24
27
|
* The input id. Field labels and descriptions use this value for accessible relationships.
|
|
25
28
|
*
|
|
26
29
|
* @group Props
|
|
27
30
|
*/
|
|
28
|
-
this.id = input(`rdx-input-${inputId++}`,
|
|
31
|
+
this.id = input(`rdx-input-${inputId++}`, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
29
33
|
/**
|
|
30
34
|
* The name of the input, submitted with the form data and used by Form-level
|
|
31
35
|
* error matching.
|
|
32
36
|
*
|
|
33
37
|
* @group Props
|
|
34
38
|
*/
|
|
35
|
-
this.name = input(
|
|
39
|
+
this.name = input(/* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ []));
|
|
36
41
|
/**
|
|
37
42
|
* The controlled input value.
|
|
38
43
|
*
|
|
39
44
|
* @group Props
|
|
40
45
|
*/
|
|
41
|
-
this.value = model(undefined,
|
|
46
|
+
this.value = model(undefined, /* @ts-ignore */
|
|
47
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
42
48
|
/**
|
|
43
49
|
* The initial value when the input is uncontrolled.
|
|
44
50
|
*
|
|
45
51
|
* @group Props
|
|
46
52
|
*/
|
|
47
|
-
this.defaultValue = input(undefined,
|
|
53
|
+
this.defaultValue = input(undefined, /* @ts-ignore */
|
|
54
|
+
...(ngDevMode ? [{ debugName: "defaultValue" }] : /* istanbul ignore next */ []));
|
|
48
55
|
/**
|
|
49
56
|
* Whether the input is disabled.
|
|
50
57
|
*
|
|
@@ -76,7 +83,8 @@ class RdxInputDirective {
|
|
|
76
83
|
*
|
|
77
84
|
* @group Props
|
|
78
85
|
*/
|
|
79
|
-
this.touched = model(false,
|
|
86
|
+
this.touched = model(false, /* @ts-ignore */
|
|
87
|
+
...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
80
88
|
/**
|
|
81
89
|
* Whether the input value has changed from its initial value. Merged with the
|
|
82
90
|
* internally tracked state; a form system can own it through this input.
|
|
@@ -89,7 +97,8 @@ class RdxInputDirective {
|
|
|
89
97
|
*
|
|
90
98
|
* @group Props
|
|
91
99
|
*/
|
|
92
|
-
this.errors = input([],
|
|
100
|
+
this.errors = input([], /* @ts-ignore */
|
|
101
|
+
...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
93
102
|
/**
|
|
94
103
|
* Minimum number of characters.
|
|
95
104
|
*
|
|
@@ -108,7 +117,8 @@ class RdxInputDirective {
|
|
|
108
117
|
*
|
|
109
118
|
* @group Props
|
|
110
119
|
*/
|
|
111
|
-
this.pattern = input([],
|
|
120
|
+
this.pattern = input([], /* @ts-ignore */
|
|
121
|
+
...(ngDevMode ? [{ debugName: "pattern" }] : /* istanbul ignore next */ []));
|
|
112
122
|
/**
|
|
113
123
|
* Emits when the input value changes.
|
|
114
124
|
*
|
|
@@ -124,17 +134,25 @@ class RdxInputDirective {
|
|
|
124
134
|
* @group Emits
|
|
125
135
|
*/
|
|
126
136
|
this.touch = output();
|
|
127
|
-
this.invalidState = computed(() => this.invalid() || (this.errors()?.length ?? 0) > 0 || Boolean(this.fieldRootContext?.invalidState()),
|
|
128
|
-
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
this.
|
|
137
|
+
this.invalidState = computed(() => this.invalid() || (this.errors()?.length ?? 0) > 0 || Boolean(this.fieldRootContext?.invalidState()), /* @ts-ignore */
|
|
138
|
+
...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
|
|
139
|
+
this.disabledState = computed(() => this.disabled() || Boolean(this.fieldRootContext?.disabledState()), /* @ts-ignore */
|
|
140
|
+
...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
|
|
141
|
+
this.requiredState = computed(() => this.required() || Boolean(this.fieldRootContext?.requiredState()), /* @ts-ignore */
|
|
142
|
+
...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
|
|
143
|
+
this.filledState = computed(() => this.filledValue() || Boolean(this.fieldRootContext?.filledState()), /* @ts-ignore */
|
|
144
|
+
...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
|
|
145
|
+
this.focusedState = computed(() => this.focusedValue() || Boolean(this.fieldRootContext?.focusedState()), /* @ts-ignore */
|
|
146
|
+
...(ngDevMode ? [{ debugName: "focusedState" }] : /* istanbul ignore next */ []));
|
|
147
|
+
this.touchedState = computed(() => this.touched() || Boolean(this.fieldRootContext?.touchedState()), /* @ts-ignore */
|
|
148
|
+
...(ngDevMode ? [{ debugName: "touchedState" }] : /* istanbul ignore next */ []));
|
|
149
|
+
this.dirtyState = computed(() => this.dirty() || this.dirtyValue() || Boolean(this.fieldRootContext?.dirtyState()), /* @ts-ignore */
|
|
150
|
+
...(ngDevMode ? [{ debugName: "dirtyState" }] : /* istanbul ignore next */ []));
|
|
134
151
|
this.patternAttr = computed(() => {
|
|
135
152
|
const patterns = this.pattern();
|
|
136
153
|
return patterns?.length === 1 ? patterns[0].source : undefined;
|
|
137
|
-
},
|
|
154
|
+
}, /* @ts-ignore */
|
|
155
|
+
...(ngDevMode ? [{ debugName: "patternAttr" }] : /* istanbul ignore next */ []));
|
|
138
156
|
this.describedBy = computed(() => {
|
|
139
157
|
if (!this.fieldRootContext) {
|
|
140
158
|
return undefined;
|
|
@@ -144,7 +162,8 @@ class RdxInputDirective {
|
|
|
144
162
|
...(this.fieldRootContext.invalidState() ? this.fieldRootContext.errorIds() : [])
|
|
145
163
|
];
|
|
146
164
|
return ids.length ? ids.join(' ') : undefined;
|
|
147
|
-
},
|
|
165
|
+
}, /* @ts-ignore */
|
|
166
|
+
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
148
167
|
this.dataAttr = attr;
|
|
149
168
|
effect(() => {
|
|
150
169
|
const value = this.value();
|
|
@@ -207,10 +226,10 @@ class RdxInputDirective {
|
|
|
207
226
|
this.element.value = value;
|
|
208
227
|
this.syncFieldState();
|
|
209
228
|
}
|
|
210
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
211
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
229
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxInputDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
230
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: RdxInputDirective, isStandalone: true, selector: "input[rdxInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", onValueChange: "onValueChange", touch: "touch" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "input": "onInput($event)", "change": "syncFieldState()" }, properties: { "attr.id": "id()", "attr.name": "name() || undefined", "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.required": "requiredState() ? \"\" : undefined", "attr.readonly": "readonly() ? \"\" : undefined", "attr.minlength": "minLength() ?? undefined", "attr.maxlength": "maxLength() ?? undefined", "attr.pattern": "patternAttr()", "attr.data-invalid": "dataAttr(invalidState())", "attr.data-valid": "dataAttr(!invalidState())", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-readonly": "dataAttr(readonly())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())", "attr.data-touched": "dataAttr(touchedState())", "attr.data-dirty": "dataAttr(dirtyState())" } }, exportAs: ["rdxInput"], ngImport: i0 }); }
|
|
212
231
|
}
|
|
213
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
232
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RdxInputDirective, decorators: [{
|
|
214
233
|
type: Directive,
|
|
215
234
|
args: [{
|
|
216
235
|
selector: 'input[rdxInput]',
|