ngx-vest-forms 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -1
- package/fesm2022/ngx-vest-forms.mjs +803 -237
- package/fesm2022/ngx-vest-forms.mjs.map +1 -1
- package/package.json +3 -2
- package/types/ngx-vest-forms.d.ts +120 -30
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-vest-forms.mjs","sources":["../../../projects/ngx-vest-forms/src/lib/directives/error-display-mode.token.ts","../../../projects/ngx-vest-forms/src/lib/errors/error-catalog.ts","../../../projects/ngx-vest-forms/src/lib/tokens/debounce.token.ts","../../../projects/ngx-vest-forms/src/lib/utils/equality.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-path.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/first-invalid.utils.ts","../../../projects/ngx-vest-forms/src/lib/constants.ts","../../../projects/ngx-vest-forms/src/lib/utils/form-utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/shape-validation.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-submitted-state.ts","../../../projects/ngx-vest-forms/src/lib/directives/form.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-control-state.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-error-display.directive.ts","../../../projects/ngx-vest-forms/src/lib/utils/aria-association.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/pending-state.utils.ts","../../../projects/ngx-vest-forms/src/lib/components/control-wrapper/control-wrapper.component.ts","../../../projects/ngx-vest-forms/src/lib/components/control-wrapper/control-wrapper.component.html","../../../projects/ngx-vest-forms/src/lib/components/form-group-wrapper/form-group-wrapper.component.ts","../../../projects/ngx-vest-forms/src/lib/components/form-group-wrapper/form-group-wrapper.component.html","../../../projects/ngx-vest-forms/src/lib/directives/form-error-control.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/async-validator-bridge.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-model-group.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-model.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/validate-root-form.directive.ts","../../../projects/ngx-vest-forms/src/lib/exports.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-path-types.ts","../../../projects/ngx-vest-forms/src/lib/utils/form-state.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/validation-config-builder.ts","../../../projects/ngx-vest-forms/src/lib/utils/array-to-object.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-clearing.ts","../../../projects/ngx-vest-forms/src/public-api.ts","../../../projects/ngx-vest-forms/src/ngx-vest-forms.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport {\n NgxWarningDisplayMode,\n ScErrorDisplayMode,\n} from './form-error-display.directive';\n\n/**\n * @deprecated Use NGX_ERROR_DISPLAY_MODE_TOKEN instead\n */\nexport const SC_ERROR_DISPLAY_MODE_TOKEN =\n new InjectionToken<ScErrorDisplayMode>('SC_ERROR_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-blur-or-submit',\n });\n\n/**\n * Injection token for configuring the default error display mode.\n * Values:\n * - 'on-blur': Show errors after field is touched/blurred\n * - 'on-submit': Show errors after form submission\n * - 'on-blur-or-submit': Show errors after blur or form submission (default)\n * - 'on-dirty': Show errors as soon as the field value changes\n * - 'always': Show errors immediately, even on pristine fields\n */\nexport const NGX_ERROR_DISPLAY_MODE_TOKEN =\n new InjectionToken<ScErrorDisplayMode>('NGX_ERROR_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-blur-or-submit',\n });\n\n/**\n * Injection token for configuring the default warning display mode.\n * Values:\n * - 'on-touch': Show warnings after field is touched/blurred\n * - 'on-validated-or-touch': Show warnings after validation runs or field is touched (default)\n * - 'on-dirty': Show warnings as soon as the field value changes\n * - 'always': Show warnings immediately, even on pristine fields\n */\nexport const NGX_WARNING_DISPLAY_MODE_TOKEN =\n new InjectionToken<NgxWarningDisplayMode>('NGX_WARNING_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-validated-or-touch',\n });\n","export const NGX_VEST_FORMS_ERRORS = {\n EXTRA_PROPERTY: {\n code: 'NGX-001',\n message: (path: string) =>\n `Shape mismatch: Property '${path}' is present in the form value but not defined in the form shape.`,\n },\n TYPE_MISMATCH: {\n code: 'NGX-002',\n message: (path: string, expected: string, actual: string) =>\n `Type mismatch at '${path}': Expected '${expected}' but got '${actual}'.`,\n },\n CONTROL_NOT_FOUND: {\n code: 'NGX-003',\n message: (path: string) =>\n `Control not found: Could not find form control at path '${path}'. Check your [ngModel] name attributes.`,\n },\n} as const;\n\nexport function logWarning<T extends unknown[]>(\n error: { code: string; message: (...args: T) => string },\n ...args: T\n): void {\n console.warn(\n `[${error.code}] ${error.message(...args)}\\nCheck your [formShape] input and the initial [formValue].`\n );\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Injection token for configurable validation config debounce timing.\n *\n * This token allows you to configure the debounce time for validation config\n * dependencies at the application, route, or component level.\n *\n * @example\n * ```typescript\n * /// Global configuration\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 200\n * }\n * ]\n * };\n *\n * /// Per-route configuration\n * {\n * path: 'checkout',\n * component: CheckoutComponent,\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 50\n * }\n * ]\n * }\n *\n * /// Per-component override\n * @Component({\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 0 // for testing\n * }\n * ]\n * })\n * export class TestFormComponent {}\n * ```\n *\n * @default 100ms - Maintains backward compatibility with existing behavior\n */\nexport const NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN = new InjectionToken<number>(\n 'NgxValidationConfigDebounceTime',\n {\n providedIn: 'root',\n factory: () => 100,\n }\n);\n","/**\n * Type guard to check if a value is a primitive type.\n *\n * @param value - The value to check\n * @returns true if the value is a primitive (string, number, boolean, null, undefined, symbol, bigint)\n */\nexport function isPrimitive(\n value: unknown\n): value is string | number | boolean | null | undefined | symbol | bigint {\n return (\n value === null || (typeof value !== 'object' && typeof value !== 'function')\n );\n}\n\n/**\n * @internal\n * Internal utility for shallow equality checks.\n *\n * **Not intended for external use.** This function is used internally by the library\n * for performance-critical operations. Consider using your own comparison logic or\n * a library like lodash if you need shallow equality checks in your application.\n *\n * Optimized shallow equality check for objects.\n *\n * **Why this custom implementation is preferred:**\n * - **Performance**: Direct property comparison is significantly faster than JSON.stringify\n * - **Type Safety**: Handles null/undefined values correctly without serialization issues\n * - **Accuracy**: Doesn't suffer from JSON.stringify limitations (undefined values, functions, symbols)\n * - **Memory Efficient**: No temporary string creation or object serialization overhead\n *\n * **Use Cases:**\n * - Form value change detection where only top-level properties matter\n * - Quick object comparison in performance-critical code paths\n * - Validation triggers where deep comparison is unnecessary\n *\n * **Performance Comparison:**\n * ```typescript\n * /// ❌ Slow: JSON.stringify approach\n * JSON.stringify(obj1) === JSON.stringify(obj2)\n *\n * /// ✅ Fast: Direct property comparison\n * shallowEqual(obj1, obj2)\n * ```\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns true if objects are shallowly equal (same keys and same values by reference)\n */\nexport function shallowEqual(obj1: unknown, obj2: unknown): boolean {\n if (obj1 === obj2) {\n return true;\n }\n\n if (obj1 == null || obj2 == null) {\n return obj1 === obj2;\n }\n\n if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {\n return obj1 === obj2;\n }\n\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (\n !Object.hasOwn(obj2 as object, key) ||\n (obj1 as Record<string, unknown>)[key] !==\n (obj2 as Record<string, unknown>)[key]\n ) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * @internal\n * Internal utility for deep equality checks.\n *\n * **Not intended for external use.** This function is used internally by the library\n * for form value comparison and change detection. Consider using your own comparison\n * logic or a library like lodash if you need deep equality checks in your application.\n *\n * Fast deep equality check optimized for form values and Angular applications.\n *\n * **Why this custom implementation is preferred over alternatives:**\n *\n * **vs JSON.stringify():**\n * - **10-100x faster**: Direct comparison without string serialization overhead\n * - **Accurate**: Handles Date objects, RegExp, undefined values, and functions correctly\n * - **Memory efficient**: No temporary string creation or garbage collection pressure\n * - **Preserves semantics**: Maintains type information during comparison\n *\n * **vs structuredClone():**\n * - **Wrong purpose**: structuredClone creates copies, not comparisons\n * - **Performance**: Would require cloning both objects just to compare them\n * - **Memory waste**: Creates unnecessary deep copies, doubling memory usage\n * - **Still incomplete**: Even after cloning, you'd still need a comparison function\n *\n * **vs External libraries (lodash.isEqual, etc.):**\n * - **Bundle size**: Zero dependencies, smaller application bundles\n * - **Form-specific**: Optimized for common Angular form data patterns\n * - **Type safety**: Full TypeScript integration with strict typing\n * - **Performance**: Tailored algorithms for form value comparison use cases\n *\n * **Supported Data Types:**\n * - Primitives (string, number, boolean, null, undefined, symbol, bigint)\n * - Arrays (with recursive deep comparison)\n * - Plain objects (with recursive deep comparison)\n * - Date objects (by timestamp comparison)\n * - RegExp objects (by source and flags comparison)\n * - Set objects (by size and value membership)\n * - Map objects (by size and key-value pairs)\n *\n * **Safety Features:**\n * - **Circular reference protection**: MaxDepth parameter prevents infinite recursion\n * - **Type coercion prevention**: Strict type checking before comparison\n * - **Null safety**: Proper handling of null and undefined values\n *\n * **Performance Characteristics:**\n * ```typescript\n * /// Performance comparison on typical form objects:\n * /// JSON.stringify: ~100ms for complex nested forms\n * /// fastDeepEqual: ~1-5ms for the same objects\n * ///\n * /// Memory usage:\n * /// JSON.stringify: Creates temporary strings (high GC pressure)\n * /// fastDeepEqual: Zero allocations during comparison\n * ```\n *\n * **Typical Usage in Forms:**\n * ```typescript\n * /// Detect when form values actually change\n * distinctUntilChanged(fastDeepEqual)\n *\n * /// Prevent unnecessary re-renders\n * if (!fastDeepEqual(oldFormValue, newFormValue)) {\n * updateUI();\n * }\n * ```\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param maxDepth - Maximum recursion depth to prevent infinite loops (default: 10)\n * @returns true if objects are deeply equal by value\n */\nexport function fastDeepEqual(\n obj1: unknown,\n obj2: unknown,\n maxDepth = 10\n): boolean {\n if (maxDepth <= 0) {\n // Fallback to shallow comparison at max depth to prevent infinite recursion\n return obj1 === obj2;\n }\n\n if (obj1 === obj2) {\n return true;\n }\n\n if (obj1 == null || obj2 == null) {\n return obj1 === obj2;\n }\n\n if (typeof obj1 !== typeof obj2) {\n return false;\n }\n\n if (isPrimitive(obj1) || isPrimitive(obj2)) {\n return obj1 === obj2;\n }\n\n // Handle arrays early for performance (common in forms)\n if (Array.isArray(obj1) !== Array.isArray(obj2)) {\n return false;\n }\n\n if (Array.isArray(obj1)) {\n // We know obj2 is also an array here\n const arr2 = obj2 as unknown[];\n if (obj1.length !== arr2.length) {\n return false;\n }\n for (let i = 0; i < obj1.length; i++) {\n if (!fastDeepEqual(obj1[i], arr2[i], maxDepth - 1)) {\n return false;\n }\n }\n return true;\n }\n\n // Handle Date objects\n if (obj1 instanceof Date) {\n return obj2 instanceof Date && obj1.getTime() === obj2.getTime();\n }\n\n // Handle RegExp objects\n if (obj1 instanceof RegExp) {\n return (\n obj2 instanceof RegExp &&\n obj1.source === obj2.source &&\n obj1.flags === obj2.flags\n );\n }\n\n // Handle Set objects (common in forms)\n if (obj1 instanceof Set) {\n if (!(obj2 instanceof Set) || obj1.size !== obj2.size) {\n return false;\n }\n for (const value of obj1) {\n if (!obj2.has(value)) {\n return false;\n }\n }\n return true;\n }\n\n // Handle Map objects (common in forms)\n if (obj1 instanceof Map) {\n if (!(obj2 instanceof Map) || obj1.size !== obj2.size) {\n return false;\n }\n for (const [key, value] of obj1) {\n if (\n !obj2.has(key) ||\n !fastDeepEqual(value, obj2.get(key), maxDepth - 1)\n ) {\n return false;\n }\n }\n return true;\n }\n\n // Handle plain objects\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (\n !Object.hasOwn(obj2 as object, key) ||\n !fastDeepEqual(\n (obj1 as Record<string, unknown>)[key],\n (obj2 as Record<string, unknown>)[key],\n maxDepth - 1\n )\n ) {\n return false;\n }\n }\n\n return true;\n}\n","/**\n * Utilities for working with field paths in dot/bracket notation and Standard Schema path arrays.\n *\n * These utilities help convert between:\n * - **Dot/bracket notation**: `'addresses[0].street'` (used in Angular forms and Vest)\n * - **Standard Schema paths**: `['addresses', 0, 'street']` (used in schema validation)\n *\n * @example\n * ```typescript\n * // Parse string path to array\n * parseFieldPath('user.addresses[0].street')\n * // Returns: ['user', 'addresses', 0, 'street']\n *\n * // Stringify array path to string\n * stringifyFieldPath(['user', 'addresses', 0, 'street'])\n * // Returns: 'user.addresses[0].street'\n * ```\n */\n\nconst UNSAFE_PATH_SEGMENTS = new Set(['__proto__', 'prototype', 'constructor']);\n\n/**\n * @internal\n * Returns whether a path segment is unsafe for object writes/merges.\n *\n * Unsafe segments are blocked to prevent prototype pollution vectors.\n */\nexport function isUnsafePathSegment(segment: string | number): boolean {\n return typeof segment === 'string' && UNSAFE_PATH_SEGMENTS.has(segment);\n}\n\n/**\n * @internal\n * Internal utility for parsing field path strings.\n *\n * **Not intended for external use.** While this function can parse field paths,\n * it's primarily used internally. Most users won't need to parse field paths manually.\n * If you do need this functionality, consider using your own implementation tailored\n * to your specific needs.\n *\n * Converts a dot/bracket notation path (e.g. `'addresses[0].street'`)\n * to a Standard Schema path array (e.g. `['addresses', 0, 'street']`).\n *\n * **Use cases:**\n * - Converting Angular form paths to schema-compatible arrays\n * - Parsing Vest field names for array access\n * - Processing validation error paths from different sources\n *\n * **Supported formats:**\n * - Dot notation: `'user.name'` → `['user', 'name']`\n * - Bracket notation: `'addresses[0]'` → `['addresses', 0]`\n * - Mixed: `'user.addresses[0].street'` → `['user', 'addresses', 0, 'street']`\n *\n * @param path - The dot/bracket notation path string\n * @returns Array of path segments (strings for properties, numbers for array indices)\n *\n * @example\n * ```typescript\n * parseFieldPath('email') // ['email']\n * parseFieldPath('user.profile.name') // ['user', 'profile', 'name']\n * parseFieldPath('items[0]') // ['items', 0]\n * parseFieldPath('users[0].addresses[1].street')\n * // ['users', 0, 'addresses', 1, 'street']\n * ```\n */\nexport function parseFieldPath(path: string): Array<string | number> {\n if (!path) return [];\n\n return path\n .replaceAll(/\\[(\\d+)\\]/g, '.$1') // Convert brackets to dots: items[0] → items.0\n .split('.') // Split by dots\n .filter((part) => part !== '') // Remove empty strings from leading brackets\n .map((part) => (/^\\d+$/.test(part) ? Number(part) : part)); // Convert numeric strings to numbers\n}\n\n/**\n * Converts a Standard Schema path array (e.g. `['addresses', 0, 'street']`)\n * to a dot/bracket notation string (e.g. `'addresses[0].street'`).\n *\n * **Use cases:**\n * - Converting schema validation paths to Angular form field names\n * - Generating Vest field names from path arrays\n * - Creating human-readable field identifiers\n *\n * **Format rules:**\n * - String segments joined with dots: `['user', 'name']` → `'user.name'`\n * - Number segments use brackets: `['items', 0]` → `'items[0]'`\n * - Mixed paths combine both: `['users', 0, 'email']` → `'users[0].email'`\n *\n * @param path - Array of path segments (strings for properties, numbers for indices)\n * @returns Dot/bracket notation path string\n *\n * @example\n * ```typescript\n * stringifyFieldPath(['email']) // 'email'\n * stringifyFieldPath(['user', 'profile', 'name']) // 'user.profile.name'\n * stringifyFieldPath(['items', 0]) // 'items[0]'\n * stringifyFieldPath(['users', 0, 'addresses', 1, 'street'])\n * // 'users[0].addresses[1].street'\n * ```\n */\nexport function stringifyFieldPath(path: Array<string | number>): string {\n if (!path || path.length === 0) return '';\n\n let result = '';\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i];\n\n if (typeof segment === 'number') {\n // Array index - add as bracket notation\n result += `[${segment}]`;\n } else {\n // Property name - add with dot prefix if not first segment\n if (i > 0) result += '.';\n result += segment;\n }\n }\n\n return result;\n}\n","export type NgxFirstInvalidOptions = {\n /** Scroll animation behavior (default: `'smooth'`, or `'auto'` when reduced motion is preferred). */\n behavior?: ScrollBehavior;\n /** Vertical alignment when scrolling (default: `'center'`). */\n block?: ScrollLogicalPosition;\n /** Horizontal alignment when scrolling (default: `'nearest'`). */\n inline?: ScrollLogicalPosition;\n /** Whether to focus after scrolling (default: `true`). */\n focus?: boolean;\n /** Passed to `focus()` when focusing (default: `true`). */\n preventScrollOnFocus?: boolean;\n /** Opens ancestor `<details>` elements before scroll/focus (default: `true`). */\n openCollapsedParents?: boolean;\n /** Selector used to locate the first invalid element. */\n invalidSelector?: string;\n /** Selector used to resolve the best focus target within the invalid element. */\n focusSelector?: string;\n};\n\nexport const DEFAULT_INVALID_SELECTOR = [\n '.ngx-control-wrapper--invalid',\n '.ngx-form-group-wrapper--invalid',\n 'input[aria-invalid=\"true\"]',\n 'textarea[aria-invalid=\"true\"]',\n 'select[aria-invalid=\"true\"]',\n].join(', ');\n\nexport const DEFAULT_FOCUS_SELECTOR = [\n 'input:not([type=\"hidden\"]):not([disabled])',\n 'textarea:not([disabled])',\n 'select:not([disabled])',\n 'button:not([disabled])',\n 'a[href]',\n '[tabindex]:not([tabindex=\"-1\"]):not([disabled])',\n].join(', ');\n\n/**\n * Focus candidates that are already invalid.\n * This ensures invalid group wrappers focus a failing control before any valid sibling.\n */\nconst INVALID_FOCUS_PREFERRED_SELECTOR = [\n 'input[aria-invalid=\"true\"]:not([type=\"hidden\"]):not([disabled])',\n 'textarea[aria-invalid=\"true\"]:not([disabled])',\n 'select[aria-invalid=\"true\"]:not([disabled])',\n '[aria-invalid=\"true\"][tabindex]:not([tabindex=\"-1\"]):not([disabled])',\n].join(', ');\n\nconst REDUCED_MOTION_MEDIA_QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof globalThis.matchMedia === 'function' &&\n globalThis.matchMedia(REDUCED_MOTION_MEDIA_QUERY).matches\n );\n}\n\nexport function resolveFirstInvalidScrollBehavior(\n behavior?: ScrollBehavior\n): ScrollBehavior {\n if (behavior !== undefined) {\n return behavior;\n }\n return prefersReducedMotion() ? 'auto' : 'smooth';\n}\n\nexport function resolveFirstInvalidElement(\n root: HTMLFormElement,\n invalidSelector: string\n): HTMLElement | null {\n try {\n const firstInvalid = root.querySelector(invalidSelector);\n return firstInvalid instanceof HTMLElement ? firstInvalid : null;\n } catch {\n return null;\n }\n}\n\nexport function openCollapsedDetailsAncestors(\n root: HTMLFormElement,\n element: HTMLElement\n): void {\n let current: HTMLElement = element;\n while (current !== root) {\n const parentElement = current.parentElement;\n if (!parentElement) {\n break;\n }\n\n if (parentElement instanceof HTMLDetailsElement) {\n parentElement.open = true;\n }\n\n current = parentElement;\n }\n}\n\nexport function resolveFirstInvalidFocusTarget(\n firstInvalid: HTMLElement,\n focusSelector: string\n): HTMLElement | null {\n const preferredInvalidTarget = firstInvalid.querySelector(\n INVALID_FOCUS_PREFERRED_SELECTOR\n );\n if (preferredInvalidTarget instanceof HTMLElement) {\n return preferredInvalidTarget;\n }\n\n try {\n if (firstInvalid.matches(focusSelector)) {\n return firstInvalid;\n }\n\n const fallbackTarget = firstInvalid.querySelector(focusSelector);\n return fallbackTarget instanceof HTMLElement ? fallbackTarget : null;\n } catch {\n return null;\n }\n}\n","export const ROOT_FORM = 'rootForm';\n","import {\n AbstractControl,\n FormArray,\n FormGroup,\n isFormArray,\n isFormGroup,\n ValidationErrors,\n} from '@angular/forms';\nimport { ROOT_FORM } from '../constants';\nimport {\n isUnsafePathSegment,\n parseFieldPath,\n stringifyFieldPath,\n} from './field-path.utils';\n\ntype UnknownRecord = Record<string, unknown>;\n\ntype ControlWithOptionalName = AbstractControl & {\n name?: unknown;\n};\n\ntype FormContainer = FormGroup | FormArray;\ntype ErrorList = string[] & { warnings?: string[] };\n\nconst ERROR_MESSAGES_KEY = 'errors';\nconst WARNING_MESSAGES_KEY = 'warnings';\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Recursively calculates the path of a form control\n * @param formGroup\n * @param control\n */\nfunction getChildEntries(\n container: FormContainer\n): Array<[string, AbstractControl]> {\n if (isFormArray(container)) {\n return container.controls.map((child, index) => [String(index), child]);\n }\n\n return Object.entries(container.controls);\n}\n\nfunction getControlPath(\n formGroup: FormGroup,\n control: AbstractControl\n): string {\n // First attempt: depth-first traversal from provided root\n for (const [key, child] of getChildEntries(formGroup)) {\n if (child === control) {\n return key;\n }\n if (isFormGroup(child) || isFormArray(child)) {\n const subPath = getControlPath(child as FormGroup, control);\n if (subPath) {\n return `${key}.${subPath}`;\n }\n }\n }\n\n // Fallback: walk up the parent chain from control to root\n let current: AbstractControl | null | undefined = control;\n const segments: string[] = [];\n while (current?.parent) {\n const parent: FormContainer = current.parent;\n for (const [key, controlInParent] of getChildEntries(parent)) {\n if (controlInParent === current) {\n segments.unshift(key);\n break;\n }\n }\n current = parent;\n if (current === formGroup) {\n return segments.join('.');\n }\n }\n\n // Last resort: try control.name if available\n const name = (control as ControlWithOptionalName).name;\n if (typeof name === 'string') {\n return name;\n }\n return '';\n}\n\n/**\n * Recursively calculates the path of a form group\n * @param formGroup\n * @param control\n */\nfunction getGroupPath(formGroup: FormGroup, control: AbstractControl): string {\n for (const [key, ctrl] of getChildEntries(formGroup)) {\n if (ctrl === control) {\n return key;\n }\n if (isFormGroup(ctrl)) {\n const path = getGroupPath(ctrl, control);\n if (path) {\n return `${key}.${path}`;\n }\n }\n }\n return '';\n}\n\n/**\n * @internal\n * Internal utility for calculating form control field paths.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to determine field names for validation. Use the `name` attribute on your form controls\n * instead of relying on this function.\n *\n * Calculates the field name of a form control: Eg: addresses.shippingAddress.street\n * @param rootForm\n * @param control\n */\nexport function getFormControlField(\n rootForm: FormGroup,\n control: AbstractControl\n): string {\n return getControlPath(rootForm, control);\n}\n\n/**\n * @internal\n * Internal utility for calculating form group field paths.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to determine field names for nested form groups.\n *\n * Calcuates the field name of a form group Eg: addresses.shippingAddress\n * @param rootForm\n * @param control\n */\nexport function getFormGroupField(\n rootForm: FormGroup,\n control: AbstractControl\n): string {\n return getGroupPath(rootForm, control);\n}\n\n/**\n * @internal\n * Internal utility for merging form values with disabled field values.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to include disabled field values in form submissions. Use Angular's `getRawValue()`\n * method on your form if you need to access disabled field values.\n *\n * This utility merges the value of the form with the raw value.\n * By doing this we can assure that we don't lose values of disabled form fields\n *\n * Security: Unsafe prototype-related keys (`__proto__`, `prototype`, `constructor`)\n * are skipped during recursive merge.\n * @param form\n */\nexport function mergeValuesAndRawValues<T>(form: FormGroup): T {\n // Deep clone both values to prevent reference sharing.\n // This is necessary because:\n // 1. form.value may contain object references that could be mutated elsewhere\n // 2. form.getRawValue() also returns references to form control values\n // 3. Without cloning, mutations to the returned object would affect the original form state\n // 4. The merge operation itself requires a mutable copy to work with\n // Performance note: For large forms, this may have performance implications. However,\n // reference isolation is critical for maintaining form state integrity.\n const value = structuredClone(form.value);\n const rawValue = structuredClone(form.getRawValue());\n\n // Recursive function to merge rawValue into value\n function mergeRecursive(target: UnknownRecord, source: UnknownRecord): void {\n for (const key of Object.keys(source)) {\n if (isUnsafePathSegment(key)) {\n continue;\n }\n\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (targetValue === undefined) {\n // If the key is not in the target, add it directly (for disabled fields)\n target[key] = sourceValue;\n } else if (isRecord(sourceValue) && isRecord(targetValue)) {\n // If the value is an object, merge it recursively\n mergeRecursive(targetValue, sourceValue);\n }\n // If the target already has the key with a primitive value, it's left as is to maintain references\n }\n }\n\n mergeRecursive(value as UnknownRecord, rawValue as UnknownRecord);\n return value;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\ntype Primitive = undefined | null | boolean | string | number | Function;\n\nfunction isPrimitive(value: unknown): value is Primitive {\n return (\n value === null || (typeof value !== 'object' && typeof value !== 'function')\n );\n}\n\nfunction getStringArrayError(\n errors: ValidationErrors | null,\n key: string\n): string[] | undefined {\n const value = errors?.[key];\n return Array.isArray(value)\n ? value.filter((v): v is string => typeof v === 'string')\n : undefined;\n}\n\n/**\n * Performs a deep-clone of an object\n * @param obj\n *\n * @deprecated Use official ES {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone structuredClone} instead\n *\n * Browser Support: structuredClone is available in all modern browsers (Chrome 98+, Firefox 94+, Safari 15.4+, Edge 98+)\n * and Node.js 17+. A polyfill is provided in test-setup.ts for Jest test environments.\n */\nexport function cloneDeep<T>(object: T): T {\n // Handle primitives (null, undefined, boolean, string, number, function)\n if (isPrimitive(object)) {\n return object;\n }\n\n // Handle Date\n if (object instanceof Date) {\n return new Date(object) as T;\n }\n\n // Handle Array\n if (Array.isArray(object)) {\n return object.map((item) => cloneDeep(item)) as T;\n }\n\n // Handle Object\n if (object instanceof Object) {\n const clonedObject: UnknownRecord = {};\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n clonedObject[key] = cloneDeep(\n (object as UnknownRecord)[key] as unknown\n );\n }\n }\n return clonedObject as T;\n }\n\n throw new Error(\"Unable to copy object! Its type isn't supported.\");\n}\n\n/**\n * Sets a value in an object at the provided field path.\n *\n * Supports dot and bracket notation via `parseFieldPath()`.\n * Examples: `user.profile.name`, `addresses[0].street`.\n *\n * Security: If any path segment matches an unsafe prototype-related key\n * (`__proto__`, `prototype`, `constructor`), the write is ignored.\n *\n * @param obj - Target object to mutate.\n * @param path - Dot/bracket field path.\n * @param value - Value to assign at the resolved path.\n */\nexport function setValueAtPath(\n obj: object,\n path: string,\n value: unknown\n): void {\n const keys = parseFieldPath(path);\n if (keys.length === 0) {\n return;\n }\n\n let current: UnknownRecord = obj as UnknownRecord;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const segment = keys[i];\n if (segment === undefined) {\n continue;\n }\n if (isUnsafePathSegment(segment)) {\n return;\n }\n\n const key = String(segment);\n\n const next = current[key];\n if (!isRecord(next)) {\n current[key] = {};\n }\n current = current[key] as UnknownRecord;\n }\n\n const lastSegment = keys[keys.length - 1];\n if (lastSegment === undefined || isUnsafePathSegment(lastSegment)) {\n return;\n }\n\n current[String(lastSegment)] = value;\n}\n\n/**\n * @deprecated Use {@link setValueAtPath} instead\n */\nexport function set(obj: object, path: string, value: unknown): void {\n return setValueAtPath(obj, path, value);\n}\n\n/**\n * @internal\n * Internal utility for collecting all form errors by field path.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to generate the form state. Use the `formState()` signal from the `scVestForm` directive\n * to access form errors in your components.\n *\n * Traverses the form and returns the errors by path\n * @param form\n */\nexport function getAllFormErrors(\n form?: AbstractControl\n): Record<string, string[]> {\n const errors: Record<string, ErrorList> = {};\n if (!form) {\n return errors;\n }\n\n // Collect root form errors (from ValidateRootFormDirective) before processing children\n if (form.enabled) {\n const rootErrors = getStringArrayError(form.errors, ERROR_MESSAGES_KEY);\n if (rootErrors) {\n errors[ROOT_FORM] = rootErrors;\n }\n }\n\n function collect(\n control: AbstractControl,\n pathParts: Array<string | number>\n ): void {\n const pathString = stringifyFieldPath(pathParts);\n\n // Skip processing the root form control directly in NgxFormDirective\n if (pathParts.length === 0 && control === form) {\n // Instead, iterate its children if it's a group/array\n if (isFormGroup(control) || isFormArray(control)) {\n for (const [key, childControl] of getChildEntries(control)) {\n const numericKey = Number(key);\n const nextPath = [\n // ...pathParts, // pathParts is empty here\n Number.isNaN(numericKey) ? key : numericKey,\n ];\n collect(childControl, nextPath);\n }\n }\n return; // Stop processing for the root form itself at this level\n }\n\n if (isFormGroup(control) || isFormArray(control)) {\n for (const [key, childControl] of getChildEntries(control)) {\n const numericKey = Number(key);\n const nextPath = [\n ...pathParts,\n Number.isNaN(numericKey) ? key : numericKey,\n ];\n collect(childControl, nextPath);\n }\n }\n\n // Attach control errors (both errors and warnings)\n if (control.enabled) {\n const fieldErrors = getStringArrayError(\n control.errors,\n ERROR_MESSAGES_KEY\n );\n if (fieldErrors) {\n errors[pathString] = fieldErrors;\n }\n // Optionally, add warnings if present\n const fieldWarnings = getStringArrayError(\n control.errors,\n WARNING_MESSAGES_KEY\n );\n if (fieldWarnings) {\n // Attach warnings as a property on the error array (non-enumerable)\n // This is still done here for field-specific warnings, but not for root warnings.\n if (!errors[pathString]) {\n errors[pathString] = []; // Ensure array exists if only warnings are present\n }\n Object.defineProperty(errors[pathString], 'warnings', {\n value: fieldWarnings,\n enumerable: false, // Keep it non-enumerable as per previous behavior for field warnings\n configurable: true,\n writable: true,\n });\n }\n }\n }\n\n collect(form, []);\n\n // Root form errors (form.errors) are no longer processed here.\n // They are handled directly in NgxFormDirective to populate formState.root.\n\n return errors;\n}\n","import { isDevMode } from '@angular/core';\nimport { NGX_VEST_FORMS_ERRORS, logWarning } from '../errors/error-catalog';\n\n/**\n * Validates a form value against a shape to catch typos in `name` or `ngModelGroup` attributes.\n *\n * **What it checks:**\n * - Extra properties: Keys in formValue that don't exist in shape (likely typos)\n * - Type mismatches: When formValue has an object but shape expects a primitive\n *\n * **What it does NOT check:**\n * - Missing properties: Keys in shape that don't exist in formValue\n * (forms build incrementally with `NgxDeepPartial`, and `@if` conditionally renders fields)\n *\n * Only runs in development mode.\n *\n * @param formVal - The current form value\n * @param shape - The expected shape (created with `NgxDeepRequired<T>`)\n */\nexport function validateShape<\n T extends Record<string, unknown>,\n U extends Record<string, unknown>,\n>(formVal: T, shape: U): void {\n if (isDevMode()) {\n validateFormValueAgainstShape(formVal, shape);\n }\n}\n\n/**\n * Recursively validates form value keys against the shape.\n * Reports warnings for extra properties and type mismatches.\n */\nfunction validateFormValueAgainstShape(\n formValue: Record<string, unknown>,\n shape: Record<string, unknown>,\n path = ''\n): void {\n for (const key of Object.keys(formValue)) {\n const value = formValue[key];\n const fieldPath = path ? `${path}.${key}` : key;\n\n // Skip null/undefined values (valid during form initialization)\n if (value == null) {\n continue;\n }\n\n // For array items (numeric keys > 0), compare against the first item in shape\n // since we only define one example item in the shape for arrays\n const isNumericKey = !isNaN(parseFloat(key));\n const shapeKey = isNumericKey && parseFloat(key) > 0 ? '0' : key;\n const shapeValue = shape?.[shapeKey];\n\n // Skip Date fields receiving empty strings (common in date picker libraries)\n if (shapeValue instanceof Date && value === '') {\n continue;\n }\n\n // Handle object values (recurse into nested objects)\n if (typeof value === 'object') {\n // Type mismatch: formValue has object, but shape expects primitive\n if (\n !isNumericKey &&\n (typeof shapeValue !== 'object' || shapeValue === null)\n ) {\n logWarning(\n NGX_VEST_FORMS_ERRORS.TYPE_MISMATCH,\n fieldPath,\n 'primitive',\n 'object'\n );\n }\n\n // Recurse into nested object\n validateFormValueAgainstShape(\n value as Record<string, unknown>,\n (shapeValue as Record<string, unknown>) ?? {},\n fieldPath\n );\n continue;\n }\n\n // Extra property: key exists in formValue but not in shape (likely a typo)\n if (!isNumericKey && shape && !(shapeKey in shape)) {\n logWarning(NGX_VEST_FORMS_ERRORS.EXTRA_PROPERTY, fieldPath);\n }\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport { NgForm } from '@angular/forms';\n\nconst formSubmittedSignals = new WeakMap<NgForm, WritableSignal<boolean>>();\n\ntype AngularSubmittedSignalHost = {\n submittedReactive?: WritableSignal<boolean>;\n _submittedReactive?: WritableSignal<boolean>;\n};\n\nexport function getFormSubmittedSignal(\n ngForm: NgForm\n): WritableSignal<boolean> {\n let submitted = formSubmittedSignals.get(ngForm);\n if (!submitted) {\n submitted = signal(ngForm.submitted);\n formSubmittedSignals.set(ngForm, submitted);\n }\n return submitted;\n}\n\nexport function setAngularFormSubmittedState(\n ngForm: NgForm,\n submitted: boolean\n): void {\n // Angular 21.x's concrete NgForm stores submitted state on\n // `submittedReactive`, while AbstractFormDirective-backed implementations\n // expose `_submittedReactive` and may also provide a public setter on\n // `submitted`. This helper is verified against Angular 21.x in this\n // repository and falls back to the first writable `submitted` setter it can\n // find if a future Angular version changes the concrete field names.\n //\n // We try the concrete/internal signal first because NgForm overrides the\n // getter-only `submitted` property at runtime in this workspace. If neither\n // signal exists, fall back to the first writable `submitted` setter we can\n // find on the prototype chain. If no setter exists either, callers should\n // still update ngx-vest-forms' shared signal so error display state remains\n // reactive even though Angular's native submitted flag cannot be changed.\n const signalHost = ngForm as unknown as AngularSubmittedSignalHost;\n const angularSignal =\n signalHost.submittedReactive ?? signalHost._submittedReactive;\n\n if (angularSignal) {\n angularSignal.set(submitted);\n return;\n }\n\n let prototype: object | null = Object.getPrototypeOf(ngForm);\n while (prototype) {\n const submittedDescriptor = Object.getOwnPropertyDescriptor(\n prototype,\n 'submitted'\n );\n if (submittedDescriptor?.set) {\n submittedDescriptor.set.call(ngForm, submitted);\n return;\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n","import {\n ChangeDetectorRef,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n isDevMode,\n linkedSignal,\n signal,\n untracked,\n} from '@angular/core';\nimport {\n outputFromObservable,\n takeUntilDestroyed,\n toObservable,\n toSignal,\n} from '@angular/core/rxjs-interop';\nimport {\n AbstractControl,\n AsyncValidatorFn,\n FormArray,\n FormGroup,\n NgForm,\n PristineChangeEvent,\n StatusChangeEvent,\n ValidationErrors,\n ValueChangeEvent,\n} from '@angular/forms';\nimport {\n catchError,\n debounceTime,\n distinctUntilChanged,\n EMPTY,\n filter,\n map,\n Observable,\n of,\n race,\n merge as rxMerge,\n scan,\n startWith,\n switchMap,\n take,\n tap,\n timer,\n} from 'rxjs';\nimport { logWarning, NGX_VEST_FORMS_ERRORS } from '../errors/error-catalog';\nimport { NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN } from '../tokens/debounce.token';\nimport { DeepRequired } from '../utils/deep-required';\nimport { fastDeepEqual } from '../utils/equality';\nimport type { ValidationConfigMap } from '../utils/field-path-types';\nimport { stringifyFieldPath } from '../utils/field-path.utils';\nimport {\n DEFAULT_FOCUS_SELECTOR,\n DEFAULT_INVALID_SELECTOR,\n type NgxFirstInvalidOptions,\n openCollapsedDetailsAncestors,\n resolveFirstInvalidElement,\n resolveFirstInvalidFocusTarget,\n resolveFirstInvalidScrollBehavior,\n} from '../utils/first-invalid.utils';\nimport { NgxFormState } from '../utils/form-state.utils';\nimport {\n getAllFormErrors,\n mergeValuesAndRawValues,\n setValueAtPath,\n} from '../utils/form-utils';\nimport { validateShape } from '../utils/shape-validation';\nimport { NgxTypedVestSuite, NgxVestSuite } from '../utils/validation-suite';\nimport { ValidationOptions } from './validation-options';\nimport {\n getFormSubmittedSignal,\n setAngularFormSubmittedState,\n} from './form-submitted-state';\n\n/**\n * Duration (in milliseconds) to keep fields marked as \"in-progress\" after validation.\n * This prevents immediate re-triggering of bidirectional validations.\n * Increased from 100ms to 500ms to give validators enough time to complete and propagate.\n */\nconst VALIDATION_IN_PROGRESS_TIMEOUT_MS = 500;\n\n/**\n * Type for validation configuration that accepts both the typed and untyped versions.\n * This ensures backward compatibility while supporting the new typed API.\n */\nexport type NgxValidationConfig<T = unknown> =\n | Record<string, string[]>\n | ValidationConfigMap<T>\n | null;\n\n/**\n * Main form directive for ngx-vest-forms that bridges Angular template-driven forms with Vest.js validation.\n *\n * This directive provides:\n * - **Unidirectional data flow**: Use `[ngModel]` (not `[(ngModel)]`) with `(formValueChange)` for predictable state updates\n * - **Vest.js integration**: Automatic async validators from Vest suites with field-level optimization\n * - **Validation dependencies**: Configure cross-field validation triggers via `validationConfig`\n * - **Form state**: Access validity, errors, and values through the `formState` signal\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <form ngxVestForm [suite]=\"validationSuite\" (formValueChange)=\"formValue.set($event)\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </form>\n * ```\n *\n * ### With Validation Dependencies\n * ```html\n * <form ngxVestForm [suite]=\"suite\" [validationConfig]=\"validationConfig\">\n * <input name=\"password\" [ngModel]=\"formValue().password\" />\n * <input name=\"confirmPassword\" [ngModel]=\"formValue().confirmPassword\" />\n * </form>\n * ```\n * ```typescript\n * validationConfig = { 'password': ['confirmPassword'] };\n * ```\n *\n * ### Accessing Form State\n * ```typescript\n * vestForm = viewChild.required('vestForm', { read: FormDirective });\n * isValid = computed(() => this.vestForm().formState().valid);\n * ```\n *\n * @see {@link https://github.com/ngx-vest-forms/ngx-vest-forms} for full documentation\n * @publicApi\n */\n@Directive({\n selector: 'form[scVestForm], form[ngxVestForm]',\n exportAs: 'scVestForm, ngxVestForm',\n host: {\n '(focusout)': 'onFormFocusOut()',\n },\n})\nexport class FormDirective<T extends Record<string, unknown>> {\n readonly ngForm = inject(NgForm, { self: true });\n private readonly elementRef = inject(ElementRef<HTMLFormElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly configDebounceTime = inject(\n NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN\n );\n\n /**\n * Public signal storing field warnings keyed by field path.\n * This allows warnings to be stored and displayed without affecting field validity.\n * Angular's control.errors !== null marks a field as invalid, so we store warnings\n * separately when they exist without errors.\n */\n readonly fieldWarnings = signal<Map<string, readonly string[]>>(new Map());\n\n // Track last linked value to prevent unnecessary updates\n #lastLinkedValue: T | null = null;\n #lastSyncedFormValue: T | null = null;\n #lastSyncedModelValue: T | null = null;\n\n // Internal signal tracking form value changes via statusChanges\n readonly #value = toSignal(\n this.ngForm.form.statusChanges.pipe(startWith(this.ngForm.form.status)),\n { initialValue: this.ngForm.form.status }\n );\n\n /**\n * LinkedSignal that computes form values from Angular form state.\n * This eliminates timing issues with the previous dual-effect pattern.\n */\n readonly #formValueSignal = linkedSignal(() => {\n // Track form value changes\n this.#value();\n const raw = mergeValuesAndRawValues<T>(this.ngForm.form);\n if (Object.keys(this.ngForm.form.controls).length > 0) {\n this.#lastLinkedValue = raw;\n return raw;\n } else if (this.#lastLinkedValue !== null) {\n return this.#lastLinkedValue;\n }\n return null;\n });\n\n /**\n * Track the Angular form status as a signal for advanced status flags\n */\n readonly #statusSignal = toSignal(\n this.ngForm.form.statusChanges.pipe(startWith(this.ngForm.form.status)),\n { initialValue: this.ngForm.form.status }\n );\n\n /**\n * Reactive counter incremented on any focusout within the form.\n * This guarantees recomputation for every blur/tab interaction,\n * even when the form's aggregate touched flag is already true.\n */\n readonly #blurTick = signal(0);\n\n /**\n * Computed signal that returns field paths for all touched (or submitted) leaf controls.\n * Updates reactively when controls are touched (blur) or when form status changes.\n *\n * This enables consumers to determine which fields the user has interacted with,\n * useful for filtering errors/warnings to match the form's visible validation state.\n *\n * @publicApi\n */\n readonly touchedFieldPaths = computed(() => {\n this.#blurTick();\n this.#statusSignal();\n return this.#collectTouchedPaths(this.ngForm.form, this.ngForm.submitted);\n });\n\n /**\n * Computed signal for form state with validity and errors.\n * Used by templates and tests as vestForm.formState().valid/errors\n *\n * Uses custom equality function to prevent unnecessary recalculations\n * when form status changes but actual values/errors remain the same.\n */\n readonly formState = computed<NgxFormState<T>>(\n () => {\n // Tie to validation feedback instead of aggregate status so errors update\n // even when the root form remains INVALID -> INVALID.\n this.#validationFeedbackTick();\n return {\n valid: this.ngForm.form.valid,\n errors: getAllFormErrors(this.ngForm.form),\n value: this.#formValueSignal(),\n };\n },\n {\n equal: (a, b) => {\n // Fast path: reference equality\n if (a === b) return true;\n // Null/undefined check\n if (!a || !b) return false;\n // Deep equality check for form state properties\n return (\n a.valid === b.valid &&\n fastDeepEqual(a.errors, b.errors) &&\n fastDeepEqual(a.value, b.value)\n );\n },\n }\n );\n\n /**\n * The value of the form, this is needed for the validation part.\n * Using input() here because two-way binding is provided via formValueChange output.\n * In the minimal core directive (form-core.directive.ts), this would be model() instead.\n */\n readonly formValue = input<T | null>(null);\n\n /**\n * Static vest suite that will be used to feed our angular validators.\n * Accepts both NgxVestSuite and NgxTypedVestSuite through compatible type signatures.\n * NgxTypedVestSuite<T> is assignable to NgxVestSuite<T> due to bivariance and\n * FormFieldName<T> (string literal union) being assignable to string.\n */\n readonly suite = input<NgxVestSuite<T> | NgxTypedVestSuite<T> | null>(null);\n\n /**\n * The shape of our form model. This is a deep required version of the form model\n * The goal is to add default values to the shape so when the template-driven form\n * contains values that shouldn't be there (typo's) that the developer gets run-time\n * errors in dev mode\n */\n readonly formShape = input<DeepRequired<T> | null>(null);\n\n /**\n * Updates the validation config which is a dynamic object that will be used to\n * trigger validations on the dependant fields\n * Eg: ```typescript\n * validationConfig = {\n * 'passwords.password': ['passwords.confirmPassword']\n * }\n * ```\n *\n * This will trigger the updateValueAndValidity on passwords.confirmPassword every time the passwords.password gets a new value\n *\n * @param v\n */\n readonly validationConfig: InputSignal<NgxValidationConfig<T>> =\n input<NgxValidationConfig<T>>(null);\n\n /**\n * Emits whenever validation feedback may have changed, even if the aggregate\n * root form status string stays the same.\n */\n private readonly validationFeedback$ = rxMerge(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v !== 'PENDING')\n ),\n this.ngForm.ngSubmit.pipe(\n switchMap(() => {\n if (this.ngForm.form.status === 'PENDING') {\n return this.ngForm.form.statusChanges.pipe(\n filter((status) => status !== 'PENDING'),\n take(1)\n );\n }\n\n return of(this.ngForm.form.status);\n })\n )\n );\n\n /**\n * Counter signal tied to validation feedback updates so `formState()` can\n * recompute whenever the underlying error set changes.\n */\n readonly #validationFeedbackTick = toSignal(\n this.validationFeedback$.pipe(\n scan((count) => count + 1, 0),\n startWith(0)\n ),\n { initialValue: 0 }\n );\n\n private readonly pending$ = this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v === 'PENDING'),\n distinctUntilChanged()\n );\n\n /**\n * Emits every time the form status changes in a state\n * that is not PENDING\n * We need this to assure that the form is in 'idle' state\n */\n readonly idle$ = this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v !== 'PENDING'),\n distinctUntilChanged()\n );\n\n /**\n * Triggered as soon as the form value changes\n * It also contains the disabled values (raw values)\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly formValueChange = outputFromObservable(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof ValueChangeEvent),\n map((v) => (v as ValueChangeEvent<unknown>).value),\n distinctUntilChanged((prev, curr) => {\n // Use efficient deep equality instead of JSON.stringify for better performance\n return fastDeepEqual(prev, curr);\n }),\n map(() => mergeValuesAndRawValues<T>(this.ngForm.form)),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Emits an object with all the errors of the form\n * every time a form control or form groups changes its status to valid or invalid\n *\n * For submit events, waits for async validation (including ROOT_FORM) to complete\n * before emitting errors. This ensures ROOT_FORM errors are included in the output.\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly errorsChange = outputFromObservable(\n this.validationFeedback$.pipe(\n map(() => getAllFormErrors(this.ngForm.form)),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Triggered as soon as the form becomes dirty\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly dirtyChange = outputFromObservable(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof PristineChangeEvent),\n map((v) => !(v as PristineChangeEvent).pristine),\n startWith(this.ngForm.form.dirty),\n distinctUntilChanged(),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Fired when the status of the root form changes.\n */\n private readonly statusChanges$ = this.ngForm.form.statusChanges.pipe(\n startWith(this.ngForm.form.status),\n distinctUntilChanged()\n );\n\n /**\n * Triggered When the form becomes valid but waits until the form is idle\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly validChange = outputFromObservable(\n this.statusChanges$.pipe(\n filter((e) => e === 'VALID' || e === 'INVALID'),\n map((v) => v === 'VALID'),\n distinctUntilChanged(),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Track validation in progress to prevent circular triggering (Issue #19)\n */\n private readonly validationInProgress = new Set<string>();\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.fieldWarnings.set(new Map());\n });\n\n /**\n * Trigger shape validations if the form gets updated\n * This is how we can throw run-time errors\n */\n if (isDevMode()) {\n effect(() => {\n const v = this.formValue();\n if (v && this.formShape()) {\n validateShape(v, this.formShape() as DeepRequired<T>);\n }\n });\n }\n\n /**\n * Mark all the fields as touched when the form is submitted\n */\n this.ngForm.ngSubmit\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => {\n this.ngForm.form.markAllAsTouched();\n this.#blurTick.update((v) => v + 1);\n });\n\n /**\n * Single bidirectional synchronization effect using linkedSignal.\n * Uses proper deep comparison and change tracking for correct sync direction.\n * Note: formValue is read-only input(), so we emit changes via formValueChange output.\n */\n effect(() => {\n const formValue = this.#formValueSignal();\n const modelValue = this.formValue();\n\n // Skip if either is null\n if (!formValue && !modelValue) return;\n\n // Compute change flags first\n const formChanged = !fastDeepEqual(formValue, this.#lastSyncedFormValue);\n const modelChanged = !fastDeepEqual(\n modelValue,\n this.#lastSyncedModelValue\n );\n\n // Early return if nothing changed\n if (!formChanged && !modelChanged) {\n return;\n }\n\n if (formChanged && !modelChanged) {\n // Form was modified by user -> form wins\n // Note: We can't call this.formValue.set() since it's an input()\n // The formValueChange output will emit the new value\n // Use untracked() to avoid infinite loops - we're updating tracking state here\n untracked(() => {\n this.#lastSyncedFormValue = formValue;\n this.#lastSyncedModelValue = formValue;\n });\n } else if (modelChanged && !formChanged) {\n // Model was modified programmatically -> model wins\n // Use untracked() to avoid infinite loops - we're updating tracking state here\n untracked(() => {\n // Update form controls with new model values\n if (modelValue) {\n // IMPORTANT: Use root patchValue instead of per-key setValue.\n // - Supports nested objects (ngModelGroup) without throwing when partial objects are provided.\n // - patchValue ignores missing controls/keys, which is compatible with DeepPartial form models.\n // - emitEvent:false prevents feedback loops; validation still updates internally.\n this.ngForm.form.patchValue(modelValue, { emitEvent: false });\n }\n this.#lastSyncedFormValue = modelValue;\n this.#lastSyncedModelValue = modelValue;\n });\n } else if (formChanged && modelChanged) {\n // Both form and model changed simultaneously\n // Check if they changed to the same value (synchronized change) or different values (conflict)\n const valuesEqual = fastDeepEqual(formValue, modelValue);\n\n if (valuesEqual) {\n // Both changed to the same value - this is a synchronized change, not a conflict\n // Just update tracking to acknowledge the change\n untracked(() => {\n this.#lastSyncedFormValue = formValue;\n this.#lastSyncedModelValue = formValue;\n });\n } else {\n // Both changed to different values - this is a true conflict\n // This is an edge case that should rarely happen in practice.\n // We intentionally do nothing here to avoid breaking the Angular event flow.\n // The form will continue with its current values, and validation will run normally.\n // The next change (either form or model) will trigger proper synchronization.\n }\n }\n });\n\n // Set up validation config reactively\n this.#setupValidationConfig();\n }\n\n /**\n * Manually trigger form validation update.\n *\n * This is useful when form structure changes but no control values change,\n * which means validation state might be stale. This method forces a re-evaluation\n * of all form validators and updates the form validity state.\n *\n * **IMPORTANT: This method validates ALL form fields by design.**\n * This is intentional for structure changes as conditional validators may now\n * apply to different fields, requiring a complete validation refresh.\n *\n * **CRITICAL: This method does NOT mark fields as touched or show errors.**\n * It only re-runs validation logic. To show all errors (e.g., on submit),\n * use `markAllAsTouched()` instead or in combination.\n *\n * **When to use each:**\n * - `triggerFormValidation()` - Re-run validation when structure changes\n * - `markAllAsTouched()` - Show all errors to user (e.g., on submit)\n * - Both together - Rare, only if structure changed AND you want to show errors\n *\n * **Note on form submission:**\n * When using the default error display mode (`on-blur-or-submit`), you typically\n * don't need to call this method on submit. The form directive automatically marks\n * all fields as touched on `ngSubmit`, and errors will display automatically.\n * Only use this method when form structure changes without value changes.\n *\n * **Use Cases:**\n * - Conditionally showing/hiding form controls based on other field values\n * - Adding or removing form controls dynamically\n * - Switching between different form layouts where validation requirements change\n * - Any scenario where form structure changes but no ValueChangeEvent is triggered\n *\n * **Example:**\n * When switching from a form with required input fields to one with only informational content,\n * the form should become valid, but this won't happen automatically\n * when no value changes occur (e.g., switching from input fields to informational content).\n *\n * **Performance Note:**\n * This method calls `updateValueAndValidity({ emitEvent: true })` on the root form,\n * which validates all form controls. For large forms, consider if more granular\n * validation updates are possible.\n *\n * @example\n * ```typescript\n * /// After changing form structure\n * onProcedureTypeChange(newType: string) {\n * this.procedureType.set(newType);\n * /// Structure changed but no control values changed\n * this.formDirective.triggerFormValidation();\n * }\n *\n * /// For submit with multiple forms (show all errors)\n * submitAll() {\n * // Mark all as touched to show errors\n * this.form1Ref().markAllAsTouched();\n * this.form2Ref().markAllAsTouched();\n * // Only needed if structure changed without value changes\n * // this.form1Ref().triggerFormValidation();\n * // this.form2Ref().triggerFormValidation();\n * }\n * ```\n */\n triggerFormValidation(path?: string): void {\n if (path) {\n const control = this.ngForm.form.get(path);\n if (control) {\n control.updateValueAndValidity({ emitEvent: true });\n } else if (isDevMode()) {\n logWarning(NGX_VEST_FORMS_ERRORS.CONTROL_NOT_FOUND, path);\n }\n } else {\n // Update all form controls validity which will trigger all form events\n this.ngForm.form.updateValueAndValidity({ emitEvent: true });\n }\n }\n\n /**\n * Convenience method to mark all form controls as touched.\n *\n * This is useful for showing all validation errors at once, typically when\n * the user clicks a submit button. When a field is marked as touched,\n * the error display logic (based on `errorDisplayMode`) will show its errors.\n *\n * **Note on automatic behavior:**\n * When using the default error display mode (`on-blur-or-submit`), you typically\n * don't need to call this method manually for regular form submissions. The form\n * directive automatically marks all fields as touched on `ngSubmit`, so errors\n * will display automatically when the user submits the form.\n *\n * **When to use this method:**\n * - Multiple forms with a single submit button (forms without their own submit)\n * - Programmatic form submission without triggering `ngSubmit`\n * - Custom validation flows outside the normal submit process\n *\n * **Note:** This method only marks fields as touched—it does NOT re-run validation.\n * If you also need to re-run validation (e.g., after structure changes), call\n * `triggerFormValidation()` as well.\n *\n * @example\n * ```typescript\n * /// Standard form submission - NO need to call markAllAsTouched()\n * /// The directive handles this automatically on ngSubmit\n * <form ngxVestForm (ngSubmit)=\"save()\">\n * <button type=\"submit\">Submit</button>\n * </form>\n *\n * /// Multiple forms with one submit button\n * submitAll() {\n * this.form1().markAllAsTouched();\n * this.form2().markAllAsTouched();\n * if (this.form1().formState().valid && this.form2().formState().valid) {\n * /// Submit all forms\n * }\n * }\n * ```\n */\n markAllAsTouched(): void {\n this.ngForm.form.markAllAsTouched();\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Clears the current submit cycle without resetting control values or metadata.\n *\n * Unlike {@link resetForm}, this only flips the submitted gate back to `false`.\n * Touched/dirty/pristine state is preserved so consumers can end `'on-submit'`\n * error visibility without a full form reset.\n *\n * **When to use:**\n * - You use submit-gated error visibility such as `'on-submit'`\n * - A submit attempt already happened\n * - The user resolved the current submit-time errors\n * - You want future untouched fields to wait for the next submit before showing errors\n *\n * **Why this exists:**\n * `resetForm()` would also clear touched/dirty/pristine metadata, which is often\n * too disruptive for long-form, multi-form, or mixed error-display flows.\n *\n * **What it does NOT do:**\n * - Does not change field values\n * - Does not mark controls pristine or untouched\n * - Does not re-run validation\n *\n * @example\n * ```typescript\n * submitAll(): void {\n * for (const form of this.submitForms()) {\n * form.ngForm.onSubmit(new Event('submit'));\n * }\n *\n * if (this.submitForms().every((form) => form.formState().valid)) {\n * for (const form of this.submitForms()) {\n * form.clearSubmittedState();\n * }\n * }\n * }\n * ```\n *\n * @see {@link resetForm} to fully reset values and control metadata\n * @see {@link markAllAsTouched} to manually show all errors\n * @see {@link triggerFormValidation} to re-run validation after structure changes\n */\n clearSubmittedState(): void {\n setAngularFormSubmittedState(this.ngForm, false);\n getFormSubmittedSignal(this.ngForm).set(false);\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Finds the first invalid element in this form, scrolls it into view, and focuses it.\n *\n * Useful in custom submit flows where `markAllAsTouched()` is triggered externally\n * and the app then wants to guide keyboard and assistive-technology users to the\n * first failing field.\n *\n * @returns The focused element when a focusable target exists, otherwise the first\n * matched invalid element. Returns `null` when no invalid element is found.\n */\n focusFirstInvalidControl(\n options: NgxFirstInvalidOptions = {}\n ): HTMLElement | null {\n const {\n block = 'center',\n inline = 'nearest',\n focus = true,\n preventScrollOnFocus = true,\n openCollapsedParents = true,\n invalidSelector = DEFAULT_INVALID_SELECTOR,\n focusSelector = DEFAULT_FOCUS_SELECTOR,\n } = options;\n const behavior = resolveFirstInvalidScrollBehavior(options.behavior);\n\n const root: HTMLFormElement = this.elementRef.nativeElement;\n const firstInvalid = resolveFirstInvalidElement(root, invalidSelector);\n if (!firstInvalid) {\n return null;\n }\n\n if (openCollapsedParents) {\n openCollapsedDetailsAncestors(root, firstInvalid);\n }\n\n const focusTarget = resolveFirstInvalidFocusTarget(\n firstInvalid,\n focusSelector\n );\n\n const scrollTarget = focusTarget ?? firstInvalid;\n scrollTarget.scrollIntoView({ behavior, block, inline });\n\n if (focus && focusTarget) {\n focusTarget.focus({ preventScroll: preventScrollOnFocus });\n }\n\n return focusTarget ?? firstInvalid;\n }\n\n /**\n * Finds and scrolls the first invalid element into view without moving focus.\n *\n * @returns The resolved element, or `null` when no invalid element is found.\n */\n scrollToFirstInvalidControl(\n options: NgxFirstInvalidOptions = {}\n ): HTMLElement | null {\n return this.focusFirstInvalidControl({\n ...options,\n focus: false,\n });\n }\n\n /**\n * Host handler: called whenever any descendant field loses focus.\n * Used to make touched-path tracking react immediately on blur/tab.\n */\n onFormFocusOut(): void {\n // Run on the next microtask to ensure Angular has already applied\n // control.touched changes for the field that just blurred.\n queueMicrotask(() => {\n this.#blurTick.update((v) => v + 1);\n });\n }\n\n /**\n * Resets the form to a pristine, untouched state with optional new values.\n *\n * This method properly resets the form by:\n * 1. Resetting Angular's underlying NgForm with the provided value\n * 2. Clearing the bidirectional sync tracking state\n * 3. Forcing a form validity update to clear any stale validation errors\n *\n * **Why this method exists:**\n * When using the pattern `formValue.set({})` to reset a form, there can be a timing\n * issue where the form controls in the DOM still hold their old values while the\n * signal has already been updated. This creates a conflict in the bidirectional\n * sync logic, requiring workarounds like calling `formValue.set({})` twice with\n * a setTimeout. This method provides a proper solution by:\n * - Calling Angular's `NgForm.resetForm()` which properly clears all controls\n * - Clearing the internal sync tracking state to avoid stale comparisons\n * - Triggering a form validity update to ensure validation state is current\n *\n * **Usage:**\n * Instead of the double-set workaround:\n * ```typescript\n * // ❌ Old workaround (avoid)\n * reset(): void {\n * this.formValue.set({});\n * setTimeout(() => this.formValue.set({}), 0);\n * }\n *\n * // ✅ Preferred approach\n * vestForm = viewChild.required('vestForm', { read: FormDirective });\n * reset(): void {\n * this.formValue.set({});\n * this.vestForm().resetForm();\n * }\n * ```\n *\n * **With new values:**\n * ```typescript\n * // Reset and set new initial values\n * resetWithDefaults(): void {\n * const defaults = { firstName: '', lastName: '', age: 18 };\n * this.formValue.set(defaults);\n * this.vestForm().resetForm(defaults);\n * }\n * ```\n *\n * @param value - Optional new value to reset the form to. If not provided,\n * resets to empty/default values.\n *\n * @see {@link markAllAsTouched} for showing validation errors\n * @see {@link triggerFormValidation} for re-running validation without reset\n */\n resetForm(value?: T | null): void {\n // Reset Angular's form to clear all controls and mark as pristine/untouched\n this.ngForm.resetForm(value ?? undefined);\n\n // Clear any stored warnings to avoid stale messages after reset\n this.fieldWarnings.set(new Map());\n\n // Clear the bidirectional sync tracking state so the next formValue change\n // is treated as a model change (not a conflict with stale form values)\n this.#lastSyncedFormValue = null;\n this.#lastSyncedModelValue = null;\n this.#lastLinkedValue = null;\n\n // Force change detection to ensure DOM updates are reflected\n // Note: This is still needed even with signals because we're modifying NgForm\n // (reactive forms), not signals. The formValue signal updates happen in the\n // consumer component. detectChanges() ensures NgForm's reset is reflected in\n // the DOM before we update validity.\n this.cdr.detectChanges();\n\n // Trigger validation update to clear any stale errors\n // Now synchronous since detectChanges() has flushed DOM updates\n this.ngForm.form.updateValueAndValidity({ emitEvent: true });\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Creates a one-shot async validator function for a specific field path.\n *\n * The returned validator:\n * - snapshots the current form model,\n * - injects the candidate control value at `field`,\n * - runs the Vest suite with debouncing,\n * - maps Vest errors/warnings into Angular `ValidationErrors | null`.\n *\n * Warnings are stored in `fieldWarnings` to keep warnings non-blocking when no errors exist.\n */\n createAsyncValidator(\n field: string,\n validationOptions: ValidationOptions\n ): AsyncValidatorFn {\n const suite = this.suite();\n if (!suite) return () => of(null);\n\n return (control: AbstractControl) => {\n const model = mergeValuesAndRawValues<T>(this.ngForm.form);\n\n // Targeted snapshot with candidate value injected at path\n // mergeValuesAndRawValues already returns a deep clone (via structuredClone),\n // so we can modify it directly without affecting the form state.\n const snapshot = model;\n setValueAtPath(snapshot as object, field, control.value);\n\n // Use timer() instead of ReplaySubject for proper debouncing\n return timer(validationOptions.debounceTime ?? 0).pipe(\n map(() => snapshot),\n switchMap(\n (snap) =>\n new Observable<ValidationErrors | null>((observer) => {\n try {\n // Cast to NgxVestSuite to accept string field parameter\n // Both NgxVestSuite and NgxTypedVestSuite work with string at runtime\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (suite as NgxVestSuite<T>)(snap, field).done((result: any) => {\n const errors = result.getErrors()[field];\n const warnings = result.getWarnings()[field];\n\n // Store warnings in the fieldWarnings signal for access by control wrappers.\n // This is necessary because Angular marks a field as invalid when control.errors !== null.\n // By storing warnings separately, fields can remain valid while still displaying warnings.\n this.fieldWarnings.update((map) => {\n const newMap = new Map(map);\n if (warnings?.length) {\n newMap.set(field, warnings);\n } else {\n newMap.delete(field);\n }\n return newMap;\n });\n\n // Build the validation result:\n // - Errors exist → return { errors, warnings? } (field invalid, Angular shows ng-invalid)\n // - Only warnings → return null (field valid, warnings accessed via fieldWarnings signal)\n // - Neither → return null (field valid)\n //\n // When errors exist, we also include warnings in control.errors for backwards compatibility\n // with code that reads warnings from control.errors.warnings.\n const out = errors?.length\n ? {\n errors,\n ...(warnings?.length && { warnings }),\n }\n : null;\n\n // CRITICAL: Ensure DOM validity classes update for OnPush components.\n //\n // Angular's template-driven forms update `ng-valid`/`ng-invalid` host classes\n // during change detection. When async validation completes, there may be no\n // follow-up change detection pass for OnPush hosts, leaving the DOM in a stale\n // visual state (even though the control status has updated).\n //\n // We schedule a detectChanges() on the next microtask to avoid calling it\n // synchronously inside Angular's own validation pipeline.\n queueMicrotask(() => {\n try {\n this.cdr.detectChanges();\n } catch {\n // Fallback: mark for check when immediate detectChanges isn't safe.\n // This keeps behavior resilient in edge cases.\n this.cdr.markForCheck();\n }\n });\n\n observer.next(out);\n observer.complete();\n });\n } catch {\n observer.next({ vestInternalError: 'Validation failed' });\n observer.complete();\n }\n })\n ),\n catchError(() => of({ vestInternalError: 'Validation failed' })),\n take(1)\n );\n };\n }\n\n /**\n * Set up validation config reactively using v2 pattern with toObservable + switchMap.\n * This provides automatic cleanup when config changes.\n */\n #setupValidationConfig(): void {\n const form = this.ngForm.form;\n toObservable(this.validationConfig)\n .pipe(\n distinctUntilChanged(),\n switchMap((config) => {\n // Cast to the expected type for the helper method\n const typedConfig = config as\n | ValidationConfigMap<T>\n | null\n | undefined;\n return this.#createValidationStreams(form, typedConfig);\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe();\n }\n\n /**\n * Creates validation streams for the provided configuration.\n * Returns EMPTY if config is null/undefined, otherwise merges all trigger field streams.\n *\n * @param form - The NgForm instance\n * @param config - The validation configuration mapping trigger fields to dependent fields\n * @returns Observable that emits when any trigger field changes and dependent fields need validation\n */\n #createValidationStreams(\n form: FormGroup,\n config: ValidationConfigMap<T> | null | undefined\n ): Observable<unknown> {\n if (!config) {\n this.validationInProgress.clear();\n return EMPTY;\n }\n\n const streams = Object.keys(config).map((triggerField) => {\n const dependents =\n (config as Record<string, string[]>)[triggerField] || [];\n return this.#createTriggerStream(form, triggerField, dependents);\n });\n\n return streams.length > 0 ? rxMerge(...streams) : EMPTY;\n }\n\n /**\n * Creates a stream for a single trigger field that revalidates its dependent fields.\n *\n * This method handles:\n * 1. Waiting for the trigger control to exist in the form (for @if scenarios)\n * 2. Listening to value changes with debouncing\n * 3. Waiting for form to be idle before triggering dependents\n * 4. Waiting for all dependent controls to exist\n * 5. Updating dependent field validity with loop prevention\n *\n * @param form - The NgForm instance\n * @param triggerField - Field path that triggers validation (e.g., 'password')\n * @param dependents - Array of dependent field paths to revalidate (e.g., ['confirmPassword'])\n * @returns Observable that completes after dependent fields are validated\n */\n #createTriggerStream(\n form: FormGroup,\n triggerField: string,\n dependents: string[]\n ): Observable<unknown> {\n // Wait for trigger control to exist, then stop listening (take(1) prevents feedback loops)\n const triggerControl$ = form.statusChanges.pipe(\n startWith(form.status),\n map(() => form.get(triggerField)),\n filter((c): c is AbstractControl => !!c),\n // CRITICAL: take(1) to stop listening after control is found\n // Without this, the pipeline continues to listen to statusChanges,\n // creating a feedback loop where validation triggers re-trigger the pipeline\n take(1)\n );\n\n return triggerControl$.pipe(\n switchMap((control) => {\n return control.valueChanges.pipe(\n // CRITICAL: Filter out changes when this field is being validated by another field's config\n // This prevents circular triggers in bidirectional validationConfig\n filter(() => !this.validationInProgress.has(triggerField)),\n debounceTime(this.configDebounceTime),\n switchMap(() => {\n return this.#waitForFormIdle(form, control);\n }),\n switchMap(() =>\n this.#waitForDependentControls(form, dependents, control)\n ),\n tap(() =>\n this.#updateDependentFields(form, control, triggerField, dependents)\n )\n );\n })\n );\n }\n\n /**\n * Waits for the form to reach a non-PENDING state before proceeding.\n * This prevents validation race conditions where dependent field validation\n * triggers while the trigger field's validation is still running.\n *\n * If the form stays PENDING for longer than 2 seconds (e.g., slow async validators),\n * proceeds anyway to prevent blocking the validation pipeline.\n *\n * @param form - The NgForm instance\n * @param control - The trigger control to pass through\n * @returns Observable that emits the control once form is idle or timeout\n */\n #waitForFormIdle(\n form: FormGroup,\n control: AbstractControl\n ): Observable<AbstractControl> {\n // If form is already non-PENDING, return immediately\n if (form.status !== 'PENDING') {\n return of(control);\n }\n\n // Form is PENDING, wait for it to become idle\n\n const idle$ = form.statusChanges.pipe(\n filter((s) => s !== 'PENDING'),\n take(1)\n );\n\n const timeout$ = timer(2000).pipe(\n tap(() => {\n if (isDevMode()) {\n console.warn(\n '[ngx-vest-forms] validationConfig: timed out waiting for form to leave PENDING state (2s). Continuing dependent validation to avoid stalling.'\n );\n }\n })\n );\n\n return race(idle$, timeout$).pipe(map(() => control));\n }\n\n /**\n * Waits for all dependent controls to exist in the form.\n * This handles @if scenarios where controls are conditionally rendered.\n *\n * @param form - The NgForm instance\n * @param dependents - Array of dependent field paths\n * @param control - The trigger control to pass through\n * @returns Observable that emits the control once all dependents exist\n */\n #waitForDependentControls(\n form: FormGroup,\n dependents: string[],\n control: AbstractControl\n ): Observable<AbstractControl> {\n const allDependentsExist = dependents.every(\n (depField) => !!form.get(depField)\n );\n\n if (allDependentsExist) {\n return of(control);\n }\n\n // Wait for dependent controls to be added to the form, but bound the wait to avoid silent stalls.\n const dependentControlsReady$ = form.statusChanges.pipe(\n startWith(form.status),\n filter(() => dependents.every((depField) => !!form.get(depField))),\n take(1),\n map(() => control)\n );\n\n const timeout$ = timer(2000).pipe(\n tap(() => {\n if (isDevMode()) {\n const unresolved = dependents.filter(\n (depField) => !form.get(depField)\n );\n console.warn(\n `[ngx-vest-forms] validationConfig: timed out waiting for dependent controls (2s): ${unresolved.join(', ')}. Continuing without waiting further.`\n );\n }\n }),\n map(() => control)\n );\n\n return race(dependentControlsReady$, timeout$).pipe(take(1));\n }\n\n /**\n * Updates validation for all dependent fields.\n *\n * Handles:\n * - Loop prevention via validationInProgress set\n * - Silent validation updates that avoid feedback loops\n *\n * Note: Touch state is NOT propagated to prevent premature error display\n * on conditionally revealed fields.\n *\n * Note: This method does NOT propagate touch state from trigger to dependent fields.\n * Dependent fields only show errors after the user directly interacts with them.\n *\n * @param form - The NgForm instance\n * @param control - The trigger control\n * @param triggerField - Field path of the trigger\n * @param dependents - Array of dependent field paths to update\n */\n #updateDependentFields(\n form: FormGroup,\n control: AbstractControl,\n triggerField: string,\n dependents: string[]\n ): void {\n // Mark trigger field as in-progress to prevent it from being re-triggered\n this.validationInProgress.add(triggerField);\n\n for (const depField of dependents) {\n const dependentControl = form.get(depField);\n if (!dependentControl) {\n continue;\n }\n\n // Only validate if not already in progress (prevents bidirectional loops)\n if (!this.validationInProgress.has(depField)) {\n // CRITICAL: Mark the dependent field as in-progress BEFORE calling updateValueAndValidity\n // This prevents the dependent field's valueChanges from triggering its own validationConfig\n this.validationInProgress.add(depField);\n\n // NOTE: Touch propagation removed (PR #78)\n // Previously, we propagated touch state from trigger to dependent fields.\n // This caused UX issues where dependent fields showed errors immediately\n // after being revealed by a toggle, even though the user never interacted with them.\n //\n // With this change:\n // - Errors on dependent fields only show after the user directly touches/blurs them\n // - ARIA attributes (aria-invalid) still work correctly via isInvalid check\n // - Warnings still show after validation via hasBeenValidated check\n //\n // The removed code was:\n // if (control.touched && !dependentControl.touched) {\n // dependentControl.markAsTouched({ onlySelf: true });\n // }\n\n // emitEvent: true is REQUIRED for async validators to actually run\n // The validationInProgress Set prevents infinite loops:\n // 1. Field A changes → triggers validation on dependent field B\n // 2. B is added to validationInProgress Set\n // 3. B's statusChanges emits → #handleValueChange checks validationInProgress\n // 4. Since B is in validationInProgress, its validationConfig is not triggered\n // 5. After 500ms timeout, B is removed from validationInProgress\n // This way:\n // - Async validators CAN run (emitEvent: true)\n // - BUT circular triggers are prevented (validationInProgress check)\n dependentControl.updateValueAndValidity({\n onlySelf: true,\n emitEvent: true, // Changed from false - REQUIRED for validators to run!\n });\n\n // CRITICAL: Force immediate change detection for OnPush components\n // updateValueAndValidity updates the control's status, but doesn't automatically\n // trigger change detection. Components using OnPush won't see the ng-invalid class\n // update in the DOM without this. Using detectChanges() instead of markForCheck()\n // to force immediate synchronous update rather than waiting for next CD cycle.\n this.cdr.detectChanges();\n }\n }\n\n // Keep fields marked as in-progress for a short time to prevent immediate re-triggering\n // Use setTimeout to ensure async validators have time to complete before allowing new triggers\n setTimeout(() => {\n this.validationInProgress.delete(triggerField);\n for (const depField of dependents) {\n this.validationInProgress.delete(depField);\n }\n }, VALIDATION_IN_PROGRESS_TIMEOUT_MS);\n }\n\n /**\n * Collects field paths of all touched (or submitted) leaf controls\n * by walking the form control tree.\n */\n #collectTouchedPaths(control: AbstractControl, submitted: boolean): string[] {\n const fields: string[] = [];\n\n const collect = (\n current: AbstractControl,\n path: Array<string | number>\n ): void => {\n if (current instanceof FormGroup) {\n for (const [name, child] of Object.entries(current.controls)) {\n collect(child, [...path, name]);\n }\n return;\n }\n\n if (current instanceof FormArray) {\n current.controls.forEach((child, index) => {\n collect(child, [...path, index]);\n });\n return;\n }\n\n if ((submitted || current.touched) && path.length > 0) {\n fields.push(stringifyFieldPath(path));\n }\n };\n\n collect(control, []);\n return fields;\n }\n}\n","import {\n Directive,\n Injector,\n afterEveryRender,\n computed,\n contentChild,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport {\n AbstractControlDirective,\n NgModel,\n NgModelGroup,\n ValidationErrors,\n} from '@angular/forms';\nimport { FormDirective } from './form.directive';\n\n/**\n * Angular's ValidationErrors is `{ [key: string]: any }`.\n * We extend it with Vest-specific structure for better type safety.\n */\nexport type VestValidationErrors = {\n /** Vest error messages array */\n errors?: readonly string[];\n /** Vest warning messages array */\n warnings?: readonly string[];\n} & ValidationErrors;\n\n/**\n * Form control status values as defined by Angular.\n * @see AbstractControl.status\n */\nexport type FormControlStatus = 'VALID' | 'INVALID' | 'PENDING' | 'DISABLED';\n\n/**\n * Represents the core state of an Angular form control.\n * Uses narrower types than Angular's defaults where possible.\n */\nexport type FormControlState = {\n readonly status: FormControlStatus | null;\n readonly isValid: boolean;\n readonly isInvalid: boolean;\n readonly isPending: boolean;\n readonly isDisabled: boolean;\n readonly isTouched: boolean;\n readonly isDirty: boolean;\n readonly isPristine: boolean;\n /** Errors from Angular validators or Vest validation */\n readonly errors: VestValidationErrors | null;\n};\n\nconst INITIAL_FORM_CONTROL_STATE = {\n status: 'INVALID',\n isValid: false,\n isInvalid: true,\n isPending: false,\n isDisabled: false,\n isTouched: false,\n isDirty: false,\n isPristine: true,\n errors: null,\n} as const satisfies FormControlState;\n\n@Directive({\n selector: '[formControlState], [ngxControlState]',\n exportAs: 'formControlState, ngxControlState',\n})\nexport class FormControlStateDirective {\n protected readonly contentNgModel = contentChild(NgModel);\n protected readonly contentNgModelGroup = contentChild(NgModelGroup);\n\n readonly #hostNgModel = inject(NgModel, { self: true, optional: true });\n readonly #hostNgModelGroup = inject(NgModelGroup, {\n self: true,\n optional: true,\n });\n readonly #injector = inject(Injector);\n\n /**\n * Reference to the parent FormDirective for accessing field warnings.\n * Optional to support usage outside of ngxVestForm context.\n */\n readonly #formDirective = inject(FormDirective, { optional: true });\n\n /**\n * Computed signal for the active control (NgModel or NgModelGroup)\n */\n readonly #activeControl = computed(\n (): AbstractControlDirective | null =>\n this.#hostNgModel ||\n this.#hostNgModelGroup ||\n this.contentNgModel() ||\n this.contentNgModelGroup() ||\n null\n );\n\n /**\n * Consolidated internal signal for interaction state tracking.\n * Combines touched, dirty, and hasBeenValidated into a single signal\n * to reduce signal overhead and simplify state updates.\n */\n readonly #interactionState = signal({\n isTouched: false,\n isDirty: false,\n hasBeenValidated: false,\n });\n\n /**\n * Track the previous status to detect actual status changes (not just status emissions).\n * This helps distinguish between initial control creation and actual re-validation.\n */\n #previousStatus: FormControlStatus | null = null;\n\n /**\n * Internal signal for control state (updated reactively)\n */\n readonly #controlStateSignal = signal<FormControlState>(\n INITIAL_FORM_CONTROL_STATE\n );\n\n constructor() {\n // Update control state reactively with proper cleanup\n effect((onCleanup) => {\n const control = this.#activeControl();\n const interaction = this.#interactionState();\n\n if (!control) {\n this.#controlStateSignal.set(INITIAL_FORM_CONTROL_STATE);\n return;\n }\n\n // Listen to control changes\n const sub = control.control?.statusChanges?.subscribe(() => {\n const {\n status,\n valid,\n invalid,\n pending,\n disabled,\n pristine,\n errors,\n touched,\n } = control;\n\n const currentStatus = status as FormControlStatus | null;\n\n // Mark as validated when any of the following conditions are met:\n // 1. The control has been touched (user blurred the field).\n // 2. The control's status has actually changed (not the first status emission),\n // AND the new status is not 'PENDING' (validation completed).\n //\n // This ensures hasBeenValidated is true for:\n // - User blur events (touched becomes true)\n // - Any validation that changes status (e.g., typing then validation completes)\n // - ValidationConfig-triggered validations (status changed without touch/dirty)\n // But NOT for initial page load validations (previousStatus === null).\n //\n // Note: The dirty check was removed to support validationConfig-triggered validations.\n // This allows warnings to show even when the field hasn't been touched/dirtied by the user.\n //\n // Accessibility: The logic is structured for clarity and maintainability.\n // IMPORTANT: Read touched/dirty directly from control, not from signal,\n // to avoid race conditions with afterEveryRender sync.\n if (\n touched || // Control was blurred (most common case)\n (this.#previousStatus !== null && // Not the first status emission\n this.#previousStatus !== currentStatus && // Status actually changed\n currentStatus !== null &&\n currentStatus !== 'PENDING') // Validation completed (not pending)\n ) {\n this.#interactionState.update((state) => ({\n ...state,\n hasBeenValidated: true,\n }));\n }\n\n // Track current status for next iteration\n this.#previousStatus = currentStatus;\n\n this.#controlStateSignal.set({\n status: currentStatus,\n isValid: valid ?? false,\n isInvalid: invalid ?? false,\n isPending: pending ?? false,\n isDisabled: disabled ?? false,\n isTouched: interaction.isTouched,\n isDirty: interaction.isDirty,\n isPristine: pristine ?? true,\n errors: errors as VestValidationErrors | null,\n });\n });\n\n // Initial update\n const { status, valid, invalid, pending, disabled, pristine, errors } =\n control;\n\n const initialStatus = status as FormControlStatus | null;\n this.#previousStatus = initialStatus;\n\n this.#controlStateSignal.set({\n status: initialStatus,\n isValid: valid ?? false,\n isInvalid: invalid ?? false,\n isPending: pending ?? false,\n isDisabled: disabled ?? false,\n isTouched: interaction.isTouched,\n isDirty: interaction.isDirty,\n isPristine: pristine ?? true,\n errors: errors as VestValidationErrors | null,\n });\n\n // Proper cleanup using onCleanup callback (Angular 21 best practice)\n onCleanup(() => sub?.unsubscribe());\n });\n\n // Robustly sync touched/dirty/pending after every render (Angular 18+ best practice)\n // This handles cases where statusChanges events are missed or delayed\n afterEveryRender(\n () => {\n const control = this.#activeControl();\n if (control) {\n const currentInteraction = this.#interactionState();\n const currentState = this.#controlStateSignal();\n const newTouched = control.touched ?? false;\n const newDirty = control.dirty ?? false;\n\n // Sync interaction state (touched/dirty)\n if (\n newTouched !== currentInteraction.isTouched ||\n newDirty !== currentInteraction.isDirty\n ) {\n // Mark as validated when control becomes touched (e.g., user blurred the field)\n // This handles the case where blur doesn't trigger statusChanges (field already invalid)\n const shouldMarkValidated =\n newTouched && !currentInteraction.isTouched;\n\n // Reset hasBeenValidated when a control transitions back to pristine interaction state\n // (e.g., after form.resetForm()).\n //\n // This prevents stale warning display on untouched fields after reset while preserving\n // validationConfig-triggered behavior during normal interaction.\n const wasResetToPristineInteraction =\n !newTouched &&\n !newDirty &&\n (currentInteraction.isTouched || currentInteraction.isDirty);\n\n this.#interactionState.update((state) => ({\n ...state,\n isTouched: newTouched,\n isDirty: newDirty,\n hasBeenValidated: wasResetToPristineInteraction\n ? false\n : shouldMarkValidated\n ? true\n : state.hasBeenValidated,\n }));\n }\n\n // Sync pending state only when it transitions from true to false\n // This fixes \"Validating...\" being stuck when statusChanges misses the transition\n // We only sync when pending goes false to avoid interfering with async validation in progress\n const controlPending = control.pending ?? false;\n if (currentState.isPending && !controlPending) {\n // Pending changed from true to false - update the full state\n const newStatus = control.status as FormControlStatus | null;\n this.#controlStateSignal.set({\n status: newStatus,\n isPending: false,\n isValid: control.valid ?? false,\n isInvalid: control.invalid ?? false,\n isPristine: control.pristine ?? true,\n isDisabled: control.disabled ?? false,\n isTouched: newTouched,\n isDirty: newDirty,\n errors: control.errors as VestValidationErrors | null,\n });\n }\n }\n },\n { injector: this.#injector }\n );\n }\n\n /**\n * Main control state computed signal (merges robust touched/dirty)\n */\n readonly controlState = computed(() => this.#controlStateSignal());\n\n /**\n * Recursively flattens Angular error objects into an array of error messages.\n * Handles string values, objects with a message property, and nested structures.\n */\n #flattenAngularErrors(errors: Record<string, unknown>): string[] {\n const result: string[] = [];\n\n for (const key of Object.keys(errors)) {\n const value: unknown = errors[key];\n\n if (typeof value === 'string') {\n // String values: push the value itself, not the key\n result.push(value);\n } else if (isErrorWithMessage(value)) {\n // Objects with a 'message' property: extract the message\n result.push(value.message);\n } else if (typeof value === 'object' && value !== null) {\n // Nested objects/arrays: recursively flatten\n result.push(\n ...this.#flattenAngularErrors(value as Record<string, unknown>)\n );\n } else {\n // Fallback: push the key for primitive types (backward compatibility)\n result.push(key);\n }\n }\n\n return result;\n }\n\n /**\n * Extracts error messages from Angular/Vest errors (recursively flattens)\n */\n readonly errorMessages = computed((): string[] => {\n const { errors } = this.controlState();\n if (!errors) return [];\n\n // Vest errors are stored in the 'errors' property as an array\n const vestErrors = errors.errors;\n if (vestErrors) {\n return (vestErrors as readonly unknown[])\n .map((error) => normalizeErrorMessage(error))\n .filter((error): error is string => Boolean(error));\n }\n\n // Fallback to flattened Angular error keys, excluding 'warnings' key\n // to prevent warnings from appearing in the error list\n const errorsWithoutWarnings = { ...errors };\n delete errorsWithoutWarnings['warnings'];\n return this.#flattenAngularErrors(errorsWithoutWarnings);\n });\n\n /**\n * ADVANCED: updateOn strategy (change/blur/submit) if available\n */\n readonly updateOn = computed((): 'change' | 'blur' | 'submit' => {\n const ngModel = this.contentNgModel() || this.#hostNgModel;\n return ngModel?.options?.updateOn ?? 'change';\n });\n\n /**\n * ADVANCED: Composite/derived signals for advanced error display logic\n */\n readonly isValidTouched = computed(() => this.isValid() && this.isTouched());\n\n readonly isInvalidTouched = computed(\n () => this.isInvalid() && this.isTouched()\n );\n\n readonly shouldShowErrors = computed(\n () => this.isInvalid() && this.isTouched() && !this.isPending()\n );\n\n /**\n * Extracts warning messages from Vest validation results.\n * Checks two sources:\n * 1. control.errors.warnings (when errors exist alongside warnings)\n * 2. FormDirective.fieldWarnings (for warnings-only scenarios)\n * This dual-source approach allows warnings to be displayed without affecting field validity.\n */\n readonly warningMessages = computed((): string[] => {\n // Source 1: warnings from control.errors (when field has errors)\n const { errors } = this.controlState();\n\n // Always read fieldWarnings signal to ensure reactive tracking\n // This must be read unconditionally for proper signal dependency tracking\n const fieldWarnings = this.#formDirective?.fieldWarnings();\n const activeControl = this.#activeControl();\n\n // If we have warnings in control.errors, use those (errors+warnings case)\n if (errors?.warnings) {\n return [...errors.warnings];\n }\n\n // Source 2: warnings from FormDirective (for warnings-only scenarios)\n // When a field only has warnings (no errors), they're stored in fieldWarnings\n // to keep the field valid while still allowing warnings to be displayed.\n if (fieldWarnings && activeControl) {\n // Get the field path from the control's path property\n // NgModel.path returns an array like ['passwords', 'password'] which needs to be joined\n const path = (activeControl as { path?: string[] }).path;\n if (path?.length) {\n const fieldPath = path.join('.');\n const warnings = fieldWarnings.get(fieldPath);\n if (warnings) {\n return [...warnings];\n }\n }\n }\n\n return [];\n });\n\n /**\n * Whether async validation is in progress\n */\n readonly hasPendingValidation = computed(() => this.controlState().isPending);\n\n /**\n * Convenience signals for common state checks\n */\n readonly isValid = computed(() => this.controlState().isValid);\n readonly isInvalid = computed(() => this.controlState().isInvalid);\n readonly isPending = computed(() => this.controlState().isPending);\n readonly isTouched = computed(() => this.controlState().isTouched);\n readonly isDirty = computed(() => this.controlState().isDirty);\n readonly isPristine = computed(() => this.controlState().isPristine);\n readonly isDisabled = computed(() => this.controlState().isDisabled);\n readonly hasErrors = computed(() => this.errorMessages().length > 0);\n\n /**\n * Whether this control has been validated at least once.\n * True after the first validation completes, even if the user hasn't touched the field.\n * This enables showing errors for validationConfig-triggered validations.\n */\n readonly hasBeenValidated = computed(\n () => this.#interactionState().hasBeenValidated\n );\n}\n\n/**\n * Type guard for objects with a message property\n */\nfunction isErrorWithMessage(value: unknown): value is { message: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'message' in value &&\n typeof (value as { message: unknown }).message === 'string'\n );\n}\n\nfunction normalizeErrorMessage(value: unknown): string | null {\n if (typeof value === 'string') {\n return value;\n }\n\n if (isErrorWithMessage(value)) {\n return value.message;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n return String(value);\n}\n","import {\n computed,\n Directive,\n effect,\n inject,\n input,\n signal,\n Signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormResetEvent, FormSubmittedEvent, NgForm } from '@angular/forms';\nimport { filter, map, startWith } from 'rxjs';\nimport {\n NGX_ERROR_DISPLAY_MODE_TOKEN,\n NGX_WARNING_DISPLAY_MODE_TOKEN,\n SC_ERROR_DISPLAY_MODE_TOKEN,\n} from './error-display-mode.token';\nimport { FormControlStateDirective } from './form-control-state.directive';\nimport { getFormSubmittedSignal } from './form-submitted-state';\n\n/**\n * Error display modes for form controls.\n * - 'on-blur': Show errors after field is touched/blurred\n * - 'on-submit': Show errors after form submission\n * - 'on-blur-or-submit': Show errors after blur or form submission (default)\n * - 'on-dirty': Show errors as soon as the field value changes\n * - 'always': Show errors immediately, even on pristine fields\n */\nexport type ScErrorDisplayMode =\n | 'on-blur'\n | 'on-submit'\n | 'on-blur-or-submit'\n | 'on-dirty'\n | 'always';\n\n/**\n * Warning display modes for form controls.\n * - 'on-touch': Show warnings after field is touched/blurred\n * - 'on-validated-or-touch': Show warnings after validation runs or field is touched (default)\n * - 'on-dirty': Show warnings as soon as the field value changes\n * - 'always': Show warnings immediately, even on pristine fields\n */\nexport type NgxWarningDisplayMode =\n | 'on-touch'\n | 'on-validated-or-touch'\n | 'on-dirty'\n | 'always';\n\nexport const SC_ERROR_DISPLAY_MODE_DEFAULT: ScErrorDisplayMode =\n 'on-blur-or-submit';\nexport const SC_WARNING_DISPLAY_MODE_DEFAULT: NgxWarningDisplayMode =\n 'on-validated-or-touch';\n\n@Directive({\n selector: '[formErrorDisplay], [ngxErrorDisplay]',\n exportAs: 'formErrorDisplay, ngxErrorDisplay',\n hostDirectives: [FormControlStateDirective],\n})\nexport class FormErrorDisplayDirective {\n readonly #formControlState = inject(FormControlStateDirective);\n // Optionally inject NgForm for form submission tracking\n readonly #ngForm = inject(NgForm, { optional: true });\n readonly #formSubmittedState = this.#ngForm\n ? getFormSubmittedSignal(this.#ngForm)\n : signal(false);\n\n /**\n * Input signal for error display mode.\n * Works seamlessly with hostDirectives in Angular 19+.\n */\n readonly errorDisplayMode = input<ScErrorDisplayMode>(\n inject(NGX_ERROR_DISPLAY_MODE_TOKEN, { optional: true }) ??\n inject(SC_ERROR_DISPLAY_MODE_TOKEN, { optional: true }) ??\n SC_ERROR_DISPLAY_MODE_DEFAULT\n );\n\n /**\n * Input signal for warning display mode.\n * Controls whether warnings are shown only after touch or also after validation.\n */\n readonly warningDisplayMode = input<NgxWarningDisplayMode>(\n inject(NGX_WARNING_DISPLAY_MODE_TOKEN, { optional: true }) ??\n SC_WARNING_DISPLAY_MODE_DEFAULT\n );\n\n // Expose state signals from FormControlStateDirective\n readonly controlState = this.#formControlState.controlState;\n readonly errorMessages = this.#formControlState.errorMessages;\n readonly warningMessages = this.#formControlState.warningMessages;\n readonly hasPendingValidation = this.#formControlState.hasPendingValidation;\n readonly isTouched = this.#formControlState.isTouched;\n readonly isDirty = this.#formControlState.isDirty;\n readonly isValid = this.#formControlState.isValid;\n readonly isInvalid = this.#formControlState.isInvalid;\n readonly hasBeenValidated = this.#formControlState.hasBeenValidated;\n /**\n * Expose updateOn and formSubmitted as public signals for advanced consumers.\n * updateOn: The ngModelOptions.updateOn value for the control (change/blur/submit)\n * formSubmitted: true after the form is submitted (if NgForm is present)\n */\n readonly updateOn = this.#formControlState.updateOn;\n\n /**\n * Signal that tracks NgForm.submitted state reactively.\n *\n * Map form-level submit/reset events directly to boolean state.\n *\n * This keeps programmatic `NgForm.onSubmit()` reactive in zoneless mode and\n * avoids depending on `NgForm.submitted`, whose getter intentionally reads an\n * internal signal with `untracked()`.\n */\n readonly formSubmitted: Signal<boolean> = this.#formSubmittedState;\n\n constructor() {\n const ngForm = this.#ngForm;\n if (ngForm) {\n ngForm.form.events\n .pipe(\n filter(\n (event) =>\n event.source === ngForm.form &&\n (event instanceof FormSubmittedEvent ||\n event instanceof FormResetEvent)\n ),\n map((event) => event instanceof FormSubmittedEvent),\n startWith(ngForm.submitted),\n takeUntilDestroyed()\n )\n .subscribe((submitted) => {\n this.#formSubmittedState.set(submitted);\n });\n }\n\n // Warn about problematic combinations of updateOn and errorDisplayMode\n effect(() => {\n const mode = this.errorDisplayMode();\n const updateOn = this.updateOn();\n if (updateOn === 'submit' && mode === 'on-blur') {\n console.warn(\n '[ngx-vest-forms] Potential UX issue: errorDisplayMode is \"on-blur\" but updateOn is \"submit\". Errors will only show after form submission, not after blur.'\n );\n }\n });\n }\n\n /**\n * Determines if errors should be shown based on the specified display mode\n * and the control's state (touched/submitted/validated).\n *\n * Note: We check both hasErrors (extracted error messages) AND isInvalid (Angular's validation state)\n * because in some cases (like conditional validations via validationConfig), the control is marked\n * as invalid by Angular before error messages are extracted from Vest. This ensures aria-invalid\n * is set correctly even during the validation propagation delay.\n *\n * For validationConfig-triggered validations: A field can be validated without being touched\n * (e.g., confirmPassword validated when password changes). We check hasBeenValidated to show\n * errors in these scenarios, providing better UX and proper ARIA attributes.\n */\n readonly shouldShowErrors: Signal<boolean> = computed(() => {\n const mode = this.errorDisplayMode();\n const isTouched = this.isTouched();\n const isDirty = this.isDirty();\n const isInvalid = this.isInvalid();\n const hasErrors = this.errorMessages().length > 0;\n const updateOn = this.updateOn();\n const formSubmitted = this.formSubmitted();\n\n // Consider errors present if either we have error messages OR the control is invalid\n // This handles the race condition where Angular marks control invalid before Vest errors propagate\n const hasErrorState = hasErrors || isInvalid;\n\n // Always only show errors after submit if updateOn is 'submit'\n if (updateOn === 'submit') {\n return !!(formSubmitted && hasErrorState);\n }\n\n // Handle the new display modes\n switch (mode) {\n case 'always':\n // Always show errors immediately, even on pristine fields\n return hasErrorState;\n\n case 'on-dirty':\n // Show when value has changed, OR when touched/submitted (for backwards compat)\n return !!(isDirty || isTouched || formSubmitted) && hasErrorState;\n\n case 'on-blur':\n // Show after touch (blur) or form submission (traditional behavior, not dirty-based)\n return !!(isTouched || formSubmitted) && hasErrorState;\n\n case 'on-submit':\n // Show only after form submission\n return !!(formSubmitted && hasErrorState);\n\n case 'on-blur-or-submit':\n default:\n // Show after blur (touch) OR submit (default behavior)\n return !!((isTouched || formSubmitted) && hasErrorState);\n }\n });\n\n /**\n * Errors to display (filtered for pending state)\n */\n readonly errors: Signal<string[]> = computed(() => {\n if (this.hasPendingValidation()) return [];\n return this.errorMessages();\n });\n\n /**\n * Warnings to display (filtered for pending state)\n */\n readonly warnings: Signal<string[]> = computed(() => {\n if (this.hasPendingValidation()) return [];\n return this.warningMessages();\n });\n\n /**\n * Whether the control is currently being validated (pending)\n * Excludes pristine+untouched controls to prevent \"Validating...\" on initial load\n */\n readonly isPending: Signal<boolean> = computed(() => {\n // Don't show pending state for pristine untouched controls\n // This prevents \"Validating...\" message appearing on initial page load\n const state = this.#formControlState.controlState();\n if (state.isPristine && !state.isTouched) {\n return false;\n }\n return this.hasPendingValidation();\n });\n\n /**\n * Determines if warnings should be shown based on the specified display mode\n * and the control's state (touched/validated/dirty).\n *\n * NOTE: Unlike errors, warnings can exist on VALID fields (warnings-only scenario).\n * We don't require isInvalid() because Vest warn() tests don't affect field validity.\n *\n * UX Note: We include `hasBeenValidated` for `on-validated-or-touch` mode to support\n * cross-field validation. If Field A triggers validation on Field B (via validationConfig),\n * Field B should show warnings if it has them, even if the user hasn't touched Field B yet.\n * Unlike errors (which block submission), warnings are informational and safe to show.\n */\n readonly shouldShowWarnings: Signal<boolean> = computed(() => {\n const mode = this.warningDisplayMode();\n const isTouched = this.isTouched();\n const isDirty = this.isDirty();\n const hasBeenValidated = this.hasBeenValidated();\n const hasWarnings = this.warningMessages().length > 0;\n const isPending = this.hasPendingValidation();\n const formSubmitted = this.formSubmitted();\n\n // No warnings to show or still pending\n if (!hasWarnings || isPending) {\n return false;\n }\n\n // Handle the warning display modes\n switch (mode) {\n case 'always':\n // Always show warnings immediately, even on pristine fields\n return true;\n\n case 'on-dirty':\n // Show when value has changed, OR when touched/submitted (for backwards compat)\n return isDirty || isTouched || formSubmitted;\n\n case 'on-touch':\n // Show after touch (blur) or form submission (traditional behavior, not dirty-based)\n return isTouched || formSubmitted;\n\n case 'on-validated-or-touch':\n default:\n // Show after validation runs or after touch/submit (default behavior)\n return hasBeenValidated || isTouched || formSubmitted;\n }\n });\n}\n","export type AriaAssociationMode = 'all-controls' | 'single-control' | 'none';\n\n/**\n * Splits an `aria-describedby` attribute value into normalized token IDs.\n */\nexport function parseAriaIdTokens(value: string | null): string[] {\n return (value ?? '')\n .split(/\\s+/)\n .map((token) => token.trim())\n .filter(Boolean);\n}\n\n/**\n * Merges currently-active wrapper IDs into an existing `aria-describedby` value.\n *\n * Existing tokens owned by the wrapper are removed first, then current active IDs\n * are appended while preserving non-owned tokens and token uniqueness.\n */\nexport function mergeAriaDescribedBy(\n existing: string | null,\n activeIds: readonly string[],\n ownedIds: readonly string[]\n): string | null {\n const ownedIdSet = new Set(ownedIds);\n const existingTokens = parseAriaIdTokens(existing);\n const existingWithoutOwned = existingTokens.filter(\n (token) => !ownedIdSet.has(token)\n );\n\n const merged: string[] = [...existingWithoutOwned];\n const mergedIdSet = new Set(merged);\n for (const id of activeIds) {\n if (!mergedIdSet.has(id)) {\n merged.push(id);\n mergedIdSet.add(id);\n }\n }\n\n return merged.length > 0 ? merged.join(' ') : null;\n}\n\n/**\n * Resolves control targets based on ARIA association mode.\n */\nexport function resolveAssociationTargets(\n controls: readonly HTMLElement[],\n mode: AriaAssociationMode\n): HTMLElement[] {\n if (mode === 'none') {\n return [];\n }\n\n if (mode === 'single-control') {\n return controls.length === 1 ? [...controls] : [];\n }\n\n return [...controls];\n}\n","import { effect, Signal, signal } from '@angular/core';\n\n/**\n * Options for configuring debounced pending state behavior.\n */\nexport type DebouncedPendingStateOptions = {\n /**\n * Delay in milliseconds before showing the pending message.\n * Prevents flashing for quick async validations.\n * @default 200\n */\n showAfter?: number;\n\n /**\n * Minimum display time in milliseconds once the pending message is shown.\n * Prevents flickering when validation completes shortly after being shown.\n * @default 500\n */\n minimumDisplay?: number;\n};\n\n/**\n * Result of createDebouncedPendingState containing the debounced signal\n * and cleanup function.\n */\nexport type DebouncedPendingStateResult = {\n /**\n * Signal that is true when the pending message should be shown.\n * This is debounced according to the provided options.\n */\n showPendingMessage: Signal<boolean>;\n\n /**\n * Optional cleanup function to cancel any pending timeouts.\n * Call this in ngOnDestroy if needed (though the effect cleanup handles most cases).\n */\n cleanup: () => void;\n};\n\n/**\n * Creates a debounced pending state signal that prevents flashing validation messages.\n *\n * This utility helps implement a better UX for async validations by:\n * 1. Delaying the display of \"Validating...\" messages until validation takes longer than `showAfter`ms (default: 200ms)\n * 2. Keeping the message visible for at least `minimumDisplay`ms (default: 500ms) once shown to prevent flickering\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (showPendingMessage()) {\n * <div role=\"status\" aria-live=\"polite\">Validating…</div>\n * }\n * `\n * })\n * export class CustomControlWrapperComponent {\n * protected readonly errorDisplay = inject(FormErrorDisplayDirective, { self: true });\n *\n * // Create debounced pending state\n * private readonly pendingState = createDebouncedPendingState(\n * this.errorDisplay.isPending,\n * { showAfter: 200, minimumDisplay: 500 }\n * );\n *\n * protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n * }\n * ```\n *\n * @param isPending - Signal indicating whether async validation is currently pending\n * @param options - Configuration options for debouncing behavior\n * @returns Object containing the debounced showPendingMessage signal and cleanup function\n */\nexport function createDebouncedPendingState(\n isPending: Signal<boolean>,\n options: DebouncedPendingStateOptions = {}\n): DebouncedPendingStateResult {\n const { showAfter = 200, minimumDisplay = 500 } = options;\n\n // Create writable signal for debounced state\n const showPendingMessageSignal = signal(false);\n\n // Track timeouts\n let pendingTimeout: ReturnType<typeof setTimeout> | null = null;\n let minimumDisplayTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Cleanup function\n const cleanup = () => {\n if (pendingTimeout) {\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n }\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n };\n\n // Effect to manage debounced pending message display\n effect((onCleanup) => {\n const pending = isPending();\n\n if (pending) {\n // Clear any existing minimum display timeout\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n\n // Start delay timer before showing pending message\n pendingTimeout = setTimeout(() => {\n showPendingMessageSignal.set(true);\n pendingTimeout = null;\n }, showAfter);\n\n onCleanup(() => {\n if (pendingTimeout) {\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n }\n });\n } else {\n // Validation completed\n if (pendingTimeout) {\n // Validation completed before delay - don't show message\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n } else if (showPendingMessageSignal()) {\n // Message was shown - keep it visible for minimum duration\n minimumDisplayTimeout = setTimeout(() => {\n showPendingMessageSignal.set(false);\n minimumDisplayTimeout = null;\n }, minimumDisplay);\n\n onCleanup(() => {\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n });\n }\n }\n });\n\n return {\n showPendingMessage: showPendingMessageSignal.asReadonly(),\n cleanup,\n };\n}\n","import {\n AfterContentInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n signal,\n} from '@angular/core';\nimport { FormErrorDisplayDirective } from '../../directives/form-error-display.directive';\nimport {\n AriaAssociationMode,\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from '../../utils/aria-association.utils';\nimport { createDebouncedPendingState } from '../../utils/pending-state.utils';\n\n// Counter for unique IDs\nlet nextUniqueId = 0;\n\n/**\n * Accessible form control wrapper built with WCAG 2.2 AA considerations.\n *\n * Wrap form fields to automatically display validation errors, warnings, and pending states\n * with proper accessibility attributes.\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <ngx-control-wrapper>\n * <label for=\"email\">Email</label>\n * <input id=\"email\" name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Error Display Modes\n * Control when errors appear using the `errorDisplayMode` input:\n * - `'on-blur-or-submit'` (default): Show errors after blur OR form submit\n * - `'on-blur'`: Show errors only after blur\n * - `'on-submit'`: Show errors only after form submit\n * - `'on-dirty'`: Show errors as soon as the field value changes\n * - `'always'`: Show errors immediately, even on pristine fields\n *\n * ```html\n * <ngx-control-wrapper [errorDisplayMode]=\"'on-submit'\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Warning Display Modes\n * Control when warnings appear using the `warningDisplayMode` input:\n * - `'on-validated-or-touch'` (default): Show warnings after validation runs or touch\n * - `'on-touch'`: Show warnings only after touch/blur\n * - `'on-dirty'`: Show warnings as soon as the field value changes\n * - `'always'`: Show warnings immediately, even on pristine fields\n *\n * ```html\n * <ngx-control-wrapper [warningDisplayMode]=\"'on-dirty'\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Accessibility Features (Automatic)\n * - Unique IDs for error/warning/pending regions\n * - `aria-describedby` linking errors to form controls\n * - `aria-invalid=\"true\"` when errors are shown\n * - Uses `role=\"status\"` with `aria-live=\"polite\"` for non-disruptive announcements\n * - Debounced pending state to prevent flashing for quick validations\n *\n * ### WCAG 2.2 AA - Error Severity Levels\n * This component uses `role=\"status\"` for **field-level** validation messages:\n * - **Errors**: Non-disruptive announcement (user can continue filling other fields)\n * - **Warnings**: Informational only, doesn't block submission\n * - **Pending**: Status update while async validation runs\n *\n * For **form-level blocking errors** (e.g., submission failed), implement a separate\n * error summary component with `role=\"alert\"` and `aria-live=\"assertive\"`.\n *\n * @see {@link FormErrorDisplayDirective} for custom wrapper implementation\n *\n * Form-Level Blocking Errors:\n * - For post-submit validation errors that block submission, implement a separate\n * form-level error summary with role=\"alert\" and aria-live=\"assertive\"\n * - This component uses role=\"status\" for field-level errors (non-disruptive)\n * - Example for form-level errors:\n * ```html\n * <!-- Keep in DOM; update text content on submit -->\n * <div id=\"form-errors\" role=\"alert\" aria-live=\"assertive\" aria-atomic=\"true\"></div>\n * ```\n * - This separation provides immediate announcements for blocking form errors while\n * keeping inline field errors non-disruptive. Follows WCAG ARIA21/ARIA22 guidance.\n *\n * Error & Warning Display Behavior:\n * - The error display mode can be configured globally using the NGX_ERROR_DISPLAY_MODE_TOKEN injection token, or per instance using the `errorDisplayMode` input on FormErrorDisplayDirective (which this component uses as a hostDirective).\n * - Possible error display values: 'on-blur' | 'on-submit' | 'on-blur-or-submit' | 'on-dirty' | 'always' (default: 'on-blur-or-submit')\n * - The warning display mode can be configured globally using NGX_WARNING_DISPLAY_MODE_TOKEN, or per instance using the `warningDisplayMode` input on FormErrorDisplayDirective.\n * - Possible warning display values: 'on-touch' | 'on-validated-or-touch' | 'on-dirty' | 'always' (default: 'on-validated-or-touch')\n *\n * Example (per instance):\n * <div ngxControlWrapper>\n * <label>\n * <span>First name</span>\n * <input type=\"text\" name=\"firstName\" [ngModel]=\"formValue().firstName\" />\n * </label>\n * </div>\n * /// To customize errorDisplayMode for this instance, use the errorDisplayMode input.\n *\n * Example (with warnings and pending):\n * <ngx-control-wrapper>\n * <input name=\"username\" ngModel />\n * </ngx-control-wrapper>\n * /// If async validation is running for >500ms, a spinner and 'Validating…' will be shown.\n * /// Once shown, the validation message stays visible for minimum 500ms to prevent flashing.\n * /// If Vest warnings are present, they will be shown below errors.\n *\n * Example (global config):\n * import { provide } from '@angular/core';\n * import { NGX_ERROR_DISPLAY_MODE_TOKEN } from 'ngx-vest-forms';\n * @Component({\n * providers: [\n * provide(NGX_ERROR_DISPLAY_MODE_TOKEN, { useValue: 'on-submit' })\n * ]\n * })\n * export class MyComponent {}\n *\n * Best Practices:\n * - Use for single-control wrappers.\n * - For multi-control/group containers, prefer `ngx-form-group-wrapper`.\n * - Do not manually display errors for individual fields; rely on this wrapper.\n * - Validate with tools like Accessibility Insights and real screen reader testing.\n *\n * @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA19 - ARIA19: Using ARIA role=alert\n * @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22 - ARIA22: Using role=status\n */\n@Component({\n selector:\n 'ngx-control-wrapper, sc-control-wrapper, [scControlWrapper], [ngxControlWrapper], [ngx-control-wrapper], [sc-control-wrapper]',\n templateUrl: './control-wrapper.component.html',\n styles: `\n :host {\n display: block;\n position: relative;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n\n host: {\n class: 'ngx-control-wrapper sc-control-wrapper',\n '[class.ngx-control-wrapper--invalid]': 'errorDisplay.shouldShowErrors()',\n '[attr.aria-busy]': \"errorDisplay.isPending() ? 'true' : null\",\n },\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class ControlWrapperComponent implements AfterContentInit, OnDestroy {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n private readonly elementRef = inject(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n\n /**\n * Controls how this wrapper applies ARIA attributes to descendant controls.\n *\n * - `all-controls` (default, backwards compatible): apply `aria-describedby` / `aria-invalid`\n * to all `input/select/textarea` elements inside the wrapper.\n * - `single-control`: apply ARIA attributes only when exactly one control is found.\n * (Useful for wrappers that sometimes contain helper buttons/controls.)\n * - `none`: do not mutate descendant controls at all (group-safe mode).\n *\n * Notes:\n * - Use `none` when wrapping a container (e.g. `NgModelGroup`) to avoid stamping ARIA\n * across multiple child controls.\n * - This does not affect whether messages render; it only affects ARIA wiring.\n */\n readonly ariaAssociationMode = input<AriaAssociationMode>('all-controls');\n\n // Generate unique IDs for ARIA associations\n protected readonly uniqueId = `ngx-control-wrapper-${nextUniqueId++}`;\n protected readonly errorId = `${this.uniqueId}-error`;\n protected readonly warningId = `${this.uniqueId}-warning`;\n protected readonly pendingId = `${this.uniqueId}-pending`;\n\n // Track form controls found in the wrapper\n private readonly formControls = signal<HTMLElement[]>([]);\n\n // Signals when content is initialized so effects can safely touch the DOM.\n private readonly contentInitialized = signal(false);\n\n // MutationObserver to detect dynamically added/removed controls\n private mutationObserver: MutationObserver | null = null;\n\n /**\n * Debounced pending state to prevent flashing for quick async validations.\n * Uses createDebouncedPendingState utility with 500ms delay and 500ms minimum display.\n */\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n { showAfter: 500, minimumDisplay: 500 }\n );\n protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * Whether to display warnings.\n * Delegates to FormErrorDisplayDirective's centralized shouldShowWarnings signal.\n *\n * This ensures consistent warning display behavior across all form components\n * and supports the new 'on-dirty' and 'always' display modes.\n */\n protected readonly shouldShowWarnings = this.errorDisplay.shouldShowWarnings;\n\n /**\n * Computed signal that builds aria-describedby string based on visible regions\n */\n protected readonly ariaDescribedBy = computed(() => {\n const ids: string[] = [];\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n if (this.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n return ids.length > 0 ? ids.join(' ') : null;\n });\n\n /**\n * IDs managed by this wrapper when composing aria-describedby.\n *\n * We remove only these from the consumer-provided aria-describedby tokens and then\n * append the currently-relevant wrapper IDs. This prevents clobbering app-provided\n * hint/help text associations.\n */\n private readonly wrapperOwnedDescribedByIds = [\n this.errorId,\n this.warningId,\n this.pendingId,\n ];\n\n constructor() {\n // Effect to update aria-describedby and aria-invalid on form controls\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n if (mode === 'none') {\n return;\n }\n\n const describedBy = this.ariaDescribedBy();\n const wrapperActiveIds = parseAriaIdTokens(describedBy);\n const shouldShowErrors = this.errorDisplay.shouldShowErrors();\n\n const targets = resolveAssociationTargets(this.formControls(), mode);\n\n targets.forEach((control) => {\n // Update aria-describedby (merge, don't overwrite)\n const nextDescribedBy = mergeAriaDescribedBy(\n control.getAttribute('aria-describedby'),\n wrapperActiveIds,\n this.wrapperOwnedDescribedByIds\n );\n if (nextDescribedBy) {\n control.setAttribute('aria-describedby', nextDescribedBy);\n } else {\n control.removeAttribute('aria-describedby');\n }\n\n // Update aria-invalid\n if (shouldShowErrors) {\n control.setAttribute('aria-invalid', 'true');\n } else {\n control.removeAttribute('aria-invalid');\n }\n });\n });\n\n // Clean up MutationObserver when component is destroyed\n this.destroyRef.onDestroy(() => {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n });\n\n // Effect to enable/disable DOM observation based on ariaAssociationMode.\n // This keeps the wrapper cheap in group-safe mode.\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n\n if (mode === 'none') {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n if (this.formControls().length > 0) {\n this.formControls.set([]);\n }\n return;\n }\n\n // Ensure controls list is up to date.\n this.updateFormControls();\n\n // Ensure MutationObserver is installed (dynamic @if/@for support).\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => {\n this.updateFormControls();\n });\n\n this.mutationObserver.observe(this.elementRef.nativeElement, {\n childList: true,\n subtree: true,\n });\n }\n });\n }\n\n ngAfterContentInit(): void {\n this.contentInitialized.set(true);\n\n // ARIA wiring + observer setup is managed by effects so that the wrapper can\n // opt out (ariaAssociationMode=\"none\").\n }\n\n ngOnDestroy(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n }\n\n /**\n * Query and update the list of form controls within this wrapper.\n * Called on init and whenever the DOM structure changes.\n */\n private updateFormControls(): void {\n const controls = this.elementRef.nativeElement.querySelectorAll(\n 'input, select, textarea'\n );\n this.formControls.set(Array.from(controls) as HTMLElement[]);\n }\n}\n","<div class=\"ngx-control-wrapper__content\">\n <ng-content />\n</div>\n\n<!--\n WCAG 2.2 AA Compliance for Inline Field Validation:\n\n IMPORTANT DISTINCTION - Field-level vs Form-level errors:\n - FIELD-LEVEL errors (this component): Use role=\"status\" with aria-live=\"polite\"\n These are inline validation messages that appear as users interact with fields.\n Using \"assertive\" would be too disruptive when users are filling out multiple fields.\n - FORM-LEVEL blocking errors (e.g., submission failed): Should use role=\"alert\" with\n aria-live=\"assertive\" in a separate form-level error summary component.\n\n This component handles FIELD-LEVEL messages:\n - Errors: role=\"status\" with aria-live=\"polite\" (non-disruptive, field is already\n marked with aria-invalid=\"true\" and aria-describedby points here)\n - Warnings: role=\"status\" with aria-live=\"polite\" (informational, doesn't block)\n - Pending: role=\"status\" with aria-live=\"polite\" (status update)\n\n The aria-invalid=\"true\" + aria-describedby association on the input provides\n the primary accessibility pathway; the live region is supplementary.\n\n @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA21 - Using aria-invalid\n @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22 - Using role=status\n-->\n<div\n [id]=\"errorId\"\n class=\"text-sm text-red-600\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (errorDisplay.shouldShowErrors()) {\n <ul class=\"m-0 mt-1 list-none space-y-1 p-0\">\n @for (error of errorDisplay.errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n }\n</div>\n\n<!--\n Warnings: Non-blocking validation messages (Vest warn())\n - Use role=\"status\" with aria-live=\"polite\" per WCAG ARIA22\n - Default: show after validation runs or touch; configurable to require touch only\n - Warnings do NOT affect field validity - they're informational only\n-->\n<div\n [id]=\"warningId\"\n class=\"text-sm text-yellow-700\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (shouldShowWarnings()) {\n <ul class=\"m-0 mt-1 list-none space-y-1 p-0\">\n @for (warn of errorDisplay.warnings(); track warn) {\n <li>{{ warn }}</li>\n }\n </ul>\n }\n</div>\n\n<!-- Pending state is also stable; content appears only after the debounce delay -->\n<div\n [id]=\"pendingId\"\n class=\"absolute top-0 right-0 flex items-center gap-1 text-xs text-gray-500\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (showPendingMessage()) {\n <span\n class=\"inline-block h-3 w-3 animate-spin rounded-full border-2 border-gray-400 border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n Validating…\n }\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n} from '@angular/core';\nimport { FormErrorDisplayDirective } from '../../directives/form-error-display.directive';\nimport { createDebouncedPendingState } from '../../utils/pending-state.utils';\n\nlet nextUniqueId = 0;\n\n/**\n * Group-safe wrapper for `NgModelGroup` containers.\n *\n * This component renders group-level errors/warnings/pending UI, but intentionally\n * does **not** stamp `aria-describedby` / `aria-invalid` onto descendant controls.\n *\n * Use this when you want a wrapper around a container that has multiple inputs.\n * For single inputs, prefer `<ngx-control-wrapper>`.\n */\n@Component({\n selector:\n 'ngx-form-group-wrapper, sc-form-group-wrapper, [ngxFormGroupWrapper], [scFormGroupWrapper]',\n exportAs: 'ngxFormGroupWrapper',\n templateUrl: './form-group-wrapper.component.html',\n // Minimal structural styling: custom elements are inline by default.\n styles: `\n :host {\n display: block;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'ngx-form-group-wrapper sc-form-group-wrapper',\n '[class.ngx-form-group-wrapper--invalid]':\n 'errorDisplay.shouldShowErrors()',\n '[attr.aria-busy]': \"errorDisplay.isPending() ? 'true' : null\",\n },\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class FormGroupWrapperComponent {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n\n /**\n * Controls the debounce behavior for the pending message.\n * Defaults are conservative to avoid flashing.\n */\n readonly pendingDebounce = input<{\n showAfter: number;\n minimumDisplay: number;\n }>({\n showAfter: 500,\n minimumDisplay: 500,\n });\n\n protected readonly uniqueId = `ngx-form-group-wrapper-${nextUniqueId++}`;\n readonly errorId = `${this.uniqueId}-error`;\n readonly warningId = `${this.uniqueId}-warning`;\n readonly pendingId = `${this.uniqueId}-pending`;\n\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n this.pendingDebounce()\n );\n protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * Helpful if consumers want to wire aria-describedby manually (e.g. fieldset/legend pattern).\n */\n readonly describedByIds = computed(() => {\n const ids: string[] = [];\n\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n\n if (this.errorDisplay.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n\n return ids.length > 0 ? ids.join(' ') : null;\n });\n}\n","<div class=\"ngx-form-group-wrapper__content\">\n <ng-content />\n</div>\n\n<!--\n Keep regions stable in the DOM so IDs are always valid targets.\n This wrapper does NOT modify descendant controls.\n-->\n<div [id]=\"errorId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (errorDisplay.shouldShowErrors() && errorDisplay.errors().length > 0) {\n <ul>\n @for (error of errorDisplay.errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n }\n</div>\n\n<div [id]=\"warningId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (errorDisplay.shouldShowWarnings()) {\n <ul>\n @for (warn of errorDisplay.warnings(); track warn) {\n <li>{{ warn }}</li>\n }\n </ul>\n }\n</div>\n\n<div [id]=\"pendingId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (showPendingMessage()) {\n <span aria-hidden=\"true\">Validating…</span>\n }\n</div>\n","import {\n AfterContentInit,\n computed,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n signal,\n} from '@angular/core';\nimport {\n AriaAssociationMode,\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from '../utils/aria-association.utils';\nimport { createDebouncedPendingState } from '../utils/pending-state.utils';\nimport { FormErrorDisplayDirective } from './form-error-display.directive';\n\nlet nextUniqueId = 0;\n\n/**\n * Wires a control container to its error/warning/pending regions.\n *\n * This directive is intended for custom wrappers/components.\n * It composes `FormErrorDisplayDirective` (and thus `FormControlStateDirective`)\n * and applies `aria-invalid` / `aria-describedby` to descendant controls.\n *\n * It does not render any UI; you can use the generated IDs to render messages.\n */\n@Directive({\n selector: '[formErrorControl], [ngxErrorControl]',\n exportAs: 'formErrorControl, ngxErrorControl',\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class FormErrorControlDirective implements AfterContentInit, OnDestroy {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n\n /**\n * Controls how this directive applies ARIA attributes to descendant controls.\n *\n * - `all-controls` (default): apply ARIA attributes to all input/select/textarea descendants.\n * - `single-control`: apply ARIA attributes only when exactly one control is found.\n * - `none`: do not mutate descendant controls.\n */\n readonly ariaAssociationMode = input<AriaAssociationMode>('all-controls');\n\n /**\n * Unique ID prefix for this instance.\n * Use these IDs to render message regions and to support aria-describedby.\n */\n protected readonly uniqueId = `ngx-error-control-${nextUniqueId++}`;\n readonly errorId = `${this.uniqueId}-error`;\n readonly warningId = `${this.uniqueId}-warning`;\n readonly pendingId = `${this.uniqueId}-pending`;\n\n private readonly formControls = signal<HTMLElement[]>([]);\n private readonly contentInitialized = signal(false);\n private mutationObserver: MutationObserver | null = null;\n\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n { showAfter: 500, minimumDisplay: 500 }\n );\n readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * aria-describedby value representing the *currently relevant* message regions.\n */\n readonly ariaDescribedBy = computed(() => {\n const ids: string[] = [];\n\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n\n if (this.errorDisplay.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n\n return ids.length > 0 ? ids.join(' ') : null;\n });\n\n private readonly ownedDescribedByIds: string[] = [\n this.errorId,\n this.warningId,\n this.pendingId,\n ];\n\n constructor() {\n // Effect for ARIA attribute updates\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n if (mode === 'none') return;\n\n const describedBy = this.ariaDescribedBy();\n const activeIds = parseAriaIdTokens(describedBy);\n const shouldShowErrors = this.errorDisplay.shouldShowErrors();\n\n const targets = resolveAssociationTargets(this.formControls(), mode);\n\n for (const control of targets) {\n const nextDescribedBy = mergeAriaDescribedBy(\n control.getAttribute('aria-describedby'),\n activeIds,\n this.ownedDescribedByIds\n );\n if (nextDescribedBy) {\n control.setAttribute('aria-describedby', nextDescribedBy);\n } else {\n control.removeAttribute('aria-describedby');\n }\n\n if (shouldShowErrors) {\n control.setAttribute('aria-invalid', 'true');\n } else {\n control.removeAttribute('aria-invalid');\n }\n }\n });\n\n // Effect for MutationObserver setup with proper cleanup\n effect((onCleanup) => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n\n if (mode === 'none') {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n if (this.formControls().length > 0) {\n this.formControls.set([]);\n }\n return;\n }\n\n this.updateFormControls();\n\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => {\n this.updateFormControls();\n });\n\n this.mutationObserver.observe(this.elementRef.nativeElement, {\n childList: true,\n subtree: true,\n });\n }\n\n // Proper cleanup using onCleanup callback (Angular 21 best practice)\n onCleanup(() => {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n });\n });\n }\n\n ngAfterContentInit(): void {\n this.contentInitialized.set(true);\n }\n\n ngOnDestroy(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n }\n\n private updateFormControls(): void {\n const controls = this.elementRef.nativeElement.querySelectorAll(\n 'input, select, textarea'\n );\n this.formControls.set(Array.from(controls) as HTMLElement[]);\n }\n}\n","import { isDevMode } from '@angular/core';\nimport { AbstractControl, ValidationErrors } from '@angular/forms';\nimport { Observable, from, of } from 'rxjs';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\ntype FieldResolver = (control: AbstractControl) => string;\n\ntype ValidationResult =\n | Observable<ValidationErrors | null>\n | Promise<ValidationErrors | null>\n | ValidationErrors\n | null;\n\n/**\n * @internal\n * Shared bridge for resolving a field path and invoking FormDirective async validation.\n * Keeps fail-open semantics for missing context/path while consolidating behavior.\n *\n * @param control - Control being validated by Angular forms.\n * @param context - Optional parent form directive context.\n * @param resolveField - Resolver that maps the control to a field path.\n * @param validationOptions - Per-control validation options.\n * @param source - Caller identifier for diagnostics.\n */\nexport function runAsyncValidationBridge(\n control: AbstractControl,\n context: FormDirective<Record<string, unknown>> | null,\n resolveField: FieldResolver,\n validationOptions: ValidationOptions,\n source: 'FormModelDirective' | 'FormModelGroupDirective'\n): Observable<ValidationErrors | null> {\n if (!control) {\n return of(null);\n }\n\n if (!context) {\n if (isDevMode()) {\n console.warn(\n `[ngx-vest-forms] ${source}: No FormDirective context found. Validation skipped (fail-open).`\n );\n }\n return of(null);\n }\n\n const field = resolveField(control);\n if (!field) {\n if (isDevMode()) {\n console.warn(\n `[ngx-vest-forms] ${source}: Could not resolve control path. Ensure the control has a valid name/path and is registered in the form tree.`\n );\n }\n return of(null);\n }\n\n const asyncValidator = context.createAsyncValidator(field, validationOptions);\n const validationResult: ValidationResult = asyncValidator(control);\n\n if (validationResult instanceof Observable) {\n return validationResult;\n }\n\n if (validationResult instanceof Promise) {\n return from(validationResult);\n }\n\n return of(validationResult ?? null);\n}\n","import { Directive, inject, input } from '@angular/core';\nimport {\n AbstractControl,\n AsyncValidator,\n NG_ASYNC_VALIDATORS,\n ValidationErrors,\n} from '@angular/forms';\nimport { Observable } from 'rxjs';\nimport { getFormGroupField } from '../utils/form-utils';\nimport { runAsyncValidationBridge } from './async-validator-bridge';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Hooks into `ngModelGroup`/`ngxModelGroup` and runs async group-level validation\n * through the parent `FormDirective` Vest suite bridge.\n */\n@Directive({\n selector: '[ngModelGroup],[ngxModelGroup]',\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: FormModelGroupDirective,\n multi: true,\n },\n ],\n})\nexport class FormModelGroupDirective implements AsyncValidator {\n /**\n * Per-group async validation options.\n *\n * Defaults to no debounce (`{ debounceTime: 0 }`).\n */\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n private readonly formDirective: FormDirective<\n Record<string, unknown>\n > | null = inject(FormDirective, { optional: true });\n\n /**\n * Runs async validation for the current model-group control.\n *\n * Returns `null` (fail-open) when used outside an `ngxVestForm` context.\n */\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n return runAsyncValidationBridge(\n control,\n this.formDirective,\n (currentControl) => {\n const context = this.formDirective;\n if (!context) return '';\n return getFormGroupField(context.ngForm.control, currentControl);\n },\n this.validationOptions(),\n 'FormModelGroupDirective'\n );\n }\n}\n","import { Directive, inject, input } from '@angular/core';\nimport {\n AbstractControl,\n AsyncValidator,\n NG_ASYNC_VALIDATORS,\n ValidationErrors,\n} from '@angular/forms';\nimport { Observable } from 'rxjs';\nimport { getFormControlField } from '../utils/form-utils';\nimport { runAsyncValidationBridge } from './async-validator-bridge';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Hooks into `ngModel`/`ngxModel` and runs async field-level validation\n * through the parent `FormDirective` Vest suite bridge.\n */\n@Directive({\n selector: '[ngModel],[ngxModel]',\n\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: FormModelDirective,\n multi: true,\n },\n ],\n})\nexport class FormModelDirective implements AsyncValidator {\n /**\n * Per-control async validation options.\n *\n * Defaults to no debounce (`{ debounceTime: 0 }`).\n */\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n /**\n * Reference to the form that needs to be validated\n * Injected optionally so that using ngModel outside of an ngxVestForm\n * does not crash the application. In that case, validation becomes a no-op.\n */\n private readonly formDirective: FormDirective<\n Record<string, unknown>\n > | null = inject(FormDirective, {\n optional: true,\n });\n\n /**\n * Runs field-level async validation for this control.\n *\n * Returns `null` (fail-open) when used outside an `ngxVestForm` context.\n */\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n return runAsyncValidationBridge(\n control,\n this.formDirective,\n (currentControl) => {\n const context = this.formDirective;\n if (!context) return '';\n return getFormControlField(context.ngForm.control, currentControl);\n },\n this.validationOptions(),\n 'FormModelDirective'\n );\n }\n}\n","import {\n AfterViewInit,\n booleanAttribute,\n DestroyRef,\n Directive,\n effect,\n inject,\n Injector,\n input,\n signal,\n untracked,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport {\n AbstractControl,\n AsyncValidator,\n AsyncValidatorFn,\n NG_ASYNC_VALIDATORS,\n NgForm,\n ValidationErrors,\n} from '@angular/forms';\nimport {\n catchError,\n map,\n Observable,\n of,\n switchMap,\n take,\n tap,\n timer,\n} from 'rxjs';\nimport { ROOT_FORM } from '../constants';\nimport { NgxTypedVestSuite, NgxVestSuite } from '../utils/validation-suite';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Validates the root form (cross-field validation) using a Vest suite.\n *\n * Use this directive for form-wide validations that span multiple fields, such as:\n * - Password confirmation (`password` must match `confirmPassword`)\n * - Date range validation (`startDate` must be before `endDate`)\n * - Business rules like \"at least one contact method required\"\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <form ngxVestForm ngxValidateRootForm [suite]=\"suite\" (errorsChange)=\"errors.set($event)\">\n * <!-- form fields -->\n * @if (errors()['rootForm']) {\n * <div role=\"alert\">{{ errors()['rootForm'][0] }}</div>\n * }\n * </form>\n * ```\n *\n * ### Validation Modes\n * - `'submit'` (default): Validates only after form submission. Better UX for complex cross-field rules.\n * - `'live'`: Validates on every value change. Use sparingly for simple two-field comparisons.\n *\n * ```html\n * <form ngxVestForm ngxValidateRootForm [ngxValidateRootFormMode]=\"'live'\">\n * ```\n *\n * ### Vest Suite Pattern\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * test(ROOT_FORM, 'Passwords must match', () => {\n * enforce(model.confirmPassword).equals(model.password);\n * });\n * ```\n *\n * @see {@link https://github.com/ngx-vest-forms/ngx-vest-forms/blob/master/docs/VALIDATION-CONFIG-VS-ROOT-FORM.md}\n *\n * @example\n * ```html\n * <form scVestForm\n * validateRootForm\n * [suite]=\"suite\"\n * [formValue]=\"formValue()\"\n * [validateRootFormMode]=\"'submit'\"\n * (errorsChange)=\"errors.set($event)\"\n * #form=\"ngForm\">\n * <!-- form fields -->\n * @if (errors()['rootForm']) {\n * <div role=\"alert\">{{ errors()['rootForm'][0] }}</div>\n * }\n * </form>\n * ```\n *\n * @example\n * Validation suite:\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * export const suite = staticSuite((model, field?) => {\n * only(field);\n *\n * test(ROOT_FORM, 'Passwords must match', () => {\n * enforce(model.confirmPassword).equals(model.password);\n * });\n * });\n * ```\n *\n * @publicApi\n */\n@Directive({\n selector: 'form[validateRootForm], form[ngxValidateRootForm]',\n\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: ValidateRootFormDirective,\n multi: true,\n },\n ],\n})\nexport class ValidateRootFormDirective<T>\n implements AsyncValidator, AfterViewInit\n{\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly lastControl = signal<NgForm | null>(null);\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n private readonly hasSubmitted = signal(false);\n private readonly hasSubmitted$: Observable<boolean>;\n private readonly formValue$: Observable<T | null>;\n\n readonly formValue = input<T | null>(null);\n readonly suite = input<NgxVestSuite<T> | NgxTypedVestSuite<T> | null>(null);\n\n /**\n * Whether the root form should be validated or not\n * This will use the field rootForm\n * Accepts both validateRootForm and ngxValidateRootForm\n */\n readonly validateRootForm = input(false, {\n transform: booleanAttribute,\n });\n readonly ngxValidateRootForm = input(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Validation mode:\n * - 'submit' (default): Only validates after form submission\n * - 'live': Validates on every value change\n * Accepts both validateRootFormMode and ngxValidateRootFormMode\n */\n readonly validateRootFormMode = input<'submit' | 'live'>('submit');\n readonly ngxValidateRootFormMode = input<'submit' | 'live'>('submit');\n\n constructor() {\n // Convert signals to Observables in injection context\n this.hasSubmitted$ = toObservable(this.hasSubmitted);\n this.formValue$ = toObservable(this.formValue);\n\n // Trigger validation when hasSubmitted or formValue changes\n effect(() => {\n // Track dependencies\n this.hasSubmitted();\n this.formValue();\n\n // Also track inputs that affect whether validation should run.\n // These can be set after the first validation pass and we want the\n // root form to re-evaluate once they become available.\n this.suite();\n this.validateRootForm();\n this.ngxValidateRootForm();\n this.validateRootFormMode();\n this.ngxValidateRootFormMode();\n this.validationOptions();\n\n // Trigger revalidation if form exists\n // Use emitEvent: true so the form directive can update its errors\n // Use untracked() to avoid making the effect reactive to lastControl changes\n const ngForm = untracked(() => this.lastControl());\n if (ngForm?.control) {\n // Defer to the next microtask so Angular has a chance to finish\n // wiring up controls/groups (ngModel/ngModelGroup) on initial render.\n queueMicrotask(() => ngForm.control.updateValueAndValidity());\n }\n });\n }\n\n /**\n * Subscribe to form submit event using NgForm.ngSubmit EventEmitter\n * This approach avoids conflicts with component's (ngSubmit) handlers\n * Uses Injector to lazily get NgForm, avoiding circular dependency\n * (Directive → NgForm → AsyncValidators → Directive)\n */\n ngAfterViewInit(): void {\n // Lazily inject NgForm to avoid circular dependency\n const ngForm = this.injector.get(NgForm, null);\n this.lastControl.set(ngForm);\n\n if (!ngForm) {\n console.error(\n '[ValidateRootFormDirective] NgForm not found. Ensure the directive is used on a <form> element with the scVestForm directive. ' +\n 'Common setup mistakes: (1) Missing scVestForm directive, (2) Directive on non-form element, (3) NgForm not imported in module/component.'\n );\n return;\n }\n\n // Ensure we run at least one validation pass after the form is ready.\n // This matters for 'live' mode root-form errors that should appear\n // without requiring a user interaction.\n queueMicrotask(() => ngForm.control.updateValueAndValidity());\n\n // Subscribe to form submission to set hasSubmitted flag\n ngForm.ngSubmit\n .pipe(\n tap(() => {\n this.hasSubmitted.set(true);\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe();\n }\n\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n // Skip validation if suite or formValue not set\n if (!this.suite() || !this.formValue()) {\n return of(null);\n }\n\n // Check both validateRootForm and ngxValidateRootForm inputs\n const isEnabled = this.validateRootForm() || this.ngxValidateRootForm();\n if (!isEnabled) {\n return of(null);\n }\n\n // Get mode from either input (ngx prefix takes precedence if both set)\n const mode =\n this.ngxValidateRootFormMode() !== 'submit'\n ? this.ngxValidateRootFormMode()\n : this.validateRootFormMode();\n\n // In 'submit' mode, skip validation until form is submitted\n if (mode === 'submit' && !this.hasSubmitted()) {\n return of(null);\n }\n\n // Call the validator and return its Observable\n // Angular expects this to complete after emitting once\n const validationResult = this.createAsyncValidator(\n ROOT_FORM,\n this.validationOptions()\n )(control) as Observable<ValidationErrors | null>;\n\n return validationResult;\n }\n\n createAsyncValidator(\n field: typeof ROOT_FORM,\n validationOptions: ValidationOptions\n ): AsyncValidatorFn {\n if (!this.suite()) {\n return () => of(null);\n }\n\n // Note: AsyncValidatorFn requires (control: AbstractControl) signature,\n // but root form validation uses formValue input (typed model) instead of control.value.\n // This is intentional - cross-field validation operates on the complete form model,\n // not individual control values. The underscore prefix indicates intentional non-use.\n\n return (_control: AbstractControl) => {\n const currentFormValue = this.formValue();\n if (!currentFormValue) {\n return of(null);\n }\n // Use the formValue input which contains the actual model data\n const mod = structuredClone(currentFormValue) as T;\n\n const debounce = validationOptions.debounceTime ?? 0;\n const source$ =\n debounce > 0 ? timer(debounce).pipe(map(() => mod)) : of(mod);\n\n return source$.pipe(\n switchMap((model) => {\n return new Observable((observer) => {\n try {\n const suite = this.suite();\n if (!suite) {\n observer.next(null);\n observer.complete();\n return;\n }\n // NOTE: `suite` can be a union of typed and untyped suite functions.\n // When calling a union of functions, TypeScript requires arguments\n // to satisfy all call signatures, which can produce overly-strict\n // errors in template type-checking. At runtime this is always the\n // ROOT_FORM field ('rootForm'), which is valid for both variants.\n const runSuite = suite as unknown as (\n model: T,\n field?: unknown\n ) => {\n done: (\n cb: (result: {\n getErrors: () => Record<string, string[]>;\n }) => void\n ) => void;\n };\n\n runSuite(model, field).done((result) => {\n const errors = result.getErrors()[field];\n // Return { errors: string[] } format expected by getAllFormErrors()\n observer.next(errors ? { errors } : null);\n observer.complete();\n });\n } catch (err) {\n console.error(\n '[validate-root-form] Validation suite error:',\n err\n );\n observer.next(null);\n observer.complete();\n }\n }) as Observable<ValidationErrors | null>;\n }),\n catchError((err) => {\n console.error('[validate-root-form] Observable error:', err);\n return of(null);\n }),\n take(1),\n takeUntilDestroyed(this.destroyRef)\n );\n };\n }\n}\n","import { Optional, Provider } from '@angular/core';\nimport {\n ControlContainer,\n FormsModule,\n NgForm,\n NgModelGroup,\n} from '@angular/forms';\nimport { ControlWrapperComponent } from './components/control-wrapper/control-wrapper.component';\nimport { FormGroupWrapperComponent } from './components/form-group-wrapper/form-group-wrapper.component';\nimport { FormControlStateDirective } from './directives/form-control-state.directive';\nimport { FormErrorControlDirective } from './directives/form-error-control.directive';\nimport { FormErrorDisplayDirective } from './directives/form-error-display.directive';\nimport { FormModelGroupDirective } from './directives/form-model-group.directive';\nimport { FormModelDirective } from './directives/form-model.directive';\nimport { FormDirective } from './directives/form.directive';\nimport { ValidateRootFormDirective } from './directives/validate-root-form.directive';\n\n/**\n * This is borrowed from [https://github.com/wardbell/ngc-validate/blob/main/src/app/core/form-container-view-provider.ts](https://github.com/wardbell/ngc-validate/blob/main/src/app/core/form-container-view-provider.ts)\n * Thank you so much Ward Bell for your effort!:\n *\n * Provide a ControlContainer to a form component from the\n * nearest parent NgModelGroup (preferred) or NgForm.\n *\n * Required for Reactive Forms as well (unless you write CVA)\n *\n * @example\n * ```\n * @Component({\n * ...\n * viewProviders[ formViewProvider ]\n * })\n * ```\n * @see Kara's AngularConnect 2017 talk: https://youtu.be/CD_t3m2WMM8?t=1826\n *\n * Without this provider\n * - Controls are not registered with parent NgForm or NgModelGroup\n * - Form-level flags say \"untouched\" and \"valid\"\n * - No form-level validation roll-up\n * - Controls still validate, update model, and update their statuses\n * - If within NgForm, no compiler error because ControlContainer is optional for ngModel\n *\n * Note: if the SubForm Component that uses this Provider\n * is not within a Form or NgModelGroup, the provider returns `null`\n * resulting in an error, something like\n * ```\n * preview-fef3604083950c709c52b.js:1 ERROR Error:\n * ngModelGroup cannot be used with a parent formGroup directive.\n *```\n */\nconst formViewProvider: Provider = {\n provide: ControlContainer,\n useFactory: _formViewProviderFactory,\n deps: [\n [new Optional(), NgForm],\n [new Optional(), NgModelGroup],\n ],\n};\n\nfunction _formViewProviderFactory(ngForm: NgForm, ngModelGroup: NgModelGroup) {\n return ngModelGroup || ngForm || null;\n}\n\n/**\n * The providers we need in every child component that holds an ngModelGroup\n */\nexport const vestFormsViewProviders = [\n { provide: ControlContainer, useExisting: NgForm },\n formViewProvider, // very important if we want nested components with ngModelGroup\n];\n\n/**\n * Collection of directives, components, and modules required for ngx-vest-forms.\n *\n * This array exports all the necessary components and directives to enable\n * Vest validation integration with Angular template-driven forms.\n *\n * @example\n * ```typescript\n * import { NgxVestForms } from 'ngx-vest-forms';\n *\n * @Component({\n *\n * imports: [NgxVestForms],\n * /// ...\n * })\n * export class MyComponent { }\n * ```\n */\nexport const NgxVestForms = [\n ValidateRootFormDirective,\n ControlWrapperComponent,\n FormGroupWrapperComponent,\n FormControlStateDirective,\n FormErrorDisplayDirective,\n FormErrorControlDirective,\n FormDirective,\n FormsModule,\n FormModelDirective,\n FormModelGroupDirective,\n] as const;\n\n/**\n * @deprecated Use `NgxVestForms` instead\n */\nexport const vestForms = NgxVestForms;\n","/**\n * Primitive types that should not be traversed for nested paths\n */\ntype Primitive = string | number | boolean | Date | null | undefined;\n\n/**\n * Helper type to extract the element type from an array.\n * Used internally for type inference with array paths.\n *\n * @template T - The array type to extract from\n * @example\n * ```typescript\n * type Element = ArrayElement<string[]>; // Result: string\n * type Element2 = ArrayElement<NotArray>; // Result: never\n * ```\n */\n\n/**\n * Recursively generates all valid field paths for a type as string literals.\n * This provides full IDE autocomplete and compile-time validation for field names.\n *\n * **Key Features:**\n * - Supports nested objects with dot notation (e.g., 'user.address.city')\n * - Works with optional properties from DeepPartial types\n * - Handles arrays and readonly arrays\n * - Stops recursion at primitive types\n * - Maximum depth of 10 levels to prevent infinite recursion\n *\n * **Type Safety Benefits:**\n * - IDE autocomplete for all valid field paths\n * - Compile-time errors for typos in field names\n * - Refactoring support (rename property → all usages update)\n * - Self-documenting code through type inference\n *\n * @template T - The model type to extract field paths from\n * @template Prefix - Internal recursion prefix (do not use directly)\n * @template Depth - Internal depth counter to prevent infinite recursion\n *\n * @example\n * ```typescript\n * type Model = {\n * name: string;\n * profile: {\n * age: number;\n * address: {\n * city: string;\n * }\n * }\n * };\n *\n * type Paths = FieldPath<Model>;\n * /// Result: 'name' | 'profile' | 'profile.age' | 'profile.address' | 'profile.address.city'\n * ```\n *\n * @example With DeepPartial\n * ```typescript\n * type FormModel = DeepPartial<{\n * user: {\n * email: string;\n * phone: string;\n * }\n * }>;\n *\n * type Paths = FieldPath<FormModel>;\n * /// Result: 'user' | 'user.email' | 'user.phone'\n * ```\n */\nexport type FieldPath<\n T,\n Prefix extends string = '',\n Depth extends readonly number[] = [],\n> = Depth['length'] extends 10\n ? never // Max depth reached, prevent infinite recursion\n : T extends Primitive\n ? never // Don't traverse primitives\n : T extends ReadonlyArray<infer U>\n ? // For arrays, generate paths for the element type\n FieldPath<U, Prefix, [...Depth, 1]>\n : {\n [K in keyof T & string]: T[K] extends Primitive\n ? // Primitive property: just the field name\n `${Prefix}${K}`\n : T[K] extends ReadonlyArray<infer U>\n ? // Array property: field name plus element paths\n | `${Prefix}${K}`\n | (U extends Primitive\n ? never\n : FieldPath<U, `${Prefix}${K}.`, [...Depth, 1]>)\n : // Object property: field name plus nested paths\n | `${Prefix}${K}`\n | FieldPath<T[K], `${Prefix}${K}.`, [...Depth, 1]>;\n }[keyof T & string];\n\n/**\n * Type-safe validation configuration map.\n * Maps trigger field paths to arrays of dependent field paths that should be revalidated.\n *\n * **Use Case:**\n * Define which fields should trigger validation of other fields when they change.\n * For example, when password changes, confirmPassword should be revalidated.\n *\n * **Type Safety:**\n * - All keys must be valid field paths from the model\n * - All dependent field paths must be valid\n * - IDE autocomplete works for both keys and values\n * - Compile-time errors for invalid field references\n *\n * @template T - The form model type\n *\n * @example\n * ```typescript\n * type FormModel = DeepPartial<{\n * password: string;\n * confirmPassword: string;\n * addresses: {\n * billing: { city: string; }\n * }\n * }>;\n *\n * /// ✅ Type-safe configuration with autocomplete\n * const config: ValidationConfigMap<FormModel> = {\n * password: ['confirmPassword'],\n * 'addresses.billing.city': ['password'],\n * };\n *\n * /// ❌ TypeScript error - invalid field name\n * const badConfig: ValidationConfigMap<FormModel> = {\n * passwordd: ['confirmPassword'], // Typo caught at compile time\n * };\n * ```\n */\nexport type ValidationConfigMap<T> = Partial<\n Record<FieldPath<T>, Array<FieldPath<T>>>\n>;\n\n/**\n * Type-safe field name for use in Vest test() calls and form APIs.\n * Combines valid field paths with the special ROOT_FORM constant.\n *\n * **Use Case:**\n * When defining Vest test() calls, use this type for the field parameter\n * to get autocomplete and type safety.\n *\n * **Special Values:**\n * - Any valid FieldPath from the model\n * - ROOT_FORM constant for form-level validations\n *\n * @template T - The form model type\n *\n * @example\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * type FormModel = DeepPartial<{\n * email: string;\n * user: { name: string; }\n * }>;\n *\n * export const suite = staticSuite(\n * (data: FormModel, field?: FormFieldName<FormModel>) => {\n * only(field);\n *\n * /// ✅ Autocomplete works\n * test('email', 'Required', () => {\n * enforce(data.email).isNotBlank();\n * });\n *\n * test('user.name', 'Required', () => {\n * enforce(data.user?.name).isNotBlank();\n * });\n *\n * /// Form-level validation\n * test(ROOT_FORM, 'At least one contact method', () => {\n * enforce(data.email || data.user?.name).isTruthy();\n * });\n * }\n * );\n * ```\n */\nexport type FormFieldName<T> = FieldPath<T> | typeof ROOT_FORM;\n\n// Re-export ROOT_FORM for convenience\nimport { ROOT_FORM } from '../constants';\nexport { ROOT_FORM };\n\n/**\n * Helper type to infer the value type at a given field path.\n * Useful for creating type-safe utilities that work with field paths.\n *\n * @template T - The model type\n * @template Path - The field path string\n *\n * @example\n * ```typescript\n * type Model = {\n * user: {\n * profile: {\n * age: number;\n * }\n * }\n * };\n *\n * type AgeType = FieldPathValue<Model, 'user.profile.age'>;\n * /// Result: number\n * ```\n */\nexport type FieldPathValue<T, Path extends string> = Path extends keyof T\n ? T[Path]\n : Path extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? FieldPathValue<NonNullable<T[K]>, Rest>\n : never\n : never;\n\n/**\n * Utility type to check if a path is valid for a given model.\n * Returns the path if valid, never otherwise.\n *\n * @template T - The model type\n * @template Path - The path to validate\n *\n * @example\n * ```typescript\n * type Model = { name: string; age: number; };\n *\n * type Valid = ValidateFieldPath<Model, 'name'>; // 'name'\n * type Invalid = ValidateFieldPath<Model, 'invalid'>; // never\n * ```\n */\nexport type ValidateFieldPath<T, Path extends string> =\n Path extends FieldPath<T> ? Path : never;\n\n/**\n * Extract all leaf field paths (paths that point to primitive values).\n * Useful when you only want paths to actual values, not intermediate objects.\n *\n * @template T - The model type\n *\n * @example\n * ```typescript\n * type Model = {\n * user: {\n * name: string;\n * profile: {\n * age: number;\n * }\n * }\n * };\n *\n * type Leaves = LeafFieldPath<Model>;\n * /// Result: 'user.name' | 'user.profile.age'\n * /// Note: 'user' and 'user.profile' are excluded (not leaves)\n * ```\n */\nexport type LeafFieldPath<\n T,\n Prefix extends string = '',\n Depth extends readonly number[] = [],\n> = Depth['length'] extends 10\n ? never\n : T extends Primitive\n ? never\n : T extends ReadonlyArray<infer U>\n ? LeafFieldPath<U, Prefix, [...Depth, 1]>\n : {\n [K in keyof T & string]: T[K] extends Primitive\n ? `${Prefix}${K}`\n : T[K] extends ReadonlyArray<infer U>\n ? U extends Primitive\n ? never\n : LeafFieldPath<U, `${Prefix}${K}.`, [...Depth, 1]>\n : LeafFieldPath<T[K], `${Prefix}${K}.`, [...Depth, 1]>;\n }[keyof T & string];\n","/**\n * Represents the state of a form managed by scVestForm directive.\n * This is the structure returned by NgxVestFormDirective.formState() or similar.\n */\nexport type NgxFormState<TModel = unknown> = {\n /** Whether the form is valid */\n valid: boolean;\n /** Map of field errors by field path */\n errors: Record<string, string[]>;\n /** Current form value (includes disabled fields) */\n value: TModel | null;\n};\n\n/**\n * Creates an empty NgxFormState with default values.\n *\n * This utility is helpful when you need to provide a fallback for components\n * that require a non-null NgxFormState, such as when child components\n * might not be initialized yet.\n *\n * @template TModel The type of the form model/value\n * @returns A complete NgxFormState object with empty/default values\n *\n * @example\n * ```typescript\n * /// In a parent component that displays child form state\n * protected readonly formState = computed(() =>\n * this.childForm()?.formState() ?? createEmptyFormState()\n * );\n * ```\n *\n * @example\n * ```typescript\n * /// With specific typing\n * interface MyFormModel {\n * name: string;\n * email: string;\n * }\n *\n * const emptyState = createEmptyFormState<MyFormModel>();\n * ```\n */\nexport function createEmptyFormState<TModel = unknown>(): NgxFormState<TModel> {\n return {\n value: null,\n errors: {},\n valid: true,\n };\n}\n","import type { FieldPath, ValidationConfigMap } from './field-path-types';\n\n// NOTE: `typeof ngDevMode !== 'undefined' && ngDevMode` is kept inline\n// (not extracted to a helper) because Angular's build optimizer relies on\n// this exact pattern for tree-shaking dev-only code from production bundles.\nconst LOG_PREFIX = '[ngx-vest-forms] ValidationConfigBuilder';\n\n/**\n * Fluent builder for creating type-safe validation configurations.\n *\n * Provides convenience methods for common validation dependency patterns:\n * - **`whenChanged()`**: One-way dependencies (when A changes, revalidate B)\n * - **`bidirectional()`**: Two-way dependencies (A ↔ B revalidate each other)\n * - **`group()`**: All fields in group revalidate each other\n * - **`merge()`**: Combine with existing configurations\n *\n * @template T - The form model type\n *\n * @example Basic usage\n * ```typescript\n * const config = createValidationConfig<MyFormModel>()\n * .whenChanged('password', 'confirmPassword')\n * .bidirectional('startDate', 'endDate')\n * .build();\n * ```\n *\n * @example Complex scenario\n * ```typescript\n * const config = createValidationConfig<OrderFormModel>()\n * .group(['firstName', 'lastName', 'email'])\n * .whenChanged('country', ['state', 'zipCode'])\n * .bidirectional('minPrice', 'maxPrice')\n * .merge(existingConfig)\n * .build();\n * ```\n */\nexport class ValidationConfigBuilder<T> {\n private config: Partial<Record<string, string[]>> = {};\n\n /**\n * Add a one-way dependency: when `trigger` changes, revalidate `dependents`.\n *\n * This method is cumulative - calling it multiple times with the same trigger\n * will merge all dependents together.\n *\n * **When to Use:**\n * - ✅ Conditional field requirements (country → state/zipCode)\n * - ✅ Calculated fields (quantity/price → total)\n * - ✅ Dependent validations where only one direction matters\n * - ✅ Cascading validations (A changes → B needs revalidation → C needs revalidation)\n *\n * **Real-World Use Case:**\n * In an e-commerce checkout form, when the user selects a country, the available\n * states/provinces and zip code format validation rules change. The country field\n * needs to trigger revalidation of state and zipCode, but changes to state/zipCode\n * don't need to revalidate country (one-way dependency).\n *\n * **Vest.js Patterns That Work Well:**\n * - `skipWhen(res => res.hasErrors('trigger'), () => { test('dependent', ...) })` -\n * Skip expensive validations on dependent field until trigger field is valid\n * - Async validations on dependent fields that need the trigger's value\n * - Calculated field validations (e.g., total depends on quantity × price)\n * - Conditional `omitWhen` based on trigger field state\n *\n * @param trigger - The field that triggers revalidation\n * @param revalidate - Single field or array of fields to revalidate\n * @returns This builder instance for method chaining\n *\n * @example Single dependent\n * ```typescript\n * builder.whenChanged('password', 'confirmPassword');\n * /// Result: { password: ['confirmPassword'] }\n * ```\n *\n * @example Multiple dependents\n * ```typescript\n * builder.whenChanged('country', ['state', 'zipCode', 'postalCode']);\n * /// Result: { country: ['state', 'zipCode', 'postalCode'] }\n * ```\n *\n * @example Cumulative calls\n * ```typescript\n * builder\n * .whenChanged('password', 'confirmPassword')\n * .whenChanged('password', 'securityScore');\n * /// Result: { password: ['confirmPassword', 'securityScore'] }\n * ```\n */\n whenChanged<K extends FieldPath<T>>(\n trigger: K,\n revalidate: FieldPath<T> | ReadonlyArray<FieldPath<T>>\n ): this {\n const deps = Array.isArray(revalidate) ? revalidate : [revalidate];\n const existing = this.config[trigger] || [];\n\n // Development mode warning for duplicate dependents\n if (typeof ngDevMode !== 'undefined' && ngDevMode) {\n const duplicates = deps.filter((d) => existing.includes(d));\n if (duplicates.length > 0) {\n console.warn(\n `${LOG_PREFIX}: Duplicate dependencies detected.\\n` +\n ` Trigger: '${trigger}'\\n` +\n ` Duplicates: ${duplicates.map((d) => `'${d}'`).join(', ')}\\n` +\n ` These will be automatically deduplicated.`\n );\n }\n }\n\n // Deduplicate dependents\n const merged = [...existing, ...deps];\n this.config[trigger] = Array.from(new Set(merged));\n\n return this;\n }\n\n /**\n * Add bidirectional dependency: when either field changes, revalidate the other.\n *\n * This is a convenience method that calls `whenChanged()` in both directions.\n * Commonly used for password/confirmPassword, min/max ranges, start/end dates.\n *\n * **When to Use:**\n * - ✅ Password confirmation (password ↔ confirmPassword)\n * - ✅ Min/max range validation (minPrice ↔ maxPrice, minAge ↔ maxAge)\n * - ✅ Start/end date validation (startDate ↔ endDate)\n * - ✅ Any field comparison where both fields need mutual revalidation\n *\n * **Real-World Use Case:**\n * In a job posting form, when setting salary range, changing either minSalary or\n * maxSalary should revalidate the other to ensure minSalary ≤ maxSalary. Users\n * can change either field first, so both directions need validation. This prevents\n * invalid ranges like \"$80k min, $50k max\".\n *\n * **Vest.js Patterns That Work Well:**\n * - Comparison validations: `enforce(data.min).lessThanOrEquals(data.max)`\n * - Password matching: `enforce(data.password).equals(data.confirmPassword)`\n * - Date range validation with `enforce(data.startDate).lessThan(data.endDate)`\n * - `skipWhen` to prevent comparison when either field has errors:\n * ```typescript\n * skipWhen(res => res.hasErrors('field1') || res.hasErrors('field2'), () => {\n * test('field1', 'Min must be ≤ Max', () => enforce(min).lessThanOrEquals(max));\n * });\n * ```\n *\n * @param field1 - First field in the bidirectional relationship\n * @param field2 - Second field in the bidirectional relationship\n * @returns This builder instance for method chaining\n *\n * @example Password confirmation\n * ```typescript\n * builder.bidirectional('password', 'confirmPassword');\n * /// Result: {\n * /// password: ['confirmPassword'],\n * /// confirmPassword: ['password']\n * /// }\n * ```\n *\n * @example Date range\n * ```typescript\n * builder.bidirectional('startDate', 'endDate');\n * /// Result: {\n * /// startDate: ['endDate'],\n * /// endDate: ['startDate']\n * /// }\n * ```\n */\n bidirectional<K1 extends FieldPath<T>, K2 extends FieldPath<T>>(\n field1: K1,\n field2: K2\n ): this {\n // Development mode warning for exact duplicate\n if (typeof ngDevMode !== 'undefined' && ngDevMode) {\n const hasField1ToField2 =\n this.config[field1]?.includes(field2 as string) ?? false;\n const hasField2ToField1 =\n this.config[field2]?.includes(field1 as string) ?? false;\n\n if (hasField1ToField2 && hasField2ToField1) {\n console.warn(\n `${LOG_PREFIX}: Duplicate bidirectional relationship detected.\\n` +\n ` Fields: '${field1}' ↔ '${field2}'\\n` +\n ` This bidirectional relationship was already configured.`\n );\n }\n }\n\n this.whenChanged(field1, field2);\n this.whenChanged(field2, field1);\n return this;\n }\n\n /**\n * Create a validation group where all fields revalidate each other.\n *\n * When any field in the group changes, all other fields in the group are revalidated.\n * This is useful for fields that collectively form a validation rule.\n *\n * **When to Use:**\n * - ✅ \"At least one required\" scenarios (email OR phone OR address)\n * - ✅ Interdependent field sets (credit card: number + expiry + CVV)\n * - ✅ Contact information (firstName + lastName + email)\n * - ✅ Fields that collectively satisfy a business rule\n *\n * **Real-World Use Case:**\n * In a customer registration form with a \"at least one contact method required\"\n * business rule, the validation suite checks `email || phone || mailingAddress`.\n * When user fills any of these fields, the other fields need revalidation to clear\n * the \"at least one required\" error. All three fields are interdependent, so\n * grouping them ensures validation updates correctly regardless of which field\n * the user fills first.\n *\n * **Vest.js Patterns That Work Well:**\n * - \"At least one required\" logic:\n * ```typescript\n * test('email', 'Provide at least one contact method', () => {\n * enforce(data.email || data.phone || data.address).isTruthy();\n * });\n * ```\n * - Interdependent field validation where all fields collectively satisfy a rule\n * - Credit card validation (number + expiry + CVV all need each other)\n * - Use `optional()` for groups where fields can all be empty together:\n * ```typescript\n * optional(['email', 'phone', 'address']);\n * ```\n *\n * **Performance Note:** This creates N×(N-1) dependencies, which can impact\n * performance for large groups. Consider using `whenChanged()` for more targeted\n * dependencies if performance is a concern (e.g., groups > 10 fields).\n *\n * @param fields - Array of fields that should all revalidate each other\n * @returns This builder instance for method chaining\n *\n * @example Contact information group\n * ```typescript\n * builder.group(['firstName', 'lastName', 'email']);\n * /// Result: {\n * /// firstName: ['lastName', 'email'],\n * /// lastName: ['firstName', 'email'],\n * /// email: ['firstName', 'lastName']\n * /// }\n * ```\n *\n * @example Address validation group\n * ```typescript\n * builder.group(['street', 'city', 'state', 'zipCode']);\n * ```\n */\n group<K extends FieldPath<T>>(fields: readonly K[]): this {\n // Each field triggers validation of all other fields in the group\n for (const field of fields) {\n const others = fields.filter((f) => f !== field);\n this.whenChanged(field, others);\n }\n return this;\n }\n\n /**\n * Merge with an existing validation configuration.\n *\n * This method is useful for:\n * - Combining base configurations with conditional configurations\n * - Composing configurations from multiple sources\n * - Adding dynamic configurations based on runtime conditions\n *\n * **When to Use:**\n * - ✅ Conditional features (international shipping adds customs fields)\n * - ✅ Reusable configuration modules (address config, payment config)\n * - ✅ Dynamic forms where validation rules change at runtime\n * - ✅ Feature flags or A/B testing variations\n *\n * **Real-World Use Case:**\n * In an e-commerce checkout, your form has base validation (shipping address,\n * payment info). When user selects international shipping, you need additional\n * validations (customs declaration, tax ID). Instead of duplicating the base\n * config, use `merge()` to conditionally add the international validation rules.\n * This keeps your code DRY and makes it easy to toggle features on/off.\n *\n * **Vest.js Patterns That Work Well:**\n * - Conditional features with `omitWhen`:\n * ```typescript\n * omitWhen(!isInternational, () => {\n * test('customsForm', 'Customs declaration required', () => {\n * enforce(data.customsForm).isNotBlank();\n * });\n * });\n * ```\n * - Reusable validation modules that can be composed\n * - Feature flags: merge different configs based on enabled features\n * - A/B testing: conditionally merge test-specific validation rules\n * - Use with computed signals for reactive configuration:\n * ```typescript\n * const config = computed(() =>\n * createValidationConfig<T>()\n * .merge(baseConfig)\n * .merge(featureEnabled() ? featureConfig : {})\n * .build()\n * );\n * ```\n *\n * **Note:** Dependencies are merged and deduplicated. If both configs have\n * the same trigger field, dependents are combined into a single array.\n *\n * @param other - Existing ValidationConfigMap to merge\n * @returns This builder instance for method chaining\n *\n * @example Conditional configuration\n * ```typescript\n * const baseConfig = createValidationConfig<FormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .build();\n *\n * const config = createValidationConfig<FormModel>()\n * .merge(baseConfig)\n * .merge(\n * isInternational\n * ? { country: ['customsForm'] }\n * : {}\n * )\n * .build();\n * ```\n *\n * @example Composition\n * ```typescript\n * const addressConfig = { 'street': ['city', 'zipCode'] };\n * const contactConfig = { 'email': ['phone'] };\n *\n * const config = createValidationConfig<FormModel>()\n * .merge(addressConfig)\n * .merge(contactConfig)\n * .build();\n * ```\n */\n merge(other: ValidationConfigMap<T>): this {\n for (const [key, deps] of Object.entries(other)) {\n if (deps && Array.isArray(deps)) {\n const existing = this.config[key] || [];\n const merged = [...existing, ...deps];\n this.config[key] = Array.from(new Set(merged));\n }\n }\n return this;\n }\n\n /**\n * Build the final validation configuration object.\n *\n * Returns a deep copy of the configuration to prevent accidental mutations.\n * The returned object can be used with the `validationConfig` input of `scVestForm`.\n *\n * @returns Immutable ValidationConfigMap ready for use\n *\n * @example\n * ```typescript\n * protected readonly validationConfig = createValidationConfig<MyFormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .whenChanged('country', 'state')\n * .build();\n * ```\n */\n build(): ValidationConfigMap<T> {\n // Return a deep copy to prevent external mutations affecting the builder\n const copy: Partial<Record<string, string[]>> = {};\n for (const [key, deps] of Object.entries(this.config)) {\n if (deps && Array.isArray(deps)) {\n copy[key] = [...deps];\n }\n }\n return copy as ValidationConfigMap<T>;\n }\n}\n\n/**\n * Factory function to create a type-safe validation configuration builder.\n *\n * This is the recommended entry point for creating validation configurations.\n * It provides full type safety and IDE autocomplete for field names.\n *\n * @template T - The form model type\n * @returns A new ValidationConfigBuilder instance\n *\n * @example Basic usage\n * ```typescript\n * protected readonly validationConfig = createValidationConfig<FormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .whenChanged('country', 'state')\n * .build();\n * ```\n *\n * @example With DeepPartial form model\n * ```typescript\n * type FormModel = DeepPartial<{\n * user: {\n * profile: {\n * email: string;\n * phone: string;\n * }\n * }\n * }>;\n *\n * const config = createValidationConfig<FormModel>()\n * .bidirectional('user.profile.email', 'user.profile.phone')\n * .build();\n * ```\n *\n * @example Complex scenario with all methods\n * ```typescript\n * const config = createValidationConfig<OrderFormModel>()\n * .group(['firstName', 'lastName', 'email'])\n * .bidirectional('startDate', 'endDate')\n * .bidirectional('minPrice', 'maxPrice')\n * .whenChanged('orderType', ['deliveryDate', 'priority'])\n * .whenChanged('country', ['state', 'zipCode'])\n * .merge(conditionalConfig)\n * .build();\n * ```\n */\nexport function createValidationConfig<T>(): ValidationConfigBuilder<T> {\n return new ValidationConfigBuilder<T>();\n}\n","/**\n * Converts a flat array to an object with numeric keys.\n * Does not recurse into nested arrays or objects.\n * Uses reduce() for optimal single-pass conversion.\n */\nexport type DeepArrayToObject<T> =\n T extends ReadonlyArray<infer U>\n ? Record<number, DeepArrayToObject<U>>\n : T extends object\n ? { [K in keyof T]: DeepArrayToObject<T[K]> }\n : T;\n\nexport function arrayToObject<T>(array: readonly T[]): Record<number, T> {\n return array.reduce(\n (acc, value, index) => {\n acc[index] = value;\n return acc;\n },\n {} as Record<number, T>\n );\n}\n\n/**\n * Recursively converts arrays to objects with numeric keys, including nested arrays in objects.\n * Useful for template-driven forms that require object structure for nested arrays.\n */\nexport function deepArrayToObject<T>(\n array: readonly T[]\n): Record<number, DeepArrayToObject<T>> {\n return Object.fromEntries(\n array.map((value, index) => [\n index,\n Array.isArray(value)\n ? deepArrayToObject(value as unknown[])\n : value && typeof value === 'object'\n ? recursivelyConvertArrays(value)\n : value,\n ])\n ) as Record<number, DeepArrayToObject<T>>;\n}\n\n/**\n * Recursively traverses an object and converts any nested arrays to objects.\n */\nfunction recursivelyConvertArrays<T>(object: T): DeepArrayToObject<T> {\n if (Array.isArray(object)) {\n return deepArrayToObject(object as unknown[]) as DeepArrayToObject<T>;\n }\n if (object && typeof object === 'object') {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [\n key,\n Array.isArray(value)\n ? deepArrayToObject(value as unknown[])\n : value && typeof value === 'object'\n ? recursivelyConvertArrays(value)\n : value,\n ])\n ) as DeepArrayToObject<T>;\n }\n return object as DeepArrayToObject<T>;\n}\n\n/**\n * Converts selected numeric-keyed object properties back to arrays.\n * Only properties listed in keys will be converted; others remain untouched.\n * Useful for converting form models back to array format before saving/sending to backend.\n */\n\n/**\n * Public API: Convert selected numeric-keyed object properties back to arrays.\n * Note: Conversion is explicit (by key) but will cascade inside converted branches\n * so nested numeric objects representing arrays become real arrays recursively.\n */\nexport function objectToArray<const K extends readonly string[]>(\n object: unknown,\n keys: K\n): unknown {\n const processed = objectToArrayInternal(object, keys);\n if (processed && typeof processed === 'object' && !Array.isArray(processed)) {\n const entries: Array<[string, unknown]> = Object.entries(\n processed as Record<string, unknown>\n );\n if (entries.length === 1) {\n const firstEntry = entries[0];\n if (!firstEntry) {\n return processed;\n }\n const [k, v] = firstEntry;\n if (\n keys.includes(k) &&\n Array.isArray(v) &&\n (v as unknown[]).every(\n (element) => typeof element === 'object' && element !== null\n )\n ) {\n return v;\n }\n }\n }\n return processed;\n}\n\n/**\n * Internal recursive worker with cascade flag: once a targeted key is converted, all nested numeric objects become arrays even if their keys were not explicitly listed.\n */\nfunction objectToArrayInternal(\n object: unknown,\n keys: readonly string[],\n currentKey?: string,\n parentCascade = false\n): unknown {\n if (Array.isArray(object)) {\n // Recursively process each item in the array\n return object.map((item) =>\n objectToArrayInternal(item, keys, undefined, parentCascade)\n );\n }\n\n if (object && typeof object === 'object') {\n if (isNumericObject(object)) {\n // First, recursively process the contents\n const processedContents: Record<string, unknown> = {};\n let hasChanges = false;\n\n const explicit = !!currentKey && keys.includes(currentKey);\n const childCascade = parentCascade || explicit;\n\n for (const [key, value] of Object.entries(object)) {\n const processedValue = objectToArrayInternal(\n value,\n keys,\n key,\n childCascade\n );\n processedContents[key] = processedValue;\n if (processedValue !== value) {\n hasChanges = true;\n }\n }\n\n // Decision: should we convert this numeric object to an array?\n // Yes, if: explicitly targeted, parent was converted, or children changed.\n const shouldConvert = explicit || parentCascade || hasChanges;\n\n return shouldConvert\n ? Object.keys(processedContents)\n .sort((a, b) => Number(a) - Number(b))\n .map((k) => processedContents[k])\n : processedContents;\n }\n\n // For regular objects, process recursively\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n result[key] = objectToArrayInternal(value, keys, key, parentCascade);\n }\n return result;\n }\n\n return object;\n}\n\n/**\n * Checks if a value is an object with only numeric keys (not an array).\n */\nfunction isNumericObject(value: unknown): value is Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.keys(value).every((k) => /^\\d+$/.test(k));\n}\n","/**\n * Utility functions for managing form field state in dynamic forms.\n * These functions help maintain component state consistency when form structure changes.\n */\n\n/**\n * Conditionally clears fields from form state based on provided conditions.\n *\n * **CRITICAL: When This Utility is Required**\n * This utility is specifically needed when conditional logic switches between:\n * - **Form inputs** (e.g., `<input>`, `<select>`, `<textarea>`)\n * - **NON-form elements** (e.g., `<p>`, `<div>`, informational content)\n *\n * **Primary Use Case - Form Input ↔ Non-Form Content:**\n * ```typescript\n * @if (mode === 'input') {\n * <input name=\"field\" [ngModel]=\"value\" /> // Form input\n * } @else {\n * <p>No input required</p> // NON-form element\n * }\n * ```\n *\n * **Why This Creates a Problem:**\n * 1. Switching FROM input TO non-form content: Angular removes FormControl, but component signal retains old value\n * 2. This creates state inconsistency between `ngForm.form.value` (clean) and `formValue()` (stale)\n * 3. Manual clearing synchronizes component state with actual form structure\n *\n * **When NOT Required:**\n * Pure form-to-form conditionals usually don't need manual clearing:\n * ```typescript\n * @if (type === 'text') {\n * <input name=\"field\" [ngModel]=\"value\" type=\"text\" />\n * } @else {\n * <input name=\"field\" [ngModel]=\"value\" type=\"number\" /> // Still a form input\n * }\n * ```\n *\n * **Performance Note:**\n * Uses `Object.entries()` for efficient field clearing without mutation.\n * Only processes fields that need to be cleared, preserving other field values.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param conditions - Object mapping field names to boolean conditions (true = clear field)\n * @returns New state object with specified fields cleared (set to undefined)\n *\n * @example\n * ```typescript\n * /// REQUIRED: Form input switching to non-form content\n * onProcedureTypeChange(newValue: string) {\n * this.formValue.update((current) =>\n * clearFieldsWhen(current, {\n * fieldA: newValue !== 'typeA', // Clear when switching to non-form content\n * fieldB: newValue !== 'typeB', // Clear when switching to non-form content\n * })\n * );\n * }\n *\n * /// Template structure that REQUIRES clearing:\n * /// @if (type === 'typeA') { <input name=\"fieldA\" /> }\n * /// @else if (type === 'typeB') { <input name=\"fieldB\" /> }\n * /// @else { <p>No input needed</p> } // ← NON-form element!\n * ```\n *\n * @example\n * ```typescript\n * /// Complex conditional clearing with mixed form/non-form scenarios\n * const cleanedState = clearFieldsWhen(form, {\n * shippingAddress: !form.useShippingAddress, // Clear when not using shipping\n * emergencyContact: (form.age || 0) >= 18, // Clear when adult (no emergency contact form)\n * childInfo: form.userType !== 'parent', // Clear when not parent (shows info text instead)\n * });\n * ```\n *\n * @example\n * ```typescript\n * /// State inconsistency example - WHY manual clearing is needed:\n *\n * /// BEFORE switching from input to non-form content (typeA → typeC):\n * formValue() = { procedureType: 'typeA', fieldA: 'user-input' }\n * ngForm.form.value = { procedureType: 'typeA', fieldA: 'user-input' }\n *\n * /// AFTER switching WITHOUT clearing (PROBLEMATIC):\n * formValue() = { procedureType: 'typeC', fieldA: 'user-input' } // ❌ Stale fieldA!\n * ngForm.form.value = { procedureType: 'typeC' } // ✅ Clean (Angular removed FormControl)\n *\n * /// AFTER switching WITH clearing (CONSISTENT):\n * formValue() = { procedureType: 'typeC' } // ✅ Clean component state\n * ngForm.form.value = { procedureType: 'typeC' } // ✅ Clean form state\n * ```\n *\n */\nexport function clearFieldsWhen<T extends Record<string, unknown>>(\n currentState: T,\n conditions: Readonly<Partial<Record<keyof T, boolean>>>\n): T {\n const result: Record<string, unknown> = { ...currentState };\n\n for (const fieldName of Object.keys(conditions) as Array<keyof T>) {\n const shouldClear = conditions[fieldName];\n if (shouldClear) {\n result[fieldName as string] = undefined;\n }\n }\n\n return result as T;\n}\n\n/**\n * Clears multiple fields from form state unconditionally.\n *\n * **Use Cases:**\n * - Form reset operations when switching between form modes\n * - Clearing temporary/wizard data when exiting multi-step forms\n * - Cleanup after form submission or cancellation\n * - When you want explicit control over which fields to clear\n *\n * **Note:** Unlike `clearFieldsWhen`, this function always clears the specified fields\n * regardless of conditions. Use this when you want unconditional field removal.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param fieldsToClear - Array of field names to clear (set to undefined)\n * @returns New state object with specified fields cleared\n *\n * @example\n * ```typescript\n * /// Clear specific fields during form mode transitions\n * const cleanedState = clearFields(currentFormValue, ['fieldA', 'fieldB']);\n *\n * /// Reset wizard or temporary data\n * onFormModeChange() {\n * this.formValue.update((current) =>\n * clearFields(current, ['temporaryData', 'wizardStep', 'draftSaved'])\n * );\n * }\n *\n * /// Clear all optional fields on form submission\n * save() {\n * const finalData = clearFields(this.formValue(), ['draftField', 'tempNotes']);\n * this.submitForm(finalData);\n * }\n * ```\n */\nexport function clearFields<T extends Record<string, unknown>>(\n currentState: T,\n fieldsToClear: ReadonlyArray<keyof T>\n): T {\n const result: Record<string, unknown> = { ...currentState };\n\n for (const fieldName of fieldsToClear) {\n result[fieldName as string] = undefined;\n }\n\n return result as T;\n}\n\n/**\n * Creates a clean form state containing only fields that meet specified conditions.\n *\n * **Philosophy:** Instead of clearing unwanted fields (like `clearFieldsWhen`), this function\n * takes a \"whitelist\" approach - building a new state with only the fields you explicitly want to keep.\n *\n * **Best Use Cases:**\n * - Complex form transformations where you want to be explicit about kept fields\n * - Building clean data objects for API submission (exclude UI-only fields)\n * - Form mode switching where different modes have completely different field sets\n * - Data export scenarios where only certain fields should be included\n *\n * **Returns:** `Partial<T>` because the result may not contain all original fields.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param conditions - Object mapping field names to boolean conditions (true = keep field)\n * @returns New state object containing only fields where condition is true\n *\n * @example\n * ```typescript\n * /// Keep only relevant fields based on form mode\n * const filteredState = keepFieldsWhen(currentFormValue, {\n * procedureType: true, // always keep\n * fieldA: procedureType === 'typeA',\n * fieldB: procedureType === 'typeB',\n * // Note: fieldC is omitted when procedureType === 'typeC' (non-form content)\n * });\n *\n * /// Build clean data for API submission (exclude UI-only fields)\n * const apiData = keepFieldsWhen(formValue(), {\n * // Business data - keep these\n * userName: true,\n * email: true,\n * preferences: true,\n * // UI state fields omitted: wizardStep, draftSaved, validationErrors, etc.\n * });\n *\n * /// Dynamic form sections based on user permissions\n * const relevantData = keepFieldsWhen(form, {\n * basicInfo: true,\n * addressInfo: form.needsAddress && userCanEditAddress,\n * paymentInfo: form.requiresPayment && userCanMakePayments,\n * adminFields: userIsAdmin,\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function keepFieldsWhen<T extends Record<string, unknown>>(\n currentState: T,\n conditions: Readonly<Partial<Record<keyof T, boolean>>>\n): Partial<T> {\n const result: Record<string, unknown> = {};\n\n for (const fieldName of Object.keys(conditions) as Array<keyof T>) {\n const shouldKeep = conditions[fieldName];\n if (shouldKeep && fieldName in currentState) {\n result[fieldName as string] = currentState[fieldName];\n }\n }\n\n return result as Partial<T>;\n}\n","/*\n * Public API Surface of ngx-vest-forms\n */\n\nexport { NgxVestForms, vestForms, vestFormsViewProviders } from './lib/exports';\n\n// Type utilities\nexport type { DeepPartial, NgxDeepPartial } from './lib/utils/deep-partial';\nexport type {\n DeepRequired,\n FormCompatibleDeepRequired,\n NgxDeepRequired,\n NgxFormCompatibleDeepRequired,\n} from './lib/utils/deep-required';\n/** @deprecated Use ROOT_FORM from 'ngx-vest-forms' instead */\nexport { ROOT_FORM as ROOT_FORM_CONSTANT } from './lib/utils/field-path-types';\nexport type {\n FieldPath,\n FieldPathValue,\n FormFieldName,\n LeafFieldPath,\n ValidateFieldPath,\n ValidationConfigMap,\n} from './lib/utils/field-path-types';\nexport { createEmptyFormState } from './lib/utils/form-state.utils';\nexport type { NgxFormState } from './lib/utils/form-state.utils';\nexport {\n ValidationConfigBuilder,\n createValidationConfig,\n} from './lib/utils/validation-config-builder';\nexport type {\n NgxFieldKey,\n NgxTypedVestSuite,\n NgxVestSuite,\n} from './lib/utils/validation-suite';\n\n// Form utilities\nexport {\n arrayToObject,\n deepArrayToObject,\n objectToArray,\n} from './lib/utils/array-to-object';\nexport {\n clearFields,\n clearFieldsWhen,\n keepFieldsWhen,\n} from './lib/utils/field-clearing';\nexport { stringifyFieldPath } from './lib/utils/field-path.utils';\nexport { setValueAtPath } from './lib/utils/form-utils';\nexport { createDebouncedPendingState } from './lib/utils/pending-state.utils';\nexport type {\n DebouncedPendingStateOptions,\n DebouncedPendingStateResult,\n} from './lib/utils/pending-state.utils';\nexport { validateShape } from './lib/utils/shape-validation';\n\n// ARIA association utilities\nexport {\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from './lib/utils/aria-association.utils';\nexport type { AriaAssociationMode } from './lib/utils/aria-association.utils';\n\n// Internal utilities - exported for advanced use cases but not part of the primary API\n// These are marked with @internal in their source files and may change without notice\n/** @internal */ export {\n fastDeepEqual,\n shallowEqual,\n} from './lib/utils/equality';\n/** @internal */ export { parseFieldPath } from './lib/utils/field-path.utils';\n/** @internal */ export {\n getAllFormErrors,\n getFormControlField,\n getFormGroupField,\n mergeValuesAndRawValues,\n} from './lib/utils/form-utils';\n\n// Deprecated - kept for backward compatibility, will be removed in future major version\n/** @deprecated Use setValueAtPath instead */ export {\n cloneDeep,\n set,\n} from './lib/utils/form-utils';\n\n// Constants\nexport { ROOT_FORM } from './lib/constants';\n\n// Tokens\nexport {\n NGX_ERROR_DISPLAY_MODE_TOKEN,\n NGX_WARNING_DISPLAY_MODE_TOKEN,\n SC_ERROR_DISPLAY_MODE_TOKEN,\n} from './lib/directives/error-display-mode.token';\nexport { NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN } from './lib/tokens/debounce.token';\n\n// Components\nexport { ControlWrapperComponent } from './lib/components/control-wrapper/control-wrapper.component';\nexport { FormGroupWrapperComponent } from './lib/components/form-group-wrapper/form-group-wrapper.component';\n\n// Directives\nexport { FormControlStateDirective } from './lib/directives/form-control-state.directive';\nexport { FormErrorControlDirective } from './lib/directives/form-error-control.directive';\nexport { FormErrorDisplayDirective } from './lib/directives/form-error-display.directive';\nexport type {\n NgxWarningDisplayMode,\n ScErrorDisplayMode,\n} from './lib/directives/form-error-display.directive';\nexport { FormModelGroupDirective } from './lib/directives/form-model-group.directive';\nexport { FormModelDirective } from './lib/directives/form-model.directive';\nexport { FormDirective } from './lib/directives/form.directive';\nexport type { NgxValidationConfig } from './lib/directives/form.directive';\nexport { ValidateRootFormDirective } from './lib/directives/validate-root-form.directive';\nexport type { ValidationOptions } from './lib/directives/validation-options';\nexport {\n DEFAULT_FOCUS_SELECTOR,\n DEFAULT_INVALID_SELECTOR,\n} from './lib/utils/first-invalid.utils';\nexport type { NgxFirstInvalidOptions } from './lib/utils/first-invalid.utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["isPrimitive","rxMerge","i1.FormControlStateDirective","nextUniqueId","i1.FormErrorDisplayDirective"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-vest-forms.mjs","sources":["../../../projects/ngx-vest-forms/src/lib/directives/error-display-mode.token.ts","../../../projects/ngx-vest-forms/src/lib/errors/error-catalog.ts","../../../projects/ngx-vest-forms/src/lib/tokens/debounce.token.ts","../../../projects/ngx-vest-forms/src/lib/utils/equality.ts","../../../projects/ngx-vest-forms/src/lib/tokens/equality.token.ts","../../../projects/ngx-vest-forms/src/lib/utils/destroy-scheduler.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-path.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/first-invalid.utils.ts","../../../projects/ngx-vest-forms/src/lib/constants.ts","../../../projects/ngx-vest-forms/src/lib/utils/form-utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/shape-validation.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-submitted-state.ts","../../../projects/ngx-vest-forms/src/lib/directives/form.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-control-state.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-error-display.directive.ts","../../../projects/ngx-vest-forms/src/lib/utils/aria-association.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/pending-state.utils.ts","../../../projects/ngx-vest-forms/src/lib/components/control-wrapper/control-wrapper.component.ts","../../../projects/ngx-vest-forms/src/lib/components/control-wrapper/control-wrapper.component.html","../../../projects/ngx-vest-forms/src/lib/components/form-group-wrapper/form-group-wrapper.component.ts","../../../projects/ngx-vest-forms/src/lib/components/form-group-wrapper/form-group-wrapper.component.html","../../../projects/ngx-vest-forms/src/lib/directives/form-error-control.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/async-validator-bridge.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-model-group.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/form-model.directive.ts","../../../projects/ngx-vest-forms/src/lib/directives/validate-root-form.directive.ts","../../../projects/ngx-vest-forms/src/lib/exports.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-path-types.ts","../../../projects/ngx-vest-forms/src/lib/utils/form-state.utils.ts","../../../projects/ngx-vest-forms/src/lib/utils/validation-config-builder.ts","../../../projects/ngx-vest-forms/src/lib/utils/array-to-object.ts","../../../projects/ngx-vest-forms/src/lib/utils/field-clearing.ts","../../../projects/ngx-vest-forms/src/public-api.ts","../../../projects/ngx-vest-forms/src/ngx-vest-forms.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport {\n NgxWarningDisplayMode,\n ScErrorDisplayMode,\n} from './form-error-display.directive';\n\n/**\n * @deprecated Use NGX_ERROR_DISPLAY_MODE_TOKEN instead\n */\nexport const SC_ERROR_DISPLAY_MODE_TOKEN =\n new InjectionToken<ScErrorDisplayMode>('SC_ERROR_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-blur-or-submit',\n });\n\n/**\n * Injection token for configuring the default error display mode.\n * Values:\n * - 'on-blur': Show errors after field is touched/blurred\n * - 'on-submit': Show errors after form submission\n * - 'on-blur-or-submit': Show errors after blur or form submission (default)\n * - 'on-dirty': Show errors as soon as the field value changes\n * - 'always': Show errors immediately, even on pristine fields\n */\nexport const NGX_ERROR_DISPLAY_MODE_TOKEN =\n new InjectionToken<ScErrorDisplayMode>('NGX_ERROR_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-blur-or-submit',\n });\n\n/**\n * Injection token for configuring the default warning display mode.\n * Values:\n * - 'on-touch': Show warnings after field is touched/blurred\n * - 'on-validated-or-touch': Show warnings after validation runs or field is touched (default)\n * - 'on-dirty': Show warnings as soon as the field value changes\n * - 'always': Show warnings immediately, even on pristine fields\n */\nexport const NGX_WARNING_DISPLAY_MODE_TOKEN =\n new InjectionToken<NgxWarningDisplayMode>('NGX_WARNING_DISPLAY_MODE_TOKEN', {\n providedIn: 'root',\n factory: () => 'on-validated-or-touch',\n });\n","export const NGX_VEST_FORMS_ERRORS = {\n EXTRA_PROPERTY: {\n code: 'NGX-001',\n message: (path: string) =>\n `Shape mismatch: Property '${path}' is present in the form value but not defined in the form shape.`,\n },\n TYPE_MISMATCH: {\n code: 'NGX-002',\n message: (path: string, expected: string, actual: string) =>\n `Type mismatch at '${path}': Expected '${expected}' but got '${actual}'.`,\n },\n CONTROL_NOT_FOUND: {\n code: 'NGX-003',\n message: (path: string) =>\n `Control not found: Could not find form control at path '${path}'. Check your [ngModel] name attributes.`,\n },\n} as const;\n\nexport function logWarning<T extends unknown[]>(\n error: { code: string; message: (...args: T) => string },\n ...args: T\n): void {\n console.warn(\n `[${error.code}] ${error.message(...args)}\\nCheck your [formShape] input and the initial [formValue].`\n );\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Injection token for configurable validation config debounce timing.\n *\n * This token allows you to configure the debounce time for validation config\n * dependencies at the application, route, or component level.\n *\n * @example\n * ```typescript\n * /// Global configuration\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 200\n * }\n * ]\n * };\n *\n * /// Per-route configuration\n * {\n * path: 'checkout',\n * component: CheckoutComponent,\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 50\n * }\n * ]\n * }\n *\n * /// Per-component override\n * @Component({\n * providers: [\n * {\n * provide: NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN,\n * useValue: 0 // for testing\n * }\n * ]\n * })\n * export class TestFormComponent {}\n * ```\n *\n * @default 100ms - Maintains backward compatibility with existing behavior\n */\nexport const NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN = new InjectionToken<number>(\n 'NgxValidationConfigDebounceTime',\n {\n providedIn: 'root',\n factory: () => 100,\n }\n);\n","/**\n * Type guard to check if a value is a primitive type.\n *\n * @param value - The value to check\n * @returns true if the value is a primitive (string, number, boolean, null, undefined, symbol, bigint)\n */\nexport function isPrimitive(\n value: unknown\n): value is string | number | boolean | null | undefined | symbol | bigint {\n return (\n value === null || (typeof value !== 'object' && typeof value !== 'function')\n );\n}\n\ntype VisitedPairs = WeakMap<object, WeakSet<object>>;\n\n/**\n * Records that we've started comparing the pair (a, b). Re-entering the same\n * pair during recursion (cycle, or repeated DAG path) short-circuits to `true`\n * — correct because if the prior descent had returned `false`, the outer call\n * would already have short-circuited before we reach the second visit.\n */\nfunction rememberPair(seen: VisitedPairs, a: object, b: object): void {\n let targets = seen.get(a);\n if (!targets) {\n targets = new WeakSet<object>();\n seen.set(a, targets);\n }\n targets.add(b);\n}\n\n/**\n * @internal\n * Internal utility for shallow equality checks.\n *\n * **Not intended for external use.** This function is used internally by the library\n * for performance-critical operations. Consider using your own comparison logic or\n * a library like lodash if you need shallow equality checks in your application.\n *\n * Optimized shallow equality check for objects.\n *\n * **Why this custom implementation is preferred:**\n * - **Performance**: Direct property comparison is significantly faster than JSON.stringify\n * - **Type Safety**: Handles null/undefined values correctly without serialization issues\n * - **Accuracy**: Doesn't suffer from JSON.stringify limitations (undefined values, functions, symbols)\n * - **Memory Efficient**: No temporary string creation or object serialization overhead\n *\n * **Use Cases:**\n * - Form value change detection where only top-level properties matter\n * - Quick object comparison in performance-critical code paths\n * - Validation triggers where deep comparison is unnecessary\n *\n * **Performance Comparison:**\n * ```typescript\n * /// ❌ Slow: JSON.stringify approach\n * JSON.stringify(obj1) === JSON.stringify(obj2)\n *\n * /// ✅ Fast: Direct property comparison\n * shallowEqual(obj1, obj2)\n * ```\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns true if objects are shallowly equal (same keys and same values by reference)\n */\nexport function shallowEqual(obj1: unknown, obj2: unknown): boolean {\n if (obj1 === obj2) {\n return true;\n }\n\n if (obj1 == null || obj2 == null) {\n return obj1 === obj2;\n }\n\n if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {\n return obj1 === obj2;\n }\n\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (\n !Object.hasOwn(obj2 as object, key) ||\n (obj1 as Record<string, unknown>)[key] !==\n (obj2 as Record<string, unknown>)[key]\n ) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * @internal\n * Internal utility for deep equality checks.\n *\n * **Not intended for external use.** This function is used internally by the library\n * for form value comparison and change detection. Consider using your own comparison\n * logic or a library like lodash if you need deep equality checks in your application.\n *\n * Fast deep equality check optimized for form values and Angular applications.\n *\n * **Why this custom implementation is preferred over alternatives:**\n *\n * **vs JSON.stringify():**\n * - **10-100x faster**: Direct comparison without string serialization overhead\n * - **Accurate**: Handles Date objects, RegExp, undefined values, and functions correctly\n * - **Memory efficient**: No temporary string creation or garbage collection pressure\n * - **Preserves semantics**: Maintains type information during comparison\n *\n * **vs structuredClone():**\n * - **Wrong purpose**: structuredClone creates copies, not comparisons\n * - **Performance**: Would require cloning both objects just to compare them\n * - **Memory waste**: Creates unnecessary deep copies, doubling memory usage\n * - **Still incomplete**: Even after cloning, you'd still need a comparison function\n *\n * **vs External libraries (lodash.isEqual, etc.):**\n * - **Bundle size**: Zero dependencies, smaller application bundles\n * - **Form-specific**: Optimized for common Angular form data patterns\n * - **Type safety**: Full TypeScript integration with strict typing\n * - **Performance**: Tailored algorithms for form value comparison use cases\n *\n * **Supported Data Types:**\n * - Primitives (string, number, boolean, null, undefined, symbol, bigint)\n * - Arrays (with recursive deep comparison)\n * - Plain objects (with recursive deep comparison)\n * - Date objects (by timestamp comparison)\n * - RegExp objects (by source and flags comparison)\n * - Set objects (reference equality only)\n * - Map objects (reference equality only)\n * - Functions (reference equality only — distinct function instances are never equal,\n * even if their source code is identical)\n *\n * **Safety Features:**\n * - **Circular reference handling**: Tracks visited object pairs with `WeakMap<object, WeakSet<object>>`\n * - **Type coercion prevention**: Strict type checking before comparison\n * - **Null safety**: Proper handling of null and undefined values\n *\n * **Performance Characteristics:**\n * ```typescript\n * /// Performance comparison on typical form objects:\n * /// JSON.stringify: ~100ms for complex nested forms\n * /// fastDeepEqual: ~1-5ms for the same objects\n * ///\n * /// Memory usage:\n * /// JSON.stringify: Creates temporary strings (high GC pressure)\n * /// fastDeepEqual: One small WeakMap of visited object pairs is allocated lazily on\n * /// first nested-container descent; primitive-only comparisons allocate nothing.\n * ```\n *\n * **Typical Usage in Forms:**\n * ```typescript\n * /// Detect when form values actually change\n * distinctUntilChanged(fastDeepEqual)\n *\n * /// Prevent unnecessary re-renders\n * if (!fastDeepEqual(oldFormValue, newFormValue)) {\n * updateUI();\n * }\n * ```\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n *\n * Cyclic arrays and plain objects are compared structurally by tracking visited object\n * pairs. Distinct cyclic graphs with the same structure compare equal. `Date` and\n * `RegExp` values compare structurally. `Map` and `Set` values compare by reference\n * only, so distinct instances are considered different even if their contents match.\n *\n * @returns true if objects are deeply equal by value\n */\nexport function fastDeepEqual(obj1: unknown, obj2: unknown): boolean {\n return fastDeepEqualInternal(obj1, obj2, undefined);\n}\n\nfunction fastDeepEqualInternal(\n obj1: unknown,\n obj2: unknown,\n seen: VisitedPairs | undefined\n): boolean {\n // Object.is gives correct semantics for NaN and ±0 — important for numeric\n // form values where `fastDeepEqual(NaN, NaN)` should be true.\n if (Object.is(obj1, obj2)) {\n return true;\n }\n\n if (obj1 == null || obj2 == null) {\n return false;\n }\n\n if (typeof obj1 !== typeof obj2) {\n return false;\n }\n\n // Functions use reference-only equality. Object.is at the top already returned\n // true for identical references, so reaching here means the references differ.\n if (typeof obj1 === 'function') {\n return false;\n }\n\n if (isPrimitive(obj1) || isPrimitive(obj2)) {\n return false;\n }\n\n // Handle Date / RegExp first — they have value semantics and can't contain cycles,\n // so they don't need pair tracking.\n if (obj1 instanceof Date || obj2 instanceof Date) {\n return (\n obj1 instanceof Date &&\n obj2 instanceof Date &&\n obj1.getTime() === obj2.getTime()\n );\n }\n\n if (obj1 instanceof RegExp || obj2 instanceof RegExp) {\n return (\n obj1 instanceof RegExp &&\n obj2 instanceof RegExp &&\n obj1.source === obj2.source &&\n obj1.flags === obj2.flags\n );\n }\n\n // Intentional contract: distinct Set / Map instances compare by reference only.\n if (obj1 instanceof Set || obj2 instanceof Set) {\n return false;\n }\n if (obj1 instanceof Map || obj2 instanceof Map) {\n return false;\n }\n\n if (Array.isArray(obj1) !== Array.isArray(obj2)) {\n return false;\n }\n\n // Cycle / repeated-pair guard for traversable containers.\n // Allocates lazily on first nested-object descent.\n const a = obj1 as object;\n const b = obj2 as object;\n if (seen?.get(a)?.has(b)) {\n return true;\n }\n seen ??= new WeakMap<object, WeakSet<object>>();\n rememberPair(seen, a, b);\n\n if (Array.isArray(obj1)) {\n const arr2 = obj2 as unknown[];\n if (obj1.length !== arr2.length) {\n return false;\n }\n for (let i = 0; i < obj1.length; i++) {\n if (!fastDeepEqualInternal(obj1[i], arr2[i], seen)) {\n return false;\n }\n }\n return true;\n }\n\n // Plain objects\n const keys1 = Object.keys(a);\n const o2 = b as Record<string, unknown>;\n if (keys1.length !== Object.keys(o2).length) {\n return false;\n }\n for (const key of keys1) {\n if (!Object.hasOwn(o2, key)) {\n return false;\n }\n if (\n !fastDeepEqualInternal(\n (a as Record<string, unknown>)[key],\n o2[key],\n seen\n )\n ) {\n return false;\n }\n }\n return true;\n}\n","import { InjectionToken } from '@angular/core';\nimport { fastDeepEqual } from '../utils/equality';\n\n/**\n * Signature of a deep-equality comparator. Must return `true` iff `a` and `b`\n * are considered equal for the purpose of change detection.\n */\nexport type NgxEqualityFn = (a: unknown, b: unknown) => boolean;\n\n/**\n * Injection token for the deep-equality function used internally by\n * {@link FormDirective} for change detection — `formValueChange`\n * `distinctUntilChanged`, the form↔model two-way sync effect, and the\n * `formState` signal's structural comparator.\n *\n * The default factory returns {@link fastDeepEqual}. Override this token to\n * plug in a smaller or differently-tuned comparator (e.g. `dequal/lite`,\n * `lodash.isEqual`) without forking the directive.\n *\n * @example Bring-your-own equality at the application level\n * ```ts\n * import { dequal } from 'dequal/lite';\n * import { NGX_EQUALITY_FN } from 'ngx-vest-forms';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * { provide: NGX_EQUALITY_FN, useValue: dequal },\n * ],\n * };\n * ```\n *\n * @example Per-component override (e.g. for tests)\n * ```ts\n * @Component({\n * providers: [\n * { provide: NGX_EQUALITY_FN, useValue: (a, b) => a === b },\n * ],\n * })\n * export class TestFormComponent {}\n * ```\n *\n * @default {@link fastDeepEqual}\n */\nexport const NGX_EQUALITY_FN = new InjectionToken<NgxEqualityFn>(\n 'NgxEqualityFn',\n {\n providedIn: 'root',\n factory: () => fastDeepEqual,\n }\n);\n","import { DestroyRef } from '@angular/core';\n\n/**\n * Schedules a callback to run after a delay, automatically cancelling it if the\n * provided `DestroyRef` fires before the timer expires.\n *\n * @param callback - Function to invoke after the delay.\n * @param delayMs - Delay in milliseconds (passed to `setTimeout`).\n * @param destroyRef - Angular `DestroyRef` to register auto-cancellation against.\n * @returns A cancel function; calling it before the timer fires prevents the\n * callback from running and unregisters the destroy listener.\n */\nexport function scheduleTimeout(\n callback: () => void,\n delayMs: number,\n destroyRef: DestroyRef\n): () => void {\n let cancelled = false;\n let unregisterCalled = false;\n // eslint-disable-next-line prefer-const -- assigned after onDestroy returns\n let unregisterDestroy: (() => void) | undefined;\n\n // Idempotent unregister wrapper so all paths (timer-fires, explicit-cancel,\n // and onDestroy) can call it safely without double-removal.\n const safeUnregister = () => {\n if (unregisterCalled) return;\n unregisterCalled = true;\n unregisterDestroy?.();\n };\n\n const handle = setTimeout(() => {\n safeUnregister();\n if (!cancelled) {\n callback();\n }\n }, delayMs);\n\n unregisterDestroy = destroyRef.onDestroy(() => {\n cancelled = true;\n clearTimeout(handle);\n safeUnregister();\n });\n\n return () => {\n if (!cancelled) {\n cancelled = true;\n clearTimeout(handle);\n safeUnregister();\n }\n };\n}\n\n/**\n * Schedules a microtask callback, automatically suppressing it if the provided\n * `DestroyRef` fires before the microtask runs.\n *\n * Since `queueMicrotask` has no native cancellation API, this relies on a\n * destroyed flag that is set inside the registered `onDestroy` hook.\n *\n * @param callback - Function to invoke in the next microtask checkpoint.\n * @param destroyRef - Angular `DestroyRef` to register auto-cancellation against.\n * @returns A cancel function; calling it before the microtask runs prevents the\n * callback from executing and unregisters the destroy listener.\n */\nexport function scheduleMicrotask(\n callback: () => void,\n destroyRef: DestroyRef\n): () => void {\n let cancelled = false;\n let unregisterCalled = false;\n\n // Register the onDestroy listener before queuing the microtask so that\n // `unregisterDestroy` is always defined when the microtask fires.\n const unregisterDestroy = destroyRef.onDestroy(() => {\n cancelled = true;\n safeUnregister();\n });\n\n // Idempotent unregister wrapper so all paths (microtask-fires, explicit-cancel,\n // and onDestroy) can call it safely without double-removal.\n function safeUnregister() {\n if (unregisterCalled) return;\n unregisterCalled = true;\n unregisterDestroy();\n }\n\n queueMicrotask(() => {\n // Always clean up the destroy listener when the microtask fires,\n // regardless of whether the callback is suppressed.\n safeUnregister();\n if (!cancelled) {\n callback();\n }\n });\n\n return () => {\n if (!cancelled) {\n cancelled = true;\n safeUnregister();\n }\n };\n}\n","/**\n * Utilities for working with field paths in dot/bracket notation and Standard Schema path arrays.\n *\n * These utilities help convert between:\n * - **Dot/bracket notation**: `'addresses[0].street'` (used in Angular forms and Vest)\n * - **Standard Schema paths**: `['addresses', 0, 'street']` (used in schema validation)\n *\n * @example\n * ```typescript\n * // Parse string path to array\n * parseFieldPath('user.addresses[0].street')\n * // Returns: ['user', 'addresses', 0, 'street']\n *\n * // Stringify array path to string\n * stringifyFieldPath(['user', 'addresses', 0, 'street'])\n * // Returns: 'user.addresses[0].street'\n * ```\n */\n\nconst UNSAFE_PATH_SEGMENTS = new Set(['__proto__', 'prototype', 'constructor']);\nconst LOG_PREFIX = '[ngx-vest-forms] field-path.utils';\n\n/**\n * @internal\n * Returns whether a path segment is unsafe for object writes/merges.\n *\n * Unsafe segments are blocked to prevent prototype pollution vectors.\n */\nexport function isUnsafePathSegment(segment: string | number): boolean {\n return typeof segment === 'string' && UNSAFE_PATH_SEGMENTS.has(segment);\n}\n\n/**\n * @internal\n * Internal utility for parsing field path strings.\n *\n * **Not intended for external use.** While this function can parse field paths,\n * it's primarily used internally. Most users won't need to parse field paths manually.\n * If you do need this functionality, consider using your own implementation tailored\n * to your specific needs.\n *\n * Converts a dot/bracket notation path (e.g. `'addresses[0].street'`)\n * to a Standard Schema path array (e.g. `['addresses', 0, 'street']`).\n *\n * **Use cases:**\n * - Converting Angular form paths to schema-compatible arrays\n * - Parsing Vest field names for array access\n * - Processing validation error paths from different sources\n *\n * **Supported formats:**\n * - Dot notation: `'user.name'` → `['user', 'name']`\n * - Bracket notation: `'addresses[0]'` → `['addresses', 0]`\n * - Mixed: `'user.addresses[0].street'` → `['user', 'addresses', 0, 'street']`\n *\n * @param path - The dot/bracket notation path string\n * @returns Array of path segments (strings for properties, numbers for array indices)\n *\n * @example\n * ```typescript\n * parseFieldPath('email') // ['email']\n * parseFieldPath('user.profile.name') // ['user', 'profile', 'name']\n * parseFieldPath('items[0]') // ['items', 0]\n * parseFieldPath('users[0].addresses[1].street')\n * // ['users', 0, 'addresses', 1, 'street']\n * ```\n */\nexport function parseFieldPath(path: string): Array<string | number> {\n if (!path) return [];\n\n // Normalize bracket notation to dot notation first so malformed inputs like\n // 'a.[0]' (which becomes 'a..0') are caught alongside 'a..b', '.a', 'a.', '.'.\n const startsWithBracket = path.startsWith('[');\n const segments = path\n .replaceAll(/\\[(\\d+)\\]/g, '.$1')\n .split('.');\n\n // Empty segments after normalization signal a malformed path. The single\n // legitimate case is a leading empty produced by a path that originally\n // started with '[' (e.g. '[0].x' → '.0.x' → ['', '0', 'x']).\n for (let i = 0; i < segments.length; i++) {\n if (segments[i] === '' && !(i === 0 && startsWithBracket)) {\n if (typeof ngDevMode !== 'undefined' && ngDevMode) {\n console.warn(\n `${LOG_PREFIX}: Invalid field path '${path}'. Leading dots, trailing dots, consecutive dots, and '.[' separators are not allowed.`\n );\n }\n return [];\n }\n }\n\n return segments\n .filter((part) => part !== '')\n .map((part) => (/^\\d+$/.test(part) ? Number(part) : part));\n}\n\n/**\n * Converts a Standard Schema path array (e.g. `['addresses', 0, 'street']`)\n * to a dot/bracket notation string (e.g. `'addresses[0].street'`).\n *\n * **Use cases:**\n * - Converting schema validation paths to Angular form field names\n * - Generating Vest field names from path arrays\n * - Creating human-readable field identifiers\n *\n * **Format rules:**\n * - String segments joined with dots: `['user', 'name']` → `'user.name'`\n * - Number segments use brackets: `['items', 0]` → `'items[0]'`\n * - Mixed paths combine both: `['users', 0, 'email']` → `'users[0].email'`\n *\n * @param path - Array of path segments (strings for properties, numbers for indices)\n * @returns Dot/bracket notation path string\n *\n * @example\n * ```typescript\n * stringifyFieldPath(['email']) // 'email'\n * stringifyFieldPath(['user', 'profile', 'name']) // 'user.profile.name'\n * stringifyFieldPath(['items', 0]) // 'items[0]'\n * stringifyFieldPath(['users', 0, 'addresses', 1, 'street'])\n * // 'users[0].addresses[1].street'\n * ```\n */\nexport function stringifyFieldPath(path: Array<string | number>): string {\n if (!path || path.length === 0) return '';\n\n let result = '';\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i];\n\n if (typeof segment === 'number') {\n // Array index - add as bracket notation\n result += `[${segment}]`;\n } else {\n // Property name - add with dot prefix if not first segment\n if (i > 0) result += '.';\n result += segment;\n }\n }\n\n return result;\n}\n","export type NgxFirstInvalidOptions = {\n /** Scroll animation behavior (default: `'smooth'`, or `'auto'` when reduced motion is preferred). */\n behavior?: ScrollBehavior;\n /** Vertical alignment when scrolling (default: `'center'`). */\n block?: ScrollLogicalPosition;\n /** Horizontal alignment when scrolling (default: `'nearest'`). */\n inline?: ScrollLogicalPosition;\n /** Whether to focus after scrolling (default: `true`). */\n focus?: boolean;\n /** Passed to `focus()` when focusing (default: `true`). */\n preventScrollOnFocus?: boolean;\n /** Opens ancestor `<details>` elements before scroll/focus (default: `true`). */\n openCollapsedParents?: boolean;\n /** Selector used to locate the first invalid element. */\n invalidSelector?: string;\n /** Selector used to resolve the best focus target within the invalid element. */\n focusSelector?: string;\n};\n\nexport const DEFAULT_INVALID_SELECTOR = [\n '.ngx-control-wrapper--invalid',\n '.ngx-form-group-wrapper--invalid',\n 'input[aria-invalid=\"true\"]',\n 'textarea[aria-invalid=\"true\"]',\n 'select[aria-invalid=\"true\"]',\n].join(', ');\n\nexport const DEFAULT_FOCUS_SELECTOR = [\n 'input:not([type=\"hidden\"]):not([disabled])',\n 'textarea:not([disabled])',\n 'select:not([disabled])',\n 'button:not([disabled])',\n 'a[href]',\n '[tabindex]:not([tabindex=\"-1\"]):not([disabled])',\n].join(', ');\n\n/**\n * Focus candidates that are already invalid.\n * This ensures invalid group wrappers focus a failing control before any valid sibling.\n */\nconst INVALID_FOCUS_PREFERRED_SELECTOR = [\n 'input[aria-invalid=\"true\"]:not([type=\"hidden\"]):not([disabled])',\n 'textarea[aria-invalid=\"true\"]:not([disabled])',\n 'select[aria-invalid=\"true\"]:not([disabled])',\n '[aria-invalid=\"true\"][tabindex]:not([tabindex=\"-1\"]):not([disabled])',\n].join(', ');\n\nconst REDUCED_MOTION_MEDIA_QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof globalThis.matchMedia === 'function' &&\n globalThis.matchMedia(REDUCED_MOTION_MEDIA_QUERY).matches\n );\n}\n\nexport function resolveFirstInvalidScrollBehavior(\n behavior?: ScrollBehavior\n): ScrollBehavior {\n if (behavior !== undefined) {\n return behavior;\n }\n return prefersReducedMotion() ? 'auto' : 'smooth';\n}\n\nexport function resolveFirstInvalidElement(\n root: HTMLFormElement,\n invalidSelector: string\n): HTMLElement | null {\n try {\n const firstInvalid = root.querySelector(invalidSelector);\n return firstInvalid instanceof HTMLElement ? firstInvalid : null;\n } catch {\n return null;\n }\n}\n\nexport function openCollapsedDetailsAncestors(\n root: HTMLFormElement,\n element: HTMLElement\n): void {\n let current: HTMLElement = element;\n while (current !== root) {\n const parentElement = current.parentElement;\n if (!parentElement) {\n break;\n }\n\n if (parentElement instanceof HTMLDetailsElement) {\n parentElement.open = true;\n }\n\n current = parentElement;\n }\n}\n\nexport function resolveFirstInvalidFocusTarget(\n firstInvalid: HTMLElement,\n focusSelector: string\n): HTMLElement | null {\n const preferredInvalidTarget = firstInvalid.querySelector(\n INVALID_FOCUS_PREFERRED_SELECTOR\n );\n if (preferredInvalidTarget instanceof HTMLElement) {\n return preferredInvalidTarget;\n }\n\n try {\n if (firstInvalid.matches(focusSelector)) {\n return firstInvalid;\n }\n\n const fallbackTarget = firstInvalid.querySelector(focusSelector);\n return fallbackTarget instanceof HTMLElement ? fallbackTarget : null;\n } catch {\n return null;\n }\n}\n","export const ROOT_FORM = 'rootForm';\n","import {\n AbstractControl,\n FormArray,\n FormGroup,\n isFormArray,\n isFormGroup,\n ValidationErrors,\n} from '@angular/forms';\nimport { ROOT_FORM } from '../constants';\nimport {\n isUnsafePathSegment,\n parseFieldPath,\n stringifyFieldPath,\n} from './field-path.utils';\n\ntype UnknownRecord = Record<string, unknown>;\n\ntype ControlWithOptionalName = AbstractControl & {\n name?: unknown;\n};\n\ntype FormContainer = FormGroup | FormArray;\ntype ErrorList = string[] & { warnings?: string[] };\n\nconst ERROR_MESSAGES_KEY = 'errors';\nconst WARNING_MESSAGES_KEY = 'warnings';\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Recursively calculates the path of a form control\n * @param formGroup\n * @param control\n */\nfunction getChildEntries(\n container: FormContainer\n): Array<[string, AbstractControl]> {\n if (isFormArray(container)) {\n return container.controls.map((child, index) => [String(index), child]);\n }\n\n return Object.entries(container.controls);\n}\n\nfunction getControlPath(\n formGroup: FormGroup,\n control: AbstractControl\n): string {\n // First attempt: depth-first traversal from provided root\n for (const [key, child] of getChildEntries(formGroup)) {\n if (child === control) {\n return key;\n }\n if (isFormGroup(child) || isFormArray(child)) {\n const subPath = getControlPath(child as FormGroup, control);\n if (subPath) {\n return `${key}.${subPath}`;\n }\n }\n }\n\n // Fallback: walk up the parent chain from control to root\n let current: AbstractControl | null | undefined = control;\n const segments: string[] = [];\n while (current?.parent) {\n const parent: FormContainer = current.parent;\n for (const [key, controlInParent] of getChildEntries(parent)) {\n if (controlInParent === current) {\n segments.unshift(key);\n break;\n }\n }\n current = parent;\n if (current === formGroup) {\n return segments.join('.');\n }\n }\n\n // Last resort: try control.name if available\n const name = (control as ControlWithOptionalName).name;\n if (typeof name === 'string') {\n return name;\n }\n return '';\n}\n\n/**\n * Recursively calculates the path of a form group\n * @param formGroup\n * @param control\n */\nfunction getGroupPath(formGroup: FormGroup, control: AbstractControl): string {\n for (const [key, ctrl] of getChildEntries(formGroup)) {\n if (ctrl === control) {\n return key;\n }\n if (isFormGroup(ctrl)) {\n const path = getGroupPath(ctrl, control);\n if (path) {\n return `${key}.${path}`;\n }\n }\n }\n return '';\n}\n\n/**\n * @internal\n * Internal utility for calculating form control field paths.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to determine field names for validation. Use the `name` attribute on your form controls\n * instead of relying on this function.\n *\n * Calculates the field name of a form control: Eg: addresses.shippingAddress.street\n * @param rootForm\n * @param control\n */\nexport function getFormControlField(\n rootForm: FormGroup,\n control: AbstractControl\n): string {\n return getControlPath(rootForm, control);\n}\n\n/**\n * @internal\n * Internal utility for calculating form group field paths.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to determine field names for nested form groups.\n *\n * Calcuates the field name of a form group Eg: addresses.shippingAddress\n * @param rootForm\n * @param control\n */\nexport function getFormGroupField(\n rootForm: FormGroup,\n control: AbstractControl\n): string {\n return getGroupPath(rootForm, control);\n}\n\n/**\n * @internal\n * Internal utility for merging form values with disabled field values.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to include disabled field values in form submissions. Use Angular's `getRawValue()`\n * method on your form if you need to access disabled field values.\n *\n * This utility merges the value of the form with the raw value.\n * By doing this we can assure that we don't lose values of disabled form fields\n *\n * Security: Unsafe prototype-related keys (`__proto__`, `prototype`, `constructor`)\n * are skipped during recursive merge.\n * @param form\n */\nexport function mergeValuesAndRawValues<T>(form: FormGroup): T {\n // Deep clone both values to prevent reference sharing.\n // This is necessary because:\n // 1. form.value may contain object references that could be mutated elsewhere\n // 2. form.getRawValue() also returns references to form control values\n // 3. Without cloning, mutations to the returned object would affect the original form state\n // 4. The merge operation itself requires a mutable copy to work with\n // Performance note: For large forms, this may have performance implications. However,\n // reference isolation is critical for maintaining form state integrity.\n const value = structuredClone(form.value);\n const rawValue = structuredClone(form.getRawValue());\n\n // Recursive function to merge rawValue into value\n function mergeRecursive(target: UnknownRecord, source: UnknownRecord): void {\n for (const key of Object.keys(source)) {\n if (isUnsafePathSegment(key)) {\n continue;\n }\n\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (targetValue === undefined || targetValue === null) {\n // Key missing from target (e.g. disabled field) or set to null —\n // copy source so raw values from disabled controls aren't dropped.\n target[key] = sourceValue;\n } else if (isRecord(sourceValue) && isRecord(targetValue)) {\n // If the value is an object, merge it recursively\n mergeRecursive(targetValue, sourceValue);\n }\n // If the target already has the key with a primitive value, it's left as is to maintain references\n }\n }\n\n mergeRecursive(value as UnknownRecord, rawValue as UnknownRecord);\n return value;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\ntype Primitive = undefined | null | boolean | string | number | Function;\n\nfunction isPrimitive(value: unknown): value is Primitive {\n return (\n value === null || (typeof value !== 'object' && typeof value !== 'function')\n );\n}\n\nfunction getStringArrayError(\n errors: ValidationErrors | null,\n key: string\n): string[] | undefined {\n const value = errors?.[key];\n return Array.isArray(value)\n ? value.filter((v): v is string => typeof v === 'string')\n : undefined;\n}\n\n/**\n * Performs a deep-clone of an object.\n *\n * @deprecated Use the standard {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone structuredClone} instead.\n *\n * `structuredClone` correctly handles `Map`, `Set`, `RegExp`, typed arrays, and\n * cyclic references; this implementation silently drops `Map` / `Set` / `RegExp`\n * data and produces incorrect results on cycles. Scheduled for removal in a\n * future major; see `docs/prd/PRD-bug-sweep.md` (Bundle D) for tracking.\n *\n * Browser Support: `structuredClone` is available in all modern browsers\n * (Chrome 98+, Firefox 94+, Safari 15.4+, Edge 98+) and Node.js 17+.\n */\nlet cloneDeepDeprecationWarned = false;\n\nexport function cloneDeep<T>(object: T): T {\n // NOTE: `typeof ngDevMode !== 'undefined' && ngDevMode` is kept inline\n // (not extracted to a helper) because Angular's build optimizer relies on\n // this exact pattern for tree-shaking dev-only code from production bundles.\n if (\n !cloneDeepDeprecationWarned &&\n typeof ngDevMode !== 'undefined' &&\n ngDevMode\n ) {\n cloneDeepDeprecationWarned = true;\n console.warn(\n '[ngx-vest-forms] cloneDeep is deprecated and silently drops Map/Set/RegExp values. ' +\n 'Use the standard structuredClone() instead.'\n );\n }\n\n // Handle primitives (null, undefined, boolean, string, number, function)\n if (isPrimitive(object)) {\n return object;\n }\n\n // Handle Date\n if (object instanceof Date) {\n return new Date(object) as T;\n }\n\n // Handle Array\n if (Array.isArray(object)) {\n return object.map((item) => cloneDeep(item)) as T;\n }\n\n // Handle Object\n if (object instanceof Object) {\n const clonedObject: UnknownRecord = {};\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n clonedObject[key] = cloneDeep(\n (object as UnknownRecord)[key] as unknown\n );\n }\n }\n return clonedObject as T;\n }\n\n throw new Error(\"Unable to copy object! Its type isn't supported.\");\n}\n\n/**\n * Sets a value in an object at the provided field path.\n *\n * Supports dot and bracket notation via `parseFieldPath()`.\n * Examples: `user.profile.name`, `addresses[0].street`.\n *\n * Security: If any path segment matches an unsafe prototype-related key\n * (`__proto__`, `prototype`, `constructor`), the write is ignored.\n *\n * @param obj - Target object to mutate.\n * @param path - Dot/bracket field path.\n * @param value - Value to assign at the resolved path.\n */\nexport function setValueAtPath(\n obj: object,\n path: string,\n value: unknown\n): void {\n const keys = parseFieldPath(path);\n if (keys.length === 0) {\n return;\n }\n\n let current: UnknownRecord = obj as UnknownRecord;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const segment = keys[i];\n const nextSegment = keys[i + 1];\n if (segment === undefined) {\n continue;\n }\n if (isUnsafePathSegment(segment)) {\n return;\n }\n\n const key = String(segment);\n\n const next = current[key];\n if (!Array.isArray(next) && !isRecord(next)) {\n const shouldCreateArray =\n typeof nextSegment === 'number' ||\n (typeof nextSegment === 'string' && /^\\d+$/.test(nextSegment));\n current[key] = shouldCreateArray ? [] : {};\n }\n current = current[key] as UnknownRecord;\n }\n\n const lastSegment = keys[keys.length - 1];\n if (lastSegment === undefined || isUnsafePathSegment(lastSegment)) {\n return;\n }\n\n current[String(lastSegment)] = value;\n}\n\n/**\n * @deprecated Use {@link setValueAtPath} instead\n */\nexport function set(obj: object, path: string, value: unknown): void {\n return setValueAtPath(obj, path, value);\n}\n\n/**\n * @internal\n * Internal utility for collecting all form errors by field path.\n *\n * **Not intended for external use.** This function is used internally by the library\n * to generate the form state. Use the `formState()` signal from the `scVestForm` directive\n * to access form errors in your components.\n *\n * Traverses the form and returns the errors by path\n * @param form\n */\nexport function getAllFormErrors(\n form?: AbstractControl\n): Record<string, string[]> {\n const errors: Record<string, ErrorList> = {};\n if (!form) {\n return errors;\n }\n\n // Collect root form errors (from ValidateRootFormDirective) before processing children\n if (form.enabled) {\n const rootErrors = getStringArrayError(form.errors, ERROR_MESSAGES_KEY);\n if (rootErrors) {\n errors[ROOT_FORM] = rootErrors;\n }\n }\n\n function collect(\n control: AbstractControl,\n pathParts: Array<string | number>\n ): void {\n const pathString = stringifyFieldPath(pathParts);\n\n // Skip processing the root form control directly in NgxFormDirective\n if (pathParts.length === 0 && control === form) {\n // Instead, iterate its children if it's a group/array\n if (isFormGroup(control) || isFormArray(control)) {\n for (const [key, childControl] of getChildEntries(control)) {\n const numericKey = Number(key);\n const nextPath = [\n // ...pathParts, // pathParts is empty here\n Number.isNaN(numericKey) ? key : numericKey,\n ];\n collect(childControl, nextPath);\n }\n }\n return; // Stop processing for the root form itself at this level\n }\n\n if (isFormGroup(control) || isFormArray(control)) {\n for (const [key, childControl] of getChildEntries(control)) {\n const numericKey = Number(key);\n const nextPath = [\n ...pathParts,\n Number.isNaN(numericKey) ? key : numericKey,\n ];\n collect(childControl, nextPath);\n }\n }\n\n // Attach control errors (both errors and warnings)\n if (control.enabled) {\n const fieldErrors = getStringArrayError(\n control.errors,\n ERROR_MESSAGES_KEY\n );\n if (fieldErrors) {\n errors[pathString] = fieldErrors;\n }\n // Optionally, add warnings if present\n const fieldWarnings = getStringArrayError(\n control.errors,\n WARNING_MESSAGES_KEY\n );\n if (fieldWarnings) {\n // Attach warnings as a property on the error array (non-enumerable)\n // This is still done here for field-specific warnings, but not for root warnings.\n if (!errors[pathString]) {\n errors[pathString] = []; // Ensure array exists if only warnings are present\n }\n Object.defineProperty(errors[pathString], 'warnings', {\n value: fieldWarnings,\n enumerable: false, // Keep it non-enumerable as per previous behavior for field warnings\n configurable: true,\n writable: true,\n });\n }\n }\n }\n\n collect(form, []);\n\n // Root form errors (form.errors) are no longer processed here.\n // They are handled directly in NgxFormDirective to populate formState.root.\n\n return errors;\n}\n","import { isDevMode } from '@angular/core';\nimport { NGX_VEST_FORMS_ERRORS, logWarning } from '../errors/error-catalog';\n\nconst NUMERIC_PATH_SEGMENT = /^\\d+$/;\ntype TraversableShapeValue = Record<string, unknown> | unknown[];\n\nfunction isOpaqueLeafValue(value: unknown): boolean {\n return (\n value instanceof Date ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof RegExp ||\n (typeof File !== 'undefined' && value instanceof File) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n );\n}\n\nfunction isTraversableValue(value: unknown): value is TraversableShapeValue {\n return typeof value === 'object' && value !== null && !isOpaqueLeafValue(value);\n}\n\n/**\n * Validates a form value against a shape to catch typos in `name` or `ngModelGroup` attributes.\n *\n * **What it checks:**\n * - Extra properties: Keys in formValue that don't exist in shape (likely typos)\n * - Type mismatches: When formValue has an object but shape expects a primitive\n *\n * **What it does NOT check:**\n * - Missing properties: Keys in shape that don't exist in formValue\n * (forms build incrementally with `NgxDeepPartial`, and `@if` conditionally renders fields)\n *\n * Only runs in development mode.\n *\n * @param formVal - The current form value\n * @param shape - The expected shape (created with `NgxDeepRequired<T>`)\n */\nexport function validateShape<\n T extends Record<string, unknown>,\n U extends Record<string, unknown>,\n>(formVal: T, shape: U): void {\n if (isDevMode()) {\n validateFormValueAgainstShape(formVal, shape);\n }\n}\n\n/**\n * Recursively validates form value keys against the shape.\n * Reports warnings for extra properties and type mismatches.\n */\nfunction validateFormValueAgainstShape(\n formValue: Record<string, unknown>,\n shape: Record<string, unknown>,\n path = ''\n): void {\n for (const key of Object.keys(formValue)) {\n const value = formValue[key];\n const fieldPath = path ? `${path}.${key}` : key;\n\n // Skip null/undefined values (valid during form initialization)\n if (value == null) {\n continue;\n }\n\n // For array items (numeric keys > 0), compare against the first item in shape\n // since we only define one example item in the shape for arrays\n const isNumericKey = NUMERIC_PATH_SEGMENT.test(key);\n // Array shapes provide one example item at index 0, so every numeric key maps to '0'.\n const shapeKey = isNumericKey && key !== '0' ? '0' : key;\n const shapeValue = shape?.[shapeKey];\n const hasShapeKey = shape != null && shapeKey in shape;\n\n // Skip Date fields receiving empty strings (common in date picker libraries)\n if (shapeValue instanceof Date && value === '') {\n continue;\n }\n\n // Handle object values (recurse into nested objects)\n if (typeof value === 'object') {\n if (!isTraversableValue(value)) {\n if (!isNumericKey && !hasShapeKey) {\n logWarning(NGX_VEST_FORMS_ERRORS.EXTRA_PROPERTY, fieldPath);\n } else if (\n !isNumericKey &&\n hasShapeKey &&\n (shapeValue === null || typeof shapeValue !== 'object')\n ) {\n // Type mismatch: formValue holds an opaque object (Date, Map, etc.)\n // but shape declares a primitive. Recursion is intentionally skipped\n // for opaque leaves, but the user still benefits from a warning.\n logWarning(\n NGX_VEST_FORMS_ERRORS.TYPE_MISMATCH,\n fieldPath,\n 'primitive',\n 'object'\n );\n }\n continue;\n }\n\n // Type mismatch: formValue has object, but shape expects primitive\n if (!isNumericKey && !isTraversableValue(shapeValue)) {\n logWarning(\n NGX_VEST_FORMS_ERRORS.TYPE_MISMATCH,\n fieldPath,\n 'primitive',\n 'object'\n );\n }\n\n // Recurse into nested object\n validateFormValueAgainstShape(\n value as Record<string, unknown>,\n isTraversableValue(shapeValue) ? (shapeValue as Record<string, unknown>) : {},\n fieldPath\n );\n continue;\n }\n\n // Extra property: key exists in formValue but not in shape (likely a typo)\n if (!isNumericKey && !hasShapeKey) {\n logWarning(NGX_VEST_FORMS_ERRORS.EXTRA_PROPERTY, fieldPath);\n }\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport { NgForm } from '@angular/forms';\n\nconst formSubmittedSignals = new WeakMap<NgForm, WritableSignal<boolean>>();\n\ntype AngularSubmittedSignalHost = {\n submittedReactive?: WritableSignal<boolean>;\n _submittedReactive?: WritableSignal<boolean>;\n};\n\nexport function getFormSubmittedSignal(\n ngForm: NgForm\n): WritableSignal<boolean> {\n let submitted = formSubmittedSignals.get(ngForm);\n if (!submitted) {\n submitted = signal(ngForm.submitted);\n formSubmittedSignals.set(ngForm, submitted);\n }\n return submitted;\n}\n\nexport function setAngularFormSubmittedState(\n ngForm: NgForm,\n submitted: boolean\n): void {\n // Angular 21.x's concrete NgForm stores submitted state on\n // `submittedReactive`, while AbstractFormDirective-backed implementations\n // expose `_submittedReactive` and may also provide a public setter on\n // `submitted`. This helper is verified against Angular 21.x in this\n // repository and falls back to the first writable `submitted` setter it can\n // find if a future Angular version changes the concrete field names.\n //\n // We try the concrete/internal signal first because NgForm overrides the\n // getter-only `submitted` property at runtime in this workspace. If neither\n // signal exists, fall back to the first writable `submitted` setter we can\n // find on the prototype chain. If no setter exists either, callers should\n // still update ngx-vest-forms' shared signal so error display state remains\n // reactive even though Angular's native submitted flag cannot be changed.\n const signalHost = ngForm as unknown as AngularSubmittedSignalHost;\n const angularSignal =\n signalHost.submittedReactive ?? signalHost._submittedReactive;\n\n if (angularSignal) {\n angularSignal.set(submitted);\n return;\n }\n\n let prototype: object | null = Object.getPrototypeOf(ngForm);\n while (prototype) {\n const submittedDescriptor = Object.getOwnPropertyDescriptor(\n prototype,\n 'submitted'\n );\n if (submittedDescriptor?.set) {\n submittedDescriptor.set.call(ngForm, submitted);\n return;\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n","import {\n ChangeDetectorRef,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n isDevMode,\n linkedSignal,\n output,\n signal,\n untracked,\n} from '@angular/core';\nimport {\n outputFromObservable,\n takeUntilDestroyed,\n toObservable,\n toSignal,\n} from '@angular/core/rxjs-interop';\nimport {\n AbstractControl,\n AsyncValidatorFn,\n ControlValueAccessor,\n FormArray,\n FormGroup,\n NgForm,\n NgModel,\n PristineChangeEvent,\n StatusChangeEvent,\n ValidationErrors,\n ValueChangeEvent,\n} from '@angular/forms';\nimport {\n catchError,\n debounceTime,\n distinctUntilChanged,\n EMPTY,\n filter,\n map,\n Observable,\n of,\n race,\n merge as rxMerge,\n scan,\n startWith,\n switchMap,\n take,\n tap,\n timer,\n} from 'rxjs';\nimport { logWarning, NGX_VEST_FORMS_ERRORS } from '../errors/error-catalog';\nimport { NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN } from '../tokens/debounce.token';\nimport { DeepRequired } from '../utils/deep-required';\nimport { NGX_EQUALITY_FN } from '../tokens/equality.token';\nimport {\n scheduleMicrotask,\n scheduleTimeout,\n} from '../utils/destroy-scheduler';\nimport type { ValidationConfigMap } from '../utils/field-path-types';\nimport { stringifyFieldPath } from '../utils/field-path.utils';\nimport {\n DEFAULT_FOCUS_SELECTOR,\n DEFAULT_INVALID_SELECTOR,\n type NgxFirstInvalidOptions,\n openCollapsedDetailsAncestors,\n resolveFirstInvalidElement,\n resolveFirstInvalidFocusTarget,\n resolveFirstInvalidScrollBehavior,\n} from '../utils/first-invalid.utils';\nimport { NgxFormState } from '../utils/form-state.utils';\nimport {\n getAllFormErrors,\n mergeValuesAndRawValues,\n setValueAtPath,\n} from '../utils/form-utils';\nimport { validateShape } from '../utils/shape-validation';\nimport { NgxTypedVestSuite, NgxVestSuite } from '../utils/validation-suite';\nimport {\n getFormSubmittedSignal,\n setAngularFormSubmittedState,\n} from './form-submitted-state';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Duration (in milliseconds) to keep fields marked as \"in-progress\" after validation.\n * This prevents immediate re-triggering of bidirectional validations.\n * Increased from 100ms to 500ms to give validators enough time to complete and propagate.\n */\nconst VALIDATION_IN_PROGRESS_TIMEOUT_MS = 500;\n\n/**\n * Type for validation configuration that accepts both the typed and untyped versions.\n * This ensures backward compatibility while supporting the new typed API.\n */\nexport type NgxValidationConfig<T = unknown> =\n | Record<string, string[]>\n | ValidationConfigMap<T>\n | null;\n\n/**\n * Payload emitted when a named control inside the form loses focus.\n *\n * This is intentionally low-level so app code can build workflows such as\n * draft auto-save, analytics, or blur-driven side effects without the form\n * library taking ownership of persistence behavior.\n *\n * It is not intended as a blur-time workaround for dependent field validation;\n * for that pattern, prefer `validationConfig` plus each target field's own\n * `errorDisplayMode`.\n *\n * The emitted `field` is the full dotted control path (e.g.\n * `passwords.confirm`, `businessHours.values.0.from`) regardless of whether\n * the surrounding groups use static `ngModelGroup=\"key\"` or dynamic\n * `[ngModelGroup]=\"expr\"` bindings, because the path is read from the live\n * `NgModel` directive registered with the form.\n *\n * @publicApi\n */\nexport type NgxFieldBlurEvent<T = unknown> = {\n field: string;\n value: unknown;\n formValue: T | null;\n dirty: boolean;\n touched: boolean;\n valid: boolean;\n pending: boolean;\n};\n\n/**\n * Main form directive for ngx-vest-forms that bridges Angular template-driven forms with Vest.js validation.\n *\n * This directive provides:\n * - **Unidirectional data flow**: Use `[ngModel]` (not `[(ngModel)]`) with `(formValueChange)` for predictable state updates\n * - **Vest.js integration**: Automatic async validators from Vest suites with field-level optimization\n * - **Validation dependencies**: Configure cross-field validation triggers via `validationConfig`\n * - **Form state**: Access validity, errors, and values through the `formState` signal\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <form ngxVestForm [suite]=\"validationSuite\" (formValueChange)=\"formValue.set($event)\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </form>\n * ```\n *\n * ### With Validation Dependencies\n * ```html\n * <form ngxVestForm [suite]=\"suite\" [validationConfig]=\"validationConfig\">\n * <input name=\"password\" [ngModel]=\"formValue().password\" />\n * <input name=\"confirmPassword\" [ngModel]=\"formValue().confirmPassword\" />\n * </form>\n * ```\n * ```typescript\n * validationConfig = { 'password': ['confirmPassword'] };\n * ```\n *\n * ### Accessing Form State\n * ```typescript\n * vestForm = viewChild.required('vestForm', { read: FormDirective });\n * isValid = computed(() => this.vestForm().formState().valid);\n * ```\n *\n * @see {@link https://github.com/ngx-vest-forms/ngx-vest-forms} for full documentation\n * @publicApi\n */\n@Directive({\n selector: 'form[scVestForm], form[ngxVestForm]',\n exportAs: 'scVestForm, ngxVestForm',\n host: {\n '(focusout)': 'onFormFocusOut($event)',\n },\n})\nexport class FormDirective<T extends Record<string, unknown>> {\n readonly ngForm = inject(NgForm, { self: true });\n private readonly elementRef = inject(ElementRef<HTMLFormElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly configDebounceTime = inject(\n NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN\n );\n /**\n * Deep-equality comparator. Defaults to `fastDeepEqual`; can be overridden\n * application-wide or per-component via {@link NGX_EQUALITY_FN}.\n */\n readonly #equal = inject(NGX_EQUALITY_FN);\n\n /**\n * Public signal storing field warnings keyed by field path.\n * This allows warnings to be stored and displayed without affecting field validity.\n * Angular's control.errors !== null marks a field as invalid, so we store warnings\n * separately when they exist without errors.\n */\n readonly fieldWarnings = signal<Map<string, readonly string[]>>(new Map());\n\n /**\n * Set to true by the onDestroy hook. Used to guard async callbacks\n * (e.g. Vest `done()`) that cannot be cancelled via RxJS operators.\n */\n #destroyed = false;\n\n #lastSyncedFormValue: T | null = null;\n #lastSyncedModelValue: T | null = null;\n\n // Internal signal tracking changes that can affect the merged form snapshot.\n // ValueChangeEvent keeps the cache fresh for blur-driven consumers like\n // draft auto-save, even when a value update doesn't change form validity.\n readonly #formSnapshotTick = toSignal(\n this.ngForm.form.events.pipe(\n filter(\n (event) =>\n event instanceof ValueChangeEvent || event instanceof StatusChangeEvent\n ),\n scan((count) => count + 1, 0),\n startWith(0)\n ),\n { initialValue: 0 }\n );\n\n /**\n * LinkedSignal that computes form values from Angular form state.\n * This eliminates timing issues with the previous dual-effect pattern.\n */\n readonly #formValueSignal = linkedSignal(() => {\n // Track changes that affect the merged form snapshot.\n this.#formSnapshotTick();\n if (Object.keys(this.ngForm.form.controls).length === 0) {\n // No controls remain (e.g. dynamic group removal): expose `null` so\n // consumers don't see ghost data from a previous form shape.\n return null;\n }\n return mergeValuesAndRawValues<T>(this.ngForm.form);\n });\n\n /**\n * Track the Angular form status as a signal for advanced status flags\n */\n readonly #statusSignal = toSignal(\n this.ngForm.form.statusChanges.pipe(startWith(this.ngForm.form.status)),\n { initialValue: this.ngForm.form.status }\n );\n\n /**\n * Reactive counter incremented on any focusout within the form.\n * This guarantees recomputation for every blur/tab interaction,\n * even when the form's aggregate touched flag is already true.\n */\n readonly #blurTick = signal(0);\n\n /**\n * Computed signal that returns field paths for all touched (or submitted) leaf controls.\n * Updates reactively when controls are touched (blur) or when form status changes.\n *\n * This enables consumers to determine which fields the user has interacted with,\n * useful for filtering errors/warnings to match the form's visible validation state.\n *\n * @publicApi\n */\n readonly touchedFieldPaths = computed(() => {\n this.#blurTick();\n this.#statusSignal();\n return this.#collectTouchedPaths(this.ngForm.form, this.ngForm.submitted);\n });\n\n /**\n * Computed signal for form state with validity and errors.\n * Used by templates and tests as vestForm.formState().valid/errors\n *\n * Uses custom equality function to prevent unnecessary recalculations\n * when form status changes but actual values/errors remain the same.\n */\n readonly formState = computed<NgxFormState<T>>(\n () => {\n // Tie to validation feedback instead of aggregate status so errors update\n // even when the root form remains INVALID -> INVALID.\n this.#validationFeedbackTick();\n return {\n valid: this.ngForm.form.valid,\n errors: getAllFormErrors(this.ngForm.form),\n value: this.#formValueSignal(),\n };\n },\n {\n equal: (a, b) => {\n // Fast path: reference equality\n if (a === b) return true;\n // Null/undefined check\n if (!a || !b) return false;\n // Deep equality check for form state properties\n return (\n a.valid === b.valid &&\n this.#equal(a.errors, b.errors) &&\n this.#equal(a.value, b.value)\n );\n },\n }\n );\n\n /**\n * The value of the form, this is needed for the validation part.\n * Using input() here because two-way binding is provided via formValueChange output.\n * In the minimal core directive (form-core.directive.ts), this would be model() instead.\n */\n readonly formValue = input<T | null>(null);\n\n /**\n * Static vest suite that will be used to feed our angular validators.\n * Accepts both NgxVestSuite and NgxTypedVestSuite through compatible type signatures.\n * NgxTypedVestSuite<T> is assignable to NgxVestSuite<T> due to bivariance and\n * FormFieldName<T> (string literal union) being assignable to string.\n */\n readonly suite = input<NgxVestSuite<T> | NgxTypedVestSuite<T> | null>(null);\n\n /**\n * The shape of our form model. This is a deep required version of the form model\n * The goal is to add default values to the shape so when the template-driven form\n * contains values that shouldn't be there (typo's) that the developer gets run-time\n * errors in dev mode\n */\n readonly formShape = input<DeepRequired<T> | null>(null);\n\n /**\n * Updates the validation config which is a dynamic object that will be used to\n * trigger validations on the dependant fields\n * Eg: ```typescript\n * validationConfig = {\n * 'passwords.password': ['passwords.confirmPassword']\n * }\n * ```\n *\n * This will trigger the updateValueAndValidity on passwords.confirmPassword every time the passwords.password gets a new value\n *\n * @param v\n */\n readonly validationConfig: InputSignal<NgxValidationConfig<T>> =\n input<NgxValidationConfig<T>>(null);\n\n /**\n * Emits whenever validation feedback may have changed, even if the aggregate\n * root form status string stays the same.\n */\n private readonly validationFeedback$ = rxMerge(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v !== 'PENDING')\n ),\n this.ngForm.ngSubmit.pipe(\n switchMap(() => {\n if (this.ngForm.form.status === 'PENDING') {\n return this.ngForm.form.statusChanges.pipe(\n filter((status) => status !== 'PENDING'),\n take(1)\n );\n }\n\n return of(this.ngForm.form.status);\n })\n )\n );\n\n /**\n * Counter signal tied to validation feedback updates so `formState()` can\n * recompute whenever the underlying error set changes.\n */\n readonly #validationFeedbackTick = toSignal(\n this.validationFeedback$.pipe(\n scan((count) => count + 1, 0),\n startWith(0)\n ),\n { initialValue: 0 }\n );\n\n private readonly pending$ = this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v === 'PENDING'),\n distinctUntilChanged()\n );\n\n /**\n * Emits every time the form status changes in a state\n * that is not PENDING\n * We need this to assure that the form is in 'idle' state\n */\n readonly idle$ = this.ngForm.form.events.pipe(\n filter((v) => v instanceof StatusChangeEvent),\n map((v) => (v as StatusChangeEvent).status),\n filter((v) => v !== 'PENDING'),\n distinctUntilChanged()\n );\n\n /**\n * Triggered as soon as the form value changes\n * It also contains the disabled values (raw values)\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly formValueChange = outputFromObservable(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof ValueChangeEvent),\n map((v) => (v as ValueChangeEvent<unknown>).value),\n distinctUntilChanged((prev, curr) => {\n // Use efficient deep equality instead of JSON.stringify for better performance\n return this.#equal(prev, curr);\n }),\n map(() => mergeValuesAndRawValues<T>(this.ngForm.form)),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Emits an object with all the errors of the form\n * every time a form control or form groups changes its status to valid or invalid\n *\n * For submit events, waits for async validation (including ROOT_FORM) to complete\n * before emitting errors. This ensures ROOT_FORM errors are included in the output.\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly errorsChange = outputFromObservable(\n this.validationFeedback$.pipe(\n map(() => getAllFormErrors(this.ngForm.form)),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Triggered as soon as the form becomes dirty\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly dirtyChange = outputFromObservable(\n this.ngForm.form.events.pipe(\n filter((v) => v instanceof PristineChangeEvent),\n map((v) => !(v as PristineChangeEvent).pristine),\n startWith(this.ngForm.form.dirty),\n distinctUntilChanged(),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Fired when the status of the root form changes.\n */\n private readonly statusChanges$ = this.ngForm.form.statusChanges.pipe(\n startWith(this.ngForm.form.status),\n distinctUntilChanged()\n );\n\n /**\n * Triggered When the form becomes valid but waits until the form is idle\n *\n * Cleanup is handled automatically by the directive when it's destroyed.\n */\n readonly validChange = outputFromObservable(\n this.statusChanges$.pipe(\n filter((e) => e === 'VALID' || e === 'INVALID'),\n map((v) => v === 'VALID'),\n distinctUntilChanged(),\n takeUntilDestroyed(this.destroyRef)\n )\n );\n\n /**\n * Emits when a named control inside the form loses focus.\n *\n * Useful for application-level workflows such as draft auto-save on blur.\n */\n readonly fieldBlur = output<NgxFieldBlurEvent<T>>();\n\n /**\n * Track validation in progress to prevent circular triggering (Issue #19)\n */\n private readonly validationInProgress = new Set<string>();\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.#destroyed = true;\n this.fieldWarnings.set(new Map());\n });\n\n /**\n * Trigger shape validations if the form gets updated\n * This is how we can throw run-time errors\n */\n if (isDevMode()) {\n effect(() => {\n const v = this.formValue();\n if (v && this.formShape()) {\n validateShape(v, this.formShape() as DeepRequired<T>);\n }\n });\n }\n\n /**\n * Mark all the fields as touched when the form is submitted\n */\n this.ngForm.ngSubmit\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => {\n this.ngForm.form.markAllAsTouched();\n this.#blurTick.update((v) => v + 1);\n });\n\n /**\n * Single bidirectional synchronization effect using linkedSignal.\n * Uses proper deep comparison and change tracking for correct sync direction.\n * Note: formValue is read-only input(), so we emit changes via formValueChange output.\n */\n effect(() => {\n const formValue = this.#formValueSignal();\n const modelValue = this.formValue();\n\n // Skip if either is null\n if (!formValue && !modelValue) return;\n\n // Compute change flags first\n const formChanged = !this.#equal(formValue, this.#lastSyncedFormValue);\n const modelChanged = !this.#equal(\n modelValue,\n this.#lastSyncedModelValue\n );\n\n // Early return if nothing changed\n if (!formChanged && !modelChanged) {\n return;\n }\n\n if (formChanged && !modelChanged) {\n // Form was modified by user -> form wins\n // Note: We can't call this.formValue.set() since it's an input()\n // The formValueChange output will emit the new value\n // Use untracked() to avoid infinite loops - we're updating tracking state here\n untracked(() => {\n this.#lastSyncedFormValue = formValue;\n this.#lastSyncedModelValue = formValue;\n });\n } else if (modelChanged && !formChanged) {\n // Model was modified programmatically -> model wins\n // Use untracked() to avoid infinite loops - we're updating tracking state here\n untracked(() => {\n // Update form controls with new model values\n if (modelValue) {\n // IMPORTANT: Use root patchValue instead of per-key setValue.\n // - Supports nested objects (ngModelGroup) without throwing when partial objects are provided.\n // - patchValue ignores missing controls/keys, which is compatible with DeepPartial form models.\n // - emitEvent:false prevents feedback loops; validation still updates internally.\n this.ngForm.form.patchValue(modelValue, { emitEvent: false });\n }\n this.#lastSyncedFormValue = modelValue;\n this.#lastSyncedModelValue = modelValue;\n });\n } else if (formChanged && modelChanged) {\n // Both form and model changed simultaneously\n // Check if they changed to the same value (synchronized change) or different values (conflict)\n const valuesEqual = this.#equal(formValue, modelValue);\n\n if (valuesEqual) {\n // Both changed to the same value - this is a synchronized change, not a conflict\n // Just update tracking to acknowledge the change\n untracked(() => {\n this.#lastSyncedFormValue = formValue;\n this.#lastSyncedModelValue = formValue;\n });\n } else {\n // Both changed to different values - this is a true conflict\n // This is an edge case that should rarely happen in practice.\n // We intentionally do nothing here to avoid breaking the Angular event flow.\n // The form will continue with its current values, and validation will run normally.\n // The next change (either form or model) will trigger proper synchronization.\n }\n }\n });\n\n // Set up validation config reactively\n this.#setupValidationConfig();\n }\n\n /**\n * Manually trigger form validation update.\n *\n * This is useful when form structure changes but no control values change,\n * which means validation state might be stale. This method forces a re-evaluation\n * of all form validators and updates the form validity state.\n *\n * **IMPORTANT: This method validates ALL form fields by design.**\n * This is intentional for structure changes as conditional validators may now\n * apply to different fields, requiring a complete validation refresh.\n *\n * **CRITICAL: This method does NOT mark fields as touched or show errors.**\n * It only re-runs validation logic. To show all errors (e.g., on submit),\n * use `markAllAsTouched()` instead or in combination.\n *\n * **When to use each:**\n * - `triggerFormValidation()` - Re-run validation when structure changes\n * - `markAllAsTouched()` - Show all errors to user (e.g., on submit)\n * - Both together - Rare, only if structure changed AND you want to show errors\n *\n * **Note on form submission:**\n * When using the default error display mode (`on-blur-or-submit`), you typically\n * don't need to call this method on submit. The form directive automatically marks\n * all fields as touched on `ngSubmit`, and errors will display automatically.\n * Only use this method when form structure changes without value changes.\n *\n * **Use Cases:**\n * - Conditionally showing/hiding form controls based on other field values\n * - Adding or removing form controls dynamically\n * - Switching between different form layouts where validation requirements change\n * - Any scenario where form structure changes but no ValueChangeEvent is triggered\n *\n * **Example:**\n * When switching from a form with required input fields to one with only informational content,\n * the form should become valid, but this won't happen automatically\n * when no value changes occur (e.g., switching from input fields to informational content).\n *\n * **Performance Note:**\n * This method calls `updateValueAndValidity({ emitEvent: true })` on the root form,\n * which validates all form controls. For large forms, consider if more granular\n * validation updates are possible.\n *\n * @example\n * ```typescript\n * /// After changing form structure\n * onProcedureTypeChange(newType: string) {\n * this.procedureType.set(newType);\n * /// Structure changed but no control values changed\n * this.formDirective.triggerFormValidation();\n * }\n *\n * /// For submit with multiple forms (show all errors)\n * submitAll() {\n * // Mark all as touched to show errors\n * this.form1Ref().markAllAsTouched();\n * this.form2Ref().markAllAsTouched();\n * // Only needed if structure changed without value changes\n * // this.form1Ref().triggerFormValidation();\n * // this.form2Ref().triggerFormValidation();\n * }\n * ```\n */\n triggerFormValidation(path?: string): void {\n if (path) {\n const control = this.ngForm.form.get(path);\n if (control) {\n control.updateValueAndValidity({ emitEvent: true });\n } else if (isDevMode()) {\n logWarning(NGX_VEST_FORMS_ERRORS.CONTROL_NOT_FOUND, path);\n }\n } else {\n // Update all form controls validity which will trigger all form events\n this.ngForm.form.updateValueAndValidity({ emitEvent: true });\n }\n }\n\n /**\n * Convenience method to mark all form controls as touched.\n *\n * This is useful for showing all validation errors at once, typically when\n * the user clicks a submit button. When a field is marked as touched,\n * the error display logic (based on `errorDisplayMode`) will show its errors.\n *\n * **Note on automatic behavior:**\n * When using the default error display mode (`on-blur-or-submit`), you typically\n * don't need to call this method manually for regular form submissions. The form\n * directive automatically marks all fields as touched on `ngSubmit`, so errors\n * will display automatically when the user submits the form.\n *\n * **When to use this method:**\n * - Multiple forms with a single submit button (forms without their own submit)\n * - Programmatic form submission without triggering `ngSubmit`\n * - Custom validation flows outside the normal submit process\n *\n * **Note:** This method only marks fields as touched—it does NOT re-run validation.\n * If you also need to re-run validation (e.g., after structure changes), call\n * `triggerFormValidation()` as well.\n *\n * @example\n * ```typescript\n * /// Standard form submission - NO need to call markAllAsTouched()\n * /// The directive handles this automatically on ngSubmit\n * <form ngxVestForm (ngSubmit)=\"save()\">\n * <button type=\"submit\">Submit</button>\n * </form>\n *\n * /// Multiple forms with one submit button\n * submitAll() {\n * this.form1().markAllAsTouched();\n * this.form2().markAllAsTouched();\n * if (this.form1().formState().valid && this.form2().formState().valid) {\n * /// Submit all forms\n * }\n * }\n * ```\n */\n markAllAsTouched(): void {\n this.ngForm.form.markAllAsTouched();\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Clears the current submit cycle without resetting control values or metadata.\n *\n * Unlike {@link resetForm}, this only flips the submitted gate back to `false`.\n * Touched/dirty/pristine state is preserved so consumers can end `'on-submit'`\n * error visibility without a full form reset.\n *\n * **When to use:**\n * - You use submit-gated error visibility such as `'on-submit'`\n * - A submit attempt already happened\n * - The user resolved the current submit-time errors\n * - You want future untouched fields to wait for the next submit before showing errors\n *\n * **Why this exists:**\n * `resetForm()` would also clear touched/dirty/pristine metadata, which is often\n * too disruptive for long-form, multi-form, or mixed error-display flows.\n *\n * **What it does NOT do:**\n * - Does not change field values\n * - Does not mark controls pristine or untouched\n * - Does not re-run validation\n *\n * @example\n * ```typescript\n * submitAll(): void {\n * for (const form of this.submitForms()) {\n * form.ngForm.onSubmit(new Event('submit'));\n * }\n *\n * if (this.submitForms().every((form) => form.formState().valid)) {\n * for (const form of this.submitForms()) {\n * form.clearSubmittedState();\n * }\n * }\n * }\n * ```\n *\n * @see {@link resetForm} to fully reset values and control metadata\n * @see {@link markAllAsTouched} to manually show all errors\n * @see {@link triggerFormValidation} to re-run validation after structure changes\n */\n clearSubmittedState(): void {\n setAngularFormSubmittedState(this.ngForm, false);\n getFormSubmittedSignal(this.ngForm).set(false);\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Finds the first invalid element in this form, scrolls it into view, and focuses it.\n *\n * Useful in custom submit flows where `markAllAsTouched()` is triggered externally\n * and the app then wants to guide keyboard and assistive-technology users to the\n * first failing field.\n *\n * @returns The focused element when a focusable target exists, otherwise the first\n * matched invalid element. Returns `null` when no invalid element is found.\n */\n focusFirstInvalidControl(\n options: NgxFirstInvalidOptions = {}\n ): HTMLElement | null {\n const {\n block = 'center',\n inline = 'nearest',\n focus = true,\n preventScrollOnFocus = true,\n openCollapsedParents = true,\n invalidSelector = DEFAULT_INVALID_SELECTOR,\n focusSelector = DEFAULT_FOCUS_SELECTOR,\n } = options;\n const behavior = resolveFirstInvalidScrollBehavior(options.behavior);\n\n const root: HTMLFormElement = this.elementRef.nativeElement;\n const firstInvalid = resolveFirstInvalidElement(root, invalidSelector);\n if (!firstInvalid) {\n return null;\n }\n\n if (openCollapsedParents) {\n openCollapsedDetailsAncestors(root, firstInvalid);\n }\n\n const focusTarget = resolveFirstInvalidFocusTarget(\n firstInvalid,\n focusSelector\n );\n\n const scrollTarget = focusTarget ?? firstInvalid;\n scrollTarget.scrollIntoView({ behavior, block, inline });\n\n if (focus && focusTarget) {\n focusTarget.focus({ preventScroll: preventScrollOnFocus });\n }\n\n return focusTarget ?? firstInvalid;\n }\n\n /**\n * Finds and scrolls the first invalid element into view without moving focus.\n *\n * @returns The resolved element, or `null` when no invalid element is found.\n */\n scrollToFirstInvalidControl(\n options: NgxFirstInvalidOptions = {}\n ): HTMLElement | null {\n return this.focusFirstInvalidControl({\n ...options,\n focus: false,\n });\n }\n\n /**\n * Host handler: called whenever any descendant field loses focus.\n * Used to make touched-path tracking react immediately on blur/tab.\n */\n onFormFocusOut(event: FocusEvent): void {\n // Run on the next microtask to ensure Angular has already applied\n // control.touched changes for the field that just blurred.\n scheduleMicrotask(() => {\n this.#blurTick.update((v) => v + 1);\n this.#emitFieldBlurEvent(event);\n }, this.destroyRef);\n }\n\n #emitFieldBlurEvent(event: FocusEvent): void {\n const resolved = this.#resolveFieldFromFocusEvent(event);\n if (!resolved) {\n return;\n }\n const { field, control, element } = resolved;\n\n // Read the latest value directly from the DOM element when it can be\n // trusted. For radio groups Angular keeps the bound `control.value` in\n // sync with the *selected* option, while a focused-but-unchecked radio\n // would expose its own option value via the DOM — so radios must always\n // fall back to `control.value`. For text/textarea/select we prefer the\n // element value to avoid `ngModelOptions.updateOn: 'submit'` staleness.\n const domValue = readElementValueForBlur(element);\n const value = domValue !== undefined ? domValue : control.value;\n\n // Prefer the cached linked-signal snapshot when it exists. Both code\n // paths produce a deep-cloned snapshot, but reusing the cached value\n // saves one of the two `structuredClone` passes performed by\n // `mergeValuesAndRawValues()` on every blur.\n const cachedSnapshot = this.#formValueSignal();\n const formValue =\n cachedSnapshot !== null\n ? (structuredClone(cachedSnapshot) as T)\n : mergeValuesAndRawValues<T>(this.ngForm.form);\n setValueAtPath(formValue as object, field, value);\n\n this.fieldBlur.emit({\n field,\n value,\n formValue,\n dirty: control.dirty,\n touched: control.touched,\n valid: control.valid,\n pending: control.pending,\n });\n }\n\n #resolveFieldFromFocusEvent(event: FocusEvent): {\n field: string;\n control: AbstractControl;\n element: HTMLElement;\n } | null {\n const target = event.target;\n if (!(target instanceof Element)) {\n return null;\n }\n\n const fieldElement = target.closest('[name]');\n if (!(fieldElement instanceof HTMLElement)) {\n return null;\n }\n\n const name = fieldElement.getAttribute('name')?.trim();\n if (!name) {\n return null;\n }\n\n const formEl = this.elementRef.nativeElement;\n\n // Authoritative path: ask the registered NgModel directive whose value\n // accessor is bound to this exact element. This handles all forms of\n // grouping uniformly — static `ngModelGroup=\"key\"`, dynamic\n // `[ngModelGroup]=\"expr\"`, repeated leaf names across siblings — because\n // the directive's `path` is computed from the live ControlContainer tree.\n const directiveMatch = resolveControlPathByNgModelDirective(\n this.ngForm,\n fieldElement\n );\n if (directiveMatch) {\n return {\n field: directiveMatch.path,\n control: directiveMatch.control,\n element: fieldElement,\n };\n }\n\n // Fallback: walk DOM ancestors collecting any `ngModelGroup` attribute\n // values, producing the canonical dotted path for the static attribute\n // form (e.g. `<div ngModelGroup=\"passwords\"><input name=\"password\">` →\n // `passwords.password`). Used when the directive lookup misses (e.g. the\n // value accessor doesn't expose its element ref in some custom CVAs).\n const staticGroups = collectNgModelGroupAttributes(fieldElement, formEl);\n const staticPath = [...staticGroups, name].join('.');\n const staticControl = this.ngForm.form.get(staticPath);\n if (staticControl) {\n return { field: staticPath, control: staticControl, element: fieldElement };\n }\n\n // Last-resort fallback for ambiguous DOM structures: probe each ancestor\n // element as a potential group boundary, querying the form tree until we\n // find a child that owns this DOM element.\n const dynamicMatch = resolveControlPathByDomAncestors(\n this.ngForm.form,\n fieldElement,\n formEl,\n name\n );\n if (dynamicMatch) {\n return {\n field: dynamicMatch.path,\n control: dynamicMatch.control,\n element: fieldElement,\n };\n }\n\n return null;\n }\n\n /**\n * Resets the form to a pristine, untouched state with optional new values.\n *\n * This method properly resets the form by:\n * 1. Resetting Angular's underlying NgForm with the provided value\n * 2. Clearing the bidirectional sync tracking state\n * 3. Forcing a form validity update to clear any stale validation errors\n *\n * **Why this method exists:**\n * When using the pattern `formValue.set({})` to reset a form, there can be a timing\n * issue where the form controls in the DOM still hold their old values while the\n * signal has already been updated. This creates a conflict in the bidirectional\n * sync logic, requiring workarounds like calling `formValue.set({})` twice with\n * a setTimeout. This method provides a proper solution by:\n * - Calling Angular's `NgForm.resetForm()` which properly clears all controls\n * - Clearing the internal sync tracking state to avoid stale comparisons\n * - Triggering a form validity update to ensure validation state is current\n *\n * **Usage:**\n * Instead of the double-set workaround:\n * ```typescript\n * // ❌ Old workaround (avoid)\n * reset(): void {\n * this.formValue.set({});\n * setTimeout(() => this.formValue.set({}), 0);\n * }\n *\n * // ✅ Preferred approach\n * vestForm = viewChild.required('vestForm', { read: FormDirective });\n * reset(): void {\n * this.formValue.set({});\n * this.vestForm().resetForm();\n * }\n * ```\n *\n * **With new values:**\n * ```typescript\n * // Reset and set new initial values\n * resetWithDefaults(): void {\n * const defaults = { firstName: '', lastName: '', age: 18 };\n * this.formValue.set(defaults);\n * this.vestForm().resetForm(defaults);\n * }\n * ```\n *\n * @param value - Optional new value to reset the form to. If not provided,\n * resets to empty/default values.\n *\n * @see {@link markAllAsTouched} for showing validation errors\n * @see {@link triggerFormValidation} for re-running validation without reset\n */\n resetForm(value?: T | null): void {\n // Reset Angular's form to clear all controls and mark as pristine/untouched\n this.ngForm.resetForm(value ?? undefined);\n\n // Clear any stored warnings to avoid stale messages after reset\n this.fieldWarnings.set(new Map());\n\n // Clear the bidirectional sync tracking state so the next formValue change\n // is treated as a model change (not a conflict with stale form values)\n this.#lastSyncedFormValue = null;\n this.#lastSyncedModelValue = null;\n\n // Force change detection to ensure DOM updates are reflected\n // Note: This is still needed even with signals because we're modifying NgForm\n // (reactive forms), not signals. The formValue signal updates happen in the\n // consumer component. detectChanges() ensures NgForm's reset is reflected in\n // the DOM before we update validity.\n this.cdr.detectChanges();\n\n // Trigger validation update to clear any stale errors\n // Now synchronous since detectChanges() has flushed DOM updates\n this.ngForm.form.updateValueAndValidity({ emitEvent: true });\n this.#blurTick.update((v) => v + 1);\n }\n\n /**\n * Creates a one-shot async validator function for a specific field path.\n *\n * The returned validator:\n * - snapshots the current form model,\n * - injects the candidate control value at `field`,\n * - runs the Vest suite with debouncing,\n * - maps Vest errors/warnings into Angular `ValidationErrors | null`.\n *\n * Warnings are stored in `fieldWarnings` to keep warnings non-blocking when no errors exist.\n */\n createAsyncValidator(\n field: string,\n validationOptions: ValidationOptions\n ): AsyncValidatorFn {\n const suite = this.suite();\n if (!suite) return () => of(null);\n\n return (control: AbstractControl) => {\n const model = mergeValuesAndRawValues<T>(this.ngForm.form);\n\n // Targeted snapshot with candidate value injected at path\n // mergeValuesAndRawValues already returns a deep clone (via structuredClone),\n // so we can modify it directly without affecting the form state.\n const snapshot = model;\n setValueAtPath(snapshot as object, field, control.value);\n\n // Use timer() instead of ReplaySubject for proper debouncing\n return timer(validationOptions.debounceTime ?? 0).pipe(\n map(() => snapshot),\n switchMap(\n (snap) =>\n new Observable<ValidationErrors | null>((observer) => {\n try {\n // Cast to NgxVestSuite to accept string field parameter\n // Both NgxVestSuite and NgxTypedVestSuite work with string at runtime\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (suite as NgxVestSuite<T>)(snap, field).done((result: any) => {\n // Guard: bail out if the directive was destroyed while\n // validation was in flight to avoid writing to disposed\n // signals or a torn-down view.\n if (this.#destroyed) {\n // Emit a neutral `null` before completing so async\n // validators always emit exactly once. Completing without\n // emission can leave consumers (e.g. a control's status)\n // in an unexpected `PENDING` state.\n observer.next(null);\n observer.complete();\n return;\n }\n\n const errors = result.getErrors()[field];\n const warnings = result.getWarnings()[field];\n\n // Store warnings in the fieldWarnings signal for access by control wrappers.\n // This is necessary because Angular marks a field as invalid when control.errors !== null.\n // By storing warnings separately, fields can remain valid while still displaying warnings.\n this.fieldWarnings.update((map) => {\n const newMap = new Map(map);\n if (warnings?.length) {\n newMap.set(field, warnings);\n } else {\n newMap.delete(field);\n }\n return newMap;\n });\n\n // Build the validation result:\n // - Errors exist → return { errors, warnings? } (field invalid, Angular shows ng-invalid)\n // - Only warnings → return null (field valid, warnings accessed via fieldWarnings signal)\n // - Neither → return null (field valid)\n //\n // When errors exist, we also include warnings in control.errors for backwards compatibility\n // with code that reads warnings from control.errors.warnings.\n const out = errors?.length\n ? {\n errors,\n ...(warnings?.length && { warnings }),\n }\n : null;\n\n // CRITICAL: Ensure DOM validity classes update for OnPush components.\n //\n // Angular's template-driven forms update `ng-valid`/`ng-invalid` host classes\n // during change detection. When async validation completes, there may be no\n // follow-up change detection pass for OnPush hosts, leaving the DOM in a stale\n // visual state (even though the control status has updated).\n //\n // We schedule a detectChanges() on the next microtask to avoid calling it\n // synchronously inside Angular's own validation pipeline. The scheduleMicrotask\n // primitive auto-cancels if the directive is destroyed before it fires.\n scheduleMicrotask(() => {\n try {\n this.cdr.detectChanges();\n } catch {\n // Fallback: mark for check when immediate detectChanges isn't safe.\n // This keeps behavior resilient in edge cases.\n this.cdr.markForCheck();\n }\n }, this.destroyRef);\n\n observer.next(out);\n observer.complete();\n });\n } catch {\n observer.next({ vestInternalError: 'Validation failed' });\n observer.complete();\n }\n })\n ),\n catchError(() => of({ vestInternalError: 'Validation failed' })),\n take(1)\n );\n };\n }\n\n /**\n * Set up validation config reactively using v2 pattern with toObservable + switchMap.\n * This provides automatic cleanup when config changes.\n */\n #setupValidationConfig(): void {\n const form = this.ngForm.form;\n toObservable(this.validationConfig)\n .pipe(\n distinctUntilChanged(),\n switchMap((config) => {\n // Cast to the expected type for the helper method\n const typedConfig = config as\n | ValidationConfigMap<T>\n | null\n | undefined;\n return this.#createValidationStreams(form, typedConfig);\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe();\n }\n\n /**\n * Creates validation streams for the provided configuration.\n * Returns EMPTY if config is null/undefined, otherwise merges all trigger field streams.\n *\n * @param form - The NgForm instance\n * @param config - The validation configuration mapping trigger fields to dependent fields\n * @returns Observable that emits when any trigger field changes and dependent fields need validation\n */\n #createValidationStreams(\n form: FormGroup,\n config: ValidationConfigMap<T> | null | undefined\n ): Observable<unknown> {\n if (!config) {\n this.validationInProgress.clear();\n return EMPTY;\n }\n\n const streams = Object.entries(config as Record<string, string[]>).map(\n ([triggerField, dependents]) =>\n this.#createTriggerStream(form, triggerField, dependents || [])\n );\n\n return streams.length > 0 ? rxMerge(...streams) : EMPTY;\n }\n\n /**\n * Creates a stream for a single trigger field that revalidates its dependent fields.\n *\n * This method handles:\n * 1. Waiting for the trigger control to exist in the form (for @if scenarios)\n * 2. Listening to value changes with debouncing\n * 3. Waiting for form to be idle before triggering dependents\n * 4. Waiting for all dependent controls to exist\n * 5. Updating dependent field validity with loop prevention\n *\n * @param form - The NgForm instance\n * @param triggerField - Field path that triggers validation (e.g., 'password')\n * @param dependents - Array of dependent field paths to revalidate (e.g., ['confirmPassword'])\n * @returns Observable that completes after dependent fields are validated\n */\n #createTriggerStream(\n form: FormGroup,\n triggerField: string,\n dependents: string[]\n ): Observable<unknown> {\n // Wait for trigger control to exist, then stop listening (take(1) prevents feedback loops)\n const triggerControl$ = form.statusChanges.pipe(\n startWith(form.status),\n map(() => form.get(triggerField)),\n filter((c): c is AbstractControl => !!c),\n // CRITICAL: take(1) to stop listening after control is found\n // Without this, the pipeline continues to listen to statusChanges,\n // creating a feedback loop where validation triggers re-trigger the pipeline\n take(1)\n );\n\n return triggerControl$.pipe(\n switchMap((control) => {\n return control.valueChanges.pipe(\n // CRITICAL: Filter out changes when this field is being validated by another field's config\n // This prevents circular triggers in bidirectional validationConfig\n filter(() => !this.validationInProgress.has(triggerField)),\n debounceTime(this.configDebounceTime),\n switchMap(() => {\n return this.#waitForFormIdle(form, control);\n }),\n switchMap(() =>\n this.#waitForDependentControls(form, dependents, control)\n ),\n tap(() =>\n this.#updateDependentFields(form, control, triggerField, dependents)\n )\n );\n })\n );\n }\n\n /**\n * Waits for the form to reach a non-PENDING state before proceeding.\n * This prevents validation race conditions where dependent field validation\n * triggers while the trigger field's validation is still running.\n *\n * If the form stays PENDING for longer than 2 seconds (e.g., slow async validators),\n * proceeds anyway to prevent blocking the validation pipeline.\n *\n * @param form - The NgForm instance\n * @param control - The trigger control to pass through\n * @returns Observable that emits the control once form is idle or timeout\n */\n #waitForFormIdle(\n form: FormGroup,\n control: AbstractControl\n ): Observable<AbstractControl> {\n // If form is already non-PENDING, return immediately\n if (form.status !== 'PENDING') {\n return of(control);\n }\n\n // Form is PENDING, wait for it to become idle\n\n const idle$ = form.statusChanges.pipe(\n filter((s) => s !== 'PENDING'),\n take(1)\n );\n\n const timeout$ = timer(2000).pipe(\n tap(() => {\n if (isDevMode()) {\n console.warn(\n '[ngx-vest-forms] validationConfig: timed out waiting for form to leave PENDING state (2s). Continuing dependent validation to avoid stalling.'\n );\n }\n })\n );\n\n return race(idle$, timeout$).pipe(map(() => control));\n }\n\n /**\n * Waits for all dependent controls to exist in the form.\n * This handles @if scenarios where controls are conditionally rendered.\n *\n * @param form - The NgForm instance\n * @param dependents - Array of dependent field paths\n * @param control - The trigger control to pass through\n * @returns Observable that emits the control once all dependents exist\n */\n #waitForDependentControls(\n form: FormGroup,\n dependents: string[],\n control: AbstractControl\n ): Observable<AbstractControl> {\n const allDependentsExist = dependents.every(\n (depField) => !!form.get(depField)\n );\n\n if (allDependentsExist) {\n return of(control);\n }\n\n // Wait for dependent controls to be added to the form, but bound the wait to avoid silent stalls.\n const dependentControlsReady$ = form.statusChanges.pipe(\n startWith(form.status),\n filter(() => dependents.every((depField) => !!form.get(depField))),\n take(1),\n map(() => control)\n );\n\n const timeout$ = timer(2000).pipe(\n tap(() => {\n if (isDevMode()) {\n const unresolved = dependents.filter(\n (depField) => !form.get(depField)\n );\n console.warn(\n `[ngx-vest-forms] validationConfig: timed out waiting for dependent controls (2s): ${unresolved.join(', ')}. Continuing without waiting further.`\n );\n }\n }),\n map(() => control)\n );\n\n return race(dependentControlsReady$, timeout$).pipe(take(1));\n }\n\n /**\n * Updates validation for all dependent fields.\n *\n * Handles:\n * - Loop prevention via validationInProgress set\n * - Silent validation updates that avoid feedback loops\n *\n * Note: Touch state is NOT propagated to prevent premature error display\n * on conditionally revealed fields.\n *\n * Note: This method does NOT propagate touch state from trigger to dependent fields.\n * Dependent fields only show errors after the user directly interacts with them.\n *\n * @param form - The NgForm instance\n * @param control - The trigger control\n * @param triggerField - Field path of the trigger\n * @param dependents - Array of dependent field paths to update\n */\n #updateDependentFields(\n form: FormGroup,\n control: AbstractControl,\n triggerField: string,\n dependents: string[]\n ): void {\n // Mark trigger field as in-progress to prevent it from being re-triggered\n this.validationInProgress.add(triggerField);\n\n for (const depField of dependents) {\n const dependentControl = form.get(depField);\n if (!dependentControl) {\n continue;\n }\n\n // Only validate if not already in progress (prevents bidirectional loops)\n if (!this.validationInProgress.has(depField)) {\n // CRITICAL: Mark the dependent field as in-progress BEFORE calling updateValueAndValidity\n // This prevents the dependent field's valueChanges from triggering its own validationConfig\n this.validationInProgress.add(depField);\n\n // emitEvent: true is REQUIRED for async validators to actually run\n // The validationInProgress Set prevents infinite loops:\n // 1. Field A changes → triggers validation on dependent field B\n // 2. B is added to validationInProgress Set\n // 3. B's statusChanges emits → #handleValueChange checks validationInProgress\n // 4. Since B is in validationInProgress, its validationConfig is not triggered\n // 5. After 500ms timeout, B is removed from validationInProgress\n // This way:\n // - Async validators CAN run (emitEvent: true)\n // - BUT circular triggers are prevented (validationInProgress check)\n dependentControl.updateValueAndValidity({\n onlySelf: true,\n emitEvent: true, // Changed from false - REQUIRED for validators to run!\n });\n\n // CRITICAL: Force immediate change detection for OnPush components\n // updateValueAndValidity updates the control's status, but doesn't automatically\n // trigger change detection. Components using OnPush won't see the ng-invalid class\n // update in the DOM without this. Using detectChanges() instead of markForCheck()\n // to force immediate synchronous update rather than waiting for next CD cycle.\n this.cdr.detectChanges();\n }\n }\n\n // Keep fields marked as in-progress for a short time to prevent immediate re-triggering\n // Use scheduleTimeout to ensure async validators have time to complete before allowing\n // new triggers. The timer auto-cancels on directive destroy so no timers leak.\n scheduleTimeout(() => {\n this.validationInProgress.delete(triggerField);\n for (const depField of dependents) {\n this.validationInProgress.delete(depField);\n }\n }, VALIDATION_IN_PROGRESS_TIMEOUT_MS, this.destroyRef);\n }\n\n /**\n * Collects field paths of all touched (or submitted) leaf controls\n * by walking the form control tree.\n */\n #collectTouchedPaths(control: AbstractControl, submitted: boolean): string[] {\n const fields: string[] = [];\n\n const collect = (\n current: AbstractControl,\n path: Array<string | number>\n ): void => {\n if (current instanceof FormGroup) {\n for (const [name, child] of Object.entries(current.controls)) {\n collect(child, [...path, name]);\n }\n return;\n }\n\n if (current instanceof FormArray) {\n current.controls.forEach((child, index) => {\n collect(child, [...path, index]);\n });\n return;\n }\n\n if ((submitted || current.touched) && path.length > 0) {\n fields.push(stringifyFieldPath(path));\n }\n };\n\n collect(control, []);\n return fields;\n }\n}\n\n/**\n * Reads the user-entered value from a blurred form element. Returns\n * `undefined` for radio inputs (caller must fall back to the bound\n * `control.value`, since the focused radio is not necessarily the\n * group's selected option) and for elements we don't handle.\n */\nfunction readElementValueForBlur(element: HTMLElement): unknown {\n if (element instanceof HTMLInputElement) {\n if (element.type === 'radio') return undefined;\n if (element.type === 'checkbox') return element.checked;\n if (element.type === 'number') {\n return element.value === '' ? null : element.valueAsNumber;\n }\n return element.value;\n }\n if (\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n return element.value;\n }\n return undefined;\n}\n\n/**\n * Walks DOM ancestors between `start` (exclusive) and `formEl` (exclusive),\n * collecting any preserved `ngModelGroup` attribute values into a path\n * suitable for `FormGroup.get()`. Only the static attribute form is\n * preserved on the DOM; dynamically-bound `[ngModelGroup]` is handled by\n * `resolveControlPathByDomAncestors`.\n */\nfunction collectNgModelGroupAttributes(\n start: HTMLElement,\n formEl: HTMLElement\n): string[] {\n const groups: string[] = [];\n let current: Element | null = start.parentElement;\n while (current && current !== formEl && formEl.contains(current)) {\n const groupName = current.getAttribute('ngModelGroup')?.trim();\n if (groupName) {\n groups.unshift(groupName);\n }\n current = current.parentElement;\n }\n return groups;\n}\n\n/**\n * Resolves the dotted control path for a blurred element when the static\n * `ngModelGroup` attribute walk failed (typically because the host used\n * `[ngModelGroup]=\"expr\"`, which Angular does not always preserve as a\n * DOM attribute). Walks the control tree top-down and at each FormGroup\n * boundary tries to descend into a child whose subtree contains an element\n * with the matching `name` — disambiguating repeated leaf names by DOM\n * containment instead of giving up.\n */\nfunction resolveControlPathByDomAncestors(\n root: FormGroup,\n fieldElement: HTMLElement,\n formEl: HTMLElement,\n leafName: string\n): { path: string; control: AbstractControl } | null {\n type Frame = { control: AbstractControl; path: Array<string | number> };\n\n const descend = (frame: Frame): Frame | null => {\n if (frame.control instanceof FormGroup) {\n for (const [key, child] of Object.entries(frame.control.controls)) {\n if (key === leafName && !(child instanceof FormGroup)) {\n return { control: child, path: [...frame.path, key] };\n }\n }\n const candidates: Frame[] = [];\n for (const [key, child] of Object.entries(frame.control.controls)) {\n if (child instanceof FormGroup || child instanceof FormArray) {\n if (subtreeContainsElement(child, fieldElement, formEl, key)) {\n candidates.push({ control: child, path: [...frame.path, key] });\n }\n }\n }\n if (candidates.length === 1 && candidates[0])\n return descend(candidates[0]);\n return null;\n }\n if (frame.control instanceof FormArray) {\n const candidates: Frame[] = [];\n frame.control.controls.forEach((child, index) => {\n if (child instanceof FormGroup || child instanceof FormArray) {\n if (subtreeContainsElement(child, fieldElement, formEl, index)) {\n candidates.push({ control: child, path: [...frame.path, index] });\n }\n }\n });\n if (candidates.length === 1 && candidates[0])\n return descend(candidates[0]);\n }\n return null;\n };\n\n const result = descend({ control: root, path: [] });\n if (!result) return null;\n return { path: stringifyFieldPath(result.path), control: result.control };\n}\n\n/**\n * Best-effort check: does the DOM subtree rooted at any element annotated\n * with `ngModelGroup=\"<key>\"` contain `fieldElement`? Used by\n * `resolveControlPathByDomAncestors` to disambiguate repeated leaf names.\n * For dynamic `[ngModelGroup]` with no preserved attribute we cannot\n * disambiguate from DOM alone — those cases return `false`, matching the\n * documented limitation.\n */\nfunction subtreeContainsElement(\n _child: AbstractControl,\n fieldElement: HTMLElement,\n formEl: HTMLElement,\n key: string | number\n): boolean {\n if (typeof key !== 'string') return false;\n const selector = `[ngModelGroup=\"${CSS.escape(key)}\"]`;\n const candidates = formEl.querySelectorAll(selector);\n for (const candidate of candidates) {\n if (candidate.contains(fieldElement)) return true;\n }\n return false;\n}\n\n/**\n * Resolves the control + dotted path for a blurred element by consulting the\n * `NgModel` directives Angular registered with this `NgForm`. Each registered\n * directive carries a live `path` (the full ControlContainer chain) and a\n * value accessor whose element ref is the input the directive is hosted on.\n *\n * This handles all grouping shapes uniformly — static `ngModelGroup=\"key\"`,\n * dynamic `[ngModelGroup]=\"expr\"`, and repeated leaf names across siblings —\n * because the path comes from the live form tree rather than DOM heuristics.\n * Returns `null` when the directive can't be matched (e.g. a custom CVA that\n * doesn't store an element ref), so the caller can fall back to DOM probes.\n */\nfunction resolveControlPathByNgModelDirective(\n ngForm: NgForm,\n fieldElement: HTMLElement\n): { path: string; control: AbstractControl } | null {\n const directives = readNgFormDirectives(ngForm);\n if (!directives) return null;\n\n for (const directive of directives) {\n const accessorEl = readValueAccessorElement(directive.valueAccessor);\n if (accessorEl !== fieldElement) continue;\n const control = directive.control ?? ngForm.form.get(directive.path);\n if (!control) return null;\n return { path: directive.path.join('.'), control };\n }\n return null;\n}\n\n/**\n * Reads the registered `NgModel` directives from `NgForm`. Angular forms keeps\n * them in a private `_directives: Set<NgModel>`. The field name is stable\n * across all Angular versions that ship `ngModel`, but is not part of the\n * public type — callers must tolerate `null`.\n */\nfunction readNgFormDirectives(ngForm: NgForm): Iterable<NgModel> | null {\n const set = (ngForm as unknown as { _directives?: Set<NgModel> })._directives;\n return set ?? null;\n}\n\n/**\n * Reads the host element of a `ControlValueAccessor`. The standard accessors\n * shipped by Angular forms (default, number, select, radio, checkbox, range)\n * all store an `ElementRef` injected at construction as `_elementRef`. This\n * is private but stable; custom accessors that don't follow the convention\n * will simply miss the fast path.\n */\nfunction readValueAccessorElement(\n accessor: ControlValueAccessor | null | undefined\n): HTMLElement | null {\n if (!accessor) return null;\n const elementRef = (accessor as { _elementRef?: { nativeElement?: unknown } })\n ._elementRef;\n const native = elementRef?.nativeElement;\n return native instanceof HTMLElement ? native : null;\n}\n","import {\n Directive,\n Injector,\n afterEveryRender,\n afterNextRender,\n computed,\n contentChild,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport {\n AbstractControlDirective,\n NgModel,\n NgModelGroup,\n ValidationErrors,\n} from '@angular/forms';\nimport { FormDirective } from './form.directive';\n\n/**\n * Angular's ValidationErrors is `{ [key: string]: any }`.\n * We extend it with Vest-specific structure for better type safety.\n */\nexport type VestValidationErrors = {\n /** Vest error messages array */\n errors?: readonly string[];\n /** Vest warning messages array */\n warnings?: readonly string[];\n} & ValidationErrors;\n\n/**\n * Form control status values as defined by Angular.\n * @see AbstractControl.status\n */\nexport type FormControlStatus = 'VALID' | 'INVALID' | 'PENDING' | 'DISABLED';\n\n/**\n * Represents the core state of an Angular form control.\n * Uses narrower types than Angular's defaults where possible.\n */\nexport type FormControlState = {\n readonly status: FormControlStatus | null;\n readonly isValid: boolean;\n readonly isInvalid: boolean;\n readonly isPending: boolean;\n readonly isDisabled: boolean;\n readonly isTouched: boolean;\n readonly isDirty: boolean;\n readonly isPristine: boolean;\n /** Errors from Angular validators or Vest validation */\n readonly errors: VestValidationErrors | null;\n};\n\nconst INITIAL_FORM_CONTROL_STATE = {\n status: 'INVALID',\n isValid: false,\n isInvalid: true,\n isPending: false,\n isDisabled: false,\n isTouched: false,\n isDirty: false,\n isPristine: true,\n errors: null,\n} as const satisfies FormControlState;\n\n@Directive({\n selector: '[formControlState], [ngxControlState]',\n exportAs: 'formControlState, ngxControlState',\n})\nexport class FormControlStateDirective {\n protected readonly contentNgModel = contentChild(NgModel);\n protected readonly contentNgModelGroup = contentChild(NgModelGroup);\n\n readonly #hostNgModel = inject(NgModel, { self: true, optional: true });\n readonly #hostNgModelGroup = inject(NgModelGroup, {\n self: true,\n optional: true,\n });\n readonly #injector = inject(Injector);\n\n /**\n * Reference to the parent FormDirective for accessing field warnings.\n * Optional to support usage outside of ngxVestForm context.\n */\n readonly #formDirective = inject(FormDirective, { optional: true });\n\n /**\n * Computed signal for the active control (NgModel or NgModelGroup)\n */\n readonly #activeControl = computed(\n (): AbstractControlDirective | null =>\n this.#hostNgModel ||\n this.#hostNgModelGroup ||\n this.contentNgModel() ||\n this.contentNgModelGroup() ||\n null\n );\n\n /**\n * Consolidated internal signal for interaction state tracking.\n * Combines touched, dirty, and hasBeenValidated into a single signal\n * to reduce signal overhead and simplify state updates.\n */\n readonly #interactionState = signal({\n isTouched: false,\n isDirty: false,\n hasBeenValidated: false,\n });\n\n /**\n * Track the previous status to detect actual status changes (not just status emissions).\n * This helps distinguish between initial control creation and actual re-validation.\n */\n #previousStatus: FormControlStatus | null = null;\n\n /**\n * Internal signal for control state (updated reactively)\n */\n readonly #controlStateSignal = signal<FormControlState>(\n INITIAL_FORM_CONTROL_STATE\n );\n\n /**\n * Tick bumped once via `afterNextRender` if `control.control` is undefined\n * at the first effect run (NgModel registers asynchronously). Reading this\n * signal inside the effect causes a re-evaluation after the next render so\n * we pick up the late-attached `FormControl`. Bookkeeping below ensures we\n * only schedule a single retry — no permanent polling.\n */\n readonly #controlAttachTick = signal(0);\n // Latch is scoped to the *current* `#activeControl` instance. When the\n // active control changes (e.g. host swaps an `@if` block, NgModel\n // recreates), the latch resets so a fresh late-attach gets one retry.\n #controlAttachRetryScheduled = false;\n #lastSeenActiveControl: AbstractControlDirective | null = null;\n\n constructor() {\n // Update control state reactively with proper cleanup\n effect((onCleanup) => {\n const control = this.#activeControl();\n const interaction = this.#interactionState();\n // Track the retry tick so a late-attached `control.control` re-runs this\n // effect after the next render.\n this.#controlAttachTick();\n\n // Re-arm the late-attach latch whenever the active control identity\n // changes — including transitions to/from null — so a newly mounted\n // directive whose `FormControl` registers asynchronously gets its own\n // single retry.\n if (control !== this.#lastSeenActiveControl) {\n this.#lastSeenActiveControl = control;\n this.#controlAttachRetryScheduled = false;\n }\n\n if (!control) {\n this.#controlStateSignal.set(INITIAL_FORM_CONTROL_STATE);\n return;\n }\n\n // NgModel attaches its `FormControl` during its own ngOnInit, which can\n // run after this effect's first execution in some host orderings. If\n // `control.control` isn't there yet, schedule a single `afterNextRender`\n // retry so we re-evaluate once Angular finishes wiring directives.\n if (!control.control && !this.#controlAttachRetryScheduled) {\n this.#controlAttachRetryScheduled = true;\n afterNextRender(\n () => {\n this.#controlAttachTick.update((v) => v + 1);\n },\n { injector: this.#injector }\n );\n return;\n }\n\n // Listen to control changes\n const sub = control.control?.statusChanges?.subscribe(() => {\n const {\n status,\n valid,\n invalid,\n pending,\n disabled,\n pristine,\n errors,\n touched,\n } = control;\n\n const currentStatus = status as FormControlStatus | null;\n\n // Mark as validated when any of the following conditions are met:\n // 1. The control has been touched (user blurred the field).\n // 2. The control's status has actually changed (not the first status emission),\n // AND the new status is not 'PENDING' (validation completed).\n //\n // This ensures hasBeenValidated is true for:\n // - User blur events (touched becomes true)\n // - Any validation that changes status (e.g., typing then validation completes)\n // - ValidationConfig-triggered validations (status changed without touch/dirty)\n // But NOT for initial page load validations (previousStatus === null).\n //\n // Note: The dirty check was removed to support validationConfig-triggered validations.\n // This allows warnings to show even when the field hasn't been touched/dirtied by the user.\n //\n // Accessibility: The logic is structured for clarity and maintainability.\n // IMPORTANT: Read touched/dirty directly from control, not from signal,\n // to avoid race conditions with afterEveryRender sync.\n if (\n touched || // Control was blurred (most common case)\n (this.#previousStatus !== null && // Not the first status emission\n this.#previousStatus !== currentStatus && // Status actually changed\n currentStatus !== null &&\n currentStatus !== 'PENDING') // Validation completed (not pending)\n ) {\n this.#interactionState.update((state) => ({\n ...state,\n hasBeenValidated: true,\n }));\n }\n\n // Track current status for next iteration\n this.#previousStatus = currentStatus;\n\n this.#controlStateSignal.set({\n status: currentStatus,\n isValid: valid ?? false,\n isInvalid: invalid ?? false,\n isPending: pending ?? false,\n isDisabled: disabled ?? false,\n isTouched: interaction.isTouched,\n isDirty: interaction.isDirty,\n isPristine: pristine ?? true,\n errors: errors as VestValidationErrors | null,\n });\n });\n\n // Initial update\n const { status, valid, invalid, pending, disabled, pristine, errors } =\n control;\n\n const initialStatus = status as FormControlStatus | null;\n this.#previousStatus = initialStatus;\n\n this.#controlStateSignal.set({\n status: initialStatus,\n isValid: valid ?? false,\n isInvalid: invalid ?? false,\n isPending: pending ?? false,\n isDisabled: disabled ?? false,\n isTouched: interaction.isTouched,\n isDirty: interaction.isDirty,\n isPristine: pristine ?? true,\n errors: errors as VestValidationErrors | null,\n });\n\n // Proper cleanup using onCleanup callback (Angular 21 best practice)\n onCleanup(() => sub?.unsubscribe());\n });\n\n // Robustly sync touched/dirty/pending after every render (Angular 18+ best practice)\n // This handles cases where statusChanges events are missed or delayed\n afterEveryRender(\n () => {\n const control = this.#activeControl();\n if (control) {\n const currentInteraction = this.#interactionState();\n const currentState = this.#controlStateSignal();\n const newTouched = control.touched ?? false;\n const newDirty = control.dirty ?? false;\n\n // Sync interaction state (touched/dirty)\n if (\n newTouched !== currentInteraction.isTouched ||\n newDirty !== currentInteraction.isDirty\n ) {\n // Mark as validated when control becomes touched (e.g., user blurred the field)\n // This handles the case where blur doesn't trigger statusChanges (field already invalid)\n const shouldMarkValidated =\n newTouched && !currentInteraction.isTouched;\n\n // Reset hasBeenValidated when a control transitions back to pristine interaction state\n // (e.g., after form.resetForm()).\n //\n // This prevents stale warning display on untouched fields after reset while preserving\n // validationConfig-triggered behavior during normal interaction.\n const wasResetToPristineInteraction =\n !newTouched &&\n !newDirty &&\n (currentInteraction.isTouched || currentInteraction.isDirty);\n\n this.#interactionState.update((state) => ({\n ...state,\n isTouched: newTouched,\n isDirty: newDirty,\n hasBeenValidated: wasResetToPristineInteraction\n ? false\n : shouldMarkValidated\n ? true\n : state.hasBeenValidated,\n }));\n\n // Keep the derived control-state signal in sync even when blur/dirty\n // changes do not produce a statusChanges emission.\n //\n // This happens when a control is already INVALID due to dependent-field\n // validation and the user then blurs it. Error display modes that depend\n // on `isTouched()` must still update immediately in that case.\n this.#controlStateSignal.set({\n status: control.status as FormControlStatus | null,\n isValid: control.valid ?? false,\n isInvalid: control.invalid ?? false,\n isPending: control.pending ?? false,\n isDisabled: control.disabled ?? false,\n isTouched: newTouched,\n isDirty: newDirty,\n isPristine: control.pristine ?? true,\n errors: control.errors as VestValidationErrors | null,\n });\n }\n\n // Sync pending state only when it transitions from true to false\n // This fixes \"Validating...\" being stuck when statusChanges misses the transition\n // We only sync when pending goes false to avoid interfering with async validation in progress\n const controlPending = control.pending ?? false;\n if (currentState.isPending && !controlPending) {\n // Pending changed from true to false - update the full state\n const newStatus = control.status as FormControlStatus | null;\n this.#controlStateSignal.set({\n status: newStatus,\n isPending: false,\n isValid: control.valid ?? false,\n isInvalid: control.invalid ?? false,\n isPristine: control.pristine ?? true,\n isDisabled: control.disabled ?? false,\n isTouched: newTouched,\n isDirty: newDirty,\n errors: control.errors as VestValidationErrors | null,\n });\n }\n }\n },\n { injector: this.#injector }\n );\n }\n\n /**\n * Main control state computed signal (merges robust touched/dirty)\n */\n readonly controlState = computed(() => this.#controlStateSignal());\n\n /**\n * Recursively flattens Angular error objects into an array of error messages.\n * Handles string values, objects with a message property, and nested structures.\n */\n #flattenAngularErrors(errors: Record<string, unknown>): string[] {\n const result: string[] = [];\n\n for (const key of Object.keys(errors)) {\n const value: unknown = errors[key];\n\n if (typeof value === 'string') {\n // String values: push the value itself, not the key\n result.push(value);\n } else if (isErrorWithMessage(value)) {\n // Objects with a 'message' property: extract the message\n result.push(value.message);\n } else if (typeof value === 'object' && value !== null) {\n // Nested objects/arrays: recursively flatten\n result.push(\n ...this.#flattenAngularErrors(value as Record<string, unknown>)\n );\n } else {\n // Fallback: push the key for primitive types (backward compatibility)\n result.push(key);\n }\n }\n\n return result;\n }\n\n /**\n * Extracts error messages from Angular/Vest errors (recursively flattens)\n */\n readonly errorMessages = computed((): string[] => {\n const { errors } = this.controlState();\n if (!errors) return [];\n\n // Vest errors are stored in the 'errors' property as an array\n const vestErrors = errors.errors;\n if (vestErrors) {\n return (vestErrors as readonly unknown[])\n .map((error) => normalizeErrorMessage(error))\n .filter((error): error is string => Boolean(error));\n }\n\n // Fallback to flattened Angular error keys, excluding 'warnings' key\n // to prevent warnings from appearing in the error list\n const errorsWithoutWarnings = { ...errors };\n delete errorsWithoutWarnings['warnings'];\n return this.#flattenAngularErrors(errorsWithoutWarnings);\n });\n\n /**\n * ADVANCED: updateOn strategy (change/blur/submit) if available\n */\n readonly updateOn = computed((): 'change' | 'blur' | 'submit' => {\n const ngModel = this.contentNgModel() || this.#hostNgModel;\n return ngModel?.options?.updateOn ?? 'change';\n });\n\n /**\n * ADVANCED: Composite/derived signals for advanced error display logic\n */\n readonly isValidTouched = computed(() => this.isValid() && this.isTouched());\n\n readonly isInvalidTouched = computed(\n () => this.isInvalid() && this.isTouched()\n );\n\n readonly shouldShowErrors = computed(\n () => this.isInvalid() && this.isTouched() && !this.isPending()\n );\n\n /**\n * Extracts warning messages from Vest validation results.\n * Checks two sources:\n * 1. control.errors.warnings (when errors exist alongside warnings)\n * 2. FormDirective.fieldWarnings (for warnings-only scenarios)\n * This dual-source approach allows warnings to be displayed without affecting field validity.\n */\n readonly warningMessages = computed((): string[] => {\n // Source 1: warnings from control.errors (when field has errors)\n const { errors } = this.controlState();\n\n // Always read fieldWarnings signal to ensure reactive tracking\n // This must be read unconditionally for proper signal dependency tracking\n const fieldWarnings = this.#formDirective?.fieldWarnings();\n const activeControl = this.#activeControl();\n\n // If we have warnings in control.errors, use those (errors+warnings case)\n if (errors?.warnings) {\n return [...errors.warnings];\n }\n\n // Source 2: warnings from FormDirective (for warnings-only scenarios)\n // When a field only has warnings (no errors), they're stored in fieldWarnings\n // to keep the field valid while still allowing warnings to be displayed.\n if (fieldWarnings && activeControl) {\n // Get the field path from the control's path property\n // NgModel.path returns an array like ['passwords', 'password'] which needs to be joined\n const path = (activeControl as { path?: string[] }).path;\n if (path?.length) {\n const fieldPath = path.join('.');\n const warnings = fieldWarnings.get(fieldPath);\n if (warnings) {\n return [...warnings];\n }\n }\n }\n\n return [];\n });\n\n /**\n * Whether async validation is in progress\n */\n readonly hasPendingValidation = computed(() => this.controlState().isPending);\n\n /**\n * Convenience signals for common state checks\n */\n readonly isValid = computed(() => this.controlState().isValid);\n readonly isInvalid = computed(() => this.controlState().isInvalid);\n readonly isPending = computed(() => this.controlState().isPending);\n readonly isTouched = computed(() => this.controlState().isTouched);\n readonly isDirty = computed(() => this.controlState().isDirty);\n readonly isPristine = computed(() => this.controlState().isPristine);\n readonly isDisabled = computed(() => this.controlState().isDisabled);\n readonly hasErrors = computed(() => this.errorMessages().length > 0);\n\n /**\n * Whether this control has been validated at least once.\n * True after the first validation completes, even if the user hasn't touched the field.\n * This is primarily used for warning display and other derived state that should react\n * to validationConfig-triggered validation even before the user touches the field.\n */\n readonly hasBeenValidated = computed(\n () => this.#interactionState().hasBeenValidated\n );\n}\n\n/**\n * Type guard for objects with a message property\n */\nfunction isErrorWithMessage(value: unknown): value is { message: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'message' in value &&\n typeof (value as { message: unknown }).message === 'string'\n );\n}\n\nfunction normalizeErrorMessage(value: unknown): string | null {\n if (typeof value === 'string') {\n return value;\n }\n\n if (isErrorWithMessage(value)) {\n return value.message;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n return String(value);\n}\n","import {\n computed,\n Directive,\n effect,\n inject,\n input,\n signal,\n Signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormResetEvent, FormSubmittedEvent, NgForm } from '@angular/forms';\nimport { filter, map, startWith } from 'rxjs';\nimport {\n NGX_ERROR_DISPLAY_MODE_TOKEN,\n NGX_WARNING_DISPLAY_MODE_TOKEN,\n SC_ERROR_DISPLAY_MODE_TOKEN,\n} from './error-display-mode.token';\nimport { FormControlStateDirective } from './form-control-state.directive';\nimport { getFormSubmittedSignal } from './form-submitted-state';\n\n/**\n * Error display modes for form controls.\n * - 'on-blur': Show errors after field is touched/blurred\n * - 'on-submit': Show errors after form submission\n * - 'on-blur-or-submit': Show errors after blur or form submission (default)\n * - 'on-dirty': Show errors as soon as the field value changes\n * - 'always': Show errors immediately, even on pristine fields\n */\nexport type ScErrorDisplayMode =\n | 'on-blur'\n | 'on-submit'\n | 'on-blur-or-submit'\n | 'on-dirty'\n | 'always';\n\n/**\n * Warning display modes for form controls.\n * - 'on-touch': Show warnings after field is touched/blurred\n * - 'on-validated-or-touch': Show warnings after validation runs or field is touched (default)\n * - 'on-dirty': Show warnings as soon as the field value changes\n * - 'always': Show warnings immediately, even on pristine fields\n */\nexport type NgxWarningDisplayMode =\n | 'on-touch'\n | 'on-validated-or-touch'\n | 'on-dirty'\n | 'always';\n\nexport const SC_ERROR_DISPLAY_MODE_DEFAULT: ScErrorDisplayMode =\n 'on-blur-or-submit';\nexport const SC_WARNING_DISPLAY_MODE_DEFAULT: NgxWarningDisplayMode =\n 'on-validated-or-touch';\n\n@Directive({\n selector: '[formErrorDisplay], [ngxErrorDisplay]',\n exportAs: 'formErrorDisplay, ngxErrorDisplay',\n hostDirectives: [FormControlStateDirective],\n})\nexport class FormErrorDisplayDirective {\n readonly #formControlState = inject(FormControlStateDirective);\n // Optionally inject NgForm for form submission tracking\n readonly #ngForm = inject(NgForm, { optional: true });\n readonly #formSubmittedState = this.#ngForm\n ? getFormSubmittedSignal(this.#ngForm)\n : signal(false);\n\n /**\n * Input signal for error display mode.\n * Works seamlessly with hostDirectives in Angular 19+.\n */\n readonly errorDisplayMode = input<ScErrorDisplayMode>(\n inject(NGX_ERROR_DISPLAY_MODE_TOKEN, { optional: true }) ??\n inject(SC_ERROR_DISPLAY_MODE_TOKEN, { optional: true }) ??\n SC_ERROR_DISPLAY_MODE_DEFAULT\n );\n\n /**\n * Input signal for warning display mode.\n * Controls whether warnings are shown only after touch or also after validation.\n */\n readonly warningDisplayMode = input<NgxWarningDisplayMode>(\n inject(NGX_WARNING_DISPLAY_MODE_TOKEN, { optional: true }) ??\n SC_WARNING_DISPLAY_MODE_DEFAULT\n );\n\n // Expose state signals from FormControlStateDirective\n readonly controlState = this.#formControlState.controlState;\n readonly errorMessages = this.#formControlState.errorMessages;\n readonly warningMessages = this.#formControlState.warningMessages;\n readonly hasPendingValidation = this.#formControlState.hasPendingValidation;\n readonly isTouched = this.#formControlState.isTouched;\n readonly isDirty = this.#formControlState.isDirty;\n readonly isValid = this.#formControlState.isValid;\n readonly isInvalid = this.#formControlState.isInvalid;\n readonly hasBeenValidated = this.#formControlState.hasBeenValidated;\n /**\n * Expose updateOn and formSubmitted as public signals for advanced consumers.\n * updateOn: The ngModelOptions.updateOn value for the control (change/blur/submit)\n * formSubmitted: true after the form is submitted (if NgForm is present)\n */\n readonly updateOn = this.#formControlState.updateOn;\n\n /**\n * Signal that tracks NgForm.submitted state reactively.\n *\n * Map form-level submit/reset events directly to boolean state.\n *\n * This keeps programmatic `NgForm.onSubmit()` reactive in zoneless mode and\n * avoids depending on `NgForm.submitted`, whose getter intentionally reads an\n * internal signal with `untracked()`.\n *\n * Note: when this directive is used outside an `NgForm` (no parent form), no\n * subscription is wired up and this signal stays `false` for the lifetime of\n * the directive. Consumers relying on submitted state must host the field\n * inside an `NgForm` (or `ngxVestForm`).\n */\n readonly formSubmitted: Signal<boolean> = this.#formSubmittedState;\n\n constructor() {\n const ngForm = this.#ngForm;\n if (ngForm) {\n ngForm.form.events\n .pipe(\n filter(\n (event) =>\n event.source === ngForm.form &&\n (event instanceof FormSubmittedEvent ||\n event instanceof FormResetEvent)\n ),\n map((event) => event instanceof FormSubmittedEvent),\n startWith(ngForm.submitted),\n takeUntilDestroyed()\n )\n .subscribe((submitted) => {\n this.#formSubmittedState.set(submitted);\n });\n }\n\n // Warn about problematic combinations of updateOn and errorDisplayMode\n effect(() => {\n const mode = this.errorDisplayMode();\n const updateOn = this.updateOn();\n if (updateOn === 'submit' && mode === 'on-blur') {\n console.warn(\n '[ngx-vest-forms] Potential UX issue: errorDisplayMode is \"on-blur\" but updateOn is \"submit\". Errors will only show after form submission, not after blur.'\n );\n }\n });\n }\n\n /**\n * Determines if errors should be shown based on the specified display mode\n * and the control's state (touched/submitted/dirty).\n *\n * Note: We check both hasErrors (extracted error messages) AND isInvalid (Angular's validation state)\n * because in some cases (like conditional validations via validationConfig), the control is marked\n * as invalid by Angular before error messages are extracted from Vest. This ensures aria-invalid\n * is set correctly even during the validation propagation delay.\n *\n * For validationConfig-triggered validations, a field may become invalid before it has been\n * touched. Error visibility still respects the field's own `errorDisplayMode`, so untouched\n * dependent fields can remain visually quiet until blur or submit.\n */\n readonly shouldShowErrors: Signal<boolean> = computed(() => {\n const mode = this.errorDisplayMode();\n const isTouched = this.isTouched();\n const isDirty = this.isDirty();\n const isInvalid = this.isInvalid();\n const hasErrors = this.errorMessages().length > 0;\n const updateOn = this.updateOn();\n const formSubmitted = this.formSubmitted();\n\n // Consider errors present if either we have error messages OR the control is invalid\n // This handles the race condition where Angular marks control invalid before Vest errors propagate\n const hasErrorState = hasErrors || isInvalid;\n\n // Always only show errors after submit if updateOn is 'submit'\n if (updateOn === 'submit') {\n return !!(formSubmitted && hasErrorState);\n }\n\n // Handle the new display modes\n switch (mode) {\n case 'always':\n // Always show errors immediately, even on pristine fields\n return hasErrorState;\n\n case 'on-dirty':\n // Show when value has changed, OR when touched/submitted (for backwards compat)\n return !!(isDirty || isTouched || formSubmitted) && hasErrorState;\n\n case 'on-blur':\n // Show after touch (blur) or form submission (traditional behavior, not dirty-based)\n return !!(isTouched || formSubmitted) && hasErrorState;\n\n case 'on-submit':\n // Show only after form submission\n return !!(formSubmitted && hasErrorState);\n\n case 'on-blur-or-submit':\n default:\n // Show after blur (touch) OR submit (default behavior)\n return !!((isTouched || formSubmitted) && hasErrorState);\n }\n });\n\n /**\n * Errors to display (filtered for pending state)\n */\n readonly errors: Signal<string[]> = computed(() => {\n if (this.hasPendingValidation()) return [];\n return this.errorMessages();\n });\n\n /**\n * Warnings to display (filtered for pending state)\n */\n readonly warnings: Signal<string[]> = computed(() => {\n if (this.hasPendingValidation()) return [];\n return this.warningMessages();\n });\n\n /**\n * Whether the control is currently being validated (pending)\n * Excludes pristine+untouched controls to prevent \"Validating...\" on initial load\n */\n readonly isPending: Signal<boolean> = computed(() => {\n // Don't show pending state for pristine untouched controls\n // This prevents \"Validating...\" message appearing on initial page load\n const state = this.#formControlState.controlState();\n if (state.isPristine && !state.isTouched) {\n return false;\n }\n return this.hasPendingValidation();\n });\n\n /**\n * Determines if warnings should be shown based on the specified display mode\n * and the control's state (touched/validated/dirty).\n *\n * NOTE: Unlike errors, warnings can exist on VALID fields (warnings-only scenario).\n * We don't require isInvalid() because Vest warn() tests don't affect field validity.\n *\n * UX Note: We include `hasBeenValidated` for `on-validated-or-touch` mode to support\n * cross-field validation. If Field A triggers validation on Field B (via validationConfig),\n * Field B should show warnings if it has them, even if the user hasn't touched Field B yet.\n * Unlike errors (which block submission), warnings are informational and safe to show.\n */\n readonly shouldShowWarnings: Signal<boolean> = computed(() => {\n const mode = this.warningDisplayMode();\n const isTouched = this.isTouched();\n const isDirty = this.isDirty();\n const hasBeenValidated = this.hasBeenValidated();\n const hasWarnings = this.warningMessages().length > 0;\n const isPending = this.hasPendingValidation();\n const formSubmitted = this.formSubmitted();\n\n // No warnings to show or still pending\n if (!hasWarnings || isPending) {\n return false;\n }\n\n // Handle the warning display modes\n switch (mode) {\n case 'always':\n // Always show warnings immediately, even on pristine fields\n return true;\n\n case 'on-dirty':\n // Show when value has changed, OR when touched/submitted (for backwards compat)\n return isDirty || isTouched || formSubmitted;\n\n case 'on-touch':\n // Show after touch (blur) or form submission (traditional behavior, not dirty-based)\n return isTouched || formSubmitted;\n\n case 'on-validated-or-touch':\n default:\n // Show after validation runs or after touch/submit (default behavior)\n return hasBeenValidated || isTouched || formSubmitted;\n }\n });\n}\n","export type AriaAssociationMode = 'all-controls' | 'single-control' | 'none';\n\n/**\n * Splits an `aria-describedby` attribute value into normalized token IDs.\n */\nexport function parseAriaIdTokens(value: string | null): string[] {\n return (value ?? '')\n .split(/\\s+/)\n .map((token) => token.trim())\n .filter(Boolean);\n}\n\n/**\n * Merges currently-active wrapper IDs into an existing `aria-describedby` value.\n *\n * Existing tokens owned by the wrapper are removed first, then current active IDs\n * are appended while preserving non-owned tokens and token uniqueness.\n */\nexport function mergeAriaDescribedBy(\n existing: string | null,\n activeIds: readonly string[],\n ownedIds: readonly string[]\n): string | null {\n const ownedIdSet = new Set(ownedIds);\n const existingTokens = parseAriaIdTokens(existing);\n const existingWithoutOwned = existingTokens.filter(\n (token) => !ownedIdSet.has(token)\n );\n\n const merged: string[] = [...existingWithoutOwned];\n const mergedIdSet = new Set(merged);\n for (const id of activeIds) {\n if (!mergedIdSet.has(id)) {\n merged.push(id);\n mergedIdSet.add(id);\n }\n }\n\n return merged.length > 0 ? merged.join(' ') : null;\n}\n\n/**\n * Resolves control targets based on ARIA association mode.\n */\nexport function resolveAssociationTargets(\n controls: readonly HTMLElement[],\n mode: AriaAssociationMode\n): HTMLElement[] {\n if (mode === 'none') {\n return [];\n }\n\n if (mode === 'single-control') {\n return controls.length === 1 ? [...controls] : [];\n }\n\n return [...controls];\n}\n","import { effect, isSignal, Signal, signal } from '@angular/core';\n\n/**\n * Options for configuring debounced pending state behavior.\n */\nexport type DebouncedPendingStateOptions = {\n /**\n * Delay in milliseconds before showing the pending message.\n * Prevents flashing for quick async validations.\n * @default 200\n */\n showAfter?: number;\n\n /**\n * Minimum display time in milliseconds once the pending message is shown.\n * Prevents flickering when validation completes shortly after being shown.\n * @default 500\n */\n minimumDisplay?: number;\n};\n\n/**\n * Accepts either a static options object or a reactive `Signal` (e.g. an\n * `input()` accessor) so consumers can update debounce timings at runtime\n * without recreating the pending-state machine.\n */\nexport type DebouncedPendingStateOptionsInput =\n | DebouncedPendingStateOptions\n | Signal<DebouncedPendingStateOptions>;\n\n/**\n * Result of createDebouncedPendingState containing the debounced signal\n * and cleanup function.\n */\nexport type DebouncedPendingStateResult = {\n /**\n * Signal that is true when the pending message should be shown.\n * This is debounced according to the provided options.\n */\n showPendingMessage: Signal<boolean>;\n\n /**\n * Optional cleanup function to cancel any pending timeouts.\n * Call this in ngOnDestroy if needed (though the effect cleanup handles most cases).\n */\n cleanup: () => void;\n};\n\n/**\n * Creates a debounced pending state signal that prevents flashing validation messages.\n *\n * This utility helps implement a better UX for async validations by:\n * 1. Delaying the display of \"Validating...\" messages until validation takes longer than `showAfter`ms (default: 200ms)\n * 2. Keeping the message visible for at least `minimumDisplay`ms (default: 500ms) once shown to prevent flickering\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (showPendingMessage()) {\n * <div role=\"status\" aria-live=\"polite\">Validating…</div>\n * }\n * `\n * })\n * export class CustomControlWrapperComponent {\n * protected readonly errorDisplay = inject(FormErrorDisplayDirective, { self: true });\n *\n * // Create debounced pending state\n * private readonly pendingState = createDebouncedPendingState(\n * this.errorDisplay.isPending,\n * { showAfter: 200, minimumDisplay: 500 }\n * );\n *\n * protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n * }\n * ```\n *\n * @param isPending - Signal indicating whether async validation is currently pending\n * @param options - Configuration options for debouncing behavior\n * @returns Object containing the debounced showPendingMessage signal and cleanup function\n */\nexport function createDebouncedPendingState(\n isPending: Signal<boolean>,\n options: DebouncedPendingStateOptionsInput = {}\n): DebouncedPendingStateResult {\n // Reading the options inside the effect makes the timings reactive: when\n // a consumer passes an `input()` accessor (a Signal), changes propagate at\n // runtime rather than getting captured once at construction.\n const optionsSignal: Signal<DebouncedPendingStateOptions> | null = isSignal(\n options\n )\n ? (options as Signal<DebouncedPendingStateOptions>)\n : null;\n const staticOptions: DebouncedPendingStateOptions = optionsSignal\n ? {}\n : (options as DebouncedPendingStateOptions);\n\n // Create writable signal for debounced state\n const showPendingMessageSignal = signal(false);\n\n // Track timeouts\n let pendingTimeout: ReturnType<typeof setTimeout> | null = null;\n let minimumDisplayTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Cleanup function\n const cleanup = () => {\n if (pendingTimeout) {\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n }\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n };\n\n // Effect to manage debounced pending message display\n effect((onCleanup) => {\n const pending = isPending();\n const current = optionsSignal ? optionsSignal() : staticOptions;\n const showAfter = current.showAfter ?? 200;\n const minimumDisplay = current.minimumDisplay ?? 500;\n\n if (pending) {\n // Clear any existing minimum display timeout\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n\n // Start delay timer before showing pending message\n pendingTimeout = setTimeout(() => {\n showPendingMessageSignal.set(true);\n pendingTimeout = null;\n }, showAfter);\n\n onCleanup(() => {\n if (pendingTimeout) {\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n }\n });\n } else {\n // Validation completed\n if (pendingTimeout) {\n // Validation completed before delay - don't show message\n clearTimeout(pendingTimeout);\n pendingTimeout = null;\n } else if (showPendingMessageSignal()) {\n // Message was shown - keep it visible for minimum duration\n minimumDisplayTimeout = setTimeout(() => {\n showPendingMessageSignal.set(false);\n minimumDisplayTimeout = null;\n }, minimumDisplay);\n\n onCleanup(() => {\n if (minimumDisplayTimeout) {\n clearTimeout(minimumDisplayTimeout);\n minimumDisplayTimeout = null;\n }\n });\n }\n }\n });\n\n return {\n showPendingMessage: showPendingMessageSignal.asReadonly(),\n cleanup,\n };\n}\n","import {\n AfterContentInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n signal,\n} from '@angular/core';\nimport { FormErrorDisplayDirective } from '../../directives/form-error-display.directive';\nimport {\n AriaAssociationMode,\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from '../../utils/aria-association.utils';\nimport { createDebouncedPendingState } from '../../utils/pending-state.utils';\n\n// Counter for unique IDs\nlet nextUniqueId = 0;\n\n/**\n * Accessible form control wrapper built with WCAG 2.2 AA considerations.\n *\n * Wrap form fields to automatically display validation errors, warnings, and pending states\n * with proper accessibility attributes.\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <ngx-control-wrapper>\n * <label for=\"email\">Email</label>\n * <input id=\"email\" name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Error Display Modes\n * Control when errors appear using the `errorDisplayMode` input:\n * - `'on-blur-or-submit'` (default): Show errors after blur OR form submit\n * - `'on-blur'`: Show errors only after blur\n * - `'on-submit'`: Show errors only after form submit\n * - `'on-dirty'`: Show errors as soon as the field value changes\n * - `'always'`: Show errors immediately, even on pristine fields\n *\n * ```html\n * <ngx-control-wrapper [errorDisplayMode]=\"'on-submit'\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Warning Display Modes\n * Control when warnings appear using the `warningDisplayMode` input:\n * - `'on-validated-or-touch'` (default): Show warnings after validation runs or touch\n * - `'on-touch'`: Show warnings only after touch/blur\n * - `'on-dirty'`: Show warnings as soon as the field value changes\n * - `'always'`: Show warnings immediately, even on pristine fields\n *\n * ```html\n * <ngx-control-wrapper [warningDisplayMode]=\"'on-dirty'\">\n * <input name=\"email\" [ngModel]=\"formValue().email\" />\n * </ngx-control-wrapper>\n * ```\n *\n * ### Accessibility Features (Automatic)\n * - Unique IDs for error/warning/pending regions\n * - `aria-describedby` linking errors to form controls\n * - `aria-invalid=\"true\"` when errors are shown\n * - Uses `role=\"status\"` with `aria-live=\"polite\"` for non-disruptive announcements\n * - Debounced pending state to prevent flashing for quick validations\n *\n * ### WCAG 2.2 AA - Error Severity Levels\n * This component uses `role=\"status\"` for **field-level** validation messages:\n * - **Errors**: Non-disruptive announcement (user can continue filling other fields)\n * - **Warnings**: Informational only, doesn't block submission\n * - **Pending**: Status update while async validation runs\n *\n * For **form-level blocking errors** (e.g., submission failed), implement a separate\n * error summary component with `role=\"alert\"` and `aria-live=\"assertive\"`.\n *\n * @see {@link FormErrorDisplayDirective} for custom wrapper implementation\n *\n * Form-Level Blocking Errors:\n * - For post-submit validation errors that block submission, implement a separate\n * form-level error summary with role=\"alert\" and aria-live=\"assertive\"\n * - This component uses role=\"status\" for field-level errors (non-disruptive)\n * - Example for form-level errors:\n * ```html\n * <!-- Keep in DOM; update text content on submit -->\n * <div id=\"form-errors\" role=\"alert\" aria-live=\"assertive\" aria-atomic=\"true\"></div>\n * ```\n * - This separation provides immediate announcements for blocking form errors while\n * keeping inline field errors non-disruptive. Follows WCAG ARIA21/ARIA22 guidance.\n *\n * Error & Warning Display Behavior:\n * - The error display mode can be configured globally using the NGX_ERROR_DISPLAY_MODE_TOKEN injection token, or per instance using the `errorDisplayMode` input on FormErrorDisplayDirective (which this component uses as a hostDirective).\n * - Possible error display values: 'on-blur' | 'on-submit' | 'on-blur-or-submit' | 'on-dirty' | 'always' (default: 'on-blur-or-submit')\n * - The warning display mode can be configured globally using NGX_WARNING_DISPLAY_MODE_TOKEN, or per instance using the `warningDisplayMode` input on FormErrorDisplayDirective.\n * - Possible warning display values: 'on-touch' | 'on-validated-or-touch' | 'on-dirty' | 'always' (default: 'on-validated-or-touch')\n *\n * Example (per instance):\n * <div ngxControlWrapper>\n * <label>\n * <span>First name</span>\n * <input type=\"text\" name=\"firstName\" [ngModel]=\"formValue().firstName\" />\n * </label>\n * </div>\n * /// To customize errorDisplayMode for this instance, use the errorDisplayMode input.\n *\n * Example (with warnings and pending):\n * <ngx-control-wrapper>\n * <input name=\"username\" ngModel />\n * </ngx-control-wrapper>\n * /// If async validation is running for >500ms, a spinner and 'Validating…' will be shown.\n * /// Once shown, the validation message stays visible for minimum 500ms to prevent flashing.\n * /// If Vest warnings are present, they will be shown below errors.\n *\n * Example (global config):\n * import { provide } from '@angular/core';\n * import { NGX_ERROR_DISPLAY_MODE_TOKEN } from 'ngx-vest-forms';\n * @Component({\n * providers: [\n * provide(NGX_ERROR_DISPLAY_MODE_TOKEN, { useValue: 'on-submit' })\n * ]\n * })\n * export class MyComponent {}\n *\n * Best Practices:\n * - Use for single-control wrappers.\n * - For multi-control/group containers, prefer `ngx-form-group-wrapper`.\n * - Do not manually display errors for individual fields; rely on this wrapper.\n * - Validate with tools like Accessibility Insights and real screen reader testing.\n *\n * @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA19 - ARIA19: Using ARIA role=alert\n * @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22 - ARIA22: Using role=status\n */\n@Component({\n selector:\n 'ngx-control-wrapper, sc-control-wrapper, [scControlWrapper], [ngxControlWrapper], [ngx-control-wrapper], [sc-control-wrapper]',\n templateUrl: './control-wrapper.component.html',\n styles: `\n :host {\n display: block;\n position: relative;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n\n host: {\n class: 'ngx-control-wrapper sc-control-wrapper',\n '[class.ngx-control-wrapper--invalid]': 'errorDisplay.shouldShowErrors()',\n '[attr.aria-busy]': \"errorDisplay.isPending() ? 'true' : null\",\n },\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class ControlWrapperComponent implements AfterContentInit, OnDestroy {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n private readonly elementRef = inject(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n\n /**\n * Controls how this wrapper applies ARIA attributes to descendant controls.\n *\n * - `all-controls` (default, backwards compatible): apply `aria-describedby` / `aria-invalid`\n * to all `input/select/textarea` elements inside the wrapper.\n * - `single-control`: apply ARIA attributes only when exactly one control is found.\n * (Useful for wrappers that sometimes contain helper buttons/controls.)\n * - `none`: do not mutate descendant controls at all (group-safe mode).\n *\n * Notes:\n * - Use `none` when wrapping a container (e.g. `NgModelGroup`) to avoid stamping ARIA\n * across multiple child controls.\n * - This does not affect whether messages render; it only affects ARIA wiring.\n */\n readonly ariaAssociationMode = input<AriaAssociationMode>('all-controls');\n\n // Generate unique IDs for ARIA associations\n protected readonly uniqueId = `ngx-control-wrapper-${nextUniqueId++}`;\n protected readonly errorId = `${this.uniqueId}-error`;\n protected readonly warningId = `${this.uniqueId}-warning`;\n protected readonly pendingId = `${this.uniqueId}-pending`;\n\n // Track form controls found in the wrapper\n private readonly formControls = signal<HTMLElement[]>([]);\n\n // Signals when content is initialized so effects can safely touch the DOM.\n private readonly contentInitialized = signal(false);\n\n // MutationObserver to detect dynamically added/removed controls\n private mutationObserver: MutationObserver | null = null;\n\n /**\n * Debounced pending state to prevent flashing for quick async validations.\n * Uses createDebouncedPendingState utility with 500ms delay and 500ms minimum display.\n */\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n { showAfter: 500, minimumDisplay: 500 }\n );\n protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * Whether to display warnings.\n * Delegates to FormErrorDisplayDirective's centralized shouldShowWarnings signal.\n *\n * This ensures consistent warning display behavior across all form components\n * and supports the new 'on-dirty' and 'always' display modes.\n */\n protected readonly shouldShowWarnings = this.errorDisplay.shouldShowWarnings;\n\n /**\n * Computed signal that builds aria-describedby string based on visible regions\n */\n protected readonly ariaDescribedBy = computed(() => {\n const ids: string[] = [];\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n if (this.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n return ids.length > 0 ? ids.join(' ') : null;\n });\n\n /**\n * IDs managed by this wrapper when composing aria-describedby.\n *\n * We remove only these from the consumer-provided aria-describedby tokens and then\n * append the currently-relevant wrapper IDs. This prevents clobbering app-provided\n * hint/help text associations.\n */\n private readonly wrapperOwnedDescribedByIds = [\n this.errorId,\n this.warningId,\n this.pendingId,\n ];\n\n constructor() {\n // Effect to update aria-describedby and aria-invalid on form controls\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n if (mode === 'none') {\n return;\n }\n\n const describedBy = this.ariaDescribedBy();\n const wrapperActiveIds = parseAriaIdTokens(describedBy);\n const shouldShowErrors = this.errorDisplay.shouldShowErrors();\n\n const targets = resolveAssociationTargets(this.formControls(), mode);\n\n targets.forEach((control) => {\n // Update aria-describedby (merge, don't overwrite)\n const nextDescribedBy = mergeAriaDescribedBy(\n control.getAttribute('aria-describedby'),\n wrapperActiveIds,\n this.wrapperOwnedDescribedByIds\n );\n if (nextDescribedBy) {\n control.setAttribute('aria-describedby', nextDescribedBy);\n } else {\n control.removeAttribute('aria-describedby');\n }\n\n // Update aria-invalid\n if (shouldShowErrors) {\n control.setAttribute('aria-invalid', 'true');\n } else {\n control.removeAttribute('aria-invalid');\n }\n });\n });\n\n // Clean up MutationObserver when component is destroyed\n this.destroyRef.onDestroy(() => {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n });\n\n // Effect to enable/disable DOM observation based on ariaAssociationMode.\n // This keeps the wrapper cheap in group-safe mode.\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n\n if (mode === 'none') {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n if (this.formControls().length > 0) {\n this.formControls.set([]);\n }\n return;\n }\n\n // Ensure controls list is up to date.\n this.updateFormControls();\n\n // Ensure MutationObserver is installed (dynamic @if/@for support).\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => {\n this.updateFormControls();\n });\n\n this.mutationObserver.observe(this.elementRef.nativeElement, {\n childList: true,\n subtree: true,\n });\n }\n });\n }\n\n ngAfterContentInit(): void {\n this.contentInitialized.set(true);\n\n // ARIA wiring + observer setup is managed by effects so that the wrapper can\n // opt out (ariaAssociationMode=\"none\").\n }\n\n ngOnDestroy(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n }\n\n /**\n * Query and update the list of form controls within this wrapper.\n * Called on init and whenever the DOM structure changes.\n */\n private updateFormControls(): void {\n const controls = this.elementRef.nativeElement.querySelectorAll(\n 'input, select, textarea'\n );\n this.formControls.set(Array.from(controls) as HTMLElement[]);\n }\n}\n","<div class=\"ngx-control-wrapper__content\">\n <ng-content />\n</div>\n\n<!--\n WCAG 2.2 AA Compliance for Inline Field Validation:\n\n IMPORTANT DISTINCTION - Field-level vs Form-level errors:\n - FIELD-LEVEL errors (this component): Use role=\"status\" with aria-live=\"polite\"\n These are inline validation messages that appear as users interact with fields.\n Using \"assertive\" would be too disruptive when users are filling out multiple fields.\n - FORM-LEVEL blocking errors (e.g., submission failed): Should use role=\"alert\" with\n aria-live=\"assertive\" in a separate form-level error summary component.\n\n This component handles FIELD-LEVEL messages:\n - Errors: role=\"status\" with aria-live=\"polite\" (non-disruptive, field is already\n marked with aria-invalid=\"true\" and aria-describedby points here)\n - Warnings: role=\"status\" with aria-live=\"polite\" (informational, doesn't block)\n - Pending: role=\"status\" with aria-live=\"polite\" (status update)\n\n The aria-invalid=\"true\" + aria-describedby association on the input provides\n the primary accessibility pathway; the live region is supplementary.\n\n @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA21 - Using aria-invalid\n @see https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22 - Using role=status\n-->\n<div\n [id]=\"errorId\"\n class=\"text-sm text-red-600\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (errorDisplay.shouldShowErrors()) {\n <ul class=\"m-0 mt-1 list-none space-y-1 p-0\">\n @for (error of errorDisplay.errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n }\n</div>\n\n<!--\n Warnings: Non-blocking validation messages (Vest warn())\n - Use role=\"status\" with aria-live=\"polite\" per WCAG ARIA22\n - Default: show after validation runs or touch; configurable to require touch only\n - Warnings do NOT affect field validity - they're informational only\n-->\n<div\n [id]=\"warningId\"\n class=\"text-sm text-yellow-700\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (shouldShowWarnings()) {\n <ul class=\"m-0 mt-1 list-none space-y-1 p-0\">\n @for (warn of errorDisplay.warnings(); track warn) {\n <li>{{ warn }}</li>\n }\n </ul>\n }\n</div>\n\n<!-- Pending state is also stable; content appears only after the debounce delay -->\n<div\n [id]=\"pendingId\"\n class=\"absolute top-0 right-0 flex items-center gap-1 text-xs text-gray-500\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n>\n @if (showPendingMessage()) {\n <span\n class=\"inline-block h-3 w-3 animate-spin rounded-full border-2 border-gray-400 border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n Validating…\n }\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n} from '@angular/core';\nimport { FormErrorDisplayDirective } from '../../directives/form-error-display.directive';\nimport { createDebouncedPendingState } from '../../utils/pending-state.utils';\n\nlet nextUniqueId = 0;\n\n/**\n * Group-safe wrapper for `NgModelGroup` containers.\n *\n * This component renders group-level errors/warnings/pending UI, but intentionally\n * does **not** stamp `aria-describedby` / `aria-invalid` onto descendant controls.\n *\n * Use this when you want a wrapper around a container that has multiple inputs.\n * For single inputs, prefer `<ngx-control-wrapper>`.\n */\n@Component({\n selector:\n 'ngx-form-group-wrapper, sc-form-group-wrapper, [ngxFormGroupWrapper], [scFormGroupWrapper]',\n exportAs: 'ngxFormGroupWrapper',\n templateUrl: './form-group-wrapper.component.html',\n // Minimal structural styling: custom elements are inline by default.\n styles: `\n :host {\n display: block;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'ngx-form-group-wrapper sc-form-group-wrapper',\n '[class.ngx-form-group-wrapper--invalid]':\n 'errorDisplay.shouldShowErrors()',\n '[attr.aria-busy]': \"errorDisplay.isPending() ? 'true' : null\",\n },\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class FormGroupWrapperComponent {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n\n /**\n * Controls the debounce behavior for the pending message.\n * Defaults are conservative to avoid flashing.\n */\n readonly pendingDebounce = input<{\n showAfter: number;\n minimumDisplay: number;\n }>({\n showAfter: 500,\n minimumDisplay: 500,\n });\n\n protected readonly uniqueId = `ngx-form-group-wrapper-${nextUniqueId++}`;\n readonly errorId = `${this.uniqueId}-error`;\n readonly warningId = `${this.uniqueId}-warning`;\n readonly pendingId = `${this.uniqueId}-pending`;\n\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n this.pendingDebounce\n );\n protected readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * Helpful if consumers want to wire aria-describedby manually (e.g. fieldset/legend pattern).\n */\n readonly describedByIds = computed(() => {\n const ids: string[] = [];\n\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n\n if (this.errorDisplay.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n\n return ids.length > 0 ? ids.join(' ') : null;\n });\n}\n","<div class=\"ngx-form-group-wrapper__content\">\n <ng-content />\n</div>\n\n<!--\n Keep regions stable in the DOM so IDs are always valid targets.\n This wrapper does NOT modify descendant controls.\n-->\n<div [id]=\"errorId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (errorDisplay.shouldShowErrors() && errorDisplay.errors().length > 0) {\n <ul>\n @for (error of errorDisplay.errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n }\n</div>\n\n<div [id]=\"warningId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (errorDisplay.shouldShowWarnings()) {\n <ul>\n @for (warn of errorDisplay.warnings(); track warn) {\n <li>{{ warn }}</li>\n }\n </ul>\n }\n</div>\n\n<div [id]=\"pendingId\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (showPendingMessage()) {\n <span aria-hidden=\"true\">Validating…</span>\n }\n</div>\n","import {\n AfterContentInit,\n computed,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n signal,\n} from '@angular/core';\nimport {\n AriaAssociationMode,\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from '../utils/aria-association.utils';\nimport { createDebouncedPendingState } from '../utils/pending-state.utils';\nimport { FormErrorDisplayDirective } from './form-error-display.directive';\n\nlet nextUniqueId = 0;\n\n/**\n * Wires a control container to its error/warning/pending regions.\n *\n * This directive is intended for custom wrappers/components.\n * It composes `FormErrorDisplayDirective` (and thus `FormControlStateDirective`)\n * and applies `aria-invalid` / `aria-describedby` to descendant controls.\n *\n * It does not render any UI; you can use the generated IDs to render messages.\n */\n@Directive({\n selector: '[formErrorControl], [ngxErrorControl]',\n exportAs: 'formErrorControl, ngxErrorControl',\n hostDirectives: [\n {\n directive: FormErrorDisplayDirective,\n inputs: ['errorDisplayMode', 'warningDisplayMode'],\n },\n ],\n})\nexport class FormErrorControlDirective implements AfterContentInit, OnDestroy {\n protected readonly errorDisplay = inject(FormErrorDisplayDirective, {\n self: true,\n });\n\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n\n /**\n * Controls how this directive applies ARIA attributes to descendant controls.\n *\n * - `all-controls` (default): apply ARIA attributes to all input/select/textarea descendants.\n * - `single-control`: apply ARIA attributes only when exactly one control is found.\n * - `none`: do not mutate descendant controls.\n */\n readonly ariaAssociationMode = input<AriaAssociationMode>('all-controls');\n\n /**\n * Unique ID prefix for this instance.\n * Use these IDs to render message regions and to support aria-describedby.\n */\n protected readonly uniqueId = `ngx-error-control-${nextUniqueId++}`;\n readonly errorId = `${this.uniqueId}-error`;\n readonly warningId = `${this.uniqueId}-warning`;\n readonly pendingId = `${this.uniqueId}-pending`;\n\n private readonly formControls = signal<HTMLElement[]>([]);\n private readonly contentInitialized = signal(false);\n private mutationObserver: MutationObserver | null = null;\n\n private readonly pendingState = createDebouncedPendingState(\n this.errorDisplay.isPending,\n { showAfter: 500, minimumDisplay: 500 }\n );\n readonly showPendingMessage = this.pendingState.showPendingMessage;\n\n /**\n * aria-describedby value representing the *currently relevant* message regions.\n */\n readonly ariaDescribedBy = computed(() => {\n const ids: string[] = [];\n\n if (this.errorDisplay.shouldShowErrors()) {\n ids.push(this.errorId);\n }\n\n if (this.errorDisplay.shouldShowWarnings()) {\n ids.push(this.warningId);\n }\n\n if (this.showPendingMessage()) {\n ids.push(this.pendingId);\n }\n\n return ids.length > 0 ? ids.join(' ') : null;\n });\n\n private readonly ownedDescribedByIds: string[] = [\n this.errorId,\n this.warningId,\n this.pendingId,\n ];\n\n constructor() {\n // Effect for ARIA attribute updates\n effect(() => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n if (mode === 'none') return;\n\n const describedBy = this.ariaDescribedBy();\n const activeIds = parseAriaIdTokens(describedBy);\n const shouldShowErrors = this.errorDisplay.shouldShowErrors();\n\n const targets = resolveAssociationTargets(this.formControls(), mode);\n\n for (const control of targets) {\n const nextDescribedBy = mergeAriaDescribedBy(\n control.getAttribute('aria-describedby'),\n activeIds,\n this.ownedDescribedByIds\n );\n if (nextDescribedBy) {\n control.setAttribute('aria-describedby', nextDescribedBy);\n } else {\n control.removeAttribute('aria-describedby');\n }\n\n if (shouldShowErrors) {\n control.setAttribute('aria-invalid', 'true');\n } else {\n control.removeAttribute('aria-invalid');\n }\n }\n });\n\n // Effect for MutationObserver setup with proper cleanup\n effect((onCleanup) => {\n if (!this.contentInitialized()) return;\n\n const mode = this.ariaAssociationMode();\n\n if (mode === 'none') {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n if (this.formControls().length > 0) {\n this.formControls.set([]);\n }\n return;\n }\n\n this.updateFormControls();\n\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => {\n this.updateFormControls();\n });\n\n this.mutationObserver.observe(this.elementRef.nativeElement, {\n childList: true,\n subtree: true,\n });\n }\n\n // Proper cleanup using onCleanup callback (Angular 21 best practice)\n onCleanup(() => {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n });\n });\n }\n\n ngAfterContentInit(): void {\n this.contentInitialized.set(true);\n }\n\n ngOnDestroy(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n }\n\n private updateFormControls(): void {\n const controls = this.elementRef.nativeElement.querySelectorAll(\n 'input, select, textarea'\n );\n this.formControls.set(Array.from(controls) as HTMLElement[]);\n }\n}\n","import { isDevMode } from '@angular/core';\nimport { AbstractControl, ValidationErrors } from '@angular/forms';\nimport { Observable, from, of } from 'rxjs';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\ntype FieldResolver = (control: AbstractControl) => string;\n\ntype ValidationResult =\n | Observable<ValidationErrors | null>\n | Promise<ValidationErrors | null>\n | ValidationErrors\n | null;\n\n/**\n * @internal\n * Shared bridge for resolving a field path and invoking FormDirective async validation.\n * Keeps fail-open semantics for missing context/path while consolidating behavior.\n *\n * @param control - Control being validated by Angular forms.\n * @param context - Optional parent form directive context.\n * @param resolveField - Resolver that maps the control to a field path.\n * @param validationOptions - Per-control validation options.\n * @param source - Caller identifier for diagnostics.\n */\nexport function runAsyncValidationBridge(\n control: AbstractControl,\n context: FormDirective<Record<string, unknown>> | null,\n resolveField: FieldResolver,\n validationOptions: ValidationOptions,\n source: 'FormModelDirective' | 'FormModelGroupDirective'\n): Observable<ValidationErrors | null> {\n if (!control) {\n return of(null);\n }\n\n if (!context) {\n if (isDevMode()) {\n console.warn(\n `[ngx-vest-forms] ${source}: No FormDirective context found. Validation skipped (fail-open).`\n );\n }\n return of(null);\n }\n\n const field = resolveField(control);\n if (!field) {\n if (isDevMode()) {\n console.warn(\n `[ngx-vest-forms] ${source}: Could not resolve control path. Ensure the control has a valid name/path and is registered in the form tree.`\n );\n }\n return of(null);\n }\n\n const asyncValidator = context.createAsyncValidator(field, validationOptions);\n const validationResult: ValidationResult = asyncValidator(control);\n\n if (validationResult instanceof Observable) {\n return validationResult;\n }\n\n if (validationResult instanceof Promise) {\n return from(validationResult);\n }\n\n return of(validationResult ?? null);\n}\n","import { Directive, inject, input } from '@angular/core';\nimport {\n AbstractControl,\n AsyncValidator,\n NG_ASYNC_VALIDATORS,\n ValidationErrors,\n} from '@angular/forms';\nimport { Observable } from 'rxjs';\nimport { getFormGroupField } from '../utils/form-utils';\nimport { runAsyncValidationBridge } from './async-validator-bridge';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Hooks into `ngModelGroup`/`ngxModelGroup` and runs async group-level validation\n * through the parent `FormDirective` Vest suite bridge.\n */\n@Directive({\n selector: '[ngModelGroup],[ngxModelGroup]',\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: FormModelGroupDirective,\n multi: true,\n },\n ],\n})\nexport class FormModelGroupDirective implements AsyncValidator {\n /**\n * Per-group async validation options.\n *\n * Defaults to no debounce (`{ debounceTime: 0 }`).\n */\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n private readonly formDirective: FormDirective<\n Record<string, unknown>\n > | null = inject(FormDirective, { optional: true });\n\n /**\n * Runs async validation for the current model-group control.\n *\n * Returns `null` (fail-open) when used outside an `ngxVestForm` context.\n */\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n return runAsyncValidationBridge(\n control,\n this.formDirective,\n (currentControl) => {\n const context = this.formDirective;\n if (!context) return '';\n return getFormGroupField(context.ngForm.control, currentControl);\n },\n this.validationOptions(),\n 'FormModelGroupDirective'\n );\n }\n}\n","import { Directive, inject, input } from '@angular/core';\nimport {\n AbstractControl,\n AsyncValidator,\n NG_ASYNC_VALIDATORS,\n ValidationErrors,\n} from '@angular/forms';\nimport { Observable } from 'rxjs';\nimport { getFormControlField } from '../utils/form-utils';\nimport { runAsyncValidationBridge } from './async-validator-bridge';\nimport { FormDirective } from './form.directive';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Hooks into `ngModel`/`ngxModel` and runs async field-level validation\n * through the parent `FormDirective` Vest suite bridge.\n */\n@Directive({\n selector: '[ngModel],[ngxModel]',\n\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: FormModelDirective,\n multi: true,\n },\n ],\n})\nexport class FormModelDirective implements AsyncValidator {\n /**\n * Per-control async validation options.\n *\n * Defaults to no debounce (`{ debounceTime: 0 }`).\n */\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n /**\n * Reference to the form that needs to be validated\n * Injected optionally so that using ngModel outside of an ngxVestForm\n * does not crash the application. In that case, validation becomes a no-op.\n */\n private readonly formDirective: FormDirective<\n Record<string, unknown>\n > | null = inject(FormDirective, {\n optional: true,\n });\n\n /**\n * Runs field-level async validation for this control.\n *\n * Returns `null` (fail-open) when used outside an `ngxVestForm` context.\n */\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n return runAsyncValidationBridge(\n control,\n this.formDirective,\n (currentControl) => {\n const context = this.formDirective;\n if (!context) return '';\n return getFormControlField(context.ngForm.control, currentControl);\n },\n this.validationOptions(),\n 'FormModelDirective'\n );\n }\n}\n","import {\n AfterViewInit,\n booleanAttribute,\n DestroyRef,\n Directive,\n effect,\n inject,\n Injector,\n input,\n signal,\n untracked,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport {\n AbstractControl,\n AsyncValidator,\n AsyncValidatorFn,\n NG_ASYNC_VALIDATORS,\n NgForm,\n ValidationErrors,\n} from '@angular/forms';\nimport {\n catchError,\n map,\n Observable,\n of,\n switchMap,\n take,\n tap,\n timer,\n} from 'rxjs';\nimport { ROOT_FORM } from '../constants';\nimport { scheduleMicrotask } from '../utils/destroy-scheduler';\nimport { NgxTypedVestSuite, NgxVestSuite } from '../utils/validation-suite';\nimport { ValidationOptions } from './validation-options';\n\n/**\n * Validates the root form (cross-field validation) using a Vest suite.\n *\n * Use this directive for form-wide validations that span multiple fields, such as:\n * - Password confirmation (`password` must match `confirmPassword`)\n * - Date range validation (`startDate` must be before `endDate`)\n * - Business rules like \"at least one contact method required\"\n *\n * @usageNotes\n *\n * ### Basic Usage\n * ```html\n * <form ngxVestForm ngxValidateRootForm [suite]=\"suite\" (errorsChange)=\"errors.set($event)\">\n * <!-- form fields -->\n * @if (errors()['rootForm']) {\n * <div role=\"alert\">{{ errors()['rootForm'][0] }}</div>\n * }\n * </form>\n * ```\n *\n * ### Validation Modes\n * - `'submit'` (default): Validates only after form submission. Better UX for complex cross-field rules.\n * - `'live'`: Validates on every value change. Use sparingly for simple two-field comparisons.\n *\n * ```html\n * <form ngxVestForm ngxValidateRootForm [ngxValidateRootFormMode]=\"'live'\">\n * ```\n *\n * ### Vest Suite Pattern\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * test(ROOT_FORM, 'Passwords must match', () => {\n * enforce(model.confirmPassword).equals(model.password);\n * });\n * ```\n *\n * @see {@link https://github.com/ngx-vest-forms/ngx-vest-forms/blob/master/docs/VALIDATION-CONFIG-VS-ROOT-FORM.md}\n *\n * @example\n * ```html\n * <form scVestForm\n * validateRootForm\n * [suite]=\"suite\"\n * [formValue]=\"formValue()\"\n * [validateRootFormMode]=\"'submit'\"\n * (errorsChange)=\"errors.set($event)\"\n * #form=\"ngForm\">\n * <!-- form fields -->\n * @if (errors()['rootForm']) {\n * <div role=\"alert\">{{ errors()['rootForm'][0] }}</div>\n * }\n * </form>\n * ```\n *\n * @example\n * Validation suite:\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * export const suite = staticSuite((model, field?) => {\n * only(field);\n *\n * test(ROOT_FORM, 'Passwords must match', () => {\n * enforce(model.confirmPassword).equals(model.password);\n * });\n * });\n * ```\n *\n * @publicApi\n */\n@Directive({\n selector: 'form[validateRootForm], form[ngxValidateRootForm]',\n\n providers: [\n {\n provide: NG_ASYNC_VALIDATORS,\n useExisting: ValidateRootFormDirective,\n multi: true,\n },\n ],\n})\nexport class ValidateRootFormDirective<T>\n implements AsyncValidator, AfterViewInit\n{\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly lastControl = signal<NgForm | null>(null);\n validationOptions = input<ValidationOptions>({ debounceTime: 0 });\n private readonly hasSubmitted = signal(false);\n private readonly hasSubmitted$: Observable<boolean>;\n private readonly formValue$: Observable<T | null>;\n\n readonly formValue = input<T | null>(null);\n readonly suite = input<NgxVestSuite<T> | NgxTypedVestSuite<T> | null>(null);\n\n /**\n * Whether the root form should be validated or not\n * This will use the field rootForm\n * Accepts both validateRootForm and ngxValidateRootForm\n */\n readonly validateRootForm = input(false, {\n transform: booleanAttribute,\n });\n readonly ngxValidateRootForm = input(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Validation mode:\n * - `'submit'` (effective default): Only validates after form submission.\n * - `'live'`: Validates on every value change.\n *\n * Both inputs default to `undefined` so we can detect whether the consumer\n * set them explicitly. Precedence is `ngx ?? legacy ?? 'submit'`, which\n * matches the documented behavior — observable only when both attributes\n * are set explicitly on the same form.\n */\n readonly validateRootFormMode = input<'submit' | 'live' | undefined>(\n undefined\n );\n readonly ngxValidateRootFormMode = input<'submit' | 'live' | undefined>(\n undefined\n );\n\n constructor() {\n // Convert signals to Observables in injection context\n this.hasSubmitted$ = toObservable(this.hasSubmitted);\n this.formValue$ = toObservable(this.formValue);\n\n // Trigger validation when hasSubmitted or formValue changes\n effect(() => {\n // Track dependencies\n this.hasSubmitted();\n this.formValue();\n\n // Also track inputs that affect whether validation should run.\n // These can be set after the first validation pass and we want the\n // root form to re-evaluate once they become available.\n this.suite();\n this.validateRootForm();\n this.ngxValidateRootForm();\n this.validateRootFormMode();\n this.ngxValidateRootFormMode();\n this.validationOptions();\n\n // Trigger revalidation if form exists\n // Use emitEvent: true so the form directive can update its errors\n // Use untracked() to avoid making the effect reactive to lastControl changes\n const ngForm = untracked(() => this.lastControl());\n if (ngForm?.control) {\n // Defer to the next microtask so Angular has a chance to finish\n // wiring up controls/groups (ngModel/ngModelGroup) on initial render.\n // The scheduleMicrotask primitive auto-cancels if the directive is\n // destroyed before the microtask fires.\n scheduleMicrotask(() => ngForm.control.updateValueAndValidity(), this.destroyRef);\n }\n });\n }\n\n /**\n * Subscribe to form submit event using NgForm.ngSubmit EventEmitter\n * This approach avoids conflicts with component's (ngSubmit) handlers\n * Uses Injector to lazily get NgForm, avoiding circular dependency\n * (Directive → NgForm → AsyncValidators → Directive)\n */\n ngAfterViewInit(): void {\n // Lazily inject NgForm to avoid circular dependency\n const ngForm = this.injector.get(NgForm, null);\n this.lastControl.set(ngForm);\n\n if (!ngForm) {\n console.error(\n '[ValidateRootFormDirective] NgForm not found. Ensure the directive is used on a <form> element with the scVestForm directive. ' +\n 'Common setup mistakes: (1) Missing scVestForm directive, (2) Directive on non-form element, (3) NgForm not imported in module/component.'\n );\n return;\n }\n\n // Ensure we run at least one validation pass after the form is ready.\n // This matters for 'live' mode root-form errors that should appear\n // without requiring a user interaction.\n scheduleMicrotask(() => ngForm.control.updateValueAndValidity(), this.destroyRef);\n\n // Subscribe to form submission to set hasSubmitted flag\n ngForm.ngSubmit\n .pipe(\n tap(() => {\n this.hasSubmitted.set(true);\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe();\n }\n\n validate(control: AbstractControl): Observable<ValidationErrors | null> {\n // Skip validation if suite or formValue not set\n if (!this.suite() || !this.formValue()) {\n return of(null);\n }\n\n // Check both validateRootForm and ngxValidateRootForm inputs\n const isEnabled = this.validateRootForm() || this.ngxValidateRootForm();\n if (!isEnabled) {\n return of(null);\n }\n\n // Mode precedence: ngx-prefixed input wins over legacy input; both default\n // to `undefined` so the precedence rule is implementable without losing\n // the legacy attribute when the new one is not set.\n const mode =\n this.ngxValidateRootFormMode() ??\n this.validateRootFormMode() ??\n 'submit';\n\n // In 'submit' mode, skip validation until form is submitted\n if (mode === 'submit' && !this.hasSubmitted()) {\n return of(null);\n }\n\n // Call the validator and return its Observable\n // Angular expects this to complete after emitting once\n const validationResult = this.createAsyncValidator(\n ROOT_FORM,\n this.validationOptions()\n )(control) as Observable<ValidationErrors | null>;\n\n return validationResult;\n }\n\n createAsyncValidator(\n field: typeof ROOT_FORM,\n validationOptions: ValidationOptions\n ): AsyncValidatorFn {\n if (!this.suite()) {\n return () => of(null);\n }\n\n // Note: AsyncValidatorFn requires (control: AbstractControl) signature,\n // but root form validation uses formValue input (typed model) instead of control.value.\n // This is intentional - cross-field validation operates on the complete form model,\n // not individual control values. The underscore prefix indicates intentional non-use.\n\n return (_control: AbstractControl) => {\n const currentFormValue = this.formValue();\n if (!currentFormValue) {\n return of(null);\n }\n // Use the formValue input which contains the actual model data\n const mod = structuredClone(currentFormValue) as T;\n\n const debounce = validationOptions.debounceTime ?? 0;\n const source$ =\n debounce > 0 ? timer(debounce).pipe(map(() => mod)) : of(mod);\n\n return source$.pipe(\n switchMap((model) => {\n return new Observable((observer) => {\n try {\n const suite = this.suite();\n if (!suite) {\n observer.next(null);\n observer.complete();\n return;\n }\n // NOTE: `suite` can be a union of typed and untyped suite functions.\n // When calling a union of functions, TypeScript requires arguments\n // to satisfy all call signatures, which can produce overly-strict\n // errors in template type-checking. At runtime this is always the\n // ROOT_FORM field ('rootForm'), which is valid for both variants.\n const runSuite = suite as unknown as (\n model: T,\n field?: unknown\n ) => {\n done: (\n cb: (result: {\n getErrors: () => Record<string, string[]>;\n }) => void\n ) => void;\n };\n\n runSuite(model, field).done((result) => {\n const errors = result.getErrors()[field];\n // Return { errors: string[] } format expected by getAllFormErrors()\n observer.next(errors ? { errors } : null);\n observer.complete();\n });\n } catch (err) {\n console.error(\n '[validate-root-form] Validation suite error:',\n err\n );\n observer.next(null);\n observer.complete();\n }\n }) as Observable<ValidationErrors | null>;\n }),\n catchError((err) => {\n console.error('[validate-root-form] Observable error:', err);\n return of(null);\n }),\n take(1),\n takeUntilDestroyed(this.destroyRef)\n );\n };\n }\n}\n","import { Optional, Provider } from '@angular/core';\nimport {\n ControlContainer,\n FormsModule,\n NgForm,\n NgModelGroup,\n} from '@angular/forms';\nimport { ControlWrapperComponent } from './components/control-wrapper/control-wrapper.component';\nimport { FormGroupWrapperComponent } from './components/form-group-wrapper/form-group-wrapper.component';\nimport { FormControlStateDirective } from './directives/form-control-state.directive';\nimport { FormErrorControlDirective } from './directives/form-error-control.directive';\nimport { FormErrorDisplayDirective } from './directives/form-error-display.directive';\nimport { FormModelGroupDirective } from './directives/form-model-group.directive';\nimport { FormModelDirective } from './directives/form-model.directive';\nimport { FormDirective } from './directives/form.directive';\nimport { ValidateRootFormDirective } from './directives/validate-root-form.directive';\n\n/**\n * This is borrowed from [https://github.com/wardbell/ngc-validate/blob/main/src/app/core/form-container-view-provider.ts](https://github.com/wardbell/ngc-validate/blob/main/src/app/core/form-container-view-provider.ts)\n * Thank you so much Ward Bell for your effort!:\n *\n * Provide a ControlContainer to a form component from the\n * nearest parent NgModelGroup (preferred) or NgForm.\n *\n * Required for Reactive Forms as well (unless you write CVA)\n *\n * @example\n * ```\n * @Component({\n * ...\n * viewProviders[ formViewProvider ]\n * })\n * ```\n * @see Kara's AngularConnect 2017 talk: https://youtu.be/CD_t3m2WMM8?t=1826\n *\n * Without this provider\n * - Controls are not registered with parent NgForm or NgModelGroup\n * - Form-level flags say \"untouched\" and \"valid\"\n * - No form-level validation roll-up\n * - Controls still validate, update model, and update their statuses\n * - If within NgForm, no compiler error because ControlContainer is optional for ngModel\n *\n * Note: if the SubForm Component that uses this Provider\n * is not within a Form or NgModelGroup, the provider returns `null`\n * resulting in an error, something like\n * ```\n * preview-fef3604083950c709c52b.js:1 ERROR Error:\n * ngModelGroup cannot be used with a parent formGroup directive.\n *```\n */\nconst formViewProvider: Provider = {\n provide: ControlContainer,\n useFactory: _formViewProviderFactory,\n deps: [\n [new Optional(), NgForm],\n [new Optional(), NgModelGroup],\n ],\n};\n\nfunction _formViewProviderFactory(ngForm: NgForm, ngModelGroup: NgModelGroup) {\n return ngModelGroup || ngForm || null;\n}\n\n/**\n * The providers we need in every child component that holds an ngModelGroup\n */\nexport const vestFormsViewProviders = [\n { provide: ControlContainer, useExisting: NgForm },\n formViewProvider, // very important if we want nested components with ngModelGroup\n];\n\n/**\n * Collection of directives, components, and modules required for ngx-vest-forms.\n *\n * This array exports all the necessary components and directives to enable\n * Vest validation integration with Angular template-driven forms.\n *\n * @example\n * ```typescript\n * import { NgxVestForms } from 'ngx-vest-forms';\n *\n * @Component({\n *\n * imports: [NgxVestForms],\n * /// ...\n * })\n * export class MyComponent { }\n * ```\n */\nexport const NgxVestForms = [\n ValidateRootFormDirective,\n ControlWrapperComponent,\n FormGroupWrapperComponent,\n FormControlStateDirective,\n FormErrorDisplayDirective,\n FormErrorControlDirective,\n FormDirective,\n FormsModule,\n FormModelDirective,\n FormModelGroupDirective,\n] as const;\n\n/**\n * @deprecated Use `NgxVestForms` instead\n */\nexport const vestForms = NgxVestForms;\n","/**\n * Primitive types that should not be traversed for nested paths\n */\ntype Primitive = string | number | boolean | Date | null | undefined;\n\n/**\n * Helper type to extract the element type from an array.\n * Used internally for type inference with array paths.\n *\n * @template T - The array type to extract from\n * @example\n * ```typescript\n * type Element = ArrayElement<string[]>; // Result: string\n * type Element2 = ArrayElement<NotArray>; // Result: never\n * ```\n */\n\n/**\n * Recursively generates all valid field paths for a type as string literals.\n * This provides full IDE autocomplete and compile-time validation for field names.\n *\n * **Key Features:**\n * - Supports nested objects with dot notation (e.g., 'user.address.city')\n * - Works with optional properties from DeepPartial types\n * - Handles arrays and readonly arrays\n * - Stops recursion at primitive types\n * - Maximum depth of 10 levels to prevent infinite recursion\n *\n * **Type Safety Benefits:**\n * - IDE autocomplete for all valid field paths\n * - Compile-time errors for typos in field names\n * - Refactoring support (rename property → all usages update)\n * - Self-documenting code through type inference\n *\n * @template T - The model type to extract field paths from\n * @template Prefix - Internal recursion prefix (do not use directly)\n * @template Depth - Internal depth counter to prevent infinite recursion\n *\n * @example\n * ```typescript\n * type Model = {\n * name: string;\n * profile: {\n * age: number;\n * address: {\n * city: string;\n * }\n * }\n * };\n *\n * type Paths = FieldPath<Model>;\n * /// Result: 'name' | 'profile' | 'profile.age' | 'profile.address' | 'profile.address.city'\n * ```\n *\n * @example With DeepPartial\n * ```typescript\n * type FormModel = DeepPartial<{\n * user: {\n * email: string;\n * phone: string;\n * }\n * }>;\n *\n * type Paths = FieldPath<FormModel>;\n * /// Result: 'user' | 'user.email' | 'user.phone'\n * ```\n */\nexport type FieldPath<\n T,\n Prefix extends string = '',\n Depth extends readonly number[] = [],\n> = Depth['length'] extends 10\n ? never // Max depth reached, prevent infinite recursion\n : T extends Primitive\n ? never // Don't traverse primitives\n : T extends ReadonlyArray<infer U>\n ? // For arrays, generate paths for the element type\n FieldPath<U, Prefix, [...Depth, 1]>\n : {\n [K in keyof T & string]: T[K] extends Primitive\n ? // Primitive property: just the field name\n `${Prefix}${K}`\n : T[K] extends ReadonlyArray<infer U>\n ? // Array property: field name plus element paths\n | `${Prefix}${K}`\n | (U extends Primitive\n ? never\n : FieldPath<U, `${Prefix}${K}.`, [...Depth, 1]>)\n : // Object property: field name plus nested paths\n | `${Prefix}${K}`\n | FieldPath<T[K], `${Prefix}${K}.`, [...Depth, 1]>;\n }[keyof T & string];\n\n/**\n * Type-safe validation configuration map.\n * Maps trigger field paths to arrays of dependent field paths that should be revalidated.\n *\n * **Use Case:**\n * Define which fields should trigger validation of other fields when they change.\n * For example, when password changes, confirmPassword should be revalidated.\n *\n * **Type Safety:**\n * - All keys must be valid field paths from the model\n * - All dependent field paths must be valid\n * - IDE autocomplete works for both keys and values\n * - Compile-time errors for invalid field references\n *\n * @template T - The form model type\n *\n * @example\n * ```typescript\n * type FormModel = DeepPartial<{\n * password: string;\n * confirmPassword: string;\n * addresses: {\n * billing: { city: string; }\n * }\n * }>;\n *\n * /// ✅ Type-safe configuration with autocomplete\n * const config: ValidationConfigMap<FormModel> = {\n * password: ['confirmPassword'],\n * 'addresses.billing.city': ['password'],\n * };\n *\n * /// ❌ TypeScript error - invalid field name\n * const badConfig: ValidationConfigMap<FormModel> = {\n * passwordd: ['confirmPassword'], // Typo caught at compile time\n * };\n * ```\n */\nexport type ValidationConfigMap<T> = Partial<\n Record<FieldPath<T>, Array<FieldPath<T>>>\n>;\n\n/**\n * Type-safe field name for use in Vest test() calls and form APIs.\n * Combines valid field paths with the special ROOT_FORM constant.\n *\n * **Use Case:**\n * When defining Vest test() calls, use this type for the field parameter\n * to get autocomplete and type safety.\n *\n * **Special Values:**\n * - Any valid FieldPath from the model\n * - ROOT_FORM constant for form-level validations\n *\n * @template T - The form model type\n *\n * @example\n * ```typescript\n * import { ROOT_FORM } from 'ngx-vest-forms';\n *\n * type FormModel = DeepPartial<{\n * email: string;\n * user: { name: string; }\n * }>;\n *\n * export const suite = staticSuite(\n * (data: FormModel, field?: FormFieldName<FormModel>) => {\n * only(field);\n *\n * /// ✅ Autocomplete works\n * test('email', 'Required', () => {\n * enforce(data.email).isNotBlank();\n * });\n *\n * test('user.name', 'Required', () => {\n * enforce(data.user?.name).isNotBlank();\n * });\n *\n * /// Form-level validation\n * test(ROOT_FORM, 'At least one contact method', () => {\n * enforce(data.email || data.user?.name).isTruthy();\n * });\n * }\n * );\n * ```\n */\nexport type FormFieldName<T> = FieldPath<T> | typeof ROOT_FORM;\n\n// Re-export ROOT_FORM for convenience\nimport { ROOT_FORM } from '../constants';\nexport { ROOT_FORM };\n\n/**\n * Helper type to infer the value type at a given field path.\n * Useful for creating type-safe utilities that work with field paths.\n *\n * @template T - The model type\n * @template Path - The field path string\n *\n * @example\n * ```typescript\n * type Model = {\n * user: {\n * profile: {\n * age: number;\n * }\n * }\n * };\n *\n * type AgeType = FieldPathValue<Model, 'user.profile.age'>;\n * /// Result: number\n * ```\n */\nexport type FieldPathValue<T, Path extends string> = Path extends keyof T\n ? T[Path]\n : Path extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? FieldPathValue<NonNullable<T[K]>, Rest>\n : never\n : never;\n\n/**\n * Utility type to check if a path is valid for a given model.\n * Returns the path if valid, never otherwise.\n *\n * @template T - The model type\n * @template Path - The path to validate\n *\n * @example\n * ```typescript\n * type Model = { name: string; age: number; };\n *\n * type Valid = ValidateFieldPath<Model, 'name'>; // 'name'\n * type Invalid = ValidateFieldPath<Model, 'invalid'>; // never\n * ```\n */\nexport type ValidateFieldPath<T, Path extends string> =\n Path extends FieldPath<T> ? Path : never;\n\n/**\n * Extract all leaf field paths (paths that point to primitive values).\n * Useful when you only want paths to actual values, not intermediate objects.\n *\n * @template T - The model type\n *\n * @example\n * ```typescript\n * type Model = {\n * user: {\n * name: string;\n * profile: {\n * age: number;\n * }\n * }\n * };\n *\n * type Leaves = LeafFieldPath<Model>;\n * /// Result: 'user.name' | 'user.profile.age'\n * /// Note: 'user' and 'user.profile' are excluded (not leaves)\n * ```\n */\nexport type LeafFieldPath<\n T,\n Prefix extends string = '',\n Depth extends readonly number[] = [],\n> = Depth['length'] extends 10\n ? never\n : T extends Primitive\n ? never\n : T extends ReadonlyArray<infer U>\n ? LeafFieldPath<U, Prefix, [...Depth, 1]>\n : {\n [K in keyof T & string]: T[K] extends Primitive\n ? `${Prefix}${K}`\n : T[K] extends ReadonlyArray<infer U>\n ? U extends Primitive\n ? never\n : LeafFieldPath<U, `${Prefix}${K}.`, [...Depth, 1]>\n : LeafFieldPath<T[K], `${Prefix}${K}.`, [...Depth, 1]>;\n }[keyof T & string];\n","/**\n * Represents the state of a form managed by scVestForm directive.\n * This is the structure returned by NgxVestFormDirective.formState() or similar.\n */\nexport type NgxFormState<TModel = unknown> = {\n /** Whether the form is valid */\n valid: boolean;\n /** Map of field errors by field path */\n errors: Record<string, string[]>;\n /** Current form value (includes disabled fields) */\n value: TModel | null;\n};\n\n/**\n * Creates an empty NgxFormState with default values.\n *\n * This utility is helpful when you need to provide a fallback for components\n * that require a non-null NgxFormState, such as when child components\n * might not be initialized yet.\n *\n * @template TModel The type of the form model/value\n * @returns A complete NgxFormState object with empty/default values\n *\n * @example\n * ```typescript\n * /// In a parent component that displays child form state\n * protected readonly formState = computed(() =>\n * this.childForm()?.formState() ?? createEmptyFormState()\n * );\n * ```\n *\n * @example\n * ```typescript\n * /// With specific typing\n * interface MyFormModel {\n * name: string;\n * email: string;\n * }\n *\n * const emptyState = createEmptyFormState<MyFormModel>();\n * ```\n */\nexport function createEmptyFormState<TModel = unknown>(): NgxFormState<TModel> {\n return {\n value: null,\n errors: {},\n valid: true,\n };\n}\n","import type { FieldPath, ValidationConfigMap } from './field-path-types';\n\n// NOTE: `typeof ngDevMode !== 'undefined' && ngDevMode` is kept inline\n// (not extracted to a helper) because Angular's build optimizer relies on\n// this exact pattern for tree-shaking dev-only code from production bundles.\nconst LOG_PREFIX = '[ngx-vest-forms] ValidationConfigBuilder';\n\n/**\n * Fluent builder for creating type-safe validation configurations.\n *\n * Provides convenience methods for common validation dependency patterns:\n * - **`whenChanged()`**: One-way dependencies (when A changes, revalidate B)\n * - **`bidirectional()`**: Two-way dependencies (A ↔ B revalidate each other)\n * - **`group()`**: All fields in group revalidate each other\n * - **`merge()`**: Combine with existing configurations\n *\n * @template T - The form model type\n *\n * @example Basic usage\n * ```typescript\n * const config = createValidationConfig<MyFormModel>()\n * .whenChanged('password', 'confirmPassword')\n * .bidirectional('startDate', 'endDate')\n * .build();\n * ```\n *\n * @example Complex scenario\n * ```typescript\n * const config = createValidationConfig<OrderFormModel>()\n * .group(['firstName', 'lastName', 'email'])\n * .whenChanged('country', ['state', 'zipCode'])\n * .bidirectional('minPrice', 'maxPrice')\n * .merge(existingConfig)\n * .build();\n * ```\n */\nexport class ValidationConfigBuilder<T> {\n private config: Partial<Record<string, string[]>> = {};\n\n /**\n * Add a one-way dependency: when `trigger` changes, revalidate `dependents`.\n *\n * This method is cumulative - calling it multiple times with the same trigger\n * will merge all dependents together.\n *\n * **When to Use:**\n * - ✅ Conditional field requirements (country → state/zipCode)\n * - ✅ Calculated fields (quantity/price → total)\n * - ✅ Dependent validations where only one direction matters\n * - ✅ Cascading validations (A changes → B needs revalidation → C needs revalidation)\n *\n * **Real-World Use Case:**\n * In an e-commerce checkout form, when the user selects a country, the available\n * states/provinces and zip code format validation rules change. The country field\n * needs to trigger revalidation of state and zipCode, but changes to state/zipCode\n * don't need to revalidate country (one-way dependency).\n *\n * **Vest.js Patterns That Work Well:**\n * - `skipWhen(res => res.hasErrors('trigger'), () => { test('dependent', ...) })` -\n * Skip expensive validations on dependent field until trigger field is valid\n * - Async validations on dependent fields that need the trigger's value\n * - Calculated field validations (e.g., total depends on quantity × price)\n * - Conditional `omitWhen` based on trigger field state\n *\n * @param trigger - The field that triggers revalidation\n * @param revalidate - Single field or array of fields to revalidate\n * @returns This builder instance for method chaining\n *\n * @example Single dependent\n * ```typescript\n * builder.whenChanged('password', 'confirmPassword');\n * /// Result: { password: ['confirmPassword'] }\n * ```\n *\n * @example Multiple dependents\n * ```typescript\n * builder.whenChanged('country', ['state', 'zipCode', 'postalCode']);\n * /// Result: { country: ['state', 'zipCode', 'postalCode'] }\n * ```\n *\n * @example Cumulative calls\n * ```typescript\n * builder\n * .whenChanged('password', 'confirmPassword')\n * .whenChanged('password', 'securityScore');\n * /// Result: { password: ['confirmPassword', 'securityScore'] }\n * ```\n */\n whenChanged<K extends FieldPath<T>>(\n trigger: K,\n revalidate: FieldPath<T> | ReadonlyArray<FieldPath<T>>\n ): this {\n const deps = Array.isArray(revalidate) ? revalidate : [revalidate];\n const existing = (this.config[trigger] || []) as Array<FieldPath<T>>;\n\n // Development mode warning for duplicate dependents\n if (typeof ngDevMode !== 'undefined' && ngDevMode) {\n const duplicates = deps.filter((d) => existing.includes(d));\n if (duplicates.length > 0) {\n console.warn(\n `${LOG_PREFIX}: Duplicate dependencies detected.\\n` +\n ` Trigger: '${trigger}'\\n` +\n ` Duplicates: ${duplicates.map((d) => `'${d}'`).join(', ')}\\n` +\n ` These will be automatically deduplicated.`\n );\n }\n }\n\n // Deduplicate dependents\n const merged = [...existing, ...deps];\n this.config[trigger] = Array.from(new Set(merged));\n\n return this;\n }\n\n /**\n * Add bidirectional dependency: when either field changes, revalidate the other.\n *\n * This is a convenience method that calls `whenChanged()` in both directions.\n * Commonly used for password/confirmPassword, min/max ranges, start/end dates.\n *\n * **When to Use:**\n * - ✅ Password confirmation (password ↔ confirmPassword)\n * - ✅ Min/max range validation (minPrice ↔ maxPrice, minAge ↔ maxAge)\n * - ✅ Start/end date validation (startDate ↔ endDate)\n * - ✅ Any field comparison where both fields need mutual revalidation\n *\n * **Real-World Use Case:**\n * In a job posting form, when setting salary range, changing either minSalary or\n * maxSalary should revalidate the other to ensure minSalary ≤ maxSalary. Users\n * can change either field first, so both directions need validation. This prevents\n * invalid ranges like \"$80k min, $50k max\".\n *\n * **Vest.js Patterns That Work Well:**\n * - Comparison validations: `enforce(data.min).lessThanOrEquals(data.max)`\n * - Password matching: `enforce(data.password).equals(data.confirmPassword)`\n * - Date range validation with `enforce(data.startDate).lessThan(data.endDate)`\n * - `skipWhen` to prevent comparison when either field has errors:\n * ```typescript\n * skipWhen(res => res.hasErrors('field1') || res.hasErrors('field2'), () => {\n * test('field1', 'Min must be ≤ Max', () => enforce(min).lessThanOrEquals(max));\n * });\n * ```\n *\n * @param field1 - First field in the bidirectional relationship\n * @param field2 - Second field in the bidirectional relationship\n * @returns This builder instance for method chaining\n *\n * @example Password confirmation\n * ```typescript\n * builder.bidirectional('password', 'confirmPassword');\n * /// Result: {\n * /// password: ['confirmPassword'],\n * /// confirmPassword: ['password']\n * /// }\n * ```\n *\n * @example Date range\n * ```typescript\n * builder.bidirectional('startDate', 'endDate');\n * /// Result: {\n * /// startDate: ['endDate'],\n * /// endDate: ['startDate']\n * /// }\n * ```\n */\n bidirectional<K1 extends FieldPath<T>, K2 extends FieldPath<T>>(\n field1: K1,\n field2: K2\n ): this {\n // Development mode warning for exact duplicate\n if (typeof ngDevMode !== 'undefined' && ngDevMode) {\n const hasField1ToField2 =\n this.config[field1]?.includes(field2 as string) ?? false;\n const hasField2ToField1 =\n this.config[field2]?.includes(field1 as string) ?? false;\n\n if (hasField1ToField2 && hasField2ToField1) {\n console.warn(\n `${LOG_PREFIX}: Duplicate bidirectional relationship detected.\\n` +\n ` Fields: '${field1}' ↔ '${field2}'\\n` +\n ` This bidirectional relationship was already configured.`\n );\n }\n }\n\n this.whenChanged(field1, field2);\n this.whenChanged(field2, field1);\n return this;\n }\n\n /**\n * Create a validation group where all fields revalidate each other.\n *\n * When any field in the group changes, all other fields in the group are revalidated.\n * This is useful for fields that collectively form a validation rule.\n *\n * **When to Use:**\n * - ✅ \"At least one required\" scenarios (email OR phone OR address)\n * - ✅ Interdependent field sets (credit card: number + expiry + CVV)\n * - ✅ Contact information (firstName + lastName + email)\n * - ✅ Fields that collectively satisfy a business rule\n *\n * **Real-World Use Case:**\n * In a customer registration form with a \"at least one contact method required\"\n * business rule, the validation suite checks `email || phone || mailingAddress`.\n * When user fills any of these fields, the other fields need revalidation to clear\n * the \"at least one required\" error. All three fields are interdependent, so\n * grouping them ensures validation updates correctly regardless of which field\n * the user fills first.\n *\n * **Vest.js Patterns That Work Well:**\n * - \"At least one required\" logic:\n * ```typescript\n * test('email', 'Provide at least one contact method', () => {\n * enforce(data.email || data.phone || data.address).isTruthy();\n * });\n * ```\n * - Interdependent field validation where all fields collectively satisfy a rule\n * - Credit card validation (number + expiry + CVV all need each other)\n * - Use `optional()` for groups where fields can all be empty together:\n * ```typescript\n * optional(['email', 'phone', 'address']);\n * ```\n *\n * **Performance Note:** This creates N×(N-1) dependencies, which can impact\n * performance for large groups. Consider using `whenChanged()` for more targeted\n * dependencies if performance is a concern (e.g., groups > 10 fields).\n *\n * @param fields - Array of fields that should all revalidate each other\n * @returns This builder instance for method chaining\n *\n * @example Contact information group\n * ```typescript\n * builder.group(['firstName', 'lastName', 'email']);\n * /// Result: {\n * /// firstName: ['lastName', 'email'],\n * /// lastName: ['firstName', 'email'],\n * /// email: ['firstName', 'lastName']\n * /// }\n * ```\n *\n * @example Address validation group\n * ```typescript\n * builder.group(['street', 'city', 'state', 'zipCode']);\n * ```\n */\n group<K extends FieldPath<T>>(fields: readonly K[]): this {\n // Each field triggers validation of all other fields in the group\n for (const field of fields) {\n const others = fields.filter((f) => f !== field);\n this.whenChanged(field, others);\n }\n return this;\n }\n\n /**\n * Merge with an existing validation configuration.\n *\n * This method is useful for:\n * - Combining base configurations with conditional configurations\n * - Composing configurations from multiple sources\n * - Adding dynamic configurations based on runtime conditions\n *\n * **When to Use:**\n * - ✅ Conditional features (international shipping adds customs fields)\n * - ✅ Reusable configuration modules (address config, payment config)\n * - ✅ Dynamic forms where validation rules change at runtime\n * - ✅ Feature flags or A/B testing variations\n *\n * **Real-World Use Case:**\n * In an e-commerce checkout, your form has base validation (shipping address,\n * payment info). When user selects international shipping, you need additional\n * validations (customs declaration, tax ID). Instead of duplicating the base\n * config, use `merge()` to conditionally add the international validation rules.\n * This keeps your code DRY and makes it easy to toggle features on/off.\n *\n * **Vest.js Patterns That Work Well:**\n * - Conditional features with `omitWhen`:\n * ```typescript\n * omitWhen(!isInternational, () => {\n * test('customsForm', 'Customs declaration required', () => {\n * enforce(data.customsForm).isNotBlank();\n * });\n * });\n * ```\n * - Reusable validation modules that can be composed\n * - Feature flags: merge different configs based on enabled features\n * - A/B testing: conditionally merge test-specific validation rules\n * - Use with computed signals for reactive configuration:\n * ```typescript\n * const config = computed(() =>\n * createValidationConfig<T>()\n * .merge(baseConfig)\n * .merge(featureEnabled() ? featureConfig : {})\n * .build()\n * );\n * ```\n *\n * **Note:** Dependencies are merged and deduplicated. If both configs have\n * the same trigger field, dependents are combined into a single array.\n *\n * @param other - Existing ValidationConfigMap to merge\n * @returns This builder instance for method chaining\n *\n * @example Conditional configuration\n * ```typescript\n * const baseConfig = createValidationConfig<FormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .build();\n *\n * const config = createValidationConfig<FormModel>()\n * .merge(baseConfig)\n * .merge(\n * isInternational\n * ? { country: ['customsForm'] }\n * : {}\n * )\n * .build();\n * ```\n *\n * @example Composition\n * ```typescript\n * const addressConfig = { 'street': ['city', 'zipCode'] };\n * const contactConfig = { 'email': ['phone'] };\n *\n * const config = createValidationConfig<FormModel>()\n * .merge(addressConfig)\n * .merge(contactConfig)\n * .build();\n * ```\n */\n merge(other: ValidationConfigMap<T>): this {\n for (const [key, deps] of Object.entries(other)) {\n if (deps && Array.isArray(deps)) {\n const existing = this.config[key] || [];\n const merged = [...existing, ...deps];\n this.config[key] = Array.from(new Set(merged));\n }\n }\n return this;\n }\n\n /**\n * Build the final validation configuration object.\n *\n * Returns a deep copy of the configuration to prevent accidental mutations.\n * The returned object can be used with the `validationConfig` input of `scVestForm`.\n *\n * @returns Immutable ValidationConfigMap ready for use\n *\n * @example\n * ```typescript\n * protected readonly validationConfig = createValidationConfig<MyFormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .whenChanged('country', 'state')\n * .build();\n * ```\n */\n build(): ValidationConfigMap<T> {\n // Return a deep copy to prevent external mutations affecting the builder\n const copy: Partial<Record<string, string[]>> = {};\n for (const [key, deps] of Object.entries(this.config)) {\n if (deps && Array.isArray(deps)) {\n copy[key] = [...deps];\n }\n }\n return copy as ValidationConfigMap<T>;\n }\n}\n\n/**\n * Factory function to create a type-safe validation configuration builder.\n *\n * This is the recommended entry point for creating validation configurations.\n * It provides full type safety and IDE autocomplete for field names.\n *\n * @template T - The form model type\n * @returns A new ValidationConfigBuilder instance\n *\n * @example Basic usage\n * ```typescript\n * protected readonly validationConfig = createValidationConfig<FormModel>()\n * .bidirectional('password', 'confirmPassword')\n * .whenChanged('country', 'state')\n * .build();\n * ```\n *\n * @example With DeepPartial form model\n * ```typescript\n * type FormModel = DeepPartial<{\n * user: {\n * profile: {\n * email: string;\n * phone: string;\n * }\n * }\n * }>;\n *\n * const config = createValidationConfig<FormModel>()\n * .bidirectional('user.profile.email', 'user.profile.phone')\n * .build();\n * ```\n *\n * @example Complex scenario with all methods\n * ```typescript\n * const config = createValidationConfig<OrderFormModel>()\n * .group(['firstName', 'lastName', 'email'])\n * .bidirectional('startDate', 'endDate')\n * .bidirectional('minPrice', 'maxPrice')\n * .whenChanged('orderType', ['deliveryDate', 'priority'])\n * .whenChanged('country', ['state', 'zipCode'])\n * .merge(conditionalConfig)\n * .build();\n * ```\n */\nexport function createValidationConfig<T>(): ValidationConfigBuilder<T> {\n return new ValidationConfigBuilder<T>();\n}\n","/**\n * Converts a flat array to an object with numeric keys.\n * Does not recurse into nested arrays or objects.\n * Uses reduce() for optimal single-pass conversion.\n */\nexport type DeepArrayToObject<T> =\n T extends ReadonlyArray<infer U>\n ? Record<number, DeepArrayToObject<U>>\n : T extends object\n ? { [K in keyof T]: DeepArrayToObject<T[K]> }\n : T;\n\nexport function arrayToObject<T>(array: readonly T[]): Record<number, T> {\n return array.reduce(\n (acc, value, index) => {\n acc[index] = value;\n return acc;\n },\n {} as Record<number, T>\n );\n}\n\n/**\n * Recursively converts arrays to objects with numeric keys, including nested arrays in objects.\n * Useful for template-driven forms that require object structure for nested arrays.\n */\nexport function deepArrayToObject<T>(\n array: readonly T[]\n): Record<number, DeepArrayToObject<T>> {\n return Object.fromEntries(\n array.map((value, index) => [\n index,\n Array.isArray(value)\n ? deepArrayToObject(value as unknown[])\n : value && typeof value === 'object'\n ? recursivelyConvertArrays(value)\n : value,\n ])\n ) as Record<number, DeepArrayToObject<T>>;\n}\n\n/**\n * Recursively traverses an object and converts any nested arrays to objects.\n */\nfunction recursivelyConvertArrays<T>(object: T): DeepArrayToObject<T> {\n if (Array.isArray(object)) {\n return deepArrayToObject(object as unknown[]) as DeepArrayToObject<T>;\n }\n if (object && typeof object === 'object') {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [\n key,\n Array.isArray(value)\n ? deepArrayToObject(value as unknown[])\n : value && typeof value === 'object'\n ? recursivelyConvertArrays(value)\n : value,\n ])\n ) as DeepArrayToObject<T>;\n }\n return object as DeepArrayToObject<T>;\n}\n\n/**\n * Converts selected numeric-keyed object properties back to arrays.\n * Only properties listed in keys will be converted; others remain untouched.\n * Useful for converting form models back to array format before saving/sending to backend.\n */\n\n/**\n * Public API: Convert selected numeric-keyed object properties back to arrays.\n * Note: Conversion is explicit (by key) but will cascade inside converted branches\n * so nested numeric objects representing arrays become real arrays recursively.\n */\nexport function objectToArray<const K extends readonly string[]>(\n object: unknown,\n keys: K\n): unknown {\n const processed = objectToArrayInternal(object, keys);\n if (processed && typeof processed === 'object' && !Array.isArray(processed)) {\n const entries: Array<[string, unknown]> = Object.entries(\n processed as Record<string, unknown>\n );\n if (entries.length === 1) {\n const firstEntry = entries[0];\n if (!firstEntry) {\n return processed;\n }\n const [k, v] = firstEntry;\n if (\n keys.includes(k) &&\n Array.isArray(v) &&\n (v as unknown[]).every(\n (element) => typeof element === 'object' && element !== null\n )\n ) {\n return v;\n }\n }\n }\n return processed;\n}\n\n/**\n * Internal recursive worker with cascade flag: once a targeted key is converted, all nested numeric objects become arrays even if their keys were not explicitly listed.\n */\nfunction objectToArrayInternal(\n object: unknown,\n keys: readonly string[],\n currentKey?: string,\n parentCascade = false\n): unknown {\n if (Array.isArray(object)) {\n // Recursively process each item in the array\n return object.map((item) =>\n objectToArrayInternal(item, keys, undefined, parentCascade)\n );\n }\n\n if (object && typeof object === 'object') {\n if (isNumericObject(object)) {\n // First, recursively process the contents\n const processedContents: Record<string, unknown> = {};\n let hasChanges = false;\n\n const explicit = !!currentKey && keys.includes(currentKey);\n const childCascade = parentCascade || explicit;\n\n for (const [key, value] of Object.entries(object)) {\n const processedValue = objectToArrayInternal(\n value,\n keys,\n key,\n childCascade\n );\n processedContents[key] = processedValue;\n if (processedValue !== value) {\n hasChanges = true;\n }\n }\n\n // Decision: should we convert this numeric object to an array?\n // Yes, if: explicitly targeted, parent was converted, or children changed.\n const shouldConvert = explicit || parentCascade || hasChanges;\n\n return shouldConvert\n ? Object.keys(processedContents)\n .sort((a, b) => Number(a) - Number(b))\n .map((k) => processedContents[k])\n : processedContents;\n }\n\n // For regular objects, process recursively\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n result[key] = objectToArrayInternal(value, keys, key, parentCascade);\n }\n return result;\n }\n\n return object;\n}\n\n/**\n * Checks if a value is an object with only numeric keys (not an array).\n */\nfunction isNumericObject(value: unknown): value is Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.keys(value).every((k) => /^\\d+$/.test(k));\n}\n","/**\n * Utility functions for managing form field state in dynamic forms.\n * These functions help maintain component state consistency when form structure changes.\n */\n\n/**\n * Conditionally clears fields from form state based on provided conditions.\n *\n * **CRITICAL: When This Utility is Required**\n * This utility is specifically needed when conditional logic switches between:\n * - **Form inputs** (e.g., `<input>`, `<select>`, `<textarea>`)\n * - **NON-form elements** (e.g., `<p>`, `<div>`, informational content)\n *\n * **Primary Use Case - Form Input ↔ Non-Form Content:**\n * ```typescript\n * @if (mode === 'input') {\n * <input name=\"field\" [ngModel]=\"value\" /> // Form input\n * } @else {\n * <p>No input required</p> // NON-form element\n * }\n * ```\n *\n * **Why This Creates a Problem:**\n * 1. Switching FROM input TO non-form content: Angular removes FormControl, but component signal retains old value\n * 2. This creates state inconsistency between `ngForm.form.value` (clean) and `formValue()` (stale)\n * 3. Manual clearing synchronizes component state with actual form structure\n *\n * **When NOT Required:**\n * Pure form-to-form conditionals usually don't need manual clearing:\n * ```typescript\n * @if (type === 'text') {\n * <input name=\"field\" [ngModel]=\"value\" type=\"text\" />\n * } @else {\n * <input name=\"field\" [ngModel]=\"value\" type=\"number\" /> // Still a form input\n * }\n * ```\n *\n * **Performance Note:**\n * Uses `Object.entries()` for efficient field clearing without mutation.\n * Only processes fields that need to be cleared, preserving other field values.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param conditions - Object mapping field names to boolean conditions (true = clear field)\n * @returns New state object with specified fields cleared (set to undefined)\n *\n * @example\n * ```typescript\n * /// REQUIRED: Form input switching to non-form content\n * onProcedureTypeChange(newValue: string) {\n * this.formValue.update((current) =>\n * clearFieldsWhen(current, {\n * fieldA: newValue !== 'typeA', // Clear when switching to non-form content\n * fieldB: newValue !== 'typeB', // Clear when switching to non-form content\n * })\n * );\n * }\n *\n * /// Template structure that REQUIRES clearing:\n * /// @if (type === 'typeA') { <input name=\"fieldA\" /> }\n * /// @else if (type === 'typeB') { <input name=\"fieldB\" /> }\n * /// @else { <p>No input needed</p> } // ← NON-form element!\n * ```\n *\n * @example\n * ```typescript\n * /// Complex conditional clearing with mixed form/non-form scenarios\n * const cleanedState = clearFieldsWhen(form, {\n * shippingAddress: !form.useShippingAddress, // Clear when not using shipping\n * emergencyContact: (form.age || 0) >= 18, // Clear when adult (no emergency contact form)\n * childInfo: form.userType !== 'parent', // Clear when not parent (shows info text instead)\n * });\n * ```\n *\n * @example\n * ```typescript\n * /// State inconsistency example - WHY manual clearing is needed:\n *\n * /// BEFORE switching from input to non-form content (typeA → typeC):\n * formValue() = { procedureType: 'typeA', fieldA: 'user-input' }\n * ngForm.form.value = { procedureType: 'typeA', fieldA: 'user-input' }\n *\n * /// AFTER switching WITHOUT clearing (PROBLEMATIC):\n * formValue() = { procedureType: 'typeC', fieldA: 'user-input' } // ❌ Stale fieldA!\n * ngForm.form.value = { procedureType: 'typeC' } // ✅ Clean (Angular removed FormControl)\n *\n * /// AFTER switching WITH clearing (CONSISTENT):\n * formValue() = { procedureType: 'typeC' } // ✅ Clean component state\n * ngForm.form.value = { procedureType: 'typeC' } // ✅ Clean form state\n * ```\n *\n */\nexport function clearFieldsWhen<T extends Record<string, unknown>>(\n currentState: T,\n conditions: Readonly<Partial<Record<keyof T, boolean>>>\n): T {\n const result: Record<string, unknown> = { ...currentState };\n\n for (const fieldName of Object.keys(conditions) as Array<keyof T>) {\n const shouldClear = conditions[fieldName];\n if (shouldClear) {\n result[fieldName as string] = undefined;\n }\n }\n\n return result as T;\n}\n\n/**\n * Clears multiple fields from form state unconditionally.\n *\n * **Use Cases:**\n * - Form reset operations when switching between form modes\n * - Clearing temporary/wizard data when exiting multi-step forms\n * - Cleanup after form submission or cancellation\n * - When you want explicit control over which fields to clear\n *\n * **Note:** Unlike `clearFieldsWhen`, this function always clears the specified fields\n * regardless of conditions. Use this when you want unconditional field removal.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param fieldsToClear - Array of field names to clear (set to undefined)\n * @returns New state object with specified fields cleared\n *\n * @example\n * ```typescript\n * /// Clear specific fields during form mode transitions\n * const cleanedState = clearFields(currentFormValue, ['fieldA', 'fieldB']);\n *\n * /// Reset wizard or temporary data\n * onFormModeChange() {\n * this.formValue.update((current) =>\n * clearFields(current, ['temporaryData', 'wizardStep', 'draftSaved'])\n * );\n * }\n *\n * /// Clear all optional fields on form submission\n * save() {\n * const finalData = clearFields(this.formValue(), ['draftField', 'tempNotes']);\n * this.submitForm(finalData);\n * }\n * ```\n */\nexport function clearFields<T extends Record<string, unknown>>(\n currentState: T,\n fieldsToClear: ReadonlyArray<keyof T>\n): T {\n const result: Record<string, unknown> = { ...currentState };\n\n for (const fieldName of fieldsToClear) {\n result[fieldName as string] = undefined;\n }\n\n return result as T;\n}\n\n/**\n * Creates a clean form state containing only fields that meet specified conditions.\n *\n * **Philosophy:** Instead of clearing unwanted fields (like `clearFieldsWhen`), this function\n * takes a \"whitelist\" approach - building a new state with only the fields you explicitly want to keep.\n *\n * **Best Use Cases:**\n * - Complex form transformations where you want to be explicit about kept fields\n * - Building clean data objects for API submission (exclude UI-only fields)\n * - Form mode switching where different modes have completely different field sets\n * - Data export scenarios where only certain fields should be included\n *\n * **Returns:** `Partial<T>` because the result may not contain all original fields.\n *\n * @template T - The form model type, must extend Record<string, unknown>\n * @param currentState - The current form state object\n * @param conditions - Object mapping field names to boolean conditions (true = keep field)\n * @returns New state object containing only fields where condition is true\n *\n * @example\n * ```typescript\n * /// Keep only relevant fields based on form mode\n * const filteredState = keepFieldsWhen(currentFormValue, {\n * procedureType: true, // always keep\n * fieldA: procedureType === 'typeA',\n * fieldB: procedureType === 'typeB',\n * // Note: fieldC is omitted when procedureType === 'typeC' (non-form content)\n * });\n *\n * /// Build clean data for API submission (exclude UI-only fields)\n * const apiData = keepFieldsWhen(formValue(), {\n * // Business data - keep these\n * userName: true,\n * email: true,\n * preferences: true,\n * // UI state fields omitted: wizardStep, draftSaved, validationErrors, etc.\n * });\n *\n * /// Dynamic form sections based on user permissions\n * const relevantData = keepFieldsWhen(form, {\n * basicInfo: true,\n * addressInfo: form.needsAddress && userCanEditAddress,\n * paymentInfo: form.requiresPayment && userCanMakePayments,\n * adminFields: userIsAdmin,\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function keepFieldsWhen<T extends Record<string, unknown>>(\n currentState: T,\n conditions: Readonly<Partial<Record<keyof T, boolean>>>\n): Partial<T> {\n const result: Record<string, unknown> = {};\n\n for (const fieldName of Object.keys(conditions) as Array<keyof T>) {\n const shouldKeep = conditions[fieldName];\n if (shouldKeep && Object.hasOwn(currentState, fieldName)) {\n result[fieldName as string] = currentState[fieldName];\n }\n }\n\n return result as Partial<T>;\n}\n","/*\n * Public API Surface of ngx-vest-forms\n */\n\nexport { NgxVestForms, vestForms, vestFormsViewProviders } from './lib/exports';\n\n// Type utilities\nexport type { DeepPartial, NgxDeepPartial } from './lib/utils/deep-partial';\nexport type {\n DeepRequired,\n FormCompatibleDeepRequired,\n NgxDeepRequired,\n NgxFormCompatibleDeepRequired,\n} from './lib/utils/deep-required';\n/** @deprecated Use ROOT_FORM from 'ngx-vest-forms' instead */\nexport { ROOT_FORM as ROOT_FORM_CONSTANT } from './lib/utils/field-path-types';\nexport type {\n FieldPath,\n FieldPathValue,\n FormFieldName,\n LeafFieldPath,\n ValidateFieldPath,\n ValidationConfigMap,\n} from './lib/utils/field-path-types';\nexport { createEmptyFormState } from './lib/utils/form-state.utils';\nexport type { NgxFormState } from './lib/utils/form-state.utils';\nexport {\n ValidationConfigBuilder,\n createValidationConfig,\n} from './lib/utils/validation-config-builder';\nexport type {\n NgxFieldKey,\n NgxTypedVestSuite,\n NgxVestSuite,\n} from './lib/utils/validation-suite';\n\n// Form utilities\nexport {\n arrayToObject,\n deepArrayToObject,\n objectToArray,\n} from './lib/utils/array-to-object';\nexport {\n clearFields,\n clearFieldsWhen,\n keepFieldsWhen,\n} from './lib/utils/field-clearing';\nexport { stringifyFieldPath } from './lib/utils/field-path.utils';\nexport { setValueAtPath } from './lib/utils/form-utils';\nexport { createDebouncedPendingState } from './lib/utils/pending-state.utils';\nexport type {\n DebouncedPendingStateOptions,\n DebouncedPendingStateOptionsInput,\n DebouncedPendingStateResult,\n} from './lib/utils/pending-state.utils';\nexport { validateShape } from './lib/utils/shape-validation';\n\n// ARIA association utilities\nexport {\n mergeAriaDescribedBy,\n parseAriaIdTokens,\n resolveAssociationTargets,\n} from './lib/utils/aria-association.utils';\nexport type { AriaAssociationMode } from './lib/utils/aria-association.utils';\n\n// Internal utilities - exported for advanced use cases but not part of the primary API\n// These are marked with @internal in their source files and may change without notice\n/** @internal */ export {\n fastDeepEqual,\n shallowEqual,\n} from './lib/utils/equality';\n/** @internal */ export { parseFieldPath } from './lib/utils/field-path.utils';\n/** @internal */ export {\n getAllFormErrors,\n getFormControlField,\n getFormGroupField,\n mergeValuesAndRawValues,\n} from './lib/utils/form-utils';\n\n// Deprecated - kept for backward compatibility, will be removed in future major version\n/** @deprecated Use setValueAtPath instead */ export {\n cloneDeep,\n set,\n} from './lib/utils/form-utils';\n\n// Constants\nexport { ROOT_FORM } from './lib/constants';\n\n// Tokens\nexport {\n NGX_ERROR_DISPLAY_MODE_TOKEN,\n NGX_WARNING_DISPLAY_MODE_TOKEN,\n SC_ERROR_DISPLAY_MODE_TOKEN,\n} from './lib/directives/error-display-mode.token';\nexport { NGX_VALIDATION_CONFIG_DEBOUNCE_TOKEN } from './lib/tokens/debounce.token';\nexport { NGX_EQUALITY_FN } from './lib/tokens/equality.token';\nexport type { NgxEqualityFn } from './lib/tokens/equality.token';\n\n// Components\nexport { ControlWrapperComponent } from './lib/components/control-wrapper/control-wrapper.component';\nexport { FormGroupWrapperComponent } from './lib/components/form-group-wrapper/form-group-wrapper.component';\n\n// Directives\nexport { FormControlStateDirective } from './lib/directives/form-control-state.directive';\nexport { FormErrorControlDirective } from './lib/directives/form-error-control.directive';\nexport { FormErrorDisplayDirective } from './lib/directives/form-error-display.directive';\nexport type {\n NgxWarningDisplayMode,\n ScErrorDisplayMode,\n} from './lib/directives/form-error-display.directive';\nexport { FormModelGroupDirective } from './lib/directives/form-model-group.directive';\nexport { FormModelDirective } from './lib/directives/form-model.directive';\nexport { FormDirective } from './lib/directives/form.directive';\nexport type {\n NgxFieldBlurEvent,\n NgxValidationConfig,\n} from './lib/directives/form.directive';\nexport { ValidateRootFormDirective } from './lib/directives/validate-root-form.directive';\nexport type { ValidationOptions } from './lib/directives/validation-options';\nexport {\n DEFAULT_FOCUS_SELECTOR,\n DEFAULT_INVALID_SELECTOR,\n} from './lib/utils/first-invalid.utils';\nexport type { NgxFirstInvalidOptions } from './lib/utils/first-invalid.utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["isPrimitive","LOG_PREFIX","rxMerge","i1.FormControlStateDirective","nextUniqueId","i1.FormErrorDisplayDirective"],"mappings":"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"}
|