@vuehookform/core 0.4.7 → 0.6.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 +8 -0
- package/dist/core/useFieldArray.d.ts +17 -2
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +169 -14
- package/dist/useController.d.ts +31 -1
- package/dist/vuehookform.cjs +107 -36
- package/dist/vuehookform.cjs.map +1 -0
- package/dist/vuehookform.js +107 -36
- package/dist/vuehookform.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vuehookform.cjs","names":["result: unknown","current: Record<string, unknown>","current: unknown","clonedArray: unknown[]","__DEV__: boolean","currentSchema: ZodType","messages: Record<string, string>","value: unknown","watchStopHandles: WatchStopHandle[]","result: SchemaPathAnalysis","flatKeysToDelete: string[]","types: Record<string, string | string[]>","errorBatch: Array<[string, FieldErrorValue]>","valueHash: string | undefined","VALID_MODES: readonly ValidationMode[]","value: unknown","scoped: ReturnType<typeof createScopedMethods> | null","cachedMergedErrors: FieldErrors<FormValues> | null","result: Record<string, unknown>","FormContextKey: InjectionKey<UseFormReturn<ZodType>>","result: Record<string, unknown>","result: Partial<FormState<InferSchema<TSchema>>>"],"sources":["../lib/utils/paths.ts","../lib/utils/clone.ts","../lib/utils/devWarnings.ts","../lib/core/domSync.ts","../lib/core/formContext.ts","../lib/utils/hash.ts","../lib/utils/schemaExtract.ts","../lib/core/fieldState.ts","../lib/core/useValidation.ts","../lib/utils/modeChecks.ts","../lib/core/useFieldRegistration.ts","../lib/core/useFieldArray.ts","../lib/useForm.ts","../lib/context.ts","../lib/useWatch.ts","../lib/useController.ts","../lib/useFormState.ts","../lib/types.ts"],"sourcesContent":["/**\n * LRU cache for parsed path segments to avoid repeated string splitting.\n * Path operations are called frequently (every get/set/unset), and caching\n * provides 80-90% reduction in string splitting overhead.\n */\nconst pathCache = new Map<string, string[]>()\nconst PATH_CACHE_MAX_SIZE = 256\n\n/**\n * Maximum allowed array index to prevent memory exhaustion attacks.\n * Paths like 'items.999999.value' would create sparse arrays with millions of empty slots.\n * 10,000 is a reasonable upper limit that covers most real-world use cases.\n */\nconst MAX_ARRAY_INDEX = 10000\n\n/**\n * Get cached path segments or parse and cache them.\n * Uses simple LRU eviction (delete oldest when full).\n *\n * Exported for use by other utilities that need path parsing\n * with caching benefits (devWarnings, schemaExtract).\n */\nexport function getPathSegments(path: string): string[] {\n let segments = pathCache.get(path)\n if (segments) {\n return segments\n }\n\n segments = path.split('.')\n\n // Simple LRU: if at capacity, delete the first (oldest) entry\n if (pathCache.size >= PATH_CACHE_MAX_SIZE) {\n const firstKey = pathCache.keys().next().value\n if (firstKey !== undefined) {\n pathCache.delete(firstKey)\n }\n }\n\n pathCache.set(path, segments)\n return segments\n}\n\n/**\n * Clear the path segment cache.\n * Call this between SSR requests to prevent memory accumulation,\n * or in tests to reset state.\n *\n * The cache is bounded to 256 entries, so clearing is optional\n * for client-side only applications.\n */\nexport function clearPathCache(): void {\n pathCache.clear()\n}\n\n/**\n * Get value from object using dot notation path\n * @example get({ user: { name: 'John' } }, 'user.name') => 'John'\n */\nexport function get(obj: unknown, path: string): unknown {\n if (!path || obj === null || obj === undefined) return obj\n\n const keys = getPathSegments(path)\n let result: unknown = obj\n\n for (const key of keys) {\n if (result === null || result === undefined) {\n return undefined\n }\n result = (result as Record<string, unknown>)[key]\n }\n\n return result\n}\n\n/**\n * Set value in object using dot notation path\n * @example set({}, 'user.name', 'John') => { user: { name: 'John' } }\n */\nexport function set(obj: Record<string, unknown>, path: string, value: unknown): void {\n if (!path || obj === null || obj === undefined) return\n\n const keys = getPathSegments(path).slice() // Clone since we mutate with pop()\n\n // Prototype pollution protection\n const UNSAFE_KEYS = ['__proto__', 'constructor', 'prototype']\n if (keys.some((k) => UNSAFE_KEYS.includes(k))) return\n\n // Array index bounds protection - prevent memory exhaustion from huge indices\n // Check all numeric keys to ensure they're within safe bounds\n for (const key of keys) {\n if (/^\\d+$/.test(key)) {\n const index = parseInt(key, 10)\n if (index > MAX_ARRAY_INDEX) {\n if (typeof console !== 'undefined' && console.warn) {\n console.warn(\n `[vue-hook-form] set(): Array index ${index} exceeds maximum allowed (${MAX_ARRAY_INDEX}). ` +\n `Path \"${path}\" was not set to prevent memory exhaustion.`,\n )\n }\n return\n }\n }\n }\n\n const lastKey = keys.pop()!\n let current: Record<string, unknown> = obj\n\n // Create nested objects as needed\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i] as string\n const existing = current[key]\n\n if (existing !== undefined && existing !== null && typeof existing !== 'object') {\n // Warn when overwriting a primitive with an object structure (dev only)\n // Use try-catch to handle environments where process is not defined\n try {\n const proc = (globalThis as Record<string, unknown>).process as\n | Record<string, Record<string, string>>\n | undefined\n if (proc?.env?.NODE_ENV !== 'production') {\n console.warn(\n `[vue-hook-form] set(): Overwriting primitive value at path \"${keys.slice(0, i + 1).join('.')}\" with an object. ` +\n `Previous value: ${JSON.stringify(existing)}`,\n )\n }\n } catch {\n // Silently ignore in environments where process doesn't exist\n }\n }\n\n if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {\n // Check if next key is a number to create array vs object\n const nextKey = keys[i + 1]\n current[key] = nextKey && /^\\d+$/.test(nextKey) ? [] : {}\n }\n current = current[key] as Record<string, unknown>\n }\n\n current[lastKey] = value\n}\n\n/**\n * Delete value from object using dot notation path\n * @example unset({ user: { name: 'John' } }, 'user.name') => { user: {} }\n */\nexport function unset(obj: Record<string, unknown>, path: string): void {\n if (!path || obj === null || obj === undefined) return\n\n const keys = getPathSegments(path).slice() // Clone since we mutate with pop()\n const lastKey = keys.pop()!\n let current: Record<string, unknown> = obj\n\n for (const key of keys) {\n // Return early if path doesn't exist or intermediate value is null/non-object\n if (!(key in current)) return\n const next = current[key]\n if (next === null || typeof next !== 'object') return\n current = next as Record<string, unknown>\n }\n\n delete current[lastKey]\n}\n\n/**\n * Check if path exists in object.\n * Unlike `get(obj, path) !== undefined`, this properly distinguishes between\n * a missing path and a path that exists with an `undefined` value.\n *\n * @example\n * has({ name: undefined }, 'name') // true - path exists\n * has({ }, 'name') // false - path doesn't exist\n * has({ user: { name: 'John' } }, 'user.name') // true\n * has({ user: { name: 'John' } }, 'user.age') // false\n */\nexport function has(obj: Record<string, unknown>, path: string): boolean {\n if (!path) return false\n\n const segments = getPathSegments(path)\n let current: unknown = obj\n\n for (let i = 0; i < segments.length; i++) {\n if (current === null || current === undefined) {\n return false\n }\n\n const segment = segments[i] as string\n\n // Check if the property exists using 'in' operator\n if (!(segment in Object(current))) {\n return false\n }\n\n // Move to next level (only if not the last segment)\n if (i < segments.length - 1) {\n current = (current as Record<string, unknown>)[segment]\n }\n }\n\n return true\n}\n\n/**\n * Generate a unique ID for field array items.\n * Uses timestamp + counter + random string for uniqueness across HMR reloads.\n *\n * Format: `field_<timestamp>_<counter>_<random>`\n *\n * @returns Unique string ID, e.g., `field_1734012345678_0_a1b2c3d4e`\n *\n * @example\n * const id1 = generateId() // 'field_1734012345678_0_a1b2c3d4e'\n * const id2 = generateId() // 'field_1734012345678_1_f5g6h7i8j'\n */\nlet idCounter = 0\nexport function generateId(): string {\n const random = Math.random().toString(36).substring(2, 11)\n return `field_${Date.now()}_${idCounter++}_${random}`\n}\n\n/**\n * Check if a path represents an array index\n * @example isArrayPath('users.0') => true\n * @example isArrayPath('users.name') => false\n */\nexport function isArrayPath(path: string): boolean {\n const segments = getPathSegments(path)\n const lastSegment = segments[segments.length - 1]\n return /^\\d+$/.test(lastSegment || '')\n}\n\n/**\n * Get parent path\n * @example getParentPath('user.addresses.0.street') => 'user.addresses.0'\n */\nexport function getParentPath(path: string): string | undefined {\n const segments = getPathSegments(path)\n if (segments.length <= 1) return undefined\n return segments.slice(0, -1).join('.')\n}\n\n/**\n * Get field name from path\n * @example getFieldName('user.addresses.0.street') => 'street'\n */\nexport function getFieldName(path: string): string {\n const segments = getPathSegments(path)\n return segments[segments.length - 1] || path\n}\n","/**\n * Deep clone utility for form values.\n * Handles common types without JSON.parse/stringify overhead.\n *\n * Properly handles:\n * - Primitives (pass-through)\n * - Plain objects (recursive clone)\n * - Arrays (recursive clone)\n * - Date objects (new Date instance)\n * - null/undefined (pass-through)\n * - Circular references (recreates the circular structure in the clone)\n *\n * Does NOT handle (by design, not needed for form data):\n * - Map/Set/WeakMap/WeakSet\n * - Functions\n * - Symbols\n * - Class instances (cloned as plain objects)\n */\nexport function deepClone<T>(obj: T, seen?: Map<object, unknown>): T {\n // Handle null/undefined and primitives\n if (obj === null || obj === undefined) {\n return obj\n }\n\n if (typeof obj !== 'object') {\n return obj\n }\n\n // Handle Date\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T\n }\n\n // Initialize seen map for tracking circular references\n // Map tracks original -> clone mappings so we can recreate circular refs\n if (!seen) {\n seen = new Map()\n }\n\n // Check for circular reference - return the already-created clone\n const existingClone = seen.get(obj as object)\n if (existingClone !== undefined) {\n return existingClone as T\n }\n\n // Handle Array\n if (Array.isArray(obj)) {\n const clonedArray: unknown[] = []\n // Register clone BEFORE recursing to handle circular refs within the array\n seen.set(obj as object, clonedArray)\n for (const item of obj) {\n clonedArray.push(deepClone(item, seen))\n }\n return clonedArray as T\n }\n\n // Handle plain objects\n const cloned = {} as T\n // Register clone BEFORE recursing to handle circular refs within the object\n seen.set(obj as object, cloned)\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n cloned[key] = deepClone(obj[key], seen)\n }\n }\n\n return cloned\n}\n","/**\n * Development-mode warning utilities\n * All exports are designed to be tree-shaken in production\n */\nimport type { ZodType, ZodObject, ZodArray } from 'zod'\nimport { getPathSegments } from './paths'\n\n/**\n * DEV flag for tree-shaking\n * Uses process.env.NODE_ENV for universal bundler compatibility (ESM + CJS).\n * Consumer bundlers replace this at build time, enabling dead code elimination.\n */\nconst proc = (globalThis as Record<string, unknown>).process as\n | { env?: { NODE_ENV?: string } }\n | undefined\nexport const __DEV__: boolean = proc?.env?.NODE_ENV !== 'production'\n\n// Track warnings already shown to avoid console spam\nconst warnedMessages = new Set<string>()\n\n/**\n * Warn once per unique message (prevents spam on re-renders)\n */\nexport function warnOnce(message: string, key?: string): void {\n if (!__DEV__) return\n\n const cacheKey = key ?? message\n if (warnedMessages.has(cacheKey)) return\n\n warnedMessages.add(cacheKey)\n console.warn(`[vue-hook-form] ${message}`)\n}\n\n/**\n * Warn every time (for errors that should always be shown)\n */\nexport function warn(message: string): void {\n if (!__DEV__) return\n console.warn(`[vue-hook-form] ${message}`)\n}\n\n/**\n * Clear warning cache (useful for testing)\n */\nexport function clearWarningCache(): void {\n if (!__DEV__) return\n warnedMessages.clear()\n}\n\n/**\n * Validate a dot-notation path string for common syntax errors\n * @returns Error message or null if valid\n */\nexport function validatePathSyntax(path: string): string | null {\n if (!__DEV__) return null\n\n if (!path || path.trim() === '') {\n return 'Path cannot be empty'\n }\n\n if (path.startsWith('.') || path.endsWith('.') || path.includes('..')) {\n return `Invalid path \"${path}\": contains empty segments`\n }\n\n if (path.includes('[')) {\n return `Invalid path \"${path}\": use dot notation (e.g., \"items.0\") instead of bracket notation (e.g., \"items[0]\")`\n }\n\n if (/\\s/.test(path)) {\n return `Invalid path \"${path}\": paths cannot contain whitespace`\n }\n\n return null\n}\n\n/**\n * Traverse a Zod schema following a dot-notation path.\n * Used internally for dev-mode path validation warnings.\n *\n * @param schema - Root Zod schema to traverse\n * @param path - Dot-notation path (e.g., 'user.addresses.0.street')\n * @returns Success: `{ schema: ZodType }` - the schema at path end\n * Error: `{ error: string, availableFields?: string[], segmentIndex: number }`\n *\n * @example\n * const result = traverseSchemaPath(formSchema, 'user.email')\n * if ('error' in result) {\n * console.log(result.error, result.availableFields)\n * } else {\n * console.log('Found schema:', result.schema)\n * }\n */\nfunction traverseSchemaPath(\n schema: ZodType,\n path: string,\n): { schema: ZodType } | { error: string; availableFields?: string[]; segmentIndex: number } {\n const segments = getPathSegments(path)\n let currentSchema: ZodType = schema\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i]\n // Skip empty segments (already caught by validatePathSyntax)\n if (!segment) continue\n\n currentSchema = unwrapSchema(currentSchema)\n\n if (isZodObject(currentSchema)) {\n const shape = currentSchema.shape as Record<string, ZodType>\n if (segment in shape) {\n const nextSchema = shape[segment]\n if (nextSchema) {\n currentSchema = nextSchema\n continue\n }\n }\n return {\n error: `Field \"${segments.slice(0, i + 1).join('.')}\" does not exist in schema`,\n availableFields: Object.keys(shape),\n segmentIndex: i,\n }\n }\n\n if (isZodArray(currentSchema) && /^\\d+$/.test(segment)) {\n currentSchema = currentSchema.element\n continue\n }\n\n return {\n error: `Cannot navigate path \"${path}\" at segment \"${segment}\"`,\n segmentIndex: i,\n }\n }\n\n return { schema: currentSchema }\n}\n\n/**\n * Check if a path exists in a Zod schema\n * This is a runtime check to validate paths against the schema structure\n */\nexport function validatePathAgainstSchema(\n schema: ZodType,\n path: string,\n): { valid: boolean; reason?: string; availableFields?: string[] } {\n if (!__DEV__) return { valid: true }\n\n try {\n const result = traverseSchemaPath(schema, path)\n if ('error' in result) {\n return {\n valid: false,\n reason: result.error,\n availableFields: result.availableFields,\n }\n }\n return { valid: true }\n } catch {\n return { valid: true }\n }\n}\n\n/**\n * Check if a path points to an array field in the schema\n */\nexport function isArrayFieldInSchema(schema: ZodType, path: string): boolean | null {\n if (!__DEV__) return null\n\n try {\n const result = traverseSchemaPath(schema, path)\n if ('error' in result) return null\n return isZodArray(unwrapSchema(result.schema))\n } catch {\n return null\n }\n}\n\n/**\n * Warn about registering an invalid path with fix suggestion\n */\nexport function warnInvalidPath(fnName: string, path: string, reason: string): void {\n if (!__DEV__) return\n\n let message = `${fnName}(\"${path}\"): ${reason}`\n\n if (reason.includes('bracket notation')) {\n const fixedPath = path.replace(/\\[(\\d+)\\]/g, '.$1')\n message += `\\n FIX: Use dot notation for array indices`\n message += `\\n EXAMPLE: ${fnName}(\"${fixedPath}\")`\n } else if (reason.includes('empty')) {\n message += `\\n FIX: Provide a non-empty field path`\n message += `\\n EXAMPLE: ${fnName}(\"email\") or ${fnName}(\"user.address.city\")`\n } else if (reason.includes('whitespace')) {\n const fixedPath = path.replace(/\\s/g, '')\n message += `\\n FIX: Remove spaces from the field path`\n message += `\\n EXAMPLE: ${fnName}(\"${fixedPath}\")`\n } else if (reason.includes('empty segments')) {\n const fixedPath = path\n .replace(/\\.{2,}/g, '.')\n .replace(/^\\./, '')\n .replace(/\\.$/, '')\n message += `\\n FIX: Remove extra dots from the path`\n message += `\\n EXAMPLE: ${fnName}(\"${fixedPath}\")`\n }\n\n warnOnce(message, `invalid-path:${fnName}:${path}`)\n}\n\n/**\n * Warn about path not in schema with suggestions\n */\nexport function warnPathNotInSchema(\n fnName: string,\n path: string,\n availableFields?: string[],\n): void {\n if (!__DEV__) return\n\n let message = `${fnName}(\"${path}\"): Path does not exist in your Zod schema.`\n message += `\\n FIX: Check that the path matches your schema definition exactly (case-sensitive)`\n\n if (availableFields && availableFields.length > 0) {\n const pathLower = path.toLowerCase()\n const suggestions = availableFields.filter(\n (f) => f.toLowerCase().includes(pathLower) || pathLower.includes(f.toLowerCase()),\n )\n\n if (suggestions.length > 0) {\n message += `\\n DID YOU MEAN: ${suggestions\n .slice(0, 3)\n .map((s) => `\"${s}\"`)\n .join(', ')}`\n }\n\n message += `\\n AVAILABLE: ${availableFields.slice(0, 8).join(', ')}${availableFields.length > 8 ? '...' : ''}`\n }\n\n warnOnce(message, `path-not-in-schema:${fnName}:${path}`)\n}\n\n/**\n * Warn about calling fields() on non-array path\n */\nexport function warnFieldsOnNonArray(path: string): void {\n if (!__DEV__) return\n warnOnce(\n `fields(\"${path}\"): Expected an array field, but this path does not point to an array in your schema. ` +\n `The fields() method is only for array fields. Use register() for non-array fields.`,\n `fields-non-array:${path}`,\n )\n}\n\n/**\n * Warn about silent field array operation failures\n */\nexport function warnArrayOperationRejected(\n operation: string,\n path: string,\n reason: 'maxLength' | 'minLength',\n details?: { current: number; limit: number },\n): void {\n if (!__DEV__) return\n\n const messages: Record<string, string> = {\n maxLength: details\n ? `Would exceed maxLength (current: ${details.current}, max: ${details.limit})`\n : 'Would exceed maxLength rule',\n minLength: details\n ? `Would violate minLength (current: ${details.current}, min: ${details.limit})`\n : 'Would violate minLength rule',\n }\n\n warn(`${operation}() on \"${path}\": ${messages[reason]}. Operation was silently ignored.`)\n}\n\n/**\n * Warn about array operation with out of bounds index\n */\nexport function warnArrayIndexOutOfBounds(\n operation: string,\n path: string,\n index: number,\n length: number,\n): void {\n if (!__DEV__) return\n warn(\n `${operation}() on \"${path}\": Index ${index} is out of bounds (array length: ${length}). ` +\n `Operation was silently ignored.`,\n )\n}\n\n// Zod 4 schema type helpers\n// Zod 4 exposes `schema.type` directly (e.g., \"object\", \"array\", \"optional\")\n\nfunction getSchemaType(schema: ZodType): string | undefined {\n // Zod 4: type is a direct property on the schema\n return (schema as unknown as { type?: string }).type\n}\n\nfunction isZodObject(schema: ZodType): schema is ZodObject<Record<string, ZodType>> {\n return getSchemaType(schema) === 'object'\n}\n\nfunction isZodArray(schema: ZodType): schema is ZodArray<ZodType> {\n return getSchemaType(schema) === 'array'\n}\n\nfunction unwrapSchema(schema: ZodType): ZodType {\n const schemaType = getSchemaType(schema)\n\n // Zod 4: optional, nullable, default all have .unwrap() method\n if (schemaType === 'optional' || schemaType === 'nullable' || schemaType === 'default') {\n const schemaWithUnwrap = schema as unknown as { unwrap?: () => ZodType }\n if (typeof schemaWithUnwrap.unwrap === 'function') {\n return unwrapSchema(schemaWithUnwrap.unwrap())\n }\n }\n\n return schema\n}\n","import type { Ref } from 'vue'\nimport type { RegisterOptions } from '../types'\nimport { set } from '../utils/paths'\n\n/**\n * Extract the actual HTMLInputElement from a ref value.\n * Handles both native elements and Vue component instances (PrimeVue, Vuetify, etc.)\n *\n * Vue component libraries typically expose:\n * - $el: The root DOM element of the component\n * - Some components wrap inputs in divs, so we may need to query for the input\n *\n * @param refValue - The value from fieldRef.value (HTMLInputElement, Component, or null)\n * @returns The underlying HTMLInputElement, or null if not found\n */\nexport function getInputElement(refValue: unknown): HTMLInputElement | null {\n if (!refValue) return null\n\n // Already an HTMLInputElement - most common case (native inputs)\n if (refValue instanceof HTMLInputElement) {\n return refValue\n }\n\n // Handle HTMLSelectElement and HTMLTextAreaElement (they share similar APIs)\n if (refValue instanceof HTMLSelectElement || refValue instanceof HTMLTextAreaElement) {\n return refValue as unknown as HTMLInputElement\n }\n\n // Vue component instance - check for $el property\n if (typeof refValue === 'object' && '$el' in refValue) {\n const el = (refValue as { $el: unknown }).$el\n\n // $el is the input element directly (common for simple input wrappers like PrimeVue InputText)\n if (el instanceof HTMLInputElement) {\n return el\n }\n\n // $el is a select or textarea\n if (el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {\n return el as unknown as HTMLInputElement\n }\n\n // $el is a container element - search for input inside\n if (el instanceof Element) {\n // Query for nested input, select, or textarea\n const input = el.querySelector('input, select, textarea')\n if (\n input instanceof HTMLInputElement ||\n input instanceof HTMLSelectElement ||\n input instanceof HTMLTextAreaElement\n ) {\n return input as HTMLInputElement\n }\n }\n }\n\n return null\n}\n\n/**\n * Get a focusable element from a ref value.\n * Works with both native elements and Vue component instances.\n *\n * @param refValue - The value from fieldRef.value\n * @returns The focusable HTMLElement, or null if not found\n */\nexport function getFocusableElement(refValue: unknown): HTMLElement | null {\n // Try to get the input element first\n const input = getInputElement(refValue)\n if (input) return input\n\n // For Vue components that have focus() on $el (like some button components)\n if (typeof refValue === 'object' && refValue && '$el' in refValue) {\n const el = (refValue as { $el: unknown }).$el\n if (el instanceof HTMLElement && typeof el.focus === 'function') {\n return el\n }\n }\n\n // Check if the refValue itself is focusable\n if (refValue instanceof HTMLElement && typeof refValue.focus === 'function') {\n return refValue\n }\n\n return null\n}\n\n/**\n * Sync values from uncontrolled DOM inputs to form data\n *\n * This reads the current DOM state from uncontrolled inputs and updates\n * the formData object. Used before form submission and when getting values.\n *\n * Handles type coercion for:\n * - checkbox: returns boolean (el.checked)\n * - number/range: returns number (el.valueAsNumber)\n * - all other types: returns string (el.value)\n *\n * @param fieldRefs - Map of field names to their DOM element refs\n * @param fieldOptions - Map of field names to their registration options\n * @param formData - The reactive form data object to update\n */\nexport function syncUncontrolledInputs(\n fieldRefs: Map<string, Ref<unknown>>,\n fieldOptions: Map<string, RegisterOptions>,\n formData: Record<string, unknown>,\n): void {\n for (const [name, fieldRef] of Array.from(fieldRefs.entries())) {\n const el = getInputElement(fieldRef.value)\n if (el) {\n const opts = fieldOptions.get(name)\n if (!opts?.controlled) {\n let value: unknown\n if (el.type === 'checkbox') {\n value = el.checked\n } else if (el.type === 'number' || el.type === 'range') {\n // Use valueAsNumber for proper number coercion\n // Returns NaN for empty/invalid inputs which preserves the \"no value\" semantic\n value = el.valueAsNumber\n } else {\n value = el.value\n }\n set(formData, name, value)\n }\n }\n }\n}\n\n/**\n * Update a single DOM element with a new value\n *\n * Handles both checkbox and text inputs appropriately.\n * Supports both native elements and Vue component instances.\n *\n * @param refValue - The ref value (HTMLInputElement, Vue component, or null)\n * @param value - The value to set\n */\nexport function updateDomElement(refValue: unknown, value: unknown): void {\n const el = getInputElement(refValue)\n if (!el) return\n\n if (el.type === 'checkbox') {\n el.checked = value as boolean\n } else {\n el.value = value as string\n }\n}\n","import {\n reactive,\n ref,\n shallowRef,\n watch,\n toValue,\n type Ref,\n type ShallowRef,\n type WatchStopHandle,\n} from 'vue'\nimport type { ZodType } from 'zod'\nimport type {\n UseFormOptions,\n FieldErrors,\n FieldErrorValue,\n InferSchema,\n RegisterOptions,\n FieldArrayItem,\n FieldArrayRules,\n} from '../types'\nimport { set } from '../utils/paths'\nimport { deepClone } from '../utils/clone'\nimport { getInputElement } from './domSync'\n\n/**\n * Internal state for field array management.\n * Tracks items, their indices, and array-level validation rules.\n *\n * @internal This interface is used internally by useFieldArray and should not be\n * directly instantiated by consumers.\n */\nexport interface FieldArrayState {\n /** Reactive list of field array items with stable keys for Vue reconciliation */\n items: Ref<FieldArrayItem[]>\n /** Raw array values (kept in sync with formData) */\n values: unknown[]\n /** O(1) lookup cache mapping item keys to their current indices */\n indexCache: Map<string, number>\n /** Optional validation rules for the array itself (minLength, maxLength, custom) */\n rules?: FieldArrayRules\n}\n\n/**\n * Cached event handlers for a field.\n * These are created once per field registration and reused to prevent\n * unnecessary re-renders and closure recreation.\n *\n * @internal This interface is used internally by useFieldRegistration and should not be\n * directly instantiated by consumers.\n */\nexport interface FieldHandlers {\n /** Handler for input events, triggers validation based on mode */\n onInput: (e: Event) => Promise<void>\n /** Handler for blur events, marks field as touched and may trigger validation */\n onBlur: () => Promise<void>\n /** Ref callback to capture the DOM element reference */\n refCallback: (el: unknown) => void\n}\n\n/**\n * Shared form context containing all reactive state.\n * This is the central state container passed to sub-modules via dependency injection.\n *\n * The context is organized into several categories:\n * - **Form Data**: Raw form values and their defaults\n * - **Form State**: Validation errors, touched/dirty tracking, submission state\n * - **Field Tracking**: DOM refs, registration options, field arrays\n * - **Validation**: Caching, debouncing, and async validation coordination\n * - **Configuration**: Form options and disabled state\n *\n * @typeParam FormValues - The inferred type from the Zod schema\n *\n * @internal This interface is used internally by useForm and its sub-modules.\n * Consumers should use the public API returned by useForm() instead.\n */\nexport interface FormContext<FormValues> {\n // ═══════════════════════════════════════════════════════════════════════════\n // Form Data\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Reactive form data object containing current field values */\n formData: Record<string, unknown>\n /** Original default values used for reset() and dirty detection */\n defaultValues: Record<string, unknown>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Form State\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Current validation errors keyed by field path */\n errors: ShallowRef<FieldErrors<FormValues>>\n /** Record of field paths that have been touched (blurred) */\n touchedFields: ShallowRef<Record<string, boolean>>\n /** Record of field paths that differ from default values */\n dirtyFields: ShallowRef<Record<string, boolean>>\n /** Whether the form is currently being submitted */\n isSubmitting: Ref<boolean>\n /** Whether async default values are being loaded */\n isLoading: Ref<boolean>\n /** Number of times the form has been submitted */\n submitCount: Ref<number>\n /** Error that occurred while loading async default values */\n defaultValuesError: Ref<unknown>\n /** Whether the last submission completed successfully */\n isSubmitSuccessful: Ref<boolean>\n /** Set of field paths currently being validated (for isValidating state) */\n validatingFields: ShallowRef<Set<string>>\n /** External errors (e.g., from server) merged with validation errors */\n externalErrors: ShallowRef<FieldErrors<FormValues>>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Delayed Error Display\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Timers for delayed error display per field */\n errorDelayTimers: Map<string, ReturnType<typeof setTimeout>>\n /** Pending errors waiting for delay timer to complete */\n pendingErrors: Map<string, FieldErrorValue>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Field Tracking\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** DOM element refs for registered uncontrolled fields */\n fieldRefs: Map<string, Ref<HTMLInputElement | null>>\n /** Registration options per field path */\n fieldOptions: Map<string, RegisterOptions>\n /** Field array state for array fields managed by fields() */\n fieldArrays: Map<string, FieldArrayState>\n /** Cached event handlers to prevent recreation on re-render */\n fieldHandlers: Map<string, FieldHandlers>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Validation\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Debounce timers for custom async validation per field */\n debounceTimers: Map<string, ReturnType<typeof setTimeout>>\n /** Request IDs for canceling stale async validation results */\n validationRequestIds: Map<string, number>\n /** Generation counter incremented on reset to cancel in-flight validations */\n resetGeneration: Ref<number>\n /** Cache of validation results keyed by field path and value hash */\n validationCache: Map<string, { hash: string; isValid: boolean }>\n /** Debounce timers for schema validation per field */\n schemaValidationTimers: Map<string, ReturnType<typeof setTimeout>>\n /** Set of field paths with persistent errors (survive validation cycles) */\n persistentErrorFields: Set<string>\n /** Hashed default values for value-comparison dirty detection */\n defaultValueHashes: Map<string, string>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Configuration\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Whether the entire form is disabled */\n isDisabled: Ref<boolean>\n /** Original options passed to useForm() */\n options: UseFormOptions<ZodType>\n\n // ═══════════════════════════════════════════════════════════════════════════\n // Cleanup\n // ═══════════════════════════════════════════════════════════════════════════\n\n /** Cleanup function to stop all watchers and prevent memory leaks */\n cleanup: () => void\n}\n\n/**\n * Create a new form context with all reactive state initialized\n */\nexport function createFormContext<TSchema extends ZodType>(\n options: UseFormOptions<TSchema>,\n): FormContext<InferSchema<TSchema>> {\n type FormValues = InferSchema<TSchema>\n\n // Form data storage\n const formData = reactive<Record<string, unknown>>({})\n const defaultValues = reactive<Record<string, unknown>>({})\n\n // Check if defaultValues is a function (async) or an object (sync)\n const isAsyncDefaults = typeof options.defaultValues === 'function'\n const isLoading = ref(isAsyncDefaults)\n\n if (isAsyncDefaults) {\n // Async default values - load them\n const asyncFn = options.defaultValues as () => Promise<Partial<FormValues>>\n asyncFn()\n .then((values) => {\n // Deep clone to prevent reference sharing between defaultValues and formData\n Object.assign(defaultValues, deepClone(values))\n Object.assign(formData, deepClone(values))\n isLoading.value = false\n })\n .catch((error) => {\n console.error('Failed to load async default values:', error)\n defaultValuesError.value = error\n isLoading.value = false\n // Call error callback if provided\n options.onDefaultValuesError?.(error)\n })\n } else if (options.defaultValues) {\n // Sync default values - deep clone to prevent reference sharing\n // This ensures formData mutations don't affect defaultValues (critical for dirty tracking)\n Object.assign(defaultValues, deepClone(options.defaultValues))\n Object.assign(formData, deepClone(options.defaultValues))\n }\n\n // Form state - using Record instead of Set for per-field tracking\n // Use shallowRef for object state to prevent excessive reactivity triggering\n const errors = shallowRef<FieldErrors<FormValues>>({})\n const touchedFields = shallowRef<Record<string, boolean>>({})\n const dirtyFields = shallowRef<Record<string, boolean>>({})\n const isSubmitting = ref(false)\n const submitCount = ref(0)\n const defaultValuesError = ref<unknown>(null)\n const isSubmitSuccessful = ref(false)\n\n // Validation state tracking - which fields are currently validating (Set for O(1) operations)\n const validatingFields = shallowRef<Set<string>>(new Set())\n\n // External errors from server/parent\n const externalErrors = shallowRef<FieldErrors<FormValues>>({})\n\n // Delayed error display tracking\n const errorDelayTimers = new Map<string, ReturnType<typeof setTimeout>>()\n const pendingErrors = new Map<string, FieldErrorValue>()\n\n // Field registration tracking\n const fieldRefs = new Map<string, Ref<HTMLInputElement | null>>()\n const fieldOptions = new Map<string, RegisterOptions>()\n\n // Field array tracking for dynamic arrays\n const fieldArrays = new Map<string, FieldArrayState>()\n\n // Cached event handlers to prevent recreation on every render\n const fieldHandlers = new Map<string, FieldHandlers>()\n\n // Debounce tracking for async validation\n const debounceTimers = new Map<string, ReturnType<typeof setTimeout>>()\n const validationRequestIds = new Map<string, number>()\n\n // Reset generation counter (incremented on each reset to invalidate in-flight validations)\n const resetGeneration = ref(0)\n\n // Validation cache: skip re-validation when field value hasn't changed\n const validationCache = new Map<string, { hash: string; isValid: boolean }>()\n\n // Schema validation debounce timers per field (for validationDebounce option)\n const schemaValidationTimers = new Map<string, ReturnType<typeof setTimeout>>()\n\n // Persistent errors: field names with errors that should not be cleared by validation\n const persistentErrorFields = new Set<string>()\n\n // Hashed default values for value-comparison dirty detection (lazy-initialized)\n const defaultValueHashes = new Map<string, string>()\n\n // Form-wide disabled state (supports MaybeRef)\n const isDisabled = ref(false)\n\n // Collect watch stop handles for cleanup to prevent memory leaks\n const watchStopHandles: WatchStopHandle[] = []\n\n if (options.disabled !== undefined) {\n const initialDisabled = toValue(options.disabled)\n isDisabled.value = initialDisabled ?? false\n\n watchStopHandles.push(\n watch(\n () => toValue(options.disabled),\n (newDisabled) => {\n isDisabled.value = newDisabled ?? false\n },\n ),\n )\n }\n\n // Watch external values prop for changes\n if (options.values !== undefined) {\n // Set initial values from prop (if provided and not loading async defaults)\n const initialValues = toValue(options.values)\n if (initialValues && !isAsyncDefaults) {\n for (const [key, value] of Object.entries(initialValues)) {\n if (value !== undefined) {\n set(formData, key, value)\n }\n }\n }\n\n // Watch for changes - update formData without marking dirty\n watchStopHandles.push(\n watch(\n () => toValue(options.values),\n (newValues) => {\n if (newValues) {\n for (const [key, value] of Object.entries(newValues)) {\n if (value !== undefined) {\n set(formData, key, value)\n\n // Also update DOM elements for uncontrolled fields\n const fieldRef = fieldRefs.get(key)\n const opts = fieldOptions.get(key)\n if (fieldRef?.value && !opts?.controlled) {\n const el = getInputElement(fieldRef.value)\n if (el) {\n if (el.type === 'checkbox') {\n el.checked = value as boolean\n } else {\n el.value = value as string\n }\n }\n }\n }\n }\n }\n },\n { deep: true },\n ),\n )\n }\n\n // Watch external errors prop for changes\n if (options.errors !== undefined) {\n // Set initial external errors\n const initialErrors = toValue(options.errors)\n if (initialErrors) {\n externalErrors.value = initialErrors as FieldErrors<FormValues>\n }\n\n // Watch for changes\n watchStopHandles.push(\n watch(\n () => toValue(options.errors),\n (newErrors) => {\n externalErrors.value = (newErrors || {}) as FieldErrors<FormValues>\n },\n { deep: true },\n ),\n )\n }\n\n return {\n formData,\n defaultValues,\n errors,\n touchedFields,\n dirtyFields,\n isSubmitting,\n isLoading,\n submitCount,\n defaultValuesError,\n isSubmitSuccessful,\n validatingFields,\n externalErrors,\n errorDelayTimers,\n pendingErrors,\n fieldRefs,\n fieldOptions,\n fieldArrays,\n fieldHandlers,\n debounceTimers,\n validationRequestIds,\n resetGeneration,\n isDisabled,\n validationCache,\n schemaValidationTimers,\n persistentErrorFields,\n defaultValueHashes,\n options: options as UseFormOptions<ZodType>,\n cleanup: () => {\n // Stop all watchers to prevent memory leaks\n for (const stop of watchStopHandles) {\n stop()\n }\n },\n }\n}\n","/**\n * Monotonic counter for generating unique hashes for non-serializable values.\n * Used instead of Date.now() to avoid collisions within the same millisecond.\n */\nlet uniqueIdCounter = 0\n\n/**\n * WeakMap to track circular references for stable hashing.\n * Same circular object always returns the same hash ID.\n */\nconst circularRefMap = new WeakMap<object, string>()\n\n/**\n * Fast value hashing for validation cache.\n * Uses JSON.stringify for objects/arrays, direct conversion for primitives.\n * Returns a string that can be compared for equality.\n *\n * Handles circular references by assigning stable IDs via WeakMap,\n * ensuring the same object always produces the same hash.\n */\nexport function hashValue(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n\n const type = typeof value\n\n // Primitives: direct string conversion\n if (type === 'string') return `s:${value}`\n if (type === 'number') {\n const num = value as number\n // Handle special number cases for stable hashing\n if (Number.isNaN(num)) return 'n:NaN'\n // Normalize -0 to 0 for consistent dirty state tracking\n if (num === 0) return 'n:0'\n if (!Number.isFinite(num)) return `n:${num > 0 ? 'Infinity' : '-Infinity'}`\n return `n:${num}`\n }\n if (type === 'boolean') return `b:${value}`\n\n // Objects and arrays: JSON stringify\n // This handles nested structures and is fast enough for form values\n if (type === 'object') {\n try {\n return `o:${JSON.stringify(value)}`\n } catch {\n // Circular reference or other JSON error\n // Use WeakMap to ensure stable hash for same object\n let id = circularRefMap.get(value as object)\n if (!id) {\n id = String(++uniqueIdCounter)\n circularRefMap.set(value as object, id)\n }\n return `o:_${id}`\n }\n }\n\n // Functions and symbols - return unique identifier\n return `x:_${++uniqueIdCounter}`\n}\n","/**\n * Schema extraction utilities for partial validation\n *\n * These utilities enable O(1) single-field validation by extracting\n * sub-schemas and determining when partial validation is safe.\n *\n * Compatible with Zod v4 which uses:\n * - `_def.type` for type names (string values: \"object\", \"string\", etc.)\n * - `_def.checks` array for refinements (instead of ZodEffects wrapper)\n * - `_def.innerType` for optional/nullable unwrapping\n * - `_def.shape` for object shapes\n * - `_def.element` for array elements\n */\nimport type { ZodType, ZodObject, ZodArray } from 'zod'\nimport { getPathSegments } from './paths'\n\n// --- Internal helpers for Zod v4 ---\n\nfunction getDefType(schema: ZodType): string | undefined {\n const def = schema._def as unknown as Record<string, unknown> | undefined\n return def?.type as string | undefined\n}\n\nfunction getDefProp(schema: ZodType, prop: string): unknown {\n const def = schema._def as unknown as Record<string, unknown> | undefined\n return def?.[prop]\n}\n\nfunction isZodObject(schema: ZodType): schema is ZodObject<Record<string, ZodType>> {\n return getDefType(schema) === 'object'\n}\n\nfunction isZodArray(schema: ZodType): schema is ZodArray<ZodType> {\n return getDefType(schema) === 'array'\n}\n\n/**\n * Check if schema has refinements/checks that might depend on other fields\n * In Zod v4, refinements are stored in _def.checks array\n */\nfunction hasChecks(schema: ZodType): boolean {\n const checks = getDefProp(schema, 'checks') as unknown[] | undefined\n return Array.isArray(checks) && checks.length > 0\n}\n\n/**\n * Unwrap ZodOptional, ZodNullable, ZodDefault (NOT checking refinements)\n * Returns the inner schema without optional/nullable wrappers\n */\nfunction unwrapNonEffects(schema: ZodType): ZodType {\n const type = getDefType(schema)\n const innerType = getDefProp(schema, 'innerType') as ZodType | undefined\n\n // Unwrap ZodOptional, ZodNullable, ZodDefault\n if ((type === 'optional' || type === 'nullable' || type === 'default') && innerType) {\n return unwrapNonEffects(innerType)\n }\n\n return schema\n}\n\n// --- Cache for schema path analysis ---\n\ninterface SchemaPathAnalysis {\n canPartialValidate: boolean\n subSchema?: ZodType\n reason?: 'root-checks' | 'path-checks' | 'unsupported-type' | 'invalid-path'\n}\n\nconst analysisCache = new WeakMap<ZodType, Map<string, SchemaPathAnalysis>>()\n\n/**\n * Check if the root schema has refinements/checks\n * Root-level checks may depend on multiple fields, requiring full validation\n */\nexport function hasRootEffects(schema: ZodType): boolean {\n // In Zod v4, refinements are in the checks array, not as ZodEffects wrapper\n return hasChecks(schema)\n}\n\n/**\n * Extract sub-schema for a given path\n *\n * Returns the sub-schema and whether any checks/refinements were encountered.\n * If checks are found at object level, partial validation isn't safe because\n * the refinement may depend on other fields.\n *\n * @param schema - Root form schema\n * @param path - Dot-notation field path (e.g., \"user.address.city\")\n * @returns Sub-schema and effects flag, or null if path invalid\n */\nexport function extractSubSchema(\n schema: ZodType,\n path: string,\n): { schema: ZodType; hasEffects: boolean } | null {\n const segments = getPathSegments(path)\n let currentSchema = schema\n let hasEffects = false\n\n for (const segment of segments) {\n // Reject empty segments (e.g., \"user..profile\" is invalid)\n if (!segment) return null\n\n // Check for checks at this level (before unwrapping)\n if (hasChecks(currentSchema)) {\n hasEffects = true\n }\n\n // Unwrap optional/nullable/default\n const unwrapped = unwrapNonEffects(currentSchema)\n\n // Check again after unwrapping\n if (hasChecks(unwrapped)) {\n hasEffects = true\n }\n\n if (isZodObject(unwrapped)) {\n const shape = getDefProp(unwrapped, 'shape') as Record<string, ZodType> | undefined\n if (!shape || !(segment in shape)) return null\n currentSchema = shape[segment]!\n } else if (isZodArray(unwrapped) && /^\\d+$/.test(segment)) {\n const element = getDefProp(unwrapped, 'element') as ZodType | undefined\n if (!element) return null\n currentSchema = element\n } else {\n // Unsupported type (union, intersection, etc.)\n return null\n }\n }\n\n // Check final schema for checks (field-level refinements)\n // Note: Field-level checks like .email() or .min() are safe for partial validation\n // We only care about custom .refine() checks which might have cross-field dependencies\n // In Zod v4, these show up as ZodCustom in the checks array\n const finalUnwrapped = unwrapNonEffects(currentSchema)\n const finalChecks = getDefProp(finalUnwrapped, 'checks') as Array<{ type?: string }> | undefined\n if (finalChecks) {\n for (const check of finalChecks) {\n // ZodCustom checks are custom refinements that might have cross-field deps\n if (check && typeof check === 'object' && 'type' in check && check.type === 'custom') {\n hasEffects = true\n break\n }\n }\n }\n\n // Return the unwrapped final schema for validation\n return { schema: finalUnwrapped, hasEffects }\n}\n\n/**\n * Analyze if a path can be validated in isolation\n *\n * This is the main entry point for determining partial validation eligibility.\n * Results are cached per-schema for performance.\n *\n * @param schema - Root form schema\n * @param path - Dot-notation field path\n * @returns Analysis result with eligibility and reason\n */\nexport function analyzeSchemaPath(schema: ZodType, path: string): SchemaPathAnalysis {\n // Check cache first\n let cache = analysisCache.get(schema)\n if (!cache) {\n cache = new Map()\n analysisCache.set(schema, cache)\n }\n\n const cached = cache.get(path)\n if (cached) return cached\n\n // Root-level checks = ALWAYS full validation\n // Refinements at root often check cross-field dependencies\n if (hasRootEffects(schema)) {\n const result: SchemaPathAnalysis = {\n canPartialValidate: false,\n reason: 'root-checks',\n }\n cache.set(path, result)\n return result\n }\n\n const extracted = extractSubSchema(schema, path)\n\n if (!extracted) {\n const result: SchemaPathAnalysis = {\n canPartialValidate: false,\n reason: 'invalid-path',\n }\n cache.set(path, result)\n return result\n }\n\n if (extracted.hasEffects) {\n const result: SchemaPathAnalysis = {\n canPartialValidate: false,\n reason: 'path-checks',\n }\n cache.set(path, result)\n return result\n }\n\n const result: SchemaPathAnalysis = {\n canPartialValidate: true,\n subSchema: extracted.schema,\n }\n cache.set(path, result)\n return result\n}\n\n/**\n * Clear the analysis cache (useful for testing)\n */\nexport function clearAnalysisCache(): void {\n // WeakMap entries are automatically garbage collected when schema is no longer referenced\n // This function is mainly for testing where we need to reset state\n}\n","import type { ShallowRef } from 'vue'\nimport { hashValue } from '../utils/hash'\nimport { get, unset } from '../utils/paths'\n\n/**\n * Mark a field as dirty (value has changed from default).\n * Optimized to skip clone if already dirty.\n *\n * @param dirtyFields - The reactive dirty fields record\n * @param fieldName - Name of the field to mark as dirty\n */\nexport function markFieldDirty(\n dirtyFields: ShallowRef<Record<string, boolean>>,\n fieldName: string,\n): void {\n // Skip if already dirty (avoid unnecessary object clone)\n if (dirtyFields.value[fieldName]) return\n dirtyFields.value = { ...dirtyFields.value, [fieldName]: true }\n}\n\n/**\n * Mark a field as touched (user has interacted with it).\n * Optimized to skip clone if already touched.\n *\n * @param touchedFields - The reactive touched fields record\n * @param fieldName - Name of the field to mark as touched\n */\nexport function markFieldTouched(\n touchedFields: ShallowRef<Record<string, boolean>>,\n fieldName: string,\n): void {\n // Skip if already touched (avoid unnecessary object clone)\n if (touchedFields.value[fieldName]) return\n touchedFields.value = { ...touchedFields.value, [fieldName]: true }\n}\n\n/**\n * Clear dirty state for a field.\n *\n * @param dirtyFields - The reactive dirty fields record\n * @param fieldName - Name of the field to clear\n */\nexport function clearFieldDirty(\n dirtyFields: ShallowRef<Record<string, boolean>>,\n fieldName: string,\n): void {\n // Skip if not dirty (avoid unnecessary object clone)\n if (!(fieldName in dirtyFields.value)) return\n const newDirty = { ...dirtyFields.value }\n delete newDirty[fieldName]\n dirtyFields.value = newDirty\n}\n\n/**\n * Clear touched state for a field.\n *\n * @param touchedFields - The reactive touched fields record\n * @param fieldName - Name of the field to clear\n */\nexport function clearFieldTouched(\n touchedFields: ShallowRef<Record<string, boolean>>,\n fieldName: string,\n): void {\n // Skip if not touched (avoid unnecessary object clone)\n if (!(fieldName in touchedFields.value)) return\n const newTouched = { ...touchedFields.value }\n delete newTouched[fieldName]\n touchedFields.value = newTouched\n}\n\n/**\n * Clear errors for a field and its nested paths.\n * Optimized with early exit if nothing to delete.\n *\n * @param errors - The reactive errors record\n * @param fieldName - Name of the field (clears exact match and all nested paths)\n */\nexport function clearFieldErrors<T>(\n errors: ShallowRef<Record<string, T>>,\n fieldName: string,\n): void {\n const currentErrors = errors.value\n\n // Early exit if no errors\n if (Object.keys(currentErrors).length === 0) return\n\n // Check for nested path error (e.g., 'user.email' stored as { user: { email: \"error\" } })\n const nestedError = get(currentErrors, fieldName)\n\n // Check for flat key matches (e.g., 'user.email' or 'user.email.something' as top-level keys)\n const prefix = `${fieldName}.`\n const flatKeysToDelete: string[] = []\n for (const key of Object.keys(currentErrors)) {\n if (key === fieldName || key.startsWith(prefix)) {\n flatKeysToDelete.push(key)\n }\n }\n\n // Early exit if nothing to clear\n if (nestedError === undefined && flatKeysToDelete.length === 0) return\n\n // Clone and clear\n const newErrors = { ...currentErrors }\n for (const key of flatKeysToDelete) {\n delete newErrors[key]\n }\n if (nestedError !== undefined) {\n unset(newErrors as Record<string, unknown>, fieldName)\n }\n errors.value = newErrors\n}\n\n/**\n * Update field dirty state based on value comparison with default.\n * Field is dirty only if current value differs from default value.\n *\n * Uses lazy hash computation - default hashes are computed on first access\n * and cached for subsequent comparisons.\n *\n * @param dirtyFields - The reactive dirty fields record\n * @param defaultValues - The original default values\n * @param defaultValueHashes - Cache of hashed default values\n * @param fieldName - Name of the field to check\n * @param currentValue - The current value to compare against default\n */\nexport function updateFieldDirtyState(\n dirtyFields: ShallowRef<Record<string, boolean>>,\n defaultValues: Record<string, unknown>,\n defaultValueHashes: Map<string, string>,\n fieldName: string,\n currentValue: unknown,\n): void {\n // Get or compute default hash (lazy initialization)\n let defaultHash = defaultValueHashes.get(fieldName)\n if (defaultHash === undefined) {\n const defaultValue = get(defaultValues, fieldName)\n defaultHash = hashValue(defaultValue)\n defaultValueHashes.set(fieldName, defaultHash)\n }\n\n const currentHash = hashValue(currentValue)\n const isDirty = currentHash !== defaultHash\n const wasDirty = dirtyFields.value[fieldName] === true\n\n if (isDirty && !wasDirty) {\n // Became dirty - value differs from default\n dirtyFields.value = { ...dirtyFields.value, [fieldName]: true }\n } else if (!isDirty && wasDirty) {\n // Reverted to clean - value matches default\n const newDirty = { ...dirtyFields.value }\n delete newDirty[fieldName]\n dirtyFields.value = newDirty\n }\n // If isDirty === wasDirty, no change needed\n}\n","import type { FormContext } from './formContext'\nimport type { FieldErrors, FieldError, FieldErrorValue, CriteriaMode } from '../types'\nimport { get, set } from '../utils/paths'\nimport { hashValue } from '../utils/hash'\nimport { analyzeSchemaPath } from '../utils/schemaExtract'\nimport { clearFieldErrors } from './fieldState'\nimport { getInputElement } from './domSync'\n\n/**\n * Helper to mark a field as validating.\n * Uses Set<string> for O(1) add/delete operations without object spreading.\n */\nfunction setValidating<T>(ctx: FormContext<T>, fieldPath: string, isValidating: boolean): void {\n const newSet = new Set(ctx.validatingFields.value)\n if (isValidating) {\n newSet.add(fieldPath)\n } else {\n newSet.delete(fieldPath)\n }\n ctx.validatingFields.value = newSet\n}\n\n/**\n * Group errors by field path for multi-error support\n */\nfunction groupErrorsByPath(\n issues: Array<{ path: PropertyKey[]; message: string; code: string }>,\n): Map<string, Array<{ type: string; message: string }>> {\n const grouped = new Map<string, Array<{ type: string; message: string }>>()\n\n for (const issue of issues) {\n const path = issue.path.join('.')\n const existing = grouped.get(path) || []\n existing.push({ type: issue.code, message: issue.message })\n grouped.set(path, existing)\n }\n\n return grouped\n}\n\n/**\n * Convert grouped errors to FieldError format\n * criteriaMode: 'firstError' - always returns first error message (string)\n * criteriaMode: 'all' - returns structured FieldError with all error types\n */\nfunction createFieldError(\n errors: Array<{ type: string; message: string }>,\n criteriaMode: CriteriaMode = 'firstError',\n): string | FieldError {\n const firstError = errors[0]\n if (!firstError) {\n return ''\n }\n\n // criteriaMode: 'firstError' - always return just the first error message\n if (criteriaMode === 'firstError') {\n return firstError.message\n }\n\n // criteriaMode: 'all' - always return structured FieldError with all types\n const types: Record<string, string | string[]> = {}\n for (const err of errors) {\n const existing = types[err.type]\n if (existing) {\n // Multiple errors of same type - make array\n types[err.type] = Array.isArray(existing)\n ? [...existing, err.message]\n : [existing, err.message]\n } else {\n types[err.type] = err.message\n }\n }\n\n return {\n type: firstError.type,\n message: firstError.message,\n types,\n }\n}\n\n/**\n * Create validation functions for form\n */\nexport function createValidation<FormValues>(ctx: FormContext<FormValues>) {\n /**\n * Apply native validation to a field's DOM element.\n * Sets the custom validity message for browser validation UI.\n */\n function applyNativeValidation(fieldPath: string, errorMessage: string | null): void {\n if (!ctx.options.shouldUseNativeValidation) return\n\n const fieldRef = ctx.fieldRefs.get(fieldPath)\n const el = getInputElement(fieldRef?.value)\n\n if (el && 'setCustomValidity' in el) {\n el.setCustomValidity(errorMessage || '')\n }\n }\n\n /**\n * Clear native validation on all registered fields\n */\n function clearAllNativeValidation(): void {\n if (!ctx.options.shouldUseNativeValidation) return\n\n for (const [path] of ctx.fieldRefs) {\n applyNativeValidation(path, null)\n }\n }\n\n /**\n * Batch schedule multiple errors at once (optimization for full-form validation).\n * When delayError is 0, this applies all errors in a single reactive update.\n */\n function scheduleErrorsBatch(errors: Array<[string, FieldErrorValue]>): void {\n const delayMs = ctx.options.delayError || 0\n\n if (delayMs <= 0) {\n // No delay - set all errors in a single update\n const newErrors = { ...ctx.errors.value }\n for (const [fieldPath, error] of errors) {\n set(newErrors, fieldPath, error)\n // Apply native validation\n const errorMessage = typeof error === 'string' ? error : error.message\n applyNativeValidation(fieldPath, errorMessage)\n }\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n return\n }\n\n // With delay - fall back to individual scheduling\n for (const [fieldPath, error] of errors) {\n scheduleError(fieldPath, error)\n }\n }\n\n /**\n * Schedule error display with optional delay (delayError feature)\n * If delayError > 0, the error will be shown after the delay.\n * If the field becomes valid before the delay completes, the error won't be shown.\n */\n function scheduleError(fieldPath: string, error: FieldErrorValue): void {\n const delayMs = ctx.options.delayError || 0\n\n // Get error message for native validation\n const errorMessage = typeof error === 'string' ? error : error.message\n\n if (delayMs <= 0) {\n // No delay - set error immediately using set() to maintain nested structure\n const newErrors = { ...ctx.errors.value }\n set(newErrors, fieldPath, error)\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n\n // Apply native validation\n applyNativeValidation(fieldPath, errorMessage)\n return\n }\n\n // Cancel any existing timer for this field\n const existingTimer = ctx.errorDelayTimers.get(fieldPath)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n // Store pending error\n ctx.pendingErrors.set(fieldPath, error)\n\n // Schedule delayed error display\n const timer = setTimeout(() => {\n ctx.errorDelayTimers.delete(fieldPath)\n const pendingError = ctx.pendingErrors.get(fieldPath)\n if (pendingError !== undefined) {\n ctx.pendingErrors.delete(fieldPath)\n // Use set() to maintain nested structure\n const newErrors = { ...ctx.errors.value }\n set(newErrors, fieldPath, pendingError)\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n\n // Apply native validation after delay\n applyNativeValidation(fieldPath, errorMessage)\n }\n }, delayMs)\n\n ctx.errorDelayTimers.set(fieldPath, timer)\n }\n\n /**\n * Cancel pending error and clear existing error for a field (delayError feature)\n * Preserves errors for fields marked as persistent via setError(..., { persistent: true })\n */\n function cancelError(fieldPath: string): void {\n // Cancel any pending delayed error\n const timer = ctx.errorDelayTimers.get(fieldPath)\n if (timer) {\n clearTimeout(timer)\n ctx.errorDelayTimers.delete(fieldPath)\n }\n ctx.pendingErrors.delete(fieldPath)\n\n // Clear native validation\n applyNativeValidation(fieldPath, null)\n\n // Preserve persistent errors (e.g., server-side validation errors)\n if (ctx.persistentErrorFields.has(fieldPath)) {\n return\n }\n\n // Clear existing error using shared utility (mutates ctx.errors directly)\n clearFieldErrors(ctx.errors, fieldPath)\n }\n\n /**\n * Clear all pending errors and timers (called on form reset)\n */\n function clearAllPendingErrors(): void {\n for (const timer of ctx.errorDelayTimers.values()) {\n clearTimeout(timer)\n }\n ctx.errorDelayTimers.clear()\n ctx.pendingErrors.clear()\n }\n\n /**\n * Validate a single field using partial schema validation (O(1) optimization)\n * Only validates the field's sub-schema instead of the entire form.\n */\n async function validateFieldPartial(\n fieldPath: string,\n subSchema: import('zod').ZodType,\n valueHash: string | undefined,\n cacheKey: string,\n criteriaMode: CriteriaMode,\n generationAtStart: number,\n ): Promise<boolean> {\n const fieldValue = get(ctx.formData, fieldPath)\n setValidating(ctx, fieldPath, true)\n\n try {\n const result = await subSchema.safeParseAsync(fieldValue)\n\n // Check if form was reset during validation\n if (ctx.resetGeneration.value !== generationAtStart) {\n return true\n }\n\n if (result.success) {\n cancelError(fieldPath)\n if (valueHash) {\n ctx.validationCache.set(cacheKey, { hash: valueHash, isValid: true })\n }\n return true\n }\n\n // Validation failed - process errors\n // Prepend fieldPath to error paths since we validated just the sub-schema\n // But first check if the path already starts with fieldPath to avoid double-prefixing\n const fieldSegments = fieldPath.split('.')\n const fieldErrors = result.error.issues.map((issue) => {\n const issuePath = issue.path.map(String)\n // Check if issue.path already starts with fieldPath segments (avoid double-prefix)\n const alreadyPrefixed =\n issuePath.length >= fieldSegments.length &&\n fieldSegments.every((seg, i) => issuePath[i] === seg)\n return {\n ...issue,\n path: alreadyPrefixed ? issuePath : fieldSegments.concat(issuePath),\n }\n })\n\n // Cancel existing errors for this field first\n cancelError(fieldPath)\n\n // Schedule errors in batch\n const grouped = groupErrorsByPath(fieldErrors)\n const errorBatch: Array<[string, FieldErrorValue]> = []\n for (const [path, errors] of grouped) {\n errorBatch.push([path, createFieldError(errors, criteriaMode)])\n }\n scheduleErrorsBatch(errorBatch)\n\n if (valueHash) {\n ctx.validationCache.set(cacheKey, { hash: valueHash, isValid: false })\n }\n return false\n } finally {\n setValidating(ctx, fieldPath, false)\n }\n }\n\n /**\n * Validate a single field using full form validation (fallback for schemas with effects)\n * Validates entire form, then filters to this field's errors.\n */\n async function validateFieldFull(\n fieldPath: string,\n valueHash: string | undefined,\n cacheKey: string,\n criteriaMode: CriteriaMode,\n generationAtStart: number,\n ): Promise<boolean> {\n setValidating(ctx, fieldPath, true)\n\n try {\n const result = await ctx.options.schema.safeParseAsync(ctx.formData)\n\n // Check if form was reset during validation\n if (ctx.resetGeneration.value !== generationAtStart) {\n return true\n }\n\n if (result.success) {\n cancelError(fieldPath)\n if (valueHash) {\n ctx.validationCache.set(cacheKey, { hash: valueHash, isValid: true })\n }\n return true\n }\n\n // Filter to only this field's errors\n const fieldErrors = result.error.issues.filter((issue) => {\n const path = issue.path.join('.')\n return path === fieldPath || path.startsWith(`${fieldPath}.`)\n })\n\n if (fieldErrors.length === 0) {\n cancelError(fieldPath)\n if (valueHash) {\n ctx.validationCache.set(cacheKey, { hash: valueHash, isValid: true })\n }\n return true\n }\n\n // Cancel existing errors for this field first\n cancelError(fieldPath)\n\n // Schedule errors in batch\n const grouped = groupErrorsByPath(fieldErrors)\n const errorBatch: Array<[string, FieldErrorValue]> = []\n for (const [path, errors] of grouped) {\n errorBatch.push([path, createFieldError(errors, criteriaMode)])\n }\n scheduleErrorsBatch(errorBatch)\n\n if (valueHash) {\n ctx.validationCache.set(cacheKey, { hash: valueHash, isValid: false })\n }\n return false\n } finally {\n setValidating(ctx, fieldPath, false)\n }\n }\n\n /**\n * Validate a single field or entire form\n */\n async function validate(fieldPath?: string): Promise<boolean> {\n // Capture reset generation before async validation\n const generationAtStart = ctx.resetGeneration.value\n\n // Get criteriaMode from options (default: 'firstError')\n const criteriaMode = ctx.options.criteriaMode || 'firstError'\n\n // For single-field validation, check cache first\n let valueHash: string | undefined\n if (fieldPath) {\n const currentValue = get(ctx.formData, fieldPath)\n valueHash = hashValue(currentValue)\n\n // Analyze if partial validation is possible BEFORE checking cache\n // This ensures cache entries are only used with matching validation strategies\n const analysis = analyzeSchemaPath(ctx.options.schema, fieldPath)\n const usePartial = analysis.canPartialValidate && analysis.subSchema\n\n // Check cache with strategy-aware key\n const cacheKey = `${fieldPath}:${usePartial ? 'partial' : 'full'}`\n const cached = ctx.validationCache.get(cacheKey)\n\n // Only use cache for valid results - invalid results need re-validation\n // to ensure the correct error message is displayed\n if (cached && cached.hash === valueHash && cached.isValid) {\n cancelError(fieldPath)\n return true\n }\n\n if (usePartial) {\n // O(1) single-field validation - validate only the sub-schema\n return validateFieldPartial(\n fieldPath,\n analysis.subSchema!,\n valueHash,\n cacheKey,\n criteriaMode,\n generationAtStart,\n )\n }\n\n // Fallback: full form validation with filtering\n // Required when schema has refinements that may depend on other fields\n return validateFieldFull(fieldPath, valueHash, cacheKey, criteriaMode, generationAtStart)\n }\n\n // Full form validation\n const validatingKey = '_form'\n setValidating(ctx, validatingKey, true)\n\n try {\n // Use safeParseAsync to avoid throwing\n const result = await ctx.options.schema.safeParseAsync(ctx.formData)\n\n // Check if form was reset during validation - if so, discard stale results\n if (ctx.resetGeneration.value !== generationAtStart) {\n return true // Form was reset, don't update errors\n }\n\n if (result.success) {\n // Full form valid - clear all pending errors and timers\n clearAllPendingErrors()\n ctx.errors.value = {} as FieldErrors<FormValues>\n\n // Clear native validation on all fields\n clearAllNativeValidation()\n\n // Clear validation cache on full form validation (values may have changed)\n ctx.validationCache.clear()\n return true\n }\n\n // Full form validation with multi-error support\n // Clear all pending errors first\n clearAllPendingErrors()\n ctx.errors.value = {} as FieldErrors<FormValues>\n\n // Schedule all errors in batch (optimization: single reactive update when no delay)\n const grouped = groupErrorsByPath(result.error.issues)\n const errorBatch: Array<[string, FieldErrorValue]> = []\n for (const [path, errors] of grouped) {\n errorBatch.push([path, createFieldError(errors, criteriaMode)])\n }\n scheduleErrorsBatch(errorBatch)\n\n // Clear validation cache on full form validation failure\n ctx.validationCache.clear()\n\n return false\n } finally {\n // Clear validating state\n setValidating(ctx, validatingKey, false)\n }\n }\n\n return { validate, clearAllPendingErrors }\n}\n","import type { ValidationMode } from '../types'\nimport { __DEV__, warnOnce } from './devWarnings'\n\n/** Valid validation mode values */\nconst VALID_MODES: readonly ValidationMode[] = ['onSubmit', 'onBlur', 'onChange', 'onTouched']\n\n/**\n * Validate that a mode is one of the allowed ValidationMode values.\n * Warns once per invalid mode in development.\n */\nfunction validateMode(mode: ValidationMode, paramName: string): void {\n if (__DEV__ && !VALID_MODES.includes(mode)) {\n warnOnce(\n `Invalid ${paramName}: \"${mode}\". Expected one of: ${VALID_MODES.join(', ')}`,\n `invalid-mode-${mode}`,\n )\n }\n}\n\n/**\n * Determines if validation should occur on change event.\n * Used by useController and register for consistent mode handling.\n *\n * @param mode - The form's validation mode\n * @param isTouched - Whether the field has been touched\n * @param hasSubmitted - Whether the form has been submitted at least once (for reValidateMode)\n * @param reValidateMode - The form's reValidateMode (used after first submit)\n * @returns true if validation should be triggered\n */\nexport function shouldValidateOnChange(\n mode: ValidationMode,\n isTouched: boolean,\n hasSubmitted?: boolean,\n reValidateMode?: ValidationMode,\n): boolean {\n if (__DEV__) {\n validateMode(mode, 'validation mode')\n if (reValidateMode) validateMode(reValidateMode, 'reValidateMode')\n }\n\n // Primary mode triggers (always apply)\n if (mode === 'onChange') return true\n if (mode === 'onTouched' && isTouched) return true\n\n // reValidateMode triggers (only apply after first submission)\n // hasSubmitted === true means form was submitted; false/undefined means not submitted\n // This ensures reValidateMode doesn't trigger after form reset (hasSubmitted = false)\n if (hasSubmitted === true && reValidateMode === 'onChange') return true\n\n return false\n}\n\n/**\n * Determines if validation should occur on blur event.\n * Used by useController and register for consistent mode handling.\n *\n * @param mode - The form's validation mode\n * @param hasSubmitted - Whether the form has been submitted at least once\n * @param reValidateMode - The form's reValidateMode (used after first submit)\n * @returns true if validation should be triggered\n */\nexport function shouldValidateOnBlur(\n mode: ValidationMode,\n hasSubmitted: boolean,\n reValidateMode?: ValidationMode,\n): boolean {\n if (__DEV__) {\n validateMode(mode, 'validation mode')\n if (reValidateMode) validateMode(reValidateMode, 'reValidateMode')\n }\n\n return (\n mode === 'onBlur' ||\n mode === 'onTouched' ||\n (hasSubmitted && (reValidateMode === 'onBlur' || reValidateMode === 'onTouched'))\n )\n}\n","import { computed, ref } from 'vue'\nimport type { FormContext } from './formContext'\nimport type {\n RegisterOptions,\n RegisterReturn,\n FieldErrors,\n UnregisterOptions,\n Path,\n} from '../types'\nimport { get, set, unset } from '../utils/paths'\nimport {\n __DEV__,\n validatePathSyntax,\n validatePathAgainstSchema,\n warnInvalidPath,\n warnPathNotInSchema,\n} from '../utils/devWarnings'\nimport {\n markFieldTouched,\n clearFieldDirty,\n clearFieldTouched,\n clearFieldErrors,\n updateFieldDirtyState,\n} from './fieldState'\nimport { shouldValidateOnChange, shouldValidateOnBlur } from '../utils/modeChecks'\nimport { getInputElement } from './domSync'\n\n// Monotonic counter for validation request IDs (avoids race conditions)\nlet validationRequestCounter = 0\n\n/**\n * Create field registration functions\n */\nexport function createFieldRegistration<FormValues>(\n ctx: FormContext<FormValues>,\n validate: (fieldPath?: string) => Promise<boolean>,\n) {\n /**\n * Register an input field\n */\n function register<TPath extends Path<FormValues>>(\n name: TPath,\n registerOptions?: RegisterOptions,\n ): RegisterReturn {\n // Dev-mode path validation (tree-shaken in production)\n if (__DEV__) {\n // Check for syntax errors in the path\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('register', name, syntaxError)\n }\n\n // Validate path exists in schema\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('register', name, schemaResult.availableFields)\n }\n }\n\n // Check if already registered - reuse existing ref to prevent recreation on every render\n let fieldRef = ctx.fieldRefs.get(name)\n\n if (!fieldRef) {\n fieldRef = ref<HTMLInputElement | null>(null)\n ctx.fieldRefs.set(name, fieldRef)\n\n // Only initialize field value on FIRST registration to avoid mutating state during re-renders\n if (get(ctx.formData, name) === undefined) {\n const defaultValue = get(ctx.defaultValues, name)\n if (defaultValue !== undefined) {\n set(ctx.formData, name, defaultValue)\n }\n }\n }\n\n // Update options if provided (this is safe to do on every render)\n if (registerOptions) {\n ctx.fieldOptions.set(name, registerOptions)\n }\n\n // Check if handlers are already cached - reuse to prevent recreation on every render\n let handlers = ctx.fieldHandlers.get(name)\n\n if (!handlers) {\n /**\n * Run custom field validation with optional debouncing\n */\n const runCustomValidation = async (\n fieldName: string,\n value: unknown,\n requestId: number,\n resetGenAtStart: number,\n ) => {\n // Check if field still exists (may have been unmounted during debounce)\n if (!ctx.fieldRefs.has(fieldName)) {\n return\n }\n\n const fieldOpts = ctx.fieldOptions.get(fieldName)\n if (!fieldOpts?.validate || fieldOpts.disabled) {\n return\n }\n\n const error = await fieldOpts.validate(value)\n\n // Check if this is still the latest request (race condition handling)\n const latestRequestId = ctx.validationRequestIds.get(fieldName)\n if (requestId !== latestRequestId) {\n return // Stale request, ignore result\n }\n\n // Check if form was reset during validation\n if (ctx.resetGeneration.value !== resetGenAtStart) {\n return // Form was reset, discard stale results\n }\n\n if (error) {\n const newErrors = { ...ctx.errors.value }\n set(newErrors, fieldName, error)\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n } else {\n // Clear the error if validation passes\n const newErrors = { ...ctx.errors.value }\n unset(newErrors as Record<string, unknown>, fieldName)\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n }\n }\n\n /**\n * Handle field input (fires on every keystroke)\n */\n const onInput = async (e: Event) => {\n const target = e.target as HTMLInputElement\n let value: unknown\n if (target.type === 'checkbox') {\n value = target.checked\n } else if (target.type === 'number' || target.type === 'range') {\n // Use valueAsNumber for proper number coercion (matches domSync.ts behavior)\n // Returns NaN for empty/invalid inputs which preserves the \"no value\" semantic\n value = target.valueAsNumber\n } else {\n value = target.value\n }\n\n // Update form data\n set(ctx.formData, name, value)\n\n // Update dirty state using value comparison (field is dirty only if value differs from default)\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n value,\n )\n\n // Cache field options lookup (avoid multiple Map.get calls)\n const fieldOpts = ctx.fieldOptions.get(name)\n\n // Validate based on mode\n const shouldValidate = shouldValidateOnChange(\n ctx.options.mode ?? 'onSubmit',\n ctx.touchedFields.value[name] === true,\n ctx.submitCount.value > 0,\n ctx.options.reValidateMode,\n )\n\n if (shouldValidate) {\n const validationDebounceMs = ctx.options.validationDebounce || 0\n\n if (validationDebounceMs > 0) {\n // Debounce schema validation to reduce calls during rapid typing\n const existingTimer = ctx.schemaValidationTimers.get(name)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n const timer = setTimeout(async () => {\n ctx.schemaValidationTimers.delete(name)\n await validate(name)\n\n // Trigger validation for dependent fields\n if (fieldOpts?.deps && fieldOpts.deps.length > 0) {\n const uniqueDeps = [...new Set(fieldOpts.deps)]\n await Promise.all(uniqueDeps.map((depField) => validate(depField)))\n }\n }, validationDebounceMs)\n\n ctx.schemaValidationTimers.set(name, timer)\n } else {\n // No debounce - validate immediately\n await validate(name)\n\n // Trigger validation for dependent fields in parallel (deps option)\n if (fieldOpts?.deps && fieldOpts.deps.length > 0) {\n const uniqueDeps = [...new Set(fieldOpts.deps)]\n await Promise.all(uniqueDeps.map((depField) => validate(depField)))\n }\n }\n }\n\n // Custom validation with optional debouncing (reuse cached fieldOpts)\n // Custom validation always runs on input if provided (it's an explicit opt-in)\n if (fieldOpts?.validate && !fieldOpts.disabled) {\n // Generate a new request ID for race condition handling (monotonic counter)\n const requestId = ++validationRequestCounter\n ctx.validationRequestIds.set(name, requestId)\n\n // Capture reset generation before starting async validation\n const resetGenAtStart = ctx.resetGeneration.value\n\n const debounceMs = fieldOpts.validateDebounce || 0\n\n if (debounceMs > 0) {\n // Cancel any existing debounce timer\n const existingTimer = ctx.debounceTimers.get(name)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n // Set new debounce timer\n const timer = setTimeout(async () => {\n ctx.debounceTimers.delete(name)\n await runCustomValidation(name, value, requestId, resetGenAtStart)\n // Clean up validationRequestIds ONLY if we're still the latest request.\n // A newer request might have been queued while we were validating,\n // and we shouldn't delete its request ID.\n if (ctx.validationRequestIds.get(name) === requestId) {\n ctx.validationRequestIds.delete(name)\n }\n }, debounceMs)\n\n ctx.debounceTimers.set(name, timer)\n } else {\n // No debounce, run immediately\n await runCustomValidation(name, value, requestId, resetGenAtStart)\n // Clean up only if still the latest request\n if (ctx.validationRequestIds.get(name) === requestId) {\n ctx.validationRequestIds.delete(name)\n }\n }\n }\n }\n\n /**\n * Handle field blur\n */\n const onBlur = async () => {\n // Mark as touched (optimized - skips clone if already touched)\n markFieldTouched(ctx.touchedFields, name)\n\n // Validate based on mode\n const shouldValidate = shouldValidateOnBlur(\n ctx.options.mode ?? 'onSubmit',\n ctx.submitCount.value > 0,\n ctx.options.reValidateMode,\n )\n\n if (shouldValidate) {\n await validate(name)\n\n // Trigger validation for dependent fields in parallel (deps option)\n const fieldOpts = ctx.fieldOptions.get(name)\n if (fieldOpts?.deps && fieldOpts.deps.length > 0) {\n const uniqueDeps = [...new Set(fieldOpts.deps)]\n await Promise.all(uniqueDeps.map((depField) => validate(depField)))\n }\n }\n }\n\n /**\n * Ref callback to store element reference\n */\n const refCallback = (el: unknown) => {\n // Get the current fieldRef from the Map (not closed over variable)\n const currentFieldRef = ctx.fieldRefs.get(name)\n if (!currentFieldRef) return\n\n const previousEl = currentFieldRef.value\n // Skip if same element - prevents triggering Vue reactivity unnecessarily\n if (previousEl === el) return\n\n // For fields with multiple elements (like radio buttons in v-for), only store the first one.\n // This prevents \"Maximum recursive updates exceeded\" when Vue re-binds refs on re-render:\n // - Without this check: radio5 → radio1 → radio2... triggers infinite updates\n // - With this check: we keep the first element and skip subsequent overwrites\n if (previousEl && el) return\n\n currentFieldRef.value = el as HTMLInputElement | null\n\n // Set initial value for uncontrolled inputs\n const opts = ctx.fieldOptions.get(name)\n const inputEl = getInputElement(el)\n if (inputEl && !opts?.controlled) {\n const value = get(ctx.formData, name)\n if (value !== undefined) {\n if (inputEl.type === 'checkbox') {\n inputEl.checked = value as boolean\n } else {\n inputEl.value = value as string\n }\n }\n }\n\n // Handle cleanup when element is removed (ref becomes null)\n if (previousEl && !el) {\n // Always clear debounce timers to prevent memory leaks\n // (timers hold references to form context via closure)\n const timer = ctx.debounceTimers.get(name)\n if (timer) {\n clearTimeout(timer)\n ctx.debounceTimers.delete(name)\n }\n // Clear schema validation debounce timers too\n const schemaTimer = ctx.schemaValidationTimers.get(name)\n if (schemaTimer) {\n clearTimeout(schemaTimer)\n ctx.schemaValidationTimers.delete(name)\n }\n // Clear error delay timers to prevent stale errors from appearing\n const errorTimer = ctx.errorDelayTimers.get(name)\n if (errorTimer) {\n clearTimeout(errorTimer)\n ctx.errorDelayTimers.delete(name)\n }\n ctx.pendingErrors.delete(name)\n ctx.validationRequestIds.delete(name)\n\n // Always clean up refs, options, and handlers when DOM element unmounts\n // to prevent memory accumulation for dynamically added/removed fields\n ctx.fieldRefs.delete(name)\n ctx.fieldOptions.delete(name)\n ctx.fieldHandlers.delete(name)\n\n const shouldUnreg = opts?.shouldUnregister ?? ctx.options.shouldUnregister ?? false\n\n if (shouldUnreg) {\n // Also clear form data and state for this field\n unset(ctx.formData, name)\n\n // Clear errors, touched, and dirty state (optimized with early exit)\n clearFieldErrors(ctx.errors, name)\n clearFieldTouched(ctx.touchedFields, name)\n clearFieldDirty(ctx.dirtyFields, name)\n }\n }\n }\n\n // Cache the handlers\n handlers = { onInput, onBlur, refCallback }\n ctx.fieldHandlers.set(name, handlers)\n }\n\n return {\n name,\n ref: handlers.refCallback,\n onInput: handlers.onInput,\n onBlur: handlers.onBlur,\n // Add form-level disabled\n ...(ctx.isDisabled.value && { disabled: true }),\n ...(registerOptions?.controlled && {\n value: computed({\n get: () => get(ctx.formData, name),\n set: (val) => {\n set(ctx.formData, name, val)\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n val,\n )\n },\n }),\n }),\n }\n }\n\n /**\n * Unregister a field to clean up refs, options, and form data\n */\n function unregister<TPath extends Path<FormValues>>(\n name: TPath,\n options?: UnregisterOptions,\n ): void {\n const opts = options || {}\n\n // Conditionally remove form data for this field\n if (!opts.keepValue) {\n unset(ctx.formData, name)\n }\n\n // Conditionally clear errors, touched, and dirty state (optimized)\n if (!opts.keepError) {\n clearFieldErrors(ctx.errors, name)\n }\n if (!opts.keepTouched) {\n clearFieldTouched(ctx.touchedFields, name)\n }\n if (!opts.keepDirty) {\n clearFieldDirty(ctx.dirtyFields, name)\n }\n\n // Always clean up refs, options, and handlers (internal state)\n ctx.fieldRefs.delete(name)\n ctx.fieldOptions.delete(name)\n ctx.fieldHandlers.delete(name)\n\n // Always clean up debounce timers\n const timer = ctx.debounceTimers.get(name)\n if (timer) {\n clearTimeout(timer)\n ctx.debounceTimers.delete(name)\n }\n // Clear schema validation debounce timers too\n const schemaTimer = ctx.schemaValidationTimers.get(name)\n if (schemaTimer) {\n clearTimeout(schemaTimer)\n ctx.schemaValidationTimers.delete(name)\n }\n ctx.validationRequestIds.delete(name)\n\n // Clear validation cache to prevent stale results on re-register\n // Clear both partial and full strategy cache entries\n ctx.validationCache.delete(`${name}:partial`)\n ctx.validationCache.delete(`${name}:full`)\n }\n\n return { register, unregister }\n}\n","import { ref, nextTick, type ComputedRef } from 'vue'\nimport type { FormContext } from './formContext'\nimport type {\n FieldArray,\n FieldArrayItem,\n FieldArrayOptions,\n FieldArrayFocusOptions,\n Path,\n RegisterOptions,\n RegisterReturn,\n SetValueOptions,\n FieldState,\n ErrorOption,\n} from '../types'\nimport { get, set, generateId } from '../utils/paths'\nimport {\n __DEV__,\n validatePathSyntax,\n validatePathAgainstSchema,\n isArrayFieldInSchema,\n warnInvalidPath,\n warnPathNotInSchema,\n warnFieldsOnNonArray,\n warnArrayOperationRejected,\n warnArrayIndexOutOfBounds,\n} from '../utils/devWarnings'\nimport { updateFieldDirtyState } from './fieldState'\nimport { shouldValidateOnChange } from '../utils/modeChecks'\n\n/**\n * Form methods required by field array for scoped item methods.\n * Passed from useForm to enable type-safe field access within array items.\n */\nexport interface FieldArrayFormMethods {\n register: (name: string, options?: RegisterOptions<unknown>) => RegisterReturn<unknown>\n setValue: (name: string, value: unknown, options?: SetValueOptions) => void\n getValues: (name: string) => unknown\n watch: (name: string) => ComputedRef<unknown>\n getFieldState: (name: string) => FieldState\n trigger: (name?: string | string[]) => Promise<boolean>\n clearErrors: (name?: string | string[]) => void\n setError: (name: string, error: ErrorOption) => void\n}\n\n/**\n * Create field array management functions\n */\nexport function createFieldArrayManager<FormValues>(\n ctx: FormContext<FormValues>,\n validate: (fieldPath?: string) => Promise<boolean>,\n setFocus: (name: string) => void,\n formMethods: FieldArrayFormMethods,\n) {\n /**\n * Manage dynamic field arrays with stable keys for Vue reconciliation.\n *\n * @param name - Array field path (must be an array in schema)\n * @param options - Optional configuration including validation rules\n * @returns FieldArray API with all array manipulation methods\n *\n * @example Basic field array usage\n * ```ts\n * const schema = z.object({\n * addresses: z.array(z.object({\n * street: z.string(),\n * city: z.string()\n * })).min(1)\n * })\n *\n * const { fields, register } = useForm({\n * schema,\n * defaultValues: { addresses: [{ street: '', city: '' }] }\n * })\n *\n * const addressFields = fields('addresses')\n * ```\n *\n * @example Template usage with stable keys (CRITICAL)\n * ```vue\n * <template>\n * <div v-for=\"field in addressFields.value\" :key=\"field.key\">\n * <!-- IMPORTANT: Use field.key for :key, NOT the index! -->\n * <!-- Using index causes inputs to show wrong values when items are reordered -->\n *\n * <input v-bind=\"register(`addresses.${field.index}.street`)\" />\n * <input v-bind=\"register(`addresses.${field.index}.city`)\" />\n * <button @click=\"field.remove()\">Remove</button>\n * </div>\n *\n * <button @click=\"addressFields.append({ street: '', city: '' })\">\n * Add Address\n * </button>\n * </template>\n * ```\n *\n * @example With minLength/maxLength rules\n * ```ts\n * const items = fields('items', {\n * rules: {\n * minLength: { value: 1, message: 'At least one item required' },\n * maxLength: { value: 10, message: 'Maximum 10 items' }\n * }\n * })\n *\n * // Operations that violate rules are rejected with console warning in dev\n * items.removeAll() // Rejected if minLength > 0\n * items.append(newItem) // Rejected if already at maxLength\n * ```\n *\n * @example Array operations\n * ```ts\n * // Add to end\n * addressFields.append({ street: '', city: '' })\n *\n * // Add multiple at once\n * addressFields.append([\n * { street: '123 Main St', city: 'NYC' },\n * { street: '456 Oak Ave', city: 'LA' }\n * ])\n *\n * // Add to beginning\n * addressFields.prepend({ street: '', city: '' })\n *\n * // Insert at specific index\n * addressFields.insert(1, { street: '', city: '' })\n *\n * // Reorder items\n * addressFields.swap(0, 1) // Swap first and second\n * addressFields.move(2, 0) // Move third to first position\n *\n * // Update in place (preserves key)\n * addressFields.update(0, { street: 'Updated', city: 'Updated' })\n *\n * // Remove\n * addressFields.remove(0) // Remove first\n * addressFields.removeMany([0, 2, 4]) // Remove multiple\n * addressFields.removeAll() // Remove all (respects minLength)\n *\n * // Replace all\n * addressFields.replace([{ street: 'New', city: 'New' }])\n * ```\n *\n * @example Focus after adding (accessibility)\n * ```ts\n * // Focus first field of new item after append\n * addressFields.append({ street: '', city: '' }, {\n * shouldFocus: true,\n * focusName: 'street' // Focus addresses.X.street\n * })\n * ```\n *\n * @see FieldArrayItem - Item metadata with key, index, remove()\n * @see FieldArrayFocusOptions - Auto-focus after append/prepend/insert\n */\n function fields<TPath extends Path<FormValues>>(\n name: TPath,\n options?: FieldArrayOptions,\n ): FieldArray {\n // Dev-mode path validation (tree-shaken in production)\n if (__DEV__) {\n // Check for syntax errors in the path\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('fields', name, syntaxError)\n }\n\n // Validate path exists in schema\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('fields', name, schemaResult.availableFields)\n }\n\n // Warn if path is not an array field\n const isArray = isArrayFieldInSchema(ctx.options.schema, name)\n if (isArray === false) {\n warnFieldsOnNonArray(name)\n }\n }\n\n // Get or create field array entry\n let fieldArray = ctx.fieldArrays.get(name)\n\n if (!fieldArray) {\n const existingValues = (get(ctx.formData, name) || []) as unknown[]\n fieldArray = {\n items: ref<FieldArrayItem[]>([]),\n values: existingValues,\n // Index cache stored on fieldArray for O(1) lookups, shared across fields() calls\n indexCache: new Map<string, number>(),\n // Store rules for validation\n rules: options?.rules,\n }\n ctx.fieldArrays.set(name, fieldArray)\n\n // Initialize form data if needed\n if (!get(ctx.formData, name)) {\n set(ctx.formData, name, [] as unknown[])\n }\n } else if (options?.rules) {\n // Update rules if provided on subsequent calls\n fieldArray.rules = options.rules\n }\n\n // Capture reference for closures\n const fa = fieldArray\n\n // Use the shared index cache from fieldArray state\n const indexCache = fa.indexCache\n\n /**\n * Rebuild the index cache from current items array.\n * Used when full rebuild is necessary (e.g., initial load, replace).\n */\n const rebuildIndexCache = () => {\n indexCache.clear()\n fa.items.value.forEach((item, idx) => {\n indexCache.set(item.key, idx)\n })\n }\n\n /**\n * Update cache for swap: only update 2 entries - O(1).\n */\n const swapInCache = (indexA: number, indexB: number) => {\n const items = fa.items.value\n const itemA = items[indexA]\n const itemB = items[indexB]\n if (itemA) indexCache.set(itemA.key, indexA)\n if (itemB) indexCache.set(itemB.key, indexB)\n }\n\n /**\n * Update cache after remove: delete key and shift indices - O(n-k) worst case.\n */\n const updateCacheAfterRemove = (removedKey: string, startIndex: number) => {\n indexCache.delete(removedKey)\n const items = fa.items.value\n // Update indices for all items at and after startIndex\n for (let i = startIndex; i < items.length; i++) {\n const item = items[i]\n if (item) indexCache.set(item.key, i)\n }\n }\n\n /**\n * Build a full field path from array name, index, and optional sub-path.\n * e.g., ('items', 2, 'name') => 'items.2.name'\n */\n const buildPath = (index: number, subPath?: string): string => {\n return subPath ? `${name}.${index}.${subPath}` : `${name}.${index}`\n }\n\n /**\n * Create scoped methods for a field array item.\n * These methods build full paths and delegate to form methods.\n */\n const createScopedMethods = (indexGetter: () => number) => {\n return {\n register: (subPath: string, options?: RegisterOptions<unknown>) =>\n formMethods.register(buildPath(indexGetter(), subPath), options),\n\n setValue: (subPath: string, value: unknown, options?: SetValueOptions) =>\n formMethods.setValue(buildPath(indexGetter(), subPath), value, options),\n\n getValue: (subPath: string) => formMethods.getValues(buildPath(indexGetter(), subPath)),\n\n watch: (subPath: string) => formMethods.watch(buildPath(indexGetter(), subPath)),\n\n getFieldState: (subPath: string) =>\n formMethods.getFieldState(buildPath(indexGetter(), subPath)),\n\n trigger: (subPath?: string | string[]) => {\n const index = indexGetter()\n if (!subPath) {\n // Validate entire item\n return formMethods.trigger(buildPath(index))\n }\n if (Array.isArray(subPath)) {\n return formMethods.trigger(subPath.map((p) => buildPath(index, p)))\n }\n return formMethods.trigger(buildPath(index, subPath))\n },\n\n clearErrors: (subPath?: string | string[]) => {\n const index = indexGetter()\n if (!subPath) {\n formMethods.clearErrors(buildPath(index))\n return\n }\n if (Array.isArray(subPath)) {\n formMethods.clearErrors(subPath.map((p) => buildPath(index, p)))\n return\n }\n formMethods.clearErrors(buildPath(index, subPath))\n },\n\n setError: (subPath: string, error: ErrorOption) =>\n formMethods.setError(buildPath(indexGetter(), subPath), error),\n }\n }\n\n /**\n * Helper to create items with cached index lookup and scoped methods.\n * Scoped methods are lazily initialized on first access for performance.\n *\n * Note: Runtime implementations use string paths, but type safety is enforced\n * at the FieldArray<TItem> level through the generic type parameter.\n * The 'as unknown as' casts are safe because the public API is typed correctly.\n */\n const createItem = (key: string): FieldArrayItem<unknown> => {\n const getIndex = () => indexCache.get(key) ?? -1\n\n // Lazy initialization of scoped methods\n let scoped: ReturnType<typeof createScopedMethods> | null = null\n const getScoped = () => (scoped ??= createScopedMethods(getIndex))\n\n // Type casts are needed because runtime uses strings but interface uses generics.\n // Type safety is enforced at the FieldArray<TItem> level.\n return {\n key,\n get index() {\n // O(1) lookup instead of O(n) findIndex\n return getIndex()\n },\n remove() {\n const currentIndex = getIndex()\n if (currentIndex !== -1) {\n removeAt(currentIndex)\n }\n },\n // Scoped methods - lazy getters delegate to form methods\n get register() {\n return getScoped().register as FieldArrayItem<unknown>['register']\n },\n get setValue() {\n return getScoped().setValue as FieldArrayItem<unknown>['setValue']\n },\n get getValue() {\n return getScoped().getValue as FieldArrayItem<unknown>['getValue']\n },\n get watch() {\n return getScoped().watch as FieldArrayItem<unknown>['watch']\n },\n get getFieldState() {\n return getScoped().getFieldState as FieldArrayItem<unknown>['getFieldState']\n },\n get trigger() {\n return getScoped().trigger as FieldArrayItem<unknown>['trigger']\n },\n get clearErrors() {\n return getScoped().clearErrors as FieldArrayItem<unknown>['clearErrors']\n },\n get setError() {\n return getScoped().setError as FieldArrayItem<unknown>['setError']\n },\n }\n }\n\n // Populate items if empty (first access after creation)\n if (fa.items.value.length === 0 && fa.values.length > 0) {\n fa.items.value = fa.values.map(() => createItem(generateId()))\n rebuildIndexCache()\n }\n\n /**\n * Handle focus after array operations\n */\n const handleFocus = async (\n baseIndex: number,\n addedCount: number,\n focusOptions?: FieldArrayFocusOptions,\n ) => {\n // Default shouldFocus to false (opt-in behavior)\n if (!focusOptions?.shouldFocus) return\n\n // Wait for DOM to update\n await nextTick()\n\n // Determine which item to focus (relative index within added items)\n // Clamp focusIndex to valid range [0, addedCount - 1] to prevent invalid paths\n const focusItemOffset = focusOptions?.focusIndex ?? 0\n const clampedOffset = Math.max(0, Math.min(focusItemOffset, addedCount - 1))\n const targetIndex = baseIndex + clampedOffset\n\n // Build the full field path\n let fieldPath = `${name}.${targetIndex}`\n if (focusOptions?.focusName) {\n fieldPath = `${fieldPath}.${focusOptions.focusName}`\n }\n\n // Use setFocus from useForm\n setFocus(fieldPath)\n }\n\n /**\n * Normalize input to always be an array (supports batch operations)\n */\n const normalizeToArray = <T>(value: T | T[]): T[] => {\n return Array.isArray(value) ? value : [value]\n }\n\n /**\n * Clear validation cache for this array field and all its children.\n * Must be called before mutations to prevent stale cache entries.\n */\n const clearValidationCache = () => {\n // Cache keys have format: `${fieldPath}:partial` or `${fieldPath}:full`\n // We need to clear entries for this array and all child paths\n for (const key of ctx.validationCache.keys()) {\n // Extract field path by removing the strategy suffix\n const colonIndex = key.lastIndexOf(':')\n const fieldPath = colonIndex > 0 ? key.slice(0, colonIndex) : key\n // Clear if it's the array field itself or a child path\n if (fieldPath === name || fieldPath.startsWith(`${name}.`)) {\n ctx.validationCache.delete(key)\n }\n }\n }\n\n /**\n * Validate the array field based on form validation mode.\n * Centralizes validation logic for all field array operations.\n */\n const validateIfNeeded = () => {\n const isTouched = ctx.touchedFields.value[name] === true\n const hasSubmitted = ctx.submitCount.value > 0\n const shouldValidate = shouldValidateOnChange(\n ctx.options.mode ?? 'onSubmit',\n isTouched,\n hasSubmitted,\n ctx.options.reValidateMode,\n )\n if (shouldValidate) {\n validate(name)\n }\n }\n\n /**\n * Verify sync between items array and formData.\n * Rebuilds items array if out of sync (e.g., external mutation via setValue).\n * Returns the current values array for convenience.\n */\n const ensureSync = (): unknown[] => {\n const currentValues = (get(ctx.formData, name) || []) as unknown[]\n if (fa.items.value.length !== currentValues.length) {\n if (__DEV__) {\n console.warn(\n `[vue-hook-form] Field array out of sync with formData. ` +\n `Rebuilding items array (items: ${fa.items.value.length}, formData: ${currentValues.length})`,\n )\n }\n fa.items.value = currentValues.map(() => createItem(generateId()))\n rebuildIndexCache()\n }\n return currentValues\n }\n\n const append = (value: unknown | unknown[], focusOptions?: FieldArrayFocusOptions): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n const values = normalizeToArray(value)\n if (values.length === 0) return true\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n const insertIndex = currentValues.length // Items will be added starting at this index\n\n // Check maxLength rule before adding\n const rules = fa.rules\n if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {\n if (__DEV__) {\n warnArrayOperationRejected('append', name, 'maxLength', {\n current: currentValues.length,\n limit: rules.maxLength.value,\n })\n }\n return false // Reject operation - maxLength exceeded\n }\n\n // Update form data (batch)\n const newValues = [...currentValues, ...values]\n set(ctx.formData, name, newValues)\n\n // Create items with unique keys (batch)\n const newItems = values.map(() => createItem(generateId()))\n const newItemsArray = [...fa.items.value, ...newItems]\n // Update cache BEFORE triggering Vue reactivity to prevent -1 index during render\n for (let i = insertIndex; i < newItemsArray.length; i++) {\n const item = newItemsArray[i]\n if (item) indexCache.set(item.key, i)\n }\n fa.items.value = newItemsArray\n\n // Mark dirty (optimized - skips if already dirty)\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n\n // Handle focus\n handleFocus(insertIndex, values.length, focusOptions)\n return true\n }\n\n const prepend = (\n value: unknown | unknown[],\n focusOptions?: FieldArrayFocusOptions,\n ): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n const values = normalizeToArray(value)\n if (values.length === 0) return true\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Check maxLength rule before adding\n const rules = fa.rules\n if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {\n if (__DEV__) {\n warnArrayOperationRejected('prepend', name, 'maxLength', {\n current: currentValues.length,\n limit: rules.maxLength.value,\n })\n }\n return false // Reject operation - maxLength exceeded\n }\n\n // Update form data (batch)\n const newValues = [...values, ...currentValues]\n set(ctx.formData, name, newValues)\n\n // Create items with unique keys (batch)\n const newItems = values.map(() => createItem(generateId()))\n const newItemsArray = [...newItems, ...fa.items.value]\n // Update cache BEFORE triggering Vue reactivity to prevent -1 index during render\n for (let i = 0; i < newItemsArray.length; i++) {\n const item = newItemsArray[i]\n if (item) indexCache.set(item.key, i)\n }\n fa.items.value = newItemsArray\n\n // Mark dirty (optimized)\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n\n // Handle focus (items added at index 0)\n handleFocus(0, values.length, focusOptions)\n return true\n }\n\n const update = (index: number, value: unknown): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n if (index < 0 || index >= currentValues.length) {\n if (__DEV__) {\n warnArrayIndexOutOfBounds('update', name, index, currentValues.length)\n }\n return false // Invalid index\n }\n const newValues = [...currentValues]\n newValues[index] = value\n set(ctx.formData, name, newValues)\n\n // Keep the same key - no items array change needed (preserves stable identity)\n // No cache update needed - indices haven't changed\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const removeAt = (index: number): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Bounds check\n if (index < 0 || index >= currentValues.length) {\n if (__DEV__) {\n warnArrayIndexOutOfBounds('remove', name, index, currentValues.length)\n }\n return false\n }\n\n // Check minLength rule before removing\n const rules = fa.rules\n if (rules?.minLength && currentValues.length - 1 < rules.minLength.value) {\n if (__DEV__) {\n warnArrayOperationRejected('remove', name, 'minLength', {\n current: currentValues.length,\n limit: rules.minLength.value,\n })\n }\n return false // Reject operation - minLength would be violated\n }\n\n const newValues = currentValues.filter((_: unknown, i: number) => i !== index)\n set(ctx.formData, name, newValues)\n\n // Remove item by current index, keep others\n const keyToRemove = fa.items.value[index]?.key\n fa.items.value = fa.items.value.filter((item) => item.key !== keyToRemove)\n // Incremental cache update - only shift indices after removed item\n if (keyToRemove) {\n updateCacheAfterRemove(keyToRemove, index)\n }\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const insert = (\n index: number,\n value: unknown | unknown[],\n focusOptions?: FieldArrayFocusOptions,\n ): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n const values = normalizeToArray(value)\n if (values.length === 0) return true\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Check maxLength rule before adding\n const rules = fa.rules\n if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {\n if (__DEV__) {\n warnArrayOperationRejected('insert', name, 'maxLength', {\n current: currentValues.length,\n limit: rules.maxLength.value,\n })\n }\n return false // Reject operation - maxLength exceeded\n }\n\n // Bounds validation: reject invalid indices (consistent with swap/move)\n if (index < 0 || index > currentValues.length) {\n if (__DEV__) {\n warnArrayIndexOutOfBounds('insert', name, index, currentValues.length)\n }\n return false\n }\n\n // Update form data (batch)\n const newValues = [...currentValues.slice(0, index), ...values, ...currentValues.slice(index)]\n set(ctx.formData, name, newValues)\n\n // Create items with unique keys (batch)\n const newItems = values.map(() => createItem(generateId()))\n const newItemsArray = [\n ...fa.items.value.slice(0, index),\n ...newItems,\n ...fa.items.value.slice(index),\n ]\n // Update cache BEFORE triggering Vue reactivity to prevent -1 index during render\n for (let i = index; i < newItemsArray.length; i++) {\n const item = newItemsArray[i]\n if (item) indexCache.set(item.key, i)\n }\n fa.items.value = newItemsArray\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n\n // Handle focus\n handleFocus(index, values.length, focusOptions)\n return true\n }\n\n const swap = (indexA: number, indexB: number): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Bounds validation: reject invalid indices\n if (\n indexA < 0 ||\n indexB < 0 ||\n indexA >= currentValues.length ||\n indexB >= currentValues.length\n ) {\n if (__DEV__) {\n const invalidIndex = indexA < 0 || indexA >= currentValues.length ? indexA : indexB\n warnArrayIndexOutOfBounds('swap', name, invalidIndex, currentValues.length)\n }\n return false // Invalid indices\n }\n\n const newValues = [...currentValues]\n ;[newValues[indexA], newValues[indexB]] = [newValues[indexB], newValues[indexA]]\n set(ctx.formData, name, newValues)\n\n // Swap items in array - always update to match formData state\n const newItems = [...fa.items.value]\n const itemA = newItems[indexA]\n const itemB = newItems[indexB]\n // Always swap even if items are falsy to keep items array in sync with formData\n newItems[indexA] = itemB as FieldArrayItem\n newItems[indexB] = itemA as FieldArrayItem\n fa.items.value = newItems\n // O(1) cache update - only update 2 entries\n swapInCache(indexA, indexB)\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const move = (from: number, to: number): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Bounds validation: reject invalid indices (consistent with swap)\n if (from < 0 || from >= currentValues.length || to < 0 || to >= currentValues.length) {\n if (__DEV__) {\n const invalidIndex = from < 0 || from >= currentValues.length ? from : to\n warnArrayIndexOutOfBounds('move', name, invalidIndex, currentValues.length)\n }\n return false // Invalid indices\n }\n\n const newValues = [...currentValues]\n const [removed] = newValues.splice(from, 1)\n if (removed !== undefined) {\n // No clamping needed: validation ensures to < currentValues.length,\n // and after removal newValues.length = currentValues.length - 1,\n // so to <= newValues.length is always valid for splice\n newValues.splice(to, 0, removed)\n set(ctx.formData, name, newValues)\n }\n\n // Move item in array - always update to match formData state\n const newItems = [...fa.items.value]\n const [removedItem] = newItems.splice(from, 1)\n // Always move even if item is undefined to keep items array in sync with formData\n newItems.splice(to, 0, removedItem as FieldArrayItem)\n fa.items.value = newItems\n // Update affected range in cache (from min to max of from/to)\n const minIdx = Math.min(from, to)\n const maxIdx = Math.max(from, to)\n const items = fa.items.value\n for (let i = minIdx; i <= maxIdx; i++) {\n const item = items[i]\n if (item) indexCache.set(item.key, i)\n }\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const replace = (newValues: unknown[]): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Validate input is array\n if (!Array.isArray(newValues)) {\n return false\n }\n\n // Update form data with new values\n set(ctx.formData, name, newValues)\n\n // Create new items with fresh keys for each value\n fa.items.value = newValues.map(() => createItem(generateId()))\n // Full rebuild needed - completely new set of items\n rebuildIndexCache()\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const removeAll = (): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Check minLength rule - if minLength > 0, reject\n const rules = fa.rules\n if (rules?.minLength && rules.minLength.value > 0) {\n if (__DEV__) {\n warnArrayOperationRejected('removeAll', name, 'minLength', {\n current: fa.items.value.length,\n limit: rules.minLength.value,\n })\n }\n return false // Reject operation - minLength would be violated\n }\n\n // Clear form data array\n set(ctx.formData, name, [])\n\n // Clear items tracking and cache\n fa.items.value = []\n indexCache.clear()\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n const removeMany = (indices: number[]): boolean => {\n // Clear stale validation cache before mutation\n clearValidationCache()\n\n // Ensure items array is in sync with formData before mutation\n const currentValues = ensureSync()\n\n // Validate indices and filter to valid ones\n const validIndices = indices.filter((i) => i >= 0 && i < currentValues.length)\n\n if (validIndices.length === 0) return true\n\n // Check minLength rule\n const rules = fa.rules\n const remainingCount = currentValues.length - validIndices.length\n if (rules?.minLength && remainingCount < rules.minLength.value) {\n if (__DEV__) {\n warnArrayOperationRejected('removeMany', name, 'minLength', {\n current: currentValues.length,\n limit: rules.minLength.value,\n })\n }\n return false // Reject operation - minLength would be violated\n }\n\n // Sort descending to remove from highest index first (prevents shifting issues)\n const sortedIndices = [...new Set(validIndices)].sort((a, b) => b - a)\n\n // Create set of indices to remove for O(1) lookup\n const indicesToRemove = new Set(sortedIndices)\n\n // Collect keys to remove from cache\n const keysToRemove = fa.items.value\n .filter((_, i) => indicesToRemove.has(i))\n .map((item) => item.key)\n\n // Filter out removed values\n const newValues = currentValues.filter((_, i) => !indicesToRemove.has(i))\n set(ctx.formData, name, newValues)\n\n // Remove items by indices\n fa.items.value = fa.items.value.filter((_, i) => !indicesToRemove.has(i))\n\n // Update cache: remove deleted keys and rebuild remaining indices\n for (const key of keysToRemove) {\n indexCache.delete(key)\n }\n // Rebuild remaining indices (simpler than tracking individual shifts)\n fa.items.value.forEach((item, idx) => {\n indexCache.set(item.key, idx)\n })\n\n updateFieldDirtyState(\n ctx.dirtyFields,\n ctx.defaultValues,\n ctx.defaultValueHashes,\n name,\n get(ctx.formData, name),\n )\n\n validateIfNeeded()\n return true\n }\n\n return {\n get value() {\n return fa.items.value\n },\n append,\n prepend,\n remove: removeAt,\n removeAll,\n removeMany,\n insert,\n swap,\n move,\n update,\n replace,\n }\n }\n\n return { fields }\n}\n","import { computed, reactive, onScopeDispose, getCurrentInstance, type ComputedRef } from 'vue'\nimport type { ZodType } from 'zod'\nimport type {\n UseFormOptions,\n UseFormReturn,\n FormState,\n FieldErrors,\n FieldErrorValue,\n FieldState,\n ErrorOption,\n SetFocusOptions,\n SetValueOptions,\n ResetOptions,\n ResetFieldOptions,\n TriggerOptions,\n InferSchema,\n Path,\n PathValue,\n SetErrorsOptions,\n} from './types'\nimport { get, set } from './utils/paths'\nimport { deepClone } from './utils/clone'\nimport {\n __DEV__,\n validatePathSyntax,\n validatePathAgainstSchema,\n warnInvalidPath,\n warnPathNotInSchema,\n} from './utils/devWarnings'\nimport { createFormContext } from './core/formContext'\nimport { createValidation } from './core/useValidation'\nimport { createFieldRegistration } from './core/useFieldRegistration'\nimport { createFieldArrayManager } from './core/useFieldArray'\nimport {\n syncUncontrolledInputs,\n updateDomElement,\n getInputElement,\n getFocusableElement,\n} from './core/domSync'\nimport {\n markFieldTouched,\n clearFieldDirty,\n clearFieldTouched,\n clearFieldErrors,\n updateFieldDirtyState,\n} from './core/fieldState'\nimport { hashValue } from './utils/hash'\n\n/**\n * Internal flag to suppress getFieldState snapshot warnings when called from useController.\n * When useController wraps getFieldState in a computed(), it's actually reactive,\n * but the warning system doesn't know this. This flag lets useController signal\n * that the call is intentionally inside a reactive effect.\n */\nlet isCalledFromController = false\n\n/**\n * Set the internal flag to suppress getFieldState warnings.\n * Used by useController before calling getFieldState inside computed().\n * @internal\n */\nexport function setCalledFromController(value: boolean): void {\n isCalledFromController = value\n}\n\n/**\n * Main form management composable\n *\n * @example\n * ```ts\n * const schema = z.object({\n * email: z.email(),\n * name: z.string().min(2)\n * })\n *\n * const { register, handleSubmit, formState } = useForm({ schema })\n *\n * const onSubmit = (data) => {\n * console.log(data) // { email: '...', name: '...' }\n * }\n * ```\n */\nexport function useForm<TSchema extends ZodType>(\n options: UseFormOptions<TSchema>,\n): UseFormReturn<TSchema> {\n type FormValues = InferSchema<TSchema>\n\n // Create shared context with all reactive state\n const ctx = createFormContext(options)\n\n // Synchronous submission lock to prevent double-submit race conditions.\n // Unlike ctx.isSubmitting (reactive), this is checked and set atomically\n // before any async operations, preventing the race window between checking\n // and setting the reactive value.\n let isSubmissionLocked = false\n\n // Cleanup watchers when scope is disposed (works in both component and effectScope contexts)\n onScopeDispose(() => {\n ctx.cleanup()\n })\n\n // Create validation functions\n const { validate, clearAllPendingErrors } = createValidation<FormValues>(ctx)\n\n // Create field registration functions\n const { register, unregister } = createFieldRegistration<FormValues>(ctx, validate)\n\n // Define setFocus early so it can be passed to field array manager\n function setFocus<TPath extends Path<FormValues>>(\n name: TPath,\n focusOptions?: SetFocusOptions,\n ): void {\n // Dev-mode path validation\n if (__DEV__) {\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('setFocus', name, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('setFocus', name, schemaResult.availableFields)\n }\n }\n }\n\n const fieldRef = ctx.fieldRefs.get(name)\n\n if (!fieldRef?.value) {\n return\n }\n\n const el = getFocusableElement(fieldRef.value)\n if (!el) return\n\n el.focus()\n\n // Select text if requested and element supports selection\n if (\n focusOptions?.shouldSelect &&\n el instanceof HTMLInputElement &&\n typeof el.select === 'function'\n ) {\n el.select()\n }\n }\n\n // Track last sync time to avoid redundant DOM syncs\n let lastSyncTime = 0\n const SYNC_DEBOUNCE_MS = 16 // ~1 frame\n\n /**\n * Sync uncontrolled inputs with debounce to avoid redundant syncs.\n * If called multiple times within SYNC_DEBOUNCE_MS, only the first call syncs.\n */\n function syncWithDebounce(): void {\n const now = typeof performance !== 'undefined' ? performance.now() : Date.now()\n if (now - lastSyncTime < SYNC_DEBOUNCE_MS) {\n return // Skip - synced recently\n }\n syncUncontrolledInputs(ctx.fieldRefs, ctx.fieldOptions, ctx.formData)\n lastSyncTime = now\n }\n\n /**\n * Get merged errors (internal validation + external/server errors)\n * External errors take precedence (server knows best)\n * Memoized to avoid creating new objects when inputs haven't changed.\n */\n let lastErrors = ctx.errors.value\n let lastExternalErrors = ctx.externalErrors.value\n let cachedMergedErrors: FieldErrors<FormValues> | null = null\n\n function getMergedErrors(): FieldErrors<FormValues> {\n // Return cached result if inputs haven't changed (reference equality)\n if (\n cachedMergedErrors !== null &&\n lastErrors === ctx.errors.value &&\n lastExternalErrors === ctx.externalErrors.value\n ) {\n return cachedMergedErrors\n }\n\n // Update cache\n lastErrors = ctx.errors.value\n lastExternalErrors = ctx.externalErrors.value\n cachedMergedErrors = {\n ...ctx.errors.value,\n ...ctx.externalErrors.value,\n } as FieldErrors<FormValues>\n\n return cachedMergedErrors\n }\n\n // --- Granular computed properties for optimized reactivity ---\n // Each property is computed individually, then composed into formState\n // This provides stable object reference and granular dependency tracking\n\n // isDirty: true if any field differs from default\n const isDirtyComputed = computed(() => Object.keys(ctx.dirtyFields.value).length > 0)\n\n // Memoized merged errors (internal + external)\n const errorsComputed = computed<FieldErrors<FormValues>>(() => getMergedErrors())\n\n // isValid: true if no errors (matches React Hook Form behavior)\n const isValidComputed = computed(() => {\n return Object.keys(errorsComputed.value).length === 0\n })\n\n // isReady: form initialization complete (async defaults loaded)\n const isReadyComputed = computed(() => !ctx.isLoading.value)\n\n // isValidating: O(1) check with Set\n const isValidatingComputed = computed(() => ctx.validatingFields.value.size > 0)\n\n // isSubmitted: at least one submission attempt\n const isSubmittedComputed = computed(() => ctx.submitCount.value > 0)\n\n /**\n * Get current form state\n * Uses reactive object with getters for:\n * - Stable object reference (same instance)\n * - Lazy evaluation via getters\n * - Granular dependency tracking\n * - Full backward compatibility\n */\n const formStateInternal = reactive({\n get errors() {\n return errorsComputed.value\n },\n get isDirty() {\n return isDirtyComputed.value\n },\n get dirtyFields() {\n return ctx.dirtyFields.value\n },\n get isValid() {\n return isValidComputed.value\n },\n get isSubmitting() {\n return ctx.isSubmitting.value\n },\n get isLoading() {\n return ctx.isLoading.value\n },\n get isReady() {\n return isReadyComputed.value\n },\n get isValidating() {\n return isValidatingComputed.value\n },\n get validatingFields() {\n return ctx.validatingFields.value\n },\n get touchedFields() {\n return ctx.touchedFields.value\n },\n get submitCount() {\n return ctx.submitCount.value\n },\n get defaultValuesError() {\n return ctx.defaultValuesError.value\n },\n get isSubmitted() {\n return isSubmittedComputed.value\n },\n get isSubmitSuccessful() {\n return ctx.isSubmitSuccessful.value\n },\n get disabled() {\n return ctx.isDisabled.value\n },\n }) as FormState<FormValues>\n\n // Wrap in computed for backward compatibility with formState.value access pattern\n const formState = computed<FormState<FormValues>>(() => formStateInternal)\n\n /**\n * Handle form submission\n */\n function handleSubmit(\n onValid: (data: FormValues) => void | Promise<void>,\n onInvalid?: (errors: FieldErrors<FormValues>) => void,\n ) {\n return async (e: Event) => {\n e.preventDefault()\n\n // Prevent submission if form is disabled\n if (ctx.isDisabled.value) return\n\n // Prevent double-submit using synchronous lock (checked BEFORE any async work).\n // This prevents the race condition where rapid clicks could both pass the\n // ctx.isSubmitting.value check before either sets it to true.\n if (isSubmissionLocked) return\n isSubmissionLocked = true\n\n // Also set reactive state for UI binding\n ctx.isSubmitting.value = true\n ctx.submitCount.value++\n ctx.isSubmitSuccessful.value = false\n\n try {\n // Collect values from uncontrolled inputs (debounced)\n syncWithDebounce()\n\n // Validate entire form\n const isValid = await validate()\n\n if (isValid) {\n // Call success handler with deep clone to prevent mutation of form state\n await onValid(deepClone(ctx.formData) as FormValues)\n ctx.isSubmitSuccessful.value = true\n } else {\n // Call error handler if provided (use merged errors from formState)\n onInvalid?.(formState.value.errors)\n\n // Focus first error field if shouldFocusError is enabled (default: true)\n if (options.shouldFocusError !== false) {\n const firstErrorField = Object.keys(formState.value.errors)[0]\n if (firstErrorField) {\n setFocus(firstErrorField as Path<FormValues>)\n }\n }\n }\n } finally {\n ctx.isSubmitting.value = false\n isSubmissionLocked = false\n }\n }\n }\n\n /**\n * Set a field value programmatically. Supports nested paths and\n * optional validation/dirty/touched behavior control.\n *\n * @param name - Field path (e.g., 'email' or 'user.address.city')\n * @param value - New value (typed based on path)\n * @param options - Control side effects (validation, dirty, touched)\n *\n * @example Basic usage - sets value and marks dirty (default)\n * ```ts\n * setValue('email', 'user@example.com')\n * // Equivalent to: setValue('email', '...', { shouldDirty: true })\n * ```\n *\n * @example Set value from API without marking dirty\n * ```ts\n * // When populating from server data, don't mark as user-changed\n * setValue('email', serverData.email, { shouldDirty: false })\n * ```\n *\n * @example Set value and immediately validate\n * ```ts\n * setValue('quantity', newQty, { shouldValidate: true })\n * // Useful for fields that affect other validations\n * ```\n *\n * @example Set value and mark as touched\n * ```ts\n * setValue('terms', true, { shouldTouch: true })\n * // Simulates user interaction with the field\n * ```\n *\n * @example Set nested array item value\n * ```ts\n * setValue('addresses.0.city', 'New York')\n * setValue(`addresses.${index}.zipCode`, '10001')\n * ```\n *\n * @see reset - Reset entire form to default values\n * @see resetField - Reset a single field to its default\n */\n function setValue<TPath extends Path<FormValues>>(\n name: TPath,\n value: PathValue<FormValues, TPath>,\n setValueOptions?: SetValueOptions,\n ): void {\n // Dev-mode path validation\n if (__DEV__) {\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('setValue', name, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('setValue', name, schemaResult.availableFields)\n }\n }\n }\n\n set(ctx.formData, name, value)\n\n // shouldDirty (default: true) - uses value comparison to determine dirty state\n // shouldDirty: false - explicitly clear dirty state (used when populating server data)\n if (setValueOptions?.shouldDirty === false) {\n // Clear dirty state for this field - server data shouldn't be considered user-changed\n clearFieldDirty(ctx.dirtyFields, name)\n } else {\n // Default behavior: compare value to default to determine dirty state\n updateFieldDirtyState(ctx.dirtyFields, ctx.defaultValues, ctx.defaultValueHashes, name, value)\n }\n\n // shouldTouch (default: false)\n if (setValueOptions?.shouldTouch) {\n markFieldTouched(ctx.touchedFields, name)\n }\n\n // Only update DOM element for uncontrolled inputs\n // For controlled inputs, Vue reactivity handles the sync through v-model\n const opts = ctx.fieldOptions.get(name)\n if (!opts?.controlled) {\n const fieldRef = ctx.fieldRefs.get(name)\n if (fieldRef?.value) {\n updateDomElement(fieldRef.value, value)\n }\n }\n\n // shouldValidate (default: false) - explicit opt-in to immediate validation\n // This is an explicit override that validates regardless of mode\n if (setValueOptions?.shouldValidate) {\n validate(name)\n }\n }\n\n /**\n * Reset form to default values\n */\n function reset(values?: Partial<FormValues>, resetOptions?: ResetOptions): void {\n const opts = resetOptions || {}\n\n // Clear validation cache FIRST to prevent race conditions where a new validation\n // starts after generation increment but before cache clear, finding stale entries\n ctx.validationCache.clear()\n\n // Increment reset generation to invalidate any in-flight validations\n ctx.resetGeneration.value++\n\n // Clear all pending error timers and validating state\n clearAllPendingErrors()\n ctx.validatingFields.value = new Set()\n\n // Clear any pending schema validation debounce timers\n for (const timer of ctx.schemaValidationTimers.values()) {\n clearTimeout(timer)\n }\n ctx.schemaValidationTimers.clear()\n\n // Clear any pending custom validation debounce timers to prevent memory leaks\n // (timers hold references to form context via closures)\n for (const timer of ctx.debounceTimers.values()) {\n clearTimeout(timer)\n }\n ctx.debounceTimers.clear()\n ctx.validationRequestIds.clear()\n\n // Update default values unless keepDefaultValues is true\n if (!opts.keepDefaultValues && values) {\n Object.assign(ctx.defaultValues, values)\n // Clear cached hashes since defaults changed - will be lazily recomputed\n ctx.defaultValueHashes.clear()\n }\n\n // Clear form data\n Object.keys(ctx.formData).forEach((key) => delete ctx.formData[key])\n\n // Apply new values or defaults (deep clone to prevent reference sharing)\n const sourceValues = values || ctx.defaultValues\n const newValues = deepClone(sourceValues)\n Object.assign(ctx.formData, newValues)\n\n // Reset state based on options\n if (!opts.keepErrors) {\n ctx.errors.value = {} as FieldErrors<FormValues>\n ctx.externalErrors.value = {} as FieldErrors<FormValues>\n // Also clear persistent error tracking so they don't survive validation cycles\n ctx.persistentErrorFields.clear()\n }\n if (!opts.keepTouched) {\n ctx.touchedFields.value = {}\n }\n if (!opts.keepDirty) {\n ctx.dirtyFields.value = {}\n }\n if (!opts.keepSubmitCount) {\n ctx.submitCount.value = 0\n }\n if (!opts.keepIsSubmitting) {\n ctx.isSubmitting.value = false\n }\n if (!opts.keepIsSubmitSuccessful) {\n ctx.isSubmitSuccessful.value = false\n }\n\n // Always clear field arrays (they'll be recreated on next access)\n ctx.fieldArrays.clear()\n\n // Update input elements\n for (const [name, fieldRef] of Array.from(ctx.fieldRefs.entries())) {\n const el = getInputElement(fieldRef.value)\n if (el) {\n const value = get(newValues as Record<string, unknown>, name)\n if (value !== undefined) {\n if (el.type === 'checkbox') {\n el.checked = value as boolean\n } else {\n el.value = value as string\n }\n }\n }\n }\n }\n\n /**\n * Reset an individual field to its default value\n */\n function resetField<TPath extends Path<FormValues>>(\n name: TPath,\n resetFieldOptions?: ResetFieldOptions,\n ): void {\n // Dev-mode path validation\n if (__DEV__) {\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('resetField', name, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('resetField', name, schemaResult.availableFields)\n }\n }\n }\n\n const opts = resetFieldOptions || {}\n\n // Clear validation cache for this field (both partial and full strategy variants)\n ctx.validationCache.delete(`${name}:partial`)\n ctx.validationCache.delete(`${name}:full`)\n\n // Clear error delay timer for this field\n const errorTimer = ctx.errorDelayTimers.get(name)\n if (errorTimer) {\n clearTimeout(errorTimer)\n ctx.errorDelayTimers.delete(name)\n }\n ctx.pendingErrors.delete(name)\n\n // Clear schema validation debounce timer for this field\n const schemaTimer = ctx.schemaValidationTimers.get(name)\n if (schemaTimer) {\n clearTimeout(schemaTimer)\n ctx.schemaValidationTimers.delete(name)\n }\n\n // Get default value (use provided or stored default)\n let defaultValue = opts.defaultValue\n if (defaultValue === undefined) {\n defaultValue = get(ctx.defaultValues, name)\n } else {\n // Update stored default if new one provided\n set(ctx.defaultValues, name, defaultValue)\n // Update cached hash for this field\n ctx.defaultValueHashes.set(name, hashValue(defaultValue))\n }\n\n // Update form data (deep clone to prevent reference sharing)\n const clonedValue = defaultValue !== undefined ? deepClone(defaultValue) : undefined\n set(ctx.formData, name, clonedValue)\n\n // Conditionally clear errors\n if (!opts.keepError) {\n clearFieldErrors(ctx.errors, name)\n }\n\n // Conditionally clear dirty state\n if (!opts.keepDirty) {\n clearFieldDirty(ctx.dirtyFields, name)\n }\n\n // Conditionally clear touched state\n if (!opts.keepTouched) {\n clearFieldTouched(ctx.touchedFields, name)\n }\n\n // Update DOM element for uncontrolled inputs\n const fieldOpts = ctx.fieldOptions.get(name)\n if (!fieldOpts?.controlled) {\n const fieldRef = ctx.fieldRefs.get(name)\n if (fieldRef?.value) {\n const el = getInputElement(fieldRef.value)\n updateDomElement(fieldRef.value, clonedValue ?? (el?.type === 'checkbox' ? false : ''))\n }\n }\n }\n\n /**\n * Watch field value(s) reactively. Returns a ComputedRef that updates\n * whenever the watched field(s) change.\n *\n * @overload Watch all form values\n * @returns ComputedRef containing all form values\n *\n * @example Watch all values for debugging or live preview\n * ```ts\n * const allValues = watch()\n * // In template: {{ allValues.value }}\n * // Returns: { email: 'user@example.com', name: 'John', addresses: [...] }\n * ```\n *\n * @overload Watch a single field\n * @param name - Field path (e.g., 'email' or 'user.address.city')\n * @returns ComputedRef containing the field's current value\n *\n * @example Watch single field for conditional UI\n * ```ts\n * const accountType = watch('accountType')\n *\n * // In template:\n * // <div v-if=\"accountType.value === 'business'\">\n * // <BusinessFields />\n * // </div>\n * ```\n *\n * @example Watch nested field\n * ```ts\n * const city = watch('user.address.city')\n * console.log(city.value) // 'New York'\n * ```\n *\n * @overload Watch multiple fields\n * @param names - Array of field paths\n * @returns ComputedRef containing an object with the watched fields\n *\n * @example Watch multiple fields for computed values\n * ```ts\n * const priceFields = watch(['quantity', 'price'])\n *\n * const total = computed(() => {\n * const q = Number(priceFields.value.quantity) || 0\n * const p = Number(priceFields.value.price) || 0\n * return (q * p).toFixed(2)\n * })\n * ```\n *\n * @see useWatch - Standalone composable for watching from child components\n */\n function watch(): ComputedRef<FormValues>\n function watch<TPath extends Path<FormValues>>(\n name: TPath,\n ): ComputedRef<PathValue<FormValues, TPath>>\n function watch<TPath extends Path<FormValues>>(names: TPath[]): ComputedRef<Partial<FormValues>>\n function watch<TPath extends Path<FormValues>>(\n name?: TPath | TPath[],\n ): ComputedRef<FormValues | PathValue<FormValues, TPath> | Partial<FormValues>> {\n // Dev-mode path validation\n if (__DEV__ && name) {\n const names = Array.isArray(name) ? name : [name]\n for (const n of names) {\n const syntaxError = validatePathSyntax(n)\n if (syntaxError) {\n warnInvalidPath('watch', n, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, n)\n if (!schemaResult.valid) {\n warnPathNotInSchema('watch', n, schemaResult.availableFields)\n }\n }\n }\n }\n\n return computed(() => {\n if (!name) {\n return ctx.formData as FormValues\n }\n if (Array.isArray(name)) {\n const result: Record<string, unknown> = {}\n for (const n of name) {\n result[n] = get(ctx.formData, n)\n }\n return result as Partial<FormValues>\n }\n return get(ctx.formData, name) as PathValue<FormValues, TPath>\n })\n }\n\n /**\n * Clear errors for one or more fields, or all errors\n */\n function clearErrors<TPath extends Path<FormValues>>(\n name?: TPath | TPath[] | 'root' | `root.${string}`,\n ): void {\n // Dev-mode path validation (skip for 'root' paths)\n if (__DEV__ && name && !String(name).startsWith('root')) {\n const names = Array.isArray(name) ? name : [name]\n for (const n of names) {\n if (String(n).startsWith('root')) continue\n const syntaxError = validatePathSyntax(n)\n if (syntaxError) {\n warnInvalidPath('clearErrors', n, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, n)\n if (!schemaResult.valid) {\n warnPathNotInSchema('clearErrors', n, schemaResult.availableFields)\n }\n }\n }\n }\n\n if (name === undefined) {\n // Clear all errors (internal, external) and persistent error tracking\n ctx.errors.value = {} as FieldErrors<FormValues>\n ctx.externalErrors.value = {} as FieldErrors<FormValues>\n ctx.persistentErrorFields.clear()\n return\n }\n\n const fieldsToClean = Array.isArray(name) ? name : [name]\n for (const field of fieldsToClean) {\n clearFieldErrors(ctx.errors, field)\n // Also clear from external errors (server-side errors)\n clearFieldErrors(ctx.externalErrors, field)\n // Clear exact match AND nested paths from persistent tracking\n const prefix = `${field}.`\n for (const persistentField of ctx.persistentErrorFields) {\n if (persistentField === field || persistentField.startsWith(prefix)) {\n ctx.persistentErrorFields.delete(persistentField)\n }\n }\n }\n }\n\n /**\n * Programmatically set an error for a field\n * Supports both simple string errors (backward compatible) and structured FieldError objects\n */\n function setError<TPath extends Path<FormValues>>(\n name: TPath | 'root' | `root.${string}`,\n error: ErrorOption,\n ): void {\n const newErrors = { ...ctx.errors.value }\n\n // Create structured error if type is provided, otherwise use string for backward compatibility\n const errorValue = error.type ? { type: error.type, message: error.message } : error.message\n\n set(newErrors, name, errorValue)\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n\n // Track persistent errors so they survive validation\n if (error.persistent) {\n ctx.persistentErrorFields.add(name)\n }\n }\n\n /**\n * Set multiple errors at once\n */\n function setErrors<TPath extends Path<FormValues>>(\n errors: Partial<Record<TPath | 'root' | `root.${string}`, string | ErrorOption>>,\n options?: SetErrorsOptions,\n ): void {\n // Start with empty object if replacing, otherwise preserve existing\n const newErrors = options?.shouldReplace ? {} : { ...ctx.errors.value }\n\n // Iterate over provided errors and apply them\n for (const [name, error] of Object.entries(errors)) {\n if (error === undefined) continue\n\n // Handle both string and ErrorOption formats\n const errorValue =\n typeof error === 'string'\n ? error\n : (error as ErrorOption).type\n ? { type: (error as ErrorOption).type, message: (error as ErrorOption).message }\n : (error as ErrorOption).message\n\n set(newErrors, name, errorValue)\n }\n\n ctx.errors.value = newErrors as FieldErrors<FormValues>\n }\n\n /**\n * Check if form or specific field has errors\n */\n function hasErrors<TPath extends Path<FormValues>>(\n fieldPath?: TPath | 'root' | `root.${string}`,\n ): boolean {\n const mergedErrors = getMergedErrors()\n\n if (fieldPath === undefined) {\n // Check if form has any errors\n return Object.keys(mergedErrors).length > 0\n }\n\n // Check specific field - use get() for nested path support\n const error = get(mergedErrors, fieldPath)\n return error !== undefined && error !== null\n }\n\n /**\n * Get errors for form or specific field\n */\n function getErrors(): FieldErrors<FormValues>\n function getErrors<TPath extends Path<FormValues>>(\n fieldPath: TPath | 'root' | `root.${string}`,\n ): FieldErrorValue | undefined\n function getErrors<TPath extends Path<FormValues>>(\n fieldPath?: TPath | 'root' | `root.${string}`,\n ): FieldErrors<FormValues> | FieldErrorValue | undefined {\n const mergedErrors = getMergedErrors()\n\n if (fieldPath === undefined) {\n // Return all errors\n return mergedErrors\n }\n\n // Return specific field error\n return get(mergedErrors, fieldPath) as FieldErrorValue | undefined\n }\n\n /**\n * Get current form values synchronously. For uncontrolled inputs,\n * this syncs DOM values before returning.\n *\n * @overload Get all form values\n * @returns Complete form data object (deep copy)\n *\n * @example Get all values for logging or API call\n * ```ts\n * const allData = getValues()\n * console.log(allData) // { email: '...', name: '...', addresses: [...] }\n * await api.saveDraft(allData)\n * ```\n *\n * @overload Get a single field value\n * @param name - Field path\n * @returns The field's current value (typed based on path)\n *\n * @example Get specific field value\n * ```ts\n * const email = getValues('email') // string\n * const city = getValues('addresses.0.city') // string\n * ```\n *\n * @overload Get multiple field values\n * @param names - Array of field paths\n * @returns Partial object containing only the requested fields\n *\n * @example Get subset of values\n * ```ts\n * const { email, name } = getValues(['email', 'name'])\n * // Returns: { email: '...', name: '...' }\n * ```\n *\n * @example Copy values between field groups\n * ```ts\n * // Copy shipping address to billing\n * const shipping = getValues(['shipping.street', 'shipping.city', 'shipping.zip'])\n * setValue('billing.street', getValues('shipping.street'))\n * setValue('billing.city', getValues('shipping.city'))\n * ```\n *\n * @see watch - For reactive value subscriptions\n * @see getFieldState - For field metadata (dirty, touched, error)\n */\n function getValues(): FormValues\n function getValues<TPath extends Path<FormValues>>(name: TPath): PathValue<FormValues, TPath>\n function getValues<TPath extends Path<FormValues>>(names: TPath[]): Partial<FormValues>\n function getValues<TPath extends Path<FormValues>>(\n nameOrNames?: TPath | TPath[],\n ): FormValues | PathValue<FormValues, TPath> | Partial<FormValues> {\n // Dev-mode path validation\n if (__DEV__ && nameOrNames) {\n const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames]\n for (const n of names) {\n const syntaxError = validatePathSyntax(n)\n if (syntaxError) {\n warnInvalidPath('getValues', n, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, n)\n if (!schemaResult.valid) {\n warnPathNotInSchema('getValues', n, schemaResult.availableFields)\n }\n }\n }\n }\n\n // Sync values from uncontrolled inputs before returning (debounced)\n syncWithDebounce()\n\n if (nameOrNames === undefined) {\n // Return deep copy to prevent mutation of form state\n return deepClone(ctx.formData) as FormValues\n }\n\n if (Array.isArray(nameOrNames)) {\n // Return multiple field values\n const result: Record<string, unknown> = {}\n for (const fieldName of nameOrNames) {\n result[fieldName] = deepClone(get(ctx.formData, fieldName))\n }\n return result as Partial<FormValues>\n }\n\n // Return deep copy to prevent mutation of form state\n return deepClone(get(ctx.formData, nameOrNames)) as PathValue<FormValues, TPath>\n }\n\n /**\n * Get the current state of a field (dirty, touched, error).\n *\n * ⚠️ **WARNING:** Returns a plain object snapshot, NOT reactive refs.\n *\n * This function is designed for imperative use cases (e.g., in callbacks, computed functions).\n * For reactive error display in templates, use `formState.value.errors[name]` instead.\n * For custom/reusable components, use `useController` which provides reactive `fieldState`.\n *\n * **Common mistake (error messages that persist):**\n * ```vue\n * <!-- ❌ WRONG - Snapshot never updates -->\n * <script setup>\n * const emailState = getFieldState('email')\n * </script>\n * <template>\n * <span v-if=\"emailState.error\">{{ emailState.error }}</span>\n * </template>\n * ```\n *\n * **Correct reactive alternatives:**\n * ```vue\n * <!-- ✅ Option 1: Use formState (always reactive) -->\n * <span v-if=\"formState.value.errors.email\">{{ formState.value.errors.email }}</span>\n *\n * <!-- ✅ Option 2: Use computed -->\n * <script setup>\n * const emailError = computed(() => formState.value.errors.email)\n * </script>\n *\n * <!-- ✅ Option 3: Use useController (for reusable components) -->\n * <script setup>\n * const { fieldState } = useController({ name: 'email', control })\n * // fieldState is a ComputedRef that updates automatically\n * </script>\n * ```\n *\n * @param name - Field path in dot notation (e.g., 'email', 'user.address.street')\n * @returns Field state snapshot with isDirty, isTouched, invalid, and error properties\n *\n * @see formState.value.errors - For reactive error access\n * @see useController - For reactive field state in custom components\n */\n function getFieldState<TPath extends Path<FormValues>>(name: TPath): FieldState {\n // Dev-mode path validation\n if (__DEV__) {\n const syntaxError = validatePathSyntax(name)\n if (syntaxError) {\n warnInvalidPath('getFieldState', name, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, name)\n if (!schemaResult.valid) {\n warnPathNotInSchema('getFieldState', name, schemaResult.availableFields)\n }\n }\n\n // Warn about non-reactivity when called in component setup\n // Skip warning if called from useController (which wraps this in a computed)\n if (getCurrentInstance() && !isCalledFromController) {\n console.warn(\n `[vue-hook-form] getFieldState('${name}') returns a snapshot, not reactive refs.\\n` +\n `For reactive error display, use one of these alternatives:\\n` +\n ` • formState.value.errors.${name}\\n` +\n ` • const { fieldState } = useController({ name: '${name}', control })\\n` +\n ` • const ${name}Error = computed(() => formState.value.errors.${name})\\n\\n` +\n `See docs: https://github.com/vuehookform/core#common-mistakes`,\n )\n }\n }\n\n const error = get(ctx.errors.value, name) as\n | string\n | { type: string; message: string }\n | undefined\n return {\n isDirty: ctx.dirtyFields.value[name] === true,\n isTouched: ctx.touchedFields.value[name] === true,\n invalid: error !== undefined && error !== null,\n error,\n }\n }\n\n /**\n * Manually trigger validation for specific fields or the entire form.\n * Useful for validating before certain actions or in wizard-style forms.\n *\n * @param name - Optional field path or array of paths. Validates all if omitted.\n * @returns Promise resolving to true if valid, false if errors exist\n *\n * @example Validate entire form before a custom action\n * ```ts\n * async function saveAsDraft() {\n * const isValid = await trigger()\n * if (isValid) {\n * await api.saveDraft(getValues())\n * } else {\n * console.log('Please fix errors before saving')\n * }\n * }\n * ```\n *\n * @example Validate specific field on custom event\n * ```ts\n * async function onUsernameBlur() {\n * const isValid = await trigger('username')\n * if (isValid) {\n * // Check username availability\n * const available = await api.checkUsername(getValues('username'))\n * if (!available) {\n * setError('username', { message: 'Username already taken' })\n * }\n * }\n * }\n * ```\n *\n * @example Validate step fields in multi-step form\n * ```ts\n * async function nextStep() {\n * // Validate only current step's fields\n * const stepFields = ['firstName', 'lastName', 'email']\n * const isValid = await trigger(stepFields)\n * if (isValid) {\n * currentStep.value++\n * }\n * }\n * ```\n *\n * @example Validate all addresses in array\n * ```ts\n * const addressCount = getValues('addresses').length\n * const addressFields = Array.from({ length: addressCount }, (_, i) => [\n * `addresses.${i}.street`,\n * `addresses.${i}.city`,\n * `addresses.${i}.zip`\n * ]).flat()\n * const addressesValid = await trigger(addressFields)\n * ```\n */\n async function trigger<TPath extends Path<FormValues>>(\n name?: TPath | TPath[],\n options?: TriggerOptions,\n ): Promise<boolean> {\n // Dev-mode path validation\n if (__DEV__ && name) {\n const names = Array.isArray(name) ? name : [name]\n for (const n of names) {\n const syntaxError = validatePathSyntax(n)\n if (syntaxError) {\n warnInvalidPath('trigger', n, syntaxError)\n } else {\n const schemaResult = validatePathAgainstSchema(ctx.options.schema, n)\n if (!schemaResult.valid) {\n warnPathNotInSchema('trigger', n, schemaResult.availableFields)\n }\n }\n }\n }\n\n // Increment submitCount to activate reValidateMode behavior\n if (options?.markAsSubmitted) {\n ctx.submitCount.value++\n }\n\n if (name === undefined) {\n // Validate entire form\n return await validate()\n }\n\n if (Array.isArray(name)) {\n // Validate multiple fields in parallel\n const results = await Promise.all(name.map((fieldName) => validate(fieldName)))\n return results.every((isValid) => isValid)\n }\n\n // Validate single field\n return await validate(name)\n }\n\n // Create field array manager after all form methods are defined\n // This allows scoped methods on field array items to access the full form API\n const setFocusWrapper = (name: string) => setFocus(name as Path<FormValues>)\n const formMethods = {\n register: (name: string, options?: unknown) =>\n register(name as Path<FormValues>, options as Parameters<typeof register>[1]),\n setValue: (name: string, value: unknown, options?: SetValueOptions) =>\n setValue(name as Path<FormValues>, value as PathValue<FormValues, Path<FormValues>>, options),\n getValues: (name: string) => getValues(name as Path<FormValues>),\n watch: (name: string) => watch(name as Path<FormValues>),\n getFieldState: (name: string) => getFieldState(name as Path<FormValues>),\n trigger: (name?: string | string[]) =>\n trigger(name as Path<FormValues> | Path<FormValues>[] | undefined),\n clearErrors: (name?: string | string[]) =>\n clearErrors(name as Path<FormValues> | Path<FormValues>[] | undefined),\n setError: (name: string, error: ErrorOption) => setError(name as Path<FormValues>, error),\n }\n const { fields } = createFieldArrayManager<FormValues>(\n ctx,\n validate,\n setFocusWrapper,\n formMethods,\n )\n\n // Type assertion needed because internal implementations use simpler types\n // but the public API provides full generic type safety\n return {\n register,\n unregister,\n handleSubmit,\n formState,\n fields,\n setValue,\n reset,\n resetField,\n watch,\n validate,\n clearErrors,\n setError,\n setErrors,\n hasErrors,\n getErrors,\n getValues,\n getFieldState,\n trigger,\n setFocus,\n options: {\n mode: ctx.options.mode ?? 'onSubmit',\n reValidateMode: ctx.options.reValidateMode,\n },\n } as UseFormReturn<TSchema>\n}\n","import { inject, provide, type InjectionKey } from 'vue'\nimport type { UseFormReturn } from './types'\nimport type { ZodType } from 'zod'\n\n/**\n * Injection key for form context\n */\nexport const FormContextKey: InjectionKey<UseFormReturn<ZodType>> = Symbol('FormContext')\n\n/**\n * Provide form methods to child components via Vue's dependency injection.\n *\n * Call this in a parent component's setup function after calling useForm().\n *\n * @example\n * ```ts\n * // Parent component\n * const form = useForm({ schema })\n * provideForm(form)\n * ```\n *\n * @param methods - The return value from useForm()\n */\nexport function provideForm<TSchema extends ZodType>(methods: UseFormReturn<TSchema>): void {\n provide(FormContextKey, methods as unknown as UseFormReturn<ZodType>)\n}\n\n/**\n * Access form methods in a child component via Vue's dependency injection.\n *\n * Must be used within a component tree where provideForm() has been called.\n *\n * @example\n * ```ts\n * // Child component\n * const { register, formState } = useFormContext()\n * ```\n *\n * @returns The form methods from the parent component's useForm() call\n * @throws Error if used outside of a FormProvider context\n */\nexport function useFormContext<TSchema extends ZodType>(): UseFormReturn<TSchema> {\n const context = inject(FormContextKey)\n\n if (!context) {\n throw new Error(\n 'useFormContext must be used within a component tree where provideForm() has been called. ' +\n 'Make sure to call provideForm(useForm({ schema })) in a parent component.',\n )\n }\n\n return context as unknown as UseFormReturn<TSchema>\n}\n","import { computed, type ComputedRef } from 'vue'\nimport type { ZodType } from 'zod'\nimport type { UseFormReturn, Path, PathValue, InferSchema } from './types'\nimport { useFormContext } from './context'\nimport { get } from './utils/paths'\n\n/**\n * Options for useWatch composable\n */\nexport interface UseWatchOptions<\n TSchema extends ZodType,\n TPath extends Path<InferSchema<TSchema>>,\n> {\n /** Form control from useForm (uses context if not provided) */\n control?: UseFormReturn<TSchema>\n /** Field path or array of paths to watch (watches all if not provided) */\n name?: TPath | TPath[]\n /** Default value when field is undefined */\n defaultValue?: unknown\n}\n\n/**\n * Watch form field values reactively without the full form instance\n *\n * This composable allows you to subscribe to form value changes from any component\n * in the tree, as long as the form context is provided via provideForm().\n *\n * @example\n * ```ts\n * // Watch a single field\n * const email = useWatch({ name: 'email' })\n *\n * // Watch multiple fields\n * const fields = useWatch({ name: ['firstName', 'lastName'] })\n *\n * // Watch all form values\n * const allValues = useWatch({})\n *\n * // With explicit control\n * const { control } = useForm({ schema })\n * const email = useWatch({ control, name: 'email' })\n *\n * // With default value\n * const status = useWatch({ name: 'status', defaultValue: 'pending' })\n * ```\n */\nexport function useWatch<TSchema extends ZodType>(\n options?: Omit<UseWatchOptions<TSchema, Path<InferSchema<TSchema>>>, 'name'>,\n): ComputedRef<InferSchema<TSchema>>\n\nexport function useWatch<TSchema extends ZodType, TPath extends Path<InferSchema<TSchema>>>(\n options: UseWatchOptions<TSchema, TPath> & { name: TPath },\n): ComputedRef<PathValue<InferSchema<TSchema>, TPath>>\n\nexport function useWatch<TSchema extends ZodType, TPath extends Path<InferSchema<TSchema>>>(\n options: UseWatchOptions<TSchema, TPath> & { name: TPath[] },\n): ComputedRef<Partial<InferSchema<TSchema>>>\n\nexport function useWatch<\n TSchema extends ZodType,\n TPath extends Path<InferSchema<TSchema>> = Path<InferSchema<TSchema>>,\n>(\n options: UseWatchOptions<TSchema, TPath> = {} as UseWatchOptions<TSchema, TPath>,\n): ComputedRef<\n InferSchema<TSchema> | PathValue<InferSchema<TSchema>, TPath> | Partial<InferSchema<TSchema>>\n> {\n const { control, name, defaultValue } = options\n\n // Get form control from context if not provided\n const form = control ?? useFormContext<TSchema>()\n\n return computed(() => {\n if (name === undefined) {\n // Watch all values\n return form.getValues()\n }\n\n if (Array.isArray(name)) {\n // Watch multiple fields\n const result: Record<string, unknown> = {}\n for (const fieldName of name) {\n const value = get(form.getValues(), fieldName)\n result[fieldName] = value ?? defaultValue\n }\n return result\n }\n\n // Watch single field\n const value = get(form.getValues(), name)\n return value ?? defaultValue\n }) as ComputedRef<\n InferSchema<TSchema> | PathValue<InferSchema<TSchema>, TPath> | Partial<InferSchema<TSchema>>\n >\n}\n","import { computed, ref, type ComputedRef, type Ref } from 'vue'\nimport type { ZodType } from 'zod'\nimport type { UseFormReturn, Path, PathValue, InferSchema, FieldState, LooseControl } from './types'\nimport { useFormContext } from './context'\nimport { shouldValidateOnChange, shouldValidateOnBlur } from './utils/modeChecks'\nimport { setCalledFromController } from './useForm'\n\n/**\n * Options for useController composable\n */\nexport interface UseControllerOptions<\n TSchema extends ZodType,\n TPath extends Path<InferSchema<TSchema>>,\n> {\n /** Field name/path */\n name: TPath\n /** Form control from useForm (uses context if not provided) */\n control?: UseFormReturn<TSchema>\n /** Default value for the field */\n defaultValue?: PathValue<InferSchema<TSchema>, TPath>\n}\n\n/**\n * Field props returned by useController\n */\nexport interface ControllerFieldProps<TValue> {\n /** Current field value */\n value: Ref<TValue>\n /** Field name */\n name: string\n /** Change handler - call with new value */\n onChange: (value: TValue) => void\n /** Blur handler */\n onBlur: () => void\n /** Ref callback for the input element */\n ref: (el: HTMLElement | null) => void\n}\n\n/**\n * Return value from useController\n */\nexport interface UseControllerReturn<TValue> {\n /** Field props for binding to input components */\n field: ControllerFieldProps<TValue>\n /** Current field state (errors, dirty, touched) */\n fieldState: ComputedRef<FieldState>\n}\n\n/**\n * Loose options for useController when schema type is unknown.\n * Use this for building reusable field components that work with any form.\n *\n * @example\n * ```ts\n * // Reusable field component\n * function FormInput(props: { name: string; control: LooseControl }) {\n * const { field, fieldState } = useController(props)\n * // field.value is unknown, fieldState is reactive\n * }\n * ```\n */\nexport interface LooseControllerOptions {\n /** Field name/path as a string */\n name: string\n /** Form control from useForm (uses context if not provided) */\n control?: LooseControl\n /** Default value for the field */\n defaultValue?: unknown\n}\n\n/**\n * Hook for controlled components that need fine-grained control over field state\n *\n * This composable is useful for integrating with custom input components or\n * third-party UI libraries that don't work with the standard register() approach.\n *\n * @example\n * ```ts\n * // Basic usage with context\n * const { field, fieldState } = useController({ name: 'email' })\n *\n * // With explicit control\n * const { control } = useForm({ schema })\n * const { field, fieldState } = useController({ control, name: 'email' })\n *\n * // In template:\n * // <CustomInput\n * // :value=\"field.value.value\"\n * // @update:modelValue=\"field.onChange\"\n * // @blur=\"field.onBlur\"\n * // />\n * // <span v-if=\"fieldState.value.error\">{{ fieldState.value.error }}</span>\n * ```\n *\n * @example Reusable component with loose typing\n * ```ts\n * // FormInput.vue\n * const props = defineProps<{ name: string; control: LooseControl }>()\n * const { field, fieldState } = useController(props)\n * // No 'as never' cast needed!\n * ```\n */\nexport function useController(options: LooseControllerOptions): UseControllerReturn<unknown>\nexport function useController<TSchema extends ZodType, TPath extends Path<InferSchema<TSchema>>>(\n options: UseControllerOptions<TSchema, TPath>,\n): UseControllerReturn<PathValue<InferSchema<TSchema>, TPath>>\nexport function useController<TSchema extends ZodType, TPath extends Path<InferSchema<TSchema>>>(\n options: UseControllerOptions<TSchema, TPath> | LooseControllerOptions,\n): UseControllerReturn<unknown> {\n type TValue = PathValue<InferSchema<TSchema>, TPath>\n\n const { name, control, defaultValue } = options\n\n // Get form control from context if not provided\n const form = control ?? useFormContext<TSchema>()\n\n // Element ref for focus management\n const elementRef = ref<HTMLElement | null>(null)\n\n // Initialize with default value if provided\n if (defaultValue !== undefined && form.getValues(name) === undefined) {\n form.setValue(name, defaultValue)\n }\n\n // Create reactive value for v-model binding.\n // The setter marks the field dirty by default (shouldDirty: true),\n // which is the expected behavior for controlled inputs.\n // For programmatic value loading without marking dirty, use form.setValue with { shouldDirty: false }.\n const value = computed({\n get: () => {\n const currentValue = form.getValues(name)\n return (currentValue ?? defaultValue) as TValue\n },\n set: (newValue: TValue) => {\n form.setValue(name, newValue)\n },\n })\n\n // Change handler - respects form validation mode\n const onChange = (newValue: TValue) => {\n const isTouched = form.formState.value.touchedFields[name] === true\n const hasSubmitted = form.formState.value.submitCount > 0\n const mode = form.options.mode ?? 'onSubmit'\n const reValidateMode = form.options.reValidateMode\n\n const shouldValidate = shouldValidateOnChange(mode, isTouched, hasSubmitted, reValidateMode)\n\n form.setValue(name, newValue, { shouldValidate })\n }\n\n // Blur handler - respects form validation mode\n const onBlur = () => {\n const hasSubmitted = form.formState.value.submitCount > 0\n const mode = form.options.mode ?? 'onSubmit'\n const reValidateMode = form.options.reValidateMode\n\n const shouldValidate = shouldValidateOnBlur(mode, hasSubmitted, reValidateMode)\n\n // Use setValue with shouldTouch to properly mark the field as touched\n // Mark field as touched for proper validation mode handling (onBlur, onTouched, etc.)\n const currentValue = form.getValues(name)\n form.setValue(name, currentValue, {\n shouldTouch: true,\n shouldValidate,\n shouldDirty: false, // Don't change dirty state on blur\n })\n }\n\n // Ref callback\n const refCallback = (el: HTMLElement | null) => {\n elementRef.value = el\n }\n\n // Field state computed - wrapped with flag to suppress false positive warning\n const fieldState = computed<FieldState>(() => {\n setCalledFromController(true)\n const state = form.getFieldState(name)\n setCalledFromController(false)\n return state\n })\n\n return {\n field: {\n value: value as unknown as Ref<TValue>,\n name,\n onChange: onChange as (value: unknown) => void,\n onBlur,\n ref: refCallback,\n },\n fieldState,\n } as UseControllerReturn<unknown>\n}\n","import { computed, type ComputedRef } from 'vue'\nimport type { ZodType } from 'zod'\nimport type { UseFormReturn, FormState, InferSchema } from './types'\nimport { useFormContext } from './context'\n\n/**\n * Keys of FormState that can be subscribed to\n */\nexport type FormStateKey = keyof FormState<unknown>\n\n/**\n * Options for useFormState composable\n */\nexport interface UseFormStateOptions<TSchema extends ZodType> {\n /** Form control from useForm (uses context if not provided) */\n control?: UseFormReturn<TSchema>\n /** Specific state keys to subscribe to (subscribes to all if not provided) */\n name?: FormStateKey | FormStateKey[]\n}\n\n/**\n * Subscribe to specific form state properties\n *\n * This composable allows you to efficiently subscribe to only the form state\n * properties you need, reducing unnecessary re-renders.\n *\n * @example\n * ```ts\n * // Subscribe to all form state\n * const formState = useFormState({})\n *\n * // Subscribe to specific properties\n * const { isSubmitting, errors } = useFormState({ name: ['isSubmitting', 'errors'] })\n *\n * // Subscribe to single property\n * const isDirty = useFormState({ name: 'isDirty' })\n *\n * // With explicit control\n * const { control } = useForm({ schema })\n * const formState = useFormState({ control })\n * ```\n */\nexport function useFormState<TSchema extends ZodType>(\n options: UseFormStateOptions<TSchema> = {},\n): ComputedRef<Partial<FormState<InferSchema<TSchema>>>> {\n const { control, name } = options\n\n // Get form control from context if not provided\n const form = control ?? useFormContext<TSchema>()\n\n return computed(() => {\n const fullState = form.formState.value\n\n if (name === undefined) {\n // Return all state\n return { ...fullState }\n }\n\n if (Array.isArray(name)) {\n // Return specific properties\n const result: Partial<FormState<InferSchema<TSchema>>> = {}\n for (const key of name) {\n ;(result as Record<string, unknown>)[key] = fullState[key]\n }\n return result\n }\n\n // Return single property wrapped in object\n return { [name]: fullState[name] } as Partial<FormState<InferSchema<TSchema>>>\n })\n}\n","import type { ComponentPublicInstance, ComputedRef, MaybeRef, Ref } from 'vue'\nimport type { ZodType, z } from 'zod'\n\n/**\n * Validation mode determines when validation occurs\n */\nexport type ValidationMode = 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched'\n\n/**\n * Extract the inferred type from a Zod schema\n */\nexport type InferSchema<TSchema extends ZodType> = z.infer<TSchema>\n\n/**\n * Alias for InferSchema - extracts form value type from schema.\n * Use this when you need the actual form data type.\n *\n * @example\n * const schema = z.object({ email: z.string(), age: z.number() })\n * type MyFormValues = FormValues<typeof schema>\n * // Result: { email: string; age: number }\n */\nexport type FormValues<TSchema extends ZodType> = InferSchema<TSchema>\n\n/**\n * Extract the element type from an array type.\n * Returns `never` if T is not an array.\n *\n * @example\n * type Item = ArrayElement<string[]> // string\n * type Never = ArrayElement<string> // never\n */\nexport type ArrayElement<T> = T extends Array<infer U> ? U : never\n\n/**\n * Generate all possible dot-notation paths for a nested object type.\n * Provides IDE autocomplete for valid field names.\n *\n * @example\n * type Form = { user: { name: string; age: number }; tags: string[] }\n * type FormPaths = Path<Form>\n * // Result: 'user' | 'user.name' | 'user.age' | 'tags'\n *\n * @example Using with register\n * register('user.name') // ✅ Valid - autocomplete suggests this\n * register('user.invalid') // ❌ TypeScript error\n */\nexport type Path<T> = T extends object\n ? {\n [K in keyof T & (string | number)]: K extends string | number\n ? `${K}` | `${K}.${Path<T[K]>}`\n : never\n }[keyof T & (string | number)]\n : never\n\n/**\n * Type alias for valid field paths in a form.\n * Provides autocomplete for all dot-notation paths.\n *\n * @example\n * type MyPaths = FormPath<typeof schema>\n * // Use with functions that accept field paths\n */\nexport type FormPath<TSchema extends ZodType> = Path<FormValues<TSchema>>\n\n/**\n * Get array field paths (fields that are arrays).\n * Useful for the fields() method which only works with array fields.\n *\n * @example\n * type Form = { name: string; addresses: Address[] }\n * type ArrayFields = ArrayPath<Form> // 'addresses'\n */\nexport type ArrayPath<T> = {\n [K in Path<T>]: PathValue<T, K> extends Array<unknown> ? K : never\n}[Path<T>]\n\n/**\n * Get non-array field paths (primitive fields and nested objects, excluding arrays).\n * Useful for methods like register() that work with individual fields.\n *\n * @example\n * type Form = { name: string; addresses: Address[] }\n * type Fields = FieldPath<Form> // 'name' (excludes 'addresses')\n */\nexport type FieldPath<T> = {\n [K in Path<T>]: PathValue<T, K> extends Array<unknown> ? never : K\n}[Path<T>]\n\n/**\n * Extract the value type at a given dot-notation path.\n * Used internally to ensure setValue/getValues have correct types.\n * Supports numeric string indices for array access (e.g., 'items.0.name').\n *\n * @example\n * type Form = { user: { name: string }; items: { id: number }[] }\n * type NameType = PathValue<Form, 'user.name'> // string\n * type ItemType = PathValue<Form, 'items.0'> // { id: number }\n * type ItemId = PathValue<Form, 'items.0.id'> // number\n */\nexport type PathValue<T, P extends string> = T extends unknown\n ? P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? PathValue<T[K], Rest>\n : T extends Array<infer U>\n ? K extends `${number}`\n ? PathValue<U, Rest>\n : never\n : never\n : P extends keyof T\n ? T[P]\n : T extends Array<infer U>\n ? P extends `${number}`\n ? U\n : never\n : never\n : never\n\n/**\n * Single field error with type and message.\n * When criteriaMode is 'all', the `types` property contains all validation errors.\n */\nexport interface FieldError {\n /** Error type identifier (e.g., 'required', 'too_small', 'invalid_string', 'custom') */\n type: string\n /** Primary error message to display */\n message: string\n /**\n * Additional error types when multiple validations fail.\n * Only populated when `criteriaMode: 'all'` is set in useForm options.\n *\n * @example Password with multiple requirements\n * ```ts\n * // Schema:\n * const schema = z.object({\n * password: z.string()\n * .min(8, 'At least 8 characters')\n * .regex(/[A-Z]/, 'Needs uppercase letter')\n * .regex(/[0-9]/, 'Needs a number')\n * })\n *\n * // With criteriaMode: 'all', error.types might be:\n * // {\n * // too_small: 'At least 8 characters',\n * // invalid_string: ['Needs uppercase letter', 'Needs a number']\n * // }\n *\n * // Template usage:\n * // <ul v-if=\"isFieldError(error) && error.types\">\n * // <li v-for=\"(messages, type) in error.types\" :key=\"type\">\n * // {{ Array.isArray(messages) ? messages.join(', ') : messages }}\n * // </li>\n * // </ul>\n * ```\n */\n types?: Record<string, string | string[]>\n}\n\n/**\n * Field error value - supports both simple strings and structured errors.\n *\n * - When `criteriaMode: 'firstError'` (default): Errors are typically strings\n * - When `criteriaMode: 'all'`: Errors are FieldError objects with `types` populated\n *\n * Use the `isFieldError()` type guard to safely handle both cases:\n * @example\n * const error = formState.value.errors.email\n * if (isFieldError(error)) {\n * // Structured error with type, message, and optional types\n * console.log(error.type, error.message)\n * } else if (typeof error === 'string') {\n * // Simple string error\n * console.log(error)\n * }\n */\nexport type FieldErrorValue = string | FieldError\n\n/**\n * Field error structure matching the form data structure\n */\nexport type FieldErrors<T> = {\n [K in keyof T]?: T[K] extends Array<infer U>\n ? Array<FieldErrors<U>> | FieldErrorValue\n : T[K] extends object\n ? FieldErrors<T[K]> | FieldErrorValue\n : FieldErrorValue\n} & {\n /** Root-level form errors */\n root?: FieldError\n}\n\n/**\n * Form state tracking\n */\nexport interface FormState<T> {\n /** Field validation errors */\n errors: FieldErrors<T>\n /** Whether form has been modified from default values */\n isDirty: boolean\n /** Whether form is currently valid (no errors) */\n isValid: boolean\n /** Whether form is currently submitting */\n isSubmitting: boolean\n /** Whether async default values are loading */\n isLoading: boolean\n /** Whether form is ready (initialization complete, not loading) */\n isReady: boolean\n /** Whether any field is currently being validated */\n isValidating: boolean\n /** Set of field paths currently being validated */\n validatingFields: Set<string>\n /** Record of touched field paths */\n touchedFields: Record<string, boolean>\n /** Record of dirty field paths */\n dirtyFields: Record<string, boolean>\n /** Number of times form has been submitted */\n submitCount: number\n /** Error that occurred while loading async default values */\n defaultValuesError: unknown\n /** Whether form has been submitted at least once */\n isSubmitted: boolean\n /** Whether the last submission was successful */\n isSubmitSuccessful: boolean\n /** Whether the form is disabled */\n disabled: boolean\n}\n\n/**\n * State of an individual field\n */\nexport interface FieldState {\n /** Whether field value differs from default */\n isDirty: boolean\n /** Whether field has been blurred */\n isTouched: boolean\n /** Whether field has a validation error */\n invalid: boolean\n /** The error (string for backward compatibility, or FieldError for structured errors) */\n error?: FieldErrorValue\n}\n\n/**\n * Error option for setError()\n */\nexport interface ErrorOption {\n /** Error type identifier */\n type?: string\n /** Error message to display */\n message: string\n /**\n * If true, the error will not be cleared by subsequent validations.\n * Useful for server-side validation errors that should persist until explicitly cleared.\n */\n persistent?: boolean\n}\n\n/**\n * Options for setFocus()\n */\nexport interface SetFocusOptions {\n /** Whether to select the text in the input */\n shouldSelect?: boolean\n}\n\n/**\n * Options for setValue()\n */\nexport interface SetValueOptions {\n /** Trigger validation after setting value (default: false) */\n shouldValidate?: boolean\n /** Mark field as dirty (default: true) */\n shouldDirty?: boolean\n /** Mark field as touched (default: false) */\n shouldTouch?: boolean\n}\n\n/**\n * Options for resetField()\n * @template TValue - The type of the field value (inferred from field path)\n */\nexport interface ResetFieldOptions<TValue = unknown> {\n /** Keep validation errors after reset */\n keepError?: boolean\n /** Keep dirty state after reset */\n keepDirty?: boolean\n /** Keep touched state after reset */\n keepTouched?: boolean\n /** New default value (updates stored default) - typed to match field */\n defaultValue?: TValue\n}\n\n/**\n * Options for trigger()\n */\nexport interface TriggerOptions {\n /**\n * If true, increments submitCount to activate reValidateMode behavior.\n * Useful when you want manual validation to trigger reValidation on subsequent changes.\n */\n markAsSubmitted?: boolean\n}\n\n/**\n * Options for unregister()\n */\nexport interface UnregisterOptions {\n /** Keep the field value in form data */\n keepValue?: boolean\n /** Keep validation errors */\n keepError?: boolean\n /** Keep dirty state */\n keepDirty?: boolean\n /** Keep touched state */\n keepTouched?: boolean\n /** Keep the default value */\n keepDefaultValue?: boolean\n /** Don't re-evaluate isValid */\n keepIsValid?: boolean\n}\n\n/**\n * Options for reset()\n */\nexport interface ResetOptions {\n /** Keep validation errors after reset */\n keepErrors?: boolean\n /** Keep dirty state after reset */\n keepDirty?: boolean\n /** Keep touched state after reset */\n keepTouched?: boolean\n /** Keep submit count after reset */\n keepSubmitCount?: boolean\n /** Keep current default values (don't update with new values) */\n keepDefaultValues?: boolean\n /** Keep isSubmitting state after reset */\n keepIsSubmitting?: boolean\n /** Keep isSubmitSuccessful state after reset */\n keepIsSubmitSuccessful?: boolean\n}\n\n/**\n * Options for setErrors() bulk operation\n */\nexport interface SetErrorsOptions {\n /** Replace all existing errors instead of merging (default: false) */\n shouldReplace?: boolean\n}\n\n/**\n * Options for registering a field\n * @template TValue - The type of the field value (inferred from field path)\n */\nexport interface RegisterOptions<TValue = unknown> {\n /** Use controlled mode (v-model) instead of uncontrolled (ref) */\n controlled?: boolean\n /** Disable validation for this field */\n disabled?: boolean\n /**\n * Custom validation function - receives the typed field value.\n * Return an error message string to indicate validation failure,\n * or undefined to indicate success.\n *\n * @example\n * register('email', {\n * validate: (value) => {\n * // value is typed as string (inferred from schema)\n * if (!value.includes('@')) return 'Must be a valid email'\n * }\n * })\n */\n validate?: (value: TValue) => string | undefined | Promise<string | undefined>\n /** Debounce time in ms for async validation (default: 0 = no debounce) */\n validateDebounce?: number\n /** Remove field data when unmounted (overrides global shouldUnregister option) */\n shouldUnregister?: boolean\n /** Dependent fields to re-validate when this field changes */\n deps?: string[]\n}\n\n/**\n * Return value from register() for binding to inputs.\n * Use object spread to bind all properties to your input element.\n *\n * @template TValue - The type of the field value (inferred from field path)\n *\n * @example\n * // Uncontrolled (default) - uses ref for DOM access\n * <input v-bind=\"register('email')\" />\n *\n * @example\n * // Controlled - uses v-model via value ref\n * const { value, ...rest } = register('email', { controlled: true })\n * <input v-model=\"value\" v-bind=\"rest\" />\n */\nexport interface RegisterReturn<TValue = unknown> {\n /** Field name for form data */\n name: string\n /**\n * Ref callback for uncontrolled inputs.\n * Compatible with Vue's template ref system (v-bind spreads this onto elements).\n * Internally handles HTMLInputElement, HTMLSelectElement, and HTMLTextAreaElement.\n */\n ref: (\n el:\n | HTMLInputElement\n | HTMLSelectElement\n | HTMLTextAreaElement\n | Element\n | ComponentPublicInstance\n | null,\n refs?: Record<string, unknown>,\n ) => void\n /** Input handler (fires on every keystroke) */\n onInput: (e: Event) => void\n /** Blur handler */\n onBlur: () => void\n /** Current value (for controlled mode) - only present when controlled: true */\n value?: Ref<TValue>\n /** Disabled state from form-level disabled option */\n disabled?: boolean\n}\n\n/**\n * Field metadata for dynamic arrays with scoped methods for type-safe field access.\n *\n * Scoped methods provide full type safety when accessing fields within array items,\n * solving the type inference problem with dynamic paths like `items.${index}.name`.\n *\n * @template TItem - The type of items in the array (inferred from field path)\n *\n * @example Basic usage\n * ```ts\n * const items = fields('items')\n * items.value.forEach((field) => {\n * field.register('name') // RegisterReturn<string> - fully typed!\n * field.setValue('price', 25) // Type-checked against TItem\n * field.watch('price') // ComputedRef<number>\n * })\n * ```\n *\n * @example In template with v-for\n * ```vue\n * <div v-for=\"field in items.value\" :key=\"field.key\">\n * <input v-bind=\"field.register('name')\" />\n * <span v-if=\"field.getFieldState('name').error\">\n * {{ field.getFieldState('name').error }}\n * </span>\n * </div>\n * ```\n */\nexport interface FieldArrayItem<TItem = unknown> {\n /** Stable key for v-for */\n key: string\n /** Current index in array */\n index: number\n /** Remove this item */\n remove: () => void\n\n // --- Scoped Methods ---\n // These methods operate on fields within this array item, providing full type safety\n\n /**\n * Register a field within this array item.\n * Automatically builds the full path (e.g., 'items.0.name').\n *\n * @param name - Field path relative to the item (e.g., 'name', 'address.city')\n * @param options - Registration options (validation, controlled mode, etc.)\n * @returns Props to bind to the input element\n *\n * @example\n * ```vue\n * <input v-bind=\"field.register('name')\" />\n * ```\n */\n register: <TPath extends Path<TItem>>(\n name: TPath,\n options?: RegisterOptions<PathValue<TItem, TPath>>,\n ) => RegisterReturn<PathValue<TItem, TPath>>\n\n /**\n * Set value for a field within this array item.\n *\n * @param name - Field path relative to the item\n * @param value - New value (typed based on path)\n * @param options - Control side effects (validation, dirty, touched)\n */\n setValue: <TPath extends Path<TItem>>(\n name: TPath,\n value: PathValue<TItem, TPath>,\n options?: SetValueOptions,\n ) => void\n\n /**\n * Get current value of a field within this array item.\n *\n * @param name - Field path relative to the item\n * @returns The field's current value\n */\n getValue: <TPath extends Path<TItem>>(name: TPath) => PathValue<TItem, TPath>\n\n /**\n * Watch a field within this array item reactively.\n *\n * @param name - Field path relative to the item\n * @returns ComputedRef that updates when the field changes\n */\n watch: <TPath extends Path<TItem>>(name: TPath) => ComputedRef<PathValue<TItem, TPath>>\n\n /**\n * Get the state of a field within this array item.\n * Note: Returns a snapshot, not reactive. Use watch() or formState for reactive access.\n *\n * @param name - Field path relative to the item\n * @returns Field state with isDirty, isTouched, invalid, error\n */\n getFieldState: <TPath extends Path<TItem>>(name: TPath) => FieldState\n\n /**\n * Trigger validation for fields within this array item.\n *\n * @param name - Optional field path(s) relative to the item. Validates entire item if omitted.\n * @returns Promise resolving to true if valid\n */\n trigger: <TPath extends Path<TItem>>(name?: TPath | TPath[]) => Promise<boolean>\n\n /**\n * Clear errors for fields within this array item.\n *\n * @param name - Optional field path(s) relative to the item. Clears all item errors if omitted.\n */\n clearErrors: <TPath extends Path<TItem>>(name?: TPath | TPath[]) => void\n\n /**\n * Set an error for a field within this array item.\n *\n * @param name - Field path relative to the item\n * @param error - Error option with message\n */\n setError: <TPath extends Path<TItem>>(name: TPath, error: ErrorOption) => void\n}\n\n/**\n * Focus options for field array operations\n */\nexport interface FieldArrayFocusOptions {\n /** Whether to focus after operation (default: true for append/prepend/insert) */\n shouldFocus?: boolean\n /** Which item index to focus relative to added items (default: 0 = first added) */\n focusIndex?: number\n /** Field name within the item to focus (e.g., 'name' for items.X.name) */\n focusName?: string\n}\n\n/**\n * Rules for validating field arrays\n */\nexport interface FieldArrayRules<T = unknown> {\n /** Minimum number of items required */\n minLength?: { value: number; message: string }\n /** Maximum number of items allowed */\n maxLength?: { value: number; message: string }\n /** Custom validation function - return error message or true if valid */\n validate?: (items: T[]) => string | true | Promise<string | true>\n}\n\n/**\n * Options for configuring field arrays\n */\nexport interface FieldArrayOptions<T = unknown> {\n /** Validation rules for the array itself */\n rules?: FieldArrayRules<T>\n}\n\n/**\n * API for managing dynamic field arrays.\n * All methods that accept values are typed to match the array item type.\n *\n * Most operations return a boolean indicating success or failure.\n * Operations fail (return false) when:\n * - maxLength rule would be exceeded (append, prepend, insert)\n * - minLength rule would be violated (remove, removeAll, removeMany)\n * - Index is out of bounds (remove, update, swap, move)\n *\n * **Reactivity:** The `value` property is fully reactive - it automatically\n * updates when array methods (append, remove, swap, etc.) are called.\n * Your template will re-render when items change.\n *\n * @template TItem - The type of items in the array (inferred from field path)\n *\n * @example\n * interface Address { street: string; city: string }\n * const addresses = fields('addresses') // FieldArray<Address>\n * addresses.append({ street: '123 Main', city: 'NYC' }) // Typed!\n *\n * @example Check if operation succeeded\n * const success = addresses.append({ street: '', city: '' })\n * if (!success) {\n * // Operation was rejected (e.g., maxLength exceeded)\n * showNotification('Cannot add more addresses')\n * }\n */\nexport interface FieldArray<TItem = unknown> {\n /** Current field items with metadata. Reactive - updates when array methods are called. */\n value: FieldArrayItem<TItem>[]\n /** Append item(s) to end of array. Returns false if maxLength exceeded. */\n append: (value: TItem | TItem[], options?: FieldArrayFocusOptions) => boolean\n /** Prepend item(s) to beginning of array. Returns false if maxLength exceeded. */\n prepend: (value: TItem | TItem[], options?: FieldArrayFocusOptions) => boolean\n /** Remove item at index. Returns false if minLength violated or index out of bounds. */\n remove: (index: number) => boolean\n /**\n * Remove all items from the array.\n * Returns false if minLength > 0.\n */\n removeAll: () => boolean\n /**\n * Remove multiple items by indices (handles any order, removes from highest to lowest).\n * Returns false if minLength would be violated.\n * @param indices - Array of indices to remove\n */\n removeMany: (indices: number[]) => boolean\n /** Insert item(s) at index. Returns false if maxLength exceeded. */\n insert: (index: number, value: TItem | TItem[], options?: FieldArrayFocusOptions) => boolean\n /** Swap two items. Returns false if either index is out of bounds. */\n swap: (indexA: number, indexB: number) => boolean\n /** Move item from one index to another. Returns false if from index is out of bounds. */\n move: (from: number, to: number) => boolean\n /** Update item at index (preserves key/identity). Returns false if index out of bounds. */\n update: (index: number, value: TItem) => boolean\n /** Replace all items with new values. Always succeeds (returns true). */\n replace: (values: TItem[]) => boolean\n}\n\n/**\n * Async default values function type\n */\nexport type AsyncDefaultValues<T> = () => Promise<Partial<T>>\n\n/**\n * Criteria mode for error collection\n */\nexport type CriteriaMode = 'firstError' | 'all'\n\n/**\n * Options for useForm composable\n */\nexport interface UseFormOptions<TSchema extends ZodType> {\n /** Zod schema for validation */\n schema: TSchema\n\n /**\n * Default form values. Can be a sync object or async function.\n * Async function is useful for fetching initial values from an API.\n *\n * @example Sync default values\n * ```ts\n * useForm({\n * schema,\n * defaultValues: { email: '', name: '' }\n * })\n * ```\n *\n * @example Async default values (API fetch)\n * ```ts\n * useForm({\n * schema,\n * defaultValues: async () => {\n * const user = await api.getCurrentUser()\n * return { email: user.email, name: user.name }\n * },\n * onDefaultValuesError: (err) => console.error('Failed to load user:', err)\n * })\n * // Check formState.isLoading to show loading indicator\n * ```\n */\n defaultValues?: Partial<InferSchema<TSchema>> | AsyncDefaultValues<InferSchema<TSchema>>\n\n /**\n * When to run validation.\n * - 'onSubmit' (default): Only validate on form submission\n * - 'onBlur': Validate when field loses focus\n * - 'onChange': Validate on every input change\n * - 'onTouched': Validate after field touched, then on every change\n *\n * @example Different validation modes\n * ```ts\n * // Most performant - only show errors after submit attempt\n * useForm({ schema, mode: 'onSubmit' })\n *\n * // Real-time feedback - validate as user types\n * useForm({ schema, mode: 'onChange' })\n *\n * // Balanced - validate after first interaction\n * useForm({ schema, mode: 'onTouched' })\n * ```\n */\n mode?: ValidationMode\n\n /**\n * Validation mode after first submission.\n * Useful for \"validate on submit, then real-time revalidation\" pattern.\n *\n * @example Submit first, then real-time\n * ```ts\n * useForm({\n * schema,\n * mode: 'onSubmit', // First submit validates all\n * reValidateMode: 'onChange' // After submit, revalidate on change\n * })\n * ```\n */\n reValidateMode?: ValidationMode\n\n /** Remove field data when unmounted (default: false) */\n shouldUnregister?: boolean\n\n /** Callback when async default values fail to load */\n onDefaultValuesError?: (error: unknown) => void\n\n /** Focus first field with error on submit (default: true) */\n shouldFocusError?: boolean\n\n /**\n * How to collect validation errors.\n * - 'firstError' (default): Stop at first error per field\n * - 'all': Collect all errors for each field (populates FieldError.types)\n *\n * @example Show all validation errors (password requirements)\n * ```ts\n * const schema = z.object({\n * password: z.string()\n * .min(8, 'At least 8 characters')\n * .regex(/[A-Z]/, 'Needs uppercase letter')\n * .regex(/[0-9]/, 'Needs a number')\n * })\n *\n * useForm({ schema, criteriaMode: 'all' })\n *\n * // In template - display all password requirements:\n * // <ul v-if=\"formState.errors.password?.types\">\n * // <li v-for=\"(msg, type) in formState.errors.password.types\" :key=\"type\">\n * // {{ msg }}\n * // </li>\n * // </ul>\n * ```\n *\n * @see isFieldError - Type guard for structured errors\n * @see FieldError.types - Contains all error types when criteriaMode is 'all'\n */\n criteriaMode?: CriteriaMode\n\n /**\n * Delay in milliseconds before displaying validation errors.\n * Prevents error flash during fast typing.\n *\n * @example Delay error display by 500ms\n * ```ts\n * useForm({\n * schema,\n * mode: 'onChange',\n * delayError: 500 // Wait 500ms before showing error\n * })\n * // If user fixes error within 500ms, error never appears\n * ```\n */\n delayError?: number\n\n /**\n * Debounce time in milliseconds for schema validation in onChange mode.\n * Prevents excessive validation calls during rapid typing.\n * Unlike delayError which delays showing errors, this delays the validation itself.\n *\n * @example Debounce validation by 150ms\n * ```ts\n * useForm({\n * schema,\n * mode: 'onChange',\n * validationDebounce: 150 // Wait 150ms of idle time before validating\n * })\n * // Reduces validation calls during rapid typing\n * ```\n */\n validationDebounce?: number\n\n /**\n * External values to sync to form. Changes update formData without marking dirty.\n * Useful for server-fetched data or parent component state.\n *\n * @example Sync with parent component state\n * ```ts\n * const props = defineProps<{ userData: UserData }>()\n *\n * useForm({\n * schema,\n * values: computed(() => props.userData) // Reactive sync\n * })\n * // When props.userData changes, form updates without becoming dirty\n * ```\n *\n * @example Sync with API polling\n * ```ts\n * const { data: serverData } = useQuery('user', fetchUser)\n *\n * useForm({\n * schema,\n * values: serverData // Ref from useQuery\n * })\n * ```\n */\n values?: MaybeRef<Partial<InferSchema<TSchema>>>\n\n /**\n * External/server errors to merge with validation errors.\n * These take precedence over client-side validation errors.\n *\n * @example Display server validation errors\n * ```ts\n * const serverErrors = ref({})\n *\n * const { handleSubmit } = useForm({\n * schema,\n * errors: serverErrors\n * })\n *\n * const onSubmit = async (data) => {\n * try {\n * await api.submit(data)\n * } catch (err) {\n * if (err.validationErrors) {\n * serverErrors.value = err.validationErrors\n * // e.g., { email: 'Email already registered' }\n * }\n * }\n * }\n * ```\n */\n errors?: MaybeRef<Partial<FieldErrors<InferSchema<TSchema>>>>\n\n /**\n * Disable the entire form. When true:\n * - All registered fields receive `disabled` attribute\n * - Form submission is prevented\n * - Can be reactive (MaybeRef) to toggle dynamically\n *\n * @example Disable form during submission\n * ```ts\n * const isSubmitting = ref(false)\n *\n * useForm({\n * schema,\n * disabled: isSubmitting\n * })\n * ```\n */\n disabled?: MaybeRef<boolean>\n\n /**\n * Enable browser's native validation API.\n * When true:\n * - Calls setCustomValidity() on inputs with error messages\n * - Enables :valid/:invalid CSS pseudo-selectors\n * - Shows native browser validation tooltips\n *\n * @example\n * ```ts\n * useForm({ schema, shouldUseNativeValidation: true })\n *\n * // CSS styling:\n * // input:invalid { border-color: red; }\n * // input:valid { border-color: green; }\n * ```\n */\n shouldUseNativeValidation?: boolean\n}\n\n/**\n * Loose control type for reusable components where schema type is unknown.\n * Use this when building form field components that accept any form control.\n *\n * @example\n * ```ts\n * // Reusable field component\n * function FormInput(props: { name: string; control: LooseControl }) {\n * const { field } = useController(props) // No cast needed\n * return <input v-bind=\"field\" />\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type LooseControl = UseFormReturn<ZodType<any>>\n\n/**\n * Return value from useForm composable.\n * Provides full type safety with autocomplete for field paths and typed values.\n *\n * @template TSchema - The Zod schema type for form validation\n */\nexport interface UseFormReturn<TSchema extends ZodType> {\n /**\n * Register an input field for form management.\n * Returns props to spread onto your input element.\n *\n * @param name - Field path (e.g., 'email' or 'user.address.street')\n * @param options - Registration options (validation, controlled mode, etc.)\n * @returns Props to bind to the input element\n *\n * @example\n * <input v-bind=\"register('email')\" />\n * <input v-bind=\"register('age', { validate: (v) => v >= 0 || 'Must be positive' })\" />\n */\n register: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name: TPath,\n options?: RegisterOptions<PathValue<InferSchema<TSchema>, TPath>>,\n ): RegisterReturn<PathValue<InferSchema<TSchema>, TPath>>\n /** Loose overload for dynamic paths - returns unknown-typed value */\n (name: string, options?: RegisterOptions<unknown>): RegisterReturn<unknown>\n }\n\n /**\n * Unregister a field to clean up refs and options\n * Call this when a field is unmounted to prevent memory leaks\n * @param name - Field path to unregister\n * @param options - Options for what state to preserve\n */\n unregister: {\n <TPath extends Path<InferSchema<TSchema>>>(name: TPath, options?: UnregisterOptions): void\n /** Loose overload for dynamic paths */\n (name: string, options?: UnregisterOptions): void\n }\n\n /**\n * Handle form submission\n * @param onValid - Callback called with valid data\n * @param onInvalid - Optional callback called with errors\n */\n handleSubmit: (\n onValid: (data: InferSchema<TSchema>) => void | Promise<void>,\n onInvalid?: (errors: FieldErrors<InferSchema<TSchema>>) => void,\n ) => (e: Event) => Promise<void>\n\n /** Reactive form state */\n formState: ComputedRef<FormState<InferSchema<TSchema>>>\n\n /**\n * Manage dynamic field arrays.\n * Returns a typed API for adding, removing, and reordering array items.\n *\n * @param name - Array field path (must be an array field in the schema)\n * @param options - Optional configuration including validation rules\n * @returns Typed FieldArray API\n *\n * @example\n * const addresses = fields('addresses')\n * addresses.append({ street: '', city: '' }) // Typed to Address\n */\n fields: <TPath extends ArrayPath<InferSchema<TSchema>>>(\n name: TPath,\n options?: FieldArrayOptions<ArrayElement<PathValue<InferSchema<TSchema>, TPath>>>,\n ) => FieldArray<ArrayElement<PathValue<InferSchema<TSchema>, TPath>>>\n\n /**\n * Set field value programmatically\n * @param name - Field path\n * @param value - New value (typed to match field)\n * @param options - Options for validation/dirty/touched behavior\n */\n setValue: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name: TPath,\n value: PathValue<InferSchema<TSchema>, TPath>,\n options?: SetValueOptions,\n ): void\n /** Loose overload for dynamic paths */\n (name: string, value: unknown, options?: SetValueOptions): void\n }\n\n /**\n * Reset form to default values\n * @param values - Optional new default values\n * @param options - Optional reset options\n */\n reset: (values?: Partial<InferSchema<TSchema>>, options?: ResetOptions) => void\n\n /**\n * Reset an individual field to its default value\n * @param name - Field path\n * @param options - Options for what state to preserve (with typed defaultValue)\n */\n resetField: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name: TPath,\n options?: ResetFieldOptions<PathValue<InferSchema<TSchema>, TPath>>,\n ): void\n /** Loose overload for dynamic paths */\n (name: string, options?: ResetFieldOptions<unknown>): void\n }\n\n /**\n * Watch field value(s) reactively\n * @overload Watch all form values\n * @overload Watch single field value by path\n * @overload Watch multiple field values by paths array\n */\n watch: {\n (): ComputedRef<InferSchema<TSchema>>\n <TPath extends Path<InferSchema<TSchema>>>(\n name: TPath,\n ): ComputedRef<PathValue<InferSchema<TSchema>, TPath>>\n <TPath extends Path<InferSchema<TSchema>>>(\n names: TPath[],\n ): ComputedRef<Partial<InferSchema<TSchema>>>\n /** Loose overload for dynamic paths - returns unknown */\n (name: string): ComputedRef<unknown>\n /** Loose overload for dynamic path arrays */\n (names: string[]): ComputedRef<Record<string, unknown>>\n }\n\n /**\n * Manually trigger validation\n * @param name - Optional field path (validates all if not provided)\n */\n validate: {\n <TPath extends Path<InferSchema<TSchema>>>(name?: TPath): Promise<boolean>\n /** Loose overload for dynamic paths */\n (name?: string): Promise<boolean>\n }\n\n /**\n * Clear errors for specified fields or all errors\n * @param name - Optional field path or array of paths\n */\n clearErrors: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name?: TPath | TPath[] | 'root' | `root.${string}`,\n ): void\n /** Loose overload for dynamic paths */\n (name?: string | string[]): void\n }\n\n /**\n * Set an error for a specific field\n * @param name - Field path or root error\n * @param error - Error option with message\n */\n setError: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name: TPath | 'root' | `root.${string}`,\n error: ErrorOption,\n ): void\n /** Loose overload for dynamic paths */\n (name: string, error: ErrorOption): void\n }\n\n /**\n * Set multiple errors at once. Useful for server-side validation errors\n * or bulk error handling scenarios.\n *\n * @param errors - Record of field paths to error messages or ErrorOption objects\n * @param options - Optional configuration for merge behavior\n *\n * @example\n * // Simple string errors\n * setErrors({\n * email: 'Email already exists',\n * 'user.name': 'Name is too short'\n * })\n *\n * @example\n * // Replace all errors\n * setErrors({ email: 'New error' }, { shouldReplace: true })\n */\n setErrors: <TPath extends Path<InferSchema<TSchema>>>(\n errors: Partial<Record<TPath | 'root' | `root.${string}`, string | ErrorOption>>,\n options?: SetErrorsOptions,\n ) => void\n\n /**\n * Check if the form or a specific field has validation errors\n *\n * @param fieldPath - Optional field path to check. If omitted, checks entire form.\n * @returns true if errors exist, false otherwise\n *\n * @example\n * if (hasErrors()) {\n * console.log('Form has validation errors')\n * }\n *\n * @example\n * if (hasErrors('email')) {\n * focusField('email')\n * }\n */\n hasErrors: {\n <TPath extends Path<InferSchema<TSchema>>>(\n fieldPath?: TPath | 'root' | `root.${string}`,\n ): boolean\n /** Loose overload for dynamic paths */\n (fieldPath?: string): boolean\n }\n\n /**\n * Get validation errors for the form or a specific field\n *\n * @overload Get all form errors\n * @overload Get error for a specific field\n *\n * @example\n * const allErrors = getErrors()\n *\n * @example\n * const emailError = getErrors('email')\n */\n getErrors: {\n (): FieldErrors<InferSchema<TSchema>>\n <TPath extends Path<InferSchema<TSchema>>>(\n fieldPath: TPath | 'root' | `root.${string}`,\n ): FieldErrorValue | undefined\n }\n\n /**\n * Get all form values, a single value, or multiple values\n * @overload Get all form values\n * @overload Get single field value by path\n * @overload Get multiple field values by paths array\n */\n getValues: {\n (): InferSchema<TSchema>\n <TPath extends Path<InferSchema<TSchema>>>(name: TPath): PathValue<InferSchema<TSchema>, TPath>\n <TPath extends Path<InferSchema<TSchema>>>(names: TPath[]): Partial<InferSchema<TSchema>>\n /** Loose overload for dynamic paths - returns unknown */\n (name: string): unknown\n /** Loose overload for dynamic path arrays */\n (names: string[]): Record<string, unknown>\n }\n\n /**\n * Get the state of an individual field\n * @param name - Field path\n */\n getFieldState: {\n <TPath extends Path<InferSchema<TSchema>>>(name: TPath): FieldState\n /** Loose overload for dynamic paths */\n (name: string): FieldState\n }\n\n /**\n * Manually trigger validation for specific fields or entire form\n * @param name - Optional field path or array of paths\n * @param options - Optional trigger options (e.g., markAsSubmitted)\n */\n trigger: {\n <TPath extends Path<InferSchema<TSchema>>>(\n name?: TPath | TPath[],\n options?: TriggerOptions,\n ): Promise<boolean>\n /** Loose overload for dynamic paths */\n (name?: string | string[], options?: TriggerOptions): Promise<boolean>\n }\n\n /**\n * Programmatically focus a field\n * @param name - Field path\n * @param options - Focus options\n */\n setFocus: {\n <TPath extends Path<InferSchema<TSchema>>>(name: TPath, options?: SetFocusOptions): void\n /** Loose overload for dynamic paths */\n (name: string, options?: SetFocusOptions): void\n }\n\n /**\n * Form configuration options (mode, reValidateMode).\n * Useful for composables like useController that need to respect validation modes.\n */\n options: Pick<UseFormOptions<TSchema>, 'mode' | 'reValidateMode'>\n}\n\n/**\n * Type guard to check if an error value is a structured FieldError object.\n * Use this to safely narrow FieldErrorValue when handling errors.\n *\n * @param error - The error value to check (can be string, FieldError, or undefined)\n * @returns True if the error is a FieldError object with type and message\n *\n * @example\n * const error = formState.value.errors.email\n * if (isFieldError(error)) {\n * // error is FieldError - has .type, .message, and optional .types\n * console.log(`${error.type}: ${error.message}`)\n * } else if (typeof error === 'string') {\n * // error is a simple string message\n * console.log(error)\n * }\n */\nexport function isFieldError(error: FieldErrorValue | undefined | null): error is FieldError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'type' in error &&\n 'message' in error &&\n typeof error.type === 'string' &&\n typeof error.message === 'string'\n )\n}\n"],"mappings":"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"}
|