react-f0rm 1.2.0 → 1.3.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 +107 -24
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/errors-BKrUdpfI.cjs.js +2 -0
- package/dist/errors-BKrUdpfI.cjs.js.map +1 -0
- package/dist/errors-CrQBddrJ.mjs +2 -0
- package/dist/errors-CrQBddrJ.mjs.map +1 -0
- package/dist/{form-CvmWHUrd.d.ts → form-CeKSBs31.d.ts} +68 -5
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +344 -49
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +379 -283
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/persist.cjs.js +1 -1
- package/dist/persist.cjs.js.map +1 -1
- package/dist/persist.mjs +1 -1
- package/dist/persist.mjs.map +1 -1
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.d.ts +1 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.d.ts +1 -1
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/server/index.cjs.js +1 -1
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.mjs +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/{validate-B1Gdjeaq.mjs → validate-CNtuUhmk.mjs} +2 -2
- package/dist/validate-CNtuUhmk.mjs.map +1 -0
- package/dist/{validate-DAfz8Nbb.cjs.js → validate-Cl4ksNFu.cjs.js} +2 -2
- package/dist/validate-Cl4ksNFu.cjs.js.map +1 -0
- package/dist/{validate-CUmNZqg6.d.ts → validate-nksgv1pR.d.ts} +37 -3
- package/dist/values-Cu6awQOJ.cjs.js +2 -0
- package/dist/values-Cu6awQOJ.cjs.js.map +1 -0
- package/dist/values-DRY-a32G.mjs +2 -0
- package/dist/values-DRY-a32G.mjs.map +1 -0
- package/package.json +20 -9
- package/dist/errors-CxSjrWJO.cjs.js +0 -2
- package/dist/errors-CxSjrWJO.cjs.js.map +0 -1
- package/dist/errors-CzWtwjO0.mjs +0 -2
- package/dist/errors-CzWtwjO0.mjs.map +0 -1
- package/dist/validate-B1Gdjeaq.mjs.map +0 -1
- package/dist/validate-DAfz8Nbb.cjs.js.map +0 -1
- package/dist/values-B1IV-6V4.mjs +0 -2
- package/dist/values-B1IV-6V4.mjs.map +0 -1
- package/dist/values-CDNAYEOB.cjs.js +0 -2
- package/dist/values-CDNAYEOB.cjs.js.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/util.ts","../src/path.ts","../src/core/internals.ts","../src/core/errors.ts","../src/core/touched.ts","../src/core/values.ts","../src/core/dirty.ts","../src/core/validate.ts","../src/core/change.ts","../src/core/submit.ts","../src/core/focus.ts","../src/form.ts","../src/rules.ts","../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.8/node_modules/use-sync-external-store/shim/index.js","../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.8/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js","../node_modules/.pnpm/use-sync-external-store@1.6.0_react@19.2.8/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js","../src/subscribe.ts","../src/hooks/form.tsx","../src/hooks/path.ts","../src/hooks/stage.ts","../src/hooks/field.tsx","../src/hooks/validate.ts","../src/hooks/fieldArray.ts","../src/context.ts","../src/server.ts","../src/components/Form.tsx","../src/components/FormField.tsx","../src/components/Field.tsx"],"sourcesContent":["import {on} from '@for-fun/event-emitter';\nimport type {EventEmitter} from '@for-fun/event-emitter';\n\n/** FIFO bound for {@link pathCache}. Static field names ('user.email')\n * number in the dozens per app, so the cache barely grows in practice;\n * the cap is only a backstop for dynamic keys ('items[' + id + ']'\n * style — array inputs skip the cache entirely), where long-lived forms\n * would otherwise accumulate entries forever. Map preserves insertion\n * order, so eviction drops the oldest entry; a dropped string only\n * costs a re-parse the next time normalizePath sees it — results are\n * deterministic, so eviction affects performance, never behavior. */\nconst PATH_CACHE_LIMIT = 1e4;\n\nconst pathCache = new Map<string, (string | number)[]>();\n\n/** Test-only view of the path cache size. Not re-exported from the\n * package entry — tests import this module directly to assert the\n * FIFO bound above. */\nexport const pathCacheSize = () => pathCache.size;\n\nexport function normalizePath(\n path: string | (string | number)[]\n): (string | number)[] {\n if (Array.isArray(path)) return path;\n const cached = pathCache.get(path);\n if (cached) return cached;\n const value = parsePath(path);\n if (pathCache.size >= PATH_CACHE_LIMIT) {\n // Insertion order is FIFO order; the cache is non-empty here\n // because size >= 1e4.\n const oldest = pathCache.keys().next();\n if (!oldest.done) pathCache.delete(oldest.value);\n }\n pathCache.set(path, value);\n return value;\n}\n\n/** Does a segment string denote an integer array index (optionally\n * negative)? The parser feeds it bracket contents ('items[0]' → number)\n * and rejects dotted numerics outright ('items.0' throws), so parsed\n * paths never carry index-looking strings. Its remaining duty is\n * defending programmatic segments: normalizePath also accepts raw\n * (string | number)[] arrays, and index-shaped strings can still arrive\n * from internal callers (error-tree keys) or array containers met\n * during set/setOwned walks. */\nexport const isIndex = (segment: string) => /^-?\\d+$/.test(segment);\n\nfunction parsePath(path: string): (string | number)[] {\n const result: (string | number)[] = [];\n let identifier = '';\n const flushIdentifier = () => {\n if (isIndex(identifier)) {\n // Rebuild both spellings for an actionable message: the dotted\n // form the caller wrote vs. the bracket form the parser accepts.\n const dotted = [...result.map(String), identifier].join('.');\n const bracket = result.reduce(\n (acc: string, seg: string | number) =>\n acc +\n (typeof seg === 'number' ? `[${seg}]` : `${acc ? '.' : ''}${seg}`),\n ''\n );\n throw new TypeError(\n `Numeric path segment must use bracket notation: \"${dotted}\" → \"${bracket}[${identifier}]\" (path: ${path})`\n );\n }\n result.push(identifier);\n identifier = '';\n };\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n if (char === '.') {\n if (identifier !== '') flushIdentifier();\n } else if (char === '[') {\n if (identifier !== '') flushIdentifier();\n const quote = path[i + 1];\n if (quote === '\"' || quote === \"'\") {\n const close = path.indexOf(quote, i + 2);\n if (close === -1) {\n throw new TypeError(`Unterminated quote in path: ${path}`);\n }\n if (path[close + 1] !== ']') {\n throw new TypeError(\n `Expected \"]\" after quoted segment in path: ${path}`\n );\n }\n result.push(path.slice(i + 2, close));\n i = close + 1;\n } else {\n const close = path.indexOf(']', i + 1);\n if (close === -1) {\n throw new TypeError(`Unterminated bracket in path: ${path}`);\n }\n const content = path.slice(i + 1, close);\n result.push(isIndex(content) ? Number(content) : content);\n i = close;\n }\n } else {\n identifier += char;\n }\n }\n if (identifier !== '' || result.length === 0) flushIdentifier();\n return result;\n}\n\nexport function get(values: any, path: (string | number)[]): any {\n return path.reduce((current: any, p: string | number) => {\n if (current == null) return undefined;\n return current[p];\n }, values);\n}\n\n/**\n * Immutable counterpart of {@link set}: removes the path from the value\n * tree, copying only along the touched branch (untouched branches stay\n * shared with the source, like set). Deletes the key entirely rather than\n * writing undefined, so the result carries no `a: undefined` entries.\n */\nexport function unset(values: any, path: (string | number)[]): any {\n if (!path.length || values == null) return values;\n const [prop, ...props] = path;\n if (props.length) {\n const next = unset(values[prop], props);\n // Reattach the pruned child at its parent key — NOT at the full path,\n // which would write the pruned subtree back under the removed key.\n return next === values[prop] ? values : set(values, [prop], next);\n }\n if (Array.isArray(values)) {\n if (!(prop in values)) return values;\n const arr = values.slice();\n delete arr[prop as number];\n return arr;\n }\n if (typeof values !== 'object' || !(prop in values)) return values;\n const copy = {...values};\n delete copy[prop as string];\n return copy;\n}\n\nexport function set(values: any, path: (string | number)[], value: any): any {\n if (!path.length) return value;\n\n const [prop, ...props] = path;\n // A numeric segment lands with the array copy rule — numbers, and the\n // string form dotted paths parse to ('a.0'), on an array container: an\n // object spread there would corrupt the array into {'0': ...}.\n const index =\n typeof prop === 'number'\n ? prop\n : Array.isArray(values) && typeof prop === 'string' && isIndex(prop)\n ? Number(prop)\n : undefined;\n if (index !== undefined) {\n const arr = Array.isArray(values) ? values.slice() : [];\n arr[index] = set(arr[index], props, value);\n return arr;\n }\n return {...values, [prop]: set(values && values[prop], props, value)};\n}\n\n/**\n * Ownership-tracked {@link set}: merge many paths into one tree without\n * re-copying containers the merge itself already created.\n *\n * Containers present in `owned` (freshly created by an earlier call of the\n * same merge) are mutated in place; every other container -- nodes borrowed\n * from the seed tree and user leaf values -- is copied first with the exact\n * copy rules `set` applies (numeric prop: array slice, or a fresh array\n * when the node is not one; string prop: object spread). Chaining\n * `setOwned` over a list of paths therefore produces the tree chaining\n * `set` would, in the same insertion order, but allocates each distinct\n * container once (O(distinct path prefixes)) instead of re-copying the\n * whole branch for every path (O(paths x depth)).\n *\n * Use a fresh `owned` set per merge and thread the returned root (a copied\n * replacement when the seed root itself had to be copied) into the next\n * call. Borrowed containers are never mutated.\n */\nexport function setOwned(\n root: any,\n path: (string | number)[],\n value: any,\n owned: Set<object>\n): any {\n if (!path.length) return value;\n let container = root;\n let parent: any = null;\n let parentProp: string | number = '';\n for (let i = 0; i < path.length; i++) {\n const prop = path[i];\n if (!owned.has(container)) {\n let copy: any;\n if (\n typeof prop === 'number' ||\n (Array.isArray(container) && typeof prop === 'string' && isIndex(prop))\n ) {\n copy = Array.isArray(container) ? container.slice() : [];\n } else {\n copy = {...container};\n }\n owned.add(copy);\n if (i === 0) root = copy;\n else parent[parentProp] = copy;\n container = copy;\n }\n if (i === path.length - 1) {\n container[prop] = value;\n } else {\n parent = container;\n parentProp = prop;\n container = container[prop];\n }\n }\n return root;\n}\n\nexport function isEmpty(value: any): boolean {\n if (value == null) return true;\n if (typeof value !== 'object') return false;\n\n const values = Object.values(value);\n return values.length === 0 || values.every(isEmpty);\n}\n\nexport function isPromise(value: any): value is Promise<any> {\n return value && typeof value.then === 'function';\n}\n\n/** Structural equality for form default data (primitives, arrays, plain\n * objects, Dates). Class instances and other exotic objects compare as\n * unequal, which errs on the side of re-seeding when {@link\n * setInitialValues} uses it to tell a re-rendered inline literal from\n * genuinely changed content. */\nexport function isEqual(a: any, b: any): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return false;\n const isArray = Array.isArray(a);\n if (isArray !== Array.isArray(b)) return false;\n if (isArray) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!isEqual(a[i], b[i])) return false;\n }\n return true;\n }\n const proto = Object.getPrototypeOf(a);\n if (proto !== Object.prototype && proto !== null) return false;\n if (Object.getPrototypeOf(b) !== proto) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if (!isEqual(a[key], b[key])) return false;\n }\n return true;\n}\n\nexport function waitUntil(\n emitter: EventEmitter<any>,\n event: string,\n isResolve: () => boolean,\n isReject: () => boolean\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (isReject()) return void reject();\n if (isResolve()) return void resolve();\n\n const off = on(emitter, event as any, () => {\n if (isReject()) {\n off();\n reject();\n return;\n }\n // Condition not reached yet — stay subscribed and keep waiting. (The\n // previous `if (isResolve()) return` was inverted: it hung forever\n // once the condition held and resolved prematurely while it didn't.)\n if (!isResolve()) return;\n off();\n resolve();\n });\n });\n}\n\n/**\n * DEV-only snapshot guard for {@link getValues}: deep-clones and freezes\n * plain objects and arrays so a consumer mutating the returned tree throws\n * immediately instead of silently corrupting the shared memoized result\n * (getValues hands the same cached reference to every reader between\n * writes). Non-plain values (Date, File, Blob, class instances, Map/Set)\n * pass through by reference, unfrozen — cloning would strip their\n * prototypes and freezing would break legitimate methods like\n * Date#setHours. Callers gate the call behind `__DEV__` so production\n * builds pay nothing.\n */\nexport function freezeValues(value: any): any {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) {\n return Object.freeze(value.map(freezeValues));\n }\n if (Object.getPrototypeOf(value) !== Object.prototype) return value;\n const clone: Record<string, any> = {};\n for (const key of Object.keys(value)) clone[key] = freezeValues(value[key]);\n return Object.freeze(clone);\n}\n","import {normalizePath} from './util';\n\nexport type PathSegments = (string | number)[];\nexport type Name = string | PathSegments;\nexport type Path = {value: PathSegments; key: string};\n\nexport default function create(name: Name): Path {\n const value = normalizePath(name);\n return {value, key: JSON.stringify(value)};\n}\n","import {emit} from '@for-fun/event-emitter';\nimport {get} from '../util';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldError, Form} from '../form';\n\n/** Per-form memoization of {@link getValues}, the same version-bump/read\n * pattern {@link dirtyFieldsCaches} gives {@link getDirtyFields}. */\ntype ValuesCache = {version: number; result: any};\n\nexport const valuesCaches = new WeakMap<Form, ValuesCache>();\n\n/**\n * Invalidate `form`'s cached {@link getValues} result. Called at every\n * point that can change values, parsedValues or initialValues\n * (setValueByPath, removeFieldByPath, setInitialValues, reset, resetField,\n * setParsedValues) so repeated reads hand back a stable reference until\n * the next write.\n */\nexport function bumpValuesVersion(form: Form): void {\n const cache = valuesCaches.get(form);\n if (cache) cache.version++;\n}\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\nconst dirtyBaselines = new WeakMap<Form, Map<string, any>>();\n\n/** The value a field's dirtiness is measured against: its committed\n * baseline when one exists, initialValues at the path otherwise. */\nexport function getDirtyBaseline(\n form: Form,\n key: string,\n segments: PathSegments\n): any {\n const baselines = dirtyBaselines.get(form);\n if (baselines?.has(key)) return baselines.get(key);\n return get(form.initialValues, segments);\n}\n\n/** Install a committed baseline for a `shouldDirty: false` write: the\n * field reads clean until a later write diverges from the new baseline. */\nexport function setDirtyBaseline(form: Form, {key}: Path, value: any): void {\n let baselines = dirtyBaselines.get(form);\n if (!baselines) {\n baselines = new Map();\n dirtyBaselines.set(form, baselines);\n }\n baselines.set(key, value);\n}\n\n/** A wholesale write at a path replaces the subtree below it, so baselines\n * committed under the branch die with the data they were committed against\n * (array movers rewrite the parent path, re-aligning row indices). Called\n * from every write — a no-op unless the form ever opted in. */\nexport function pruneDirtyBaselines(form: Form, {key}: Path): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines?.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const baselineKey of baselines.keys()) {\n if (baselineKey.startsWith(stem)) baselines.delete(baselineKey);\n }\n}\n\n/** Drop committed baselines at one path ({@link removeFieldByPath} /\n * {@link resetField}) or all of them ({@link setInitialValues} /\n * {@link reset}) — the state they were measured against is gone. */\nexport function clearDirtyBaselines(form: Form, key?: string): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines) return;\n if (key === undefined) baselines.clear();\n else baselines.delete(key);\n}\n\n/** Per-form memoization of {@link getDirtyFields}. `version` counts value\n * mutations since the cached `result` was computed: bump points increment\n * it, reads reset it, so a non-zero version means the cache is stale. */\ntype DirtyFieldsCache = {version: number; result: Record<string, boolean>};\n\nexport const dirtyFieldsCaches = new WeakMap<Form, DirtyFieldsCache>();\n\n/**\n * Invalidate `form`'s cached {@link getDirtyFields} result. Called at every\n * point that can change values or initialValues (setValueByPath,\n * removeFieldByPath, setInitialValues, reset) so repeated reads hand out a\n * stable reference and useWatch's Object.is snapshot check can skip\n * re-renders.\n */\nexport function bumpDirtyVersion(form: Form): void {\n const cache = dirtyFieldsCaches.get(form);\n if (cache) cache.version++;\n}\n/** Numbers only occur inside a segments path (`['a', 0]`), never as\n * standalone names, so a top-level number marks `name` as one single path\n * rather than a list of names. */\nexport function isSegmentsPath(\n name: PathSegments | Name[]\n): name is PathSegments {\n return (name as (number | unknown)[]).some(part => typeof part === 'number');\n}\n\nexport function isFieldError(value: any): value is FieldError {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof value.type === 'string' &&\n typeof value.message === 'string'\n );\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n/** Store a schema validator's parsed output as the getValues baseline\n * layer above initialValues. Payload-less 'change' notifies value\n * watchers (useValue, useDirtyFields, ...); dirty state is untouched —\n * it only compares live edits against initialValues, and parsing is not\n * an edit. */\nexport function setParsedValues(form: Form, values: any): void {\n if (values === undefined || values === form.parsedValues) return;\n form.parsedValues = values;\n // parsedValues is a getValues layer above initialValues, so a new parse\n // invalidates the cached merge (dirty state is untouched — parsing is\n // not an edit, hence no bumpDirtyVersion here).\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\n","import {emit} from '@for-fun/event-emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {FieldError, FieldErrorEntry, Form} from '../form';\nimport {isFieldError, isSegmentsPath} from './internals';\n\n/** Reserved top-level path segment for form-level errors. The Standard\n * Schema form-level adapter lands path-less issues under this key; the\n * exported constant replaces the magic string, and readers consume it via\n * getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */\nexport const FORM_ERROR = '_form';\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\n/** Brand marking a form-level validate result as a structured\n * {@link ValidationOutcome} (parsed values and/or errors) rather than a\n * plain nested error record. Symbols cannot collide with user error\n * records, so detection is an exact `VALIDATION_OUTCOME in result`. */\nexport const VALIDATION_OUTCOME: unique symbol = Symbol('validation-outcome');\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted. */\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\nexport function getError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError | undefined {\n return getErrorByPath(form, createPath(name));\n}\n\n/**\n * Get field error by path\n * @param form\n * @param path\n * @return first FieldError of the field, or undefined\n */\nexport function getErrorByPath(\n {errors}: Form,\n path: Path\n): FieldError | undefined {\n return errors.get(path.key)?.[0];\n}\n\n/** Shared empty result for {@link getFieldErrorsByPath}: a fresh `[]` per\n * call would allocate on the hot no-error path, and the stored arrays are\n * handed out by reference too, so callers must treat results as read-only. */\nconst NO_ERRORS: FieldError[] = [];\n\n/**\n * Get all errors of a field\n * @param form\n * @param name\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return getFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all errors of a field by path\n * @param form\n * @param path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrorsByPath({errors}: Form, path: Path): FieldError[] {\n return errors.get(path.key) ?? NO_ERRORS;\n}\n\n/**\n * Get all errors\n * @param form\n * @return array of {path, type, message} entries, in insertion order; path\n * is the user-facing dotted field path ('a.b', 'list.0'), and a\n * field holding several errors contributes one entry per error\n */\nexport function getErrors({errors}: Form): FieldErrorEntry[] {\n const entries: FieldErrorEntry[] = [];\n for (const [key, list] of errors) {\n const path = (JSON.parse(key) as PathSegments).join('.');\n for (const {type, message} of list) entries.push({path, type, message});\n }\n return entries;\n}\n\n/**\n * Get first error message\n * @param form\n * @return first error's message string, or undefined when there are no errors\n */\nexport function getFirstError({errors}: Form): string | undefined {\n return errors.values().next().value?.[0]?.message;\n}\n\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n */\nexport function setError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n error: string | FieldError | (string | FieldError)[] | undefined\n): void {\n setErrorByPath(form, createPath(name), error);\n}\n\n/**\n * Set field error\n * @param form\n * @param path\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n */\nexport function setErrorByPath(\n {emitter, errors}: Form,\n path: Path,\n error: string | FieldError | (string | FieldError)[] | undefined\n): void {\n const list = normalizeErrors(error);\n // An empty result (undefined, '', or an array of only falsy items) clears\n // the key: the errors Map never stores an empty list, so hasErrors stays\n // a plain size check and readers can index [0] unguarded.\n if (list) errors.set(path.key, list);\n else errors.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'errors', path);\n}\n\n/** Normalize any {@link setErrorByPath} input into the stored non-empty\n * FieldError[] shape, or undefined when there is nothing to store. */\nfunction normalizeErrors(\n error: string | FieldError | (string | FieldError)[] | undefined\n): FieldError[] | undefined {\n if (typeof error === 'string') {\n return error ? [{type: 'custom', message: error}] : undefined;\n }\n if (isFieldError(error)) return [error];\n if (!error) return undefined;\n // Falsy items drop out before normalization, so '' never becomes a\n // stored {type: 'custom', message: ''} placeholder.\n const list: FieldError[] = [];\n error.forEach(item => {\n if (typeof item === 'string' && item) {\n list.push({type: 'custom', message: item});\n } else if (isFieldError(item)) {\n list.push(item);\n }\n });\n return list.length ? list : undefined;\n}\n\n/**\n * Clear errors\n * @param form\n * @param name a single path or a list of paths; omit to clear every error\n */\nexport function clearErrors(form: Form, name?: Name | Name[]): void {\n const {emitter, errors} = form;\n if (name === undefined) {\n errors.clear();\n // Payload-less broadcast: every error subscriber re-syncs.\n emit(emitter, 'errors');\n return;\n }\n // Same single-path vs list discrimination as trigger: a segment array\n // holding a number is one path ('a.0' shape), not a list of names.\n const paths =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name)]\n : name.map(one => createPath(one));\n for (const {key} of paths) errors.delete(key);\n // Path-payload emits — the setErrorByPath scoping — wake exactly the\n // affected fields' subscribers.\n for (const path of paths) emit(emitter, 'errors', path);\n}\n\n/** Options accepted by {@link setServerErrors}. */\nexport type SetServerErrorsOptions = {\n /** Keep existing field errors instead of clearing them first. Defaults\n * to `false`: a fresh server response replaces the prior error state. */\n keepExisting?: boolean;\n};\n\n/**\n * Land a server-side error response on the form: each entry becomes the\n * named field's error(s) with `type: 'server'`, ready for the same\n * renderError/`useError` channel client-side validation uses. Takes the\n * flat `Record<string, string | string[]>` shape REST APIs commonly\n * return (RealWorld: `422 {errors: {email: ['has already been taken']}}`)\n * without a hand-rolled `Object.entries` + `setError` loop.\n *\n * A string value lands as one error, a string array as several (first one\n * is what `getError`/`error` expose); an empty array clears that field's\n * errors. By default every existing error is cleared first — a fresh\n * response describes the current state, not a patch onto stale client\n * errors; pass `keepExisting: true` to layer instead.\n * @param form\n * @param errors field errors keyed by name\n * @param options\n */\nexport function setServerErrors(\n form: Form,\n errors: Record<string, string | string[]>,\n options?: SetServerErrorsOptions\n): void {\n if (!options?.keepExisting) clearErrors(form);\n for (const [name, error] of Object.entries(errors)) {\n setError(\n form,\n name,\n (Array.isArray(error) ? error : [error]).map(message => ({\n type: 'server',\n message\n }))\n );\n }\n}\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\n/**\n * @param form\n */\nexport function hasErrors({errors}: Form): boolean {\n return errors.size > 0;\n}\n\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\n","import {emit} from '@for-fun/event-emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {Form} from '../form';\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\nexport function setTouched(form: Form, name: Name): void {\n setTouchedByPath(form, createPath(name));\n}\n\n/**\n * Set field touched state\n * @param form\n * @param path\n */\nexport function setTouchedByPath({emitter, touched}: Form, path: Path): void {\n if (touched.has(path.key)) return;\n touched.add(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'touched', path);\n}\n\n/**\n * Check if field has been touched\n * @param form\n * @param name\n */\nexport function hasTouched<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): boolean {\n return hasTouchedByPath(form, createPath(name));\n}\n\n/**\n * Check if field has been touched\n * @param form\n * @param path\n */\nexport function hasTouchedByPath({touched}: Form, path: Path): boolean {\n return touched.has(path.key);\n}\n\n/**\n * Is dirty -- any value differs from initialValues\n * @param form\n */\n/**\n * Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'), unlike\n * the JSON array keys stored in the touched Set.\n * @param form\n * @return array of touched fields' dotted paths\n */\nexport function getTouchedFields({touched}: Form): string[] {\n return Array.from(touched, key =>\n (JSON.parse(key) as PathSegments).join('.')\n );\n}\n\n/**\n * Is touched -- any field has been touched\n * @param form\n */\nexport function isTouched({touched}: Form): boolean {\n return touched.size > 0;\n}\n\n/**\n * Remove a field: by default its live value drops out of reads and\n * `getValues()` (the path is tombstoned, so it never falls back to\n * initialValues), its dirty baseline, touched flag and errors are cleared.\n * The keep-flags preserve slices of that state instead.\n *\n * @param form\n * @param name\n */\n/**\n * Options accepted by {@link removeField}. All flags default to `false` —\n * the historical remove semantics (value dropped, path tombstoned, dirty\n * baseline/touched/errors cleared). Names mirror react-hook-form's\n * `unregister` options to ease migration; RHF's `shouldValidate` and\n * `keepDefaultValue` have no counterparts (removal never validates, and\n * the tombstone is exactly the \"do not revive from initialValues\" choice).\n */\n","import {emit} from '@for-fun/event-emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport {freezeValues, get, isEqual, setOwned, unset} from '../util';\nimport type {FieldError, Form} from '../form';\nimport {clearErrors, getErrorByPath, getFieldErrorsByPath} from './errors';\nimport {setTouchedByPath} from './touched';\nimport {\n bumpDirtyVersion,\n bumpValuesVersion,\n clearDirtyBaselines,\n getDirtyBaseline,\n pruneDirtyBaselines,\n setDirtyBaseline,\n valuesCaches\n} from './internals';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\nexport function getValues<T extends Record<string, any> = any>(\n form: Form<T>\n): T {\n let cache = valuesCaches.get(form);\n if (!cache) {\n cache = {version: 0, result: computeValues(form)};\n valuesCaches.set(form, cache);\n } else if (cache.version > 0) {\n cache.result = computeValues(form);\n cache.version = 0;\n }\n return cache.result as T;\n}\n\nfunction computeValues(form: Form): any {\n const {initialValues, parsedValues, values, deleted} = form;\n const owned = new Set<object>();\n let merged = parsedValues ?? initialValues;\n for (const [key, value] of values) {\n merged = setOwned(merged, JSON.parse(key), value, owned);\n }\n // Unregistered fields leave a tombstone in `deleted`; remove those paths\n // from the merged result so they don't fall back to initialValues. unset\n // is immutable (set() shares untouched branches with initialValues, so a\n // mutating delete would corrupt them) and deletes the key outright rather\n // than writing undefined, which would leave `a: undefined` entries behind\n // in anything that spreads getValues().\n for (const key of deleted) {\n merged = unset(merged, JSON.parse(key));\n }\n // DEV-only: hand back a frozen snapshot (a clone — freezing the merged\n // tree in place would also freeze the initialValues/parsedValues\n // containers it borrows from). Consumer mutations then throw at the\n // offending site instead of silently corrupting the shared cache.\n return __DEV__ ? freezeValues(merged) : merged;\n}\n\n/**\n * Get field value\n * @param form\n * @param name\n */\nexport function getValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): PathValueOf<T, P> {\n return getValueByPath(form, createPath(name));\n}\n\n/**\n * Get field value by path\n * @param form\n * @param path\n */\nexport function getValueByPath(\n {initialValues, parsedValues, values, deleted}: Form,\n path: Path\n): any {\n const {key, value: segments} = path;\n if (values.has(key)) return values.get(key);\n // Unregistered path: the tombstone blocks the initialValues fallback.\n if (deleted.has(key)) return undefined;\n // A live ancestor key is a whole-branch write (setValue at a parent\n // path, every useFieldArray operation): it replaces the subtree below\n // it, the same way getValues' merge layers it over the baseline, so\n // reads under it resolve from that stored value instead of falling\n // back to the pre-edit initialValues snapshot. Nearest ancestor first:\n // a finer write is layered over a coarser one (setValueByPath drops the\n // superseded descendant keys), so the closest live ancestor is the\n // newest generation. Paths the ancestor's value does not carry read\n // undefined — the baseline must not fill holes inside a replaced\n // branch.\n for (let i = segments.length - 1; i > 0; i--) {\n const ancestorKey = JSON.stringify(segments.slice(0, i));\n if (values.has(ancestorKey)) {\n return get(values.get(ancestorKey), segments.slice(i));\n }\n }\n // Same layering as getValues: parsed values (when present) are the\n // baseline above initialValues.\n return get(parsedValues ?? initialValues, segments);\n}\n\n/** Options accepted by {@link setValue} / {@link setValueByPath} / {@link\n * changeValue} / {@link changeValueByPath}. `shouldValidate`/`shouldTouch`\n * default to `false`; omitting the options object entirely keeps the plain\n * set-value behavior (no validation, no touched marking, dirty stays\n * derived). */\nexport type SetFieldOptions = {\n /** Run the field's registered validator (if any) after the value lands,\n * same as triggering that single field. Defaults to `false`. */\n shouldValidate?: boolean;\n /** Mark the field as touched. Defaults to `false`. */\n shouldTouch?: boolean;\n /** Land the value as a commit instead of an edit: the value becomes the\n * field's dirty-comparison baseline, so `getDirtyFields`/`isDirty`/\n * `getFieldState().isDirty` read the field as clean, and a later write\n * dirties it only by differing from the new baseline. `true` (or\n * omitting the flag) keeps the default derived behavior — dirty while\n * the live value differs from initialValues. */\n shouldDirty?: boolean;\n};\n\n/**\n * Set field value\n * @param form\n * @param name\n * @param value\n * @param options\n */\nexport function setValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n value: PathValueOf<T, P>,\n options?: SetFieldOptions\n): void {\n setValueByPath(form, createPath(name), value, options);\n}\n\n/**\n * Set field value\n * @param form\n * @param path\n * @param value\n * @param options\n */\nexport function setValueByPath(\n form: Form,\n path: Path,\n value: any,\n options?: SetFieldOptions\n): void {\n const {emitter, values, deleted} = form;\n values.set(path.key, value);\n // The write replaces the whole subtree below it, so descendant keys in\n // the values Map belong to an older generation of that subtree: without\n // this prune they would shadow the new value on exact-key reads and\n // double-apply over it in getValues' insertion-ordered merge (a stale\n // `a.b` would survive a fresh `a` write, or corrupt an array branch\n // into an object when applied later).\n pruneDescendantKeys(values, path);\n reviveBranch(deleted, path);\n // Baselines under the replaced subtree die with it — before the emit, so\n // subscribers reading dirty state inside the emission never see a stale\n // commit suppressing the write they are being told about.\n pruneDirtyBaselines(form, path);\n if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n if (options?.shouldTouch) setTouchedByPath(form, path);\n if (options?.shouldValidate) form.validators.get(path.key)?.();\n emit(emitter, 'change', path);\n}\n\n/**\n * The write of {@link setValueByPath} minus the `'change'` emit: the\n * render-time {@link useField} `initialValue` seed. The field's first\n * paint (SSR included — effects never run on the server) must already\n * carry the value, so the write happens during render where emitting is\n * illegal; the seeding field announces it from its post-commit effect\n * through {@link emitChangeByPath} instead.\n *\n * Everything else matches a plain write: descendant keys of the seeded\n * path are pruned, the branch's tombstones and committed baselines are\n * revived/dropped, and both memo caches are invalidated. Like the effect\n * seed it replaces, the caller guards it to paths with no value yet.\n */\nexport function seedValueByPath(form: Form, path: Path, value: any): void {\n const {values, deleted} = form;\n values.set(path.key, value);\n pruneDescendantKeys(values, path);\n reviveBranch(deleted, path);\n pruneDirtyBaselines(form, path);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n}\n\n/** Announce a {@link seedValueByPath} that happened during render: the\n * payload-carrying `'change'` emit {@link setValueByPath} would have\n * fired, split out so it can run post-commit where emitting is safe.\n * Subscribers that rendered after the seed re-read an unchanged snapshot\n * and bail; subscribers from earlier commits resync. */\nexport function emitChangeByPath({emitter}: Form, path: Path): void {\n emit(emitter, 'change', path);\n}\n\n/** Per-form registry of mounted fields' validation-mode overrides: path\n * key -> the field's `mode` option (undefined = follow {@link Form.mode})\n * plus an owner token so competing mounts at one path clean up safely.\n * Presence of an entry is the \"a field is mounted at this path\" signal\n * that routes {@link changeValueByPath} into the gated user-change\n * pipeline ({@link userChangeByPath}). Held in a WeakMap so the Form\n * shape carries only plain state fields. */\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\nexport type FieldState<T = any> = {\n value: T;\n error: FieldError | undefined;\n errors: FieldError[];\n isDirty: boolean;\n isTouched: boolean;\n isValidating: boolean;\n};\n\n/**\n * Get one field's aggregated state: the layered value ({@link getValue}),\n * the first error ({@link getError}) and every error ({@link\n * getFieldErrors}), dirtiness, the touched flag, and whether a validator\n * is in flight. `isDirty` applies the same per-field rule as {@link\n * getDirtyFields}: a live value exists and differs from initialValues at\n * that path (parsedValues never counts — parsing is not an edit).\n *\n * @param form\n * @param name\n */\nexport function getFieldState<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldState<PathValueOf<T, P>> {\n const path = createPath(name);\n const {values, touched, validating} = form;\n const live = values.get(path.key);\n return {\n value: getValueByPath(form, path),\n error: getErrorByPath(form, path),\n errors: getFieldErrorsByPath(form, path),\n // Same rule as getDirtyFields, committed baselines included: the field\n // is dirty while its live value differs from its effective baseline.\n isDirty:\n values.has(path.key) &&\n getDirtyBaseline(form, path.key, path.value) !== live,\n isTouched: touched.has(path.key),\n isValidating: validating.has(path.key)\n };\n}\n\n/**\n * Remove a field: by default its live value drops out of reads and\n * `getValues()` (the path is tombstoned, so it never falls back to\n * initialValues), its dirty baseline, touched flag and errors are cleared.\n * The keep-flags preserve slices of that state instead.\n *\n * @param form\n * @param name\n */\n/**\n * Options accepted by {@link removeField}. All flags default to `false` —\n * the historical remove semantics (value dropped, path tombstoned, dirty\n * baseline/touched/errors cleared). Names mirror react-hook-form's\n * `unregister` options to ease migration; RHF's `shouldValidate` and\n * `keepDefaultValue` have no counterparts (removal never validates, and\n * the tombstone is exactly the \"do not revive from initialValues\" choice).\n */\nexport type RemoveFieldOptions = {\n /** Keep the field's live value and dirty baseline instead of\n * tombstoning: reads and `getValues()` keep returning the value, submit\n * includes it, and dirtiness against initialValues is preserved. */\n keepValue?: boolean;\n /** Keep the field's dirty baseline. Implies `keepValue` — a removed\n * value has nothing to be dirty about. */\n keepDirty?: boolean;\n /** Keep the field's touched flag instead of clearing it. */\n keepTouched?: boolean;\n /** Keep the field's errors instead of clearing them. */\n keepError?: boolean;\n};\n\nexport function removeField(\n form: Form,\n name: Name,\n options?: RemoveFieldOptions\n): void {\n removeFieldByPath(form, createPath(name), options);\n}\n\n/**\n * Remove field\n * @param form\n * @param path\n * @param options keep-flags to preserve slices of state through the removal\n */\nexport function removeFieldByPath(\n form: Form,\n path: Path,\n options?: RemoveFieldOptions\n): void {\n const {key, value: segments} = path;\n const {emitter, values, touched, errors, validating, deleted} = form;\n if (!options?.keepValue && !options?.keepDirty) {\n values.delete(key);\n // The field is gone; a remount starts fresh rather than inheriting a\n // baseline committed by the previous incarnation.\n clearDirtyBaselines(form, key);\n // Tombstone the unregistered path so later reads do not fall back to\n // initialValues and \"revive\" the field's old initial value. A tombstone\n // never shadows live values: skip it when the branch is already covered\n // by a live ancestor key (e.g. a FieldArray rewrite stored the whole\n // array at the parent path) or a still-mounted descendant key.\n if (!hasLiveBranch(values, segments)) deleted.add(key);\n }\n if (!options?.keepTouched) touched.delete(key);\n if (!options?.keepError) errors.delete(key);\n validating.delete(key);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n // Path-payload emits, scoped exactly like the writes above: every\n // mutation is bounded to this path's key (exact deletes in the four\n // stores, an exact-key tombstone), so the same matching the write sites\n // use decides who re-syncs. Leaf watchers on the path and BELOW it wake\n // (their reads fall back through the removed key), branch watchers on\n // ancestors wake (their subtree lost a leaf — the wizard/tab unmount\n // case), and global listeners (`on`, useWatch aggregates like\n // useDirtyFields/getValues readers) wake regardless — an emit with a\n // payload still reaches every plain listener. Sibling fields stay\n // asleep: unmounting one tab's fields no longer re-renders every other\n // field's subscriber.\n emit(emitter, 'change', path);\n emit(emitter, 'touched', path);\n emit(emitter, 'errors', path);\n emit(emitter, 'validating', path);\n}\n\n/**\n * Does a live value cover the branch at `segments` -- either at an ancestor\n * key or below it at a descendant key?\n */\nfunction hasLiveBranch(\n values: Map<string, any>,\n segments: PathSegments\n): boolean {\n for (let i = 1; i < segments.length; i++) {\n if (values.has(JSON.stringify(segments.slice(0, i)))) return true;\n }\n const stem = `${JSON.stringify(segments).slice(0, -1)},`;\n for (const key of values.keys()) {\n if (key.startsWith(stem)) return true;\n }\n return false;\n}\n\n/**\n * Writing a value replaces the subtree below the written path, so drop the\n * values Map keys under it: they were set against an older generation of\n * that subtree and would otherwise shadow the fresh value (exact-key reads\n * in {@link getValueByPath}) or re-apply over it (getValues' merge).\n * Deleting while iterating `keys()` is safe for a Map.\n */\nfunction pruneDescendantKeys(values: Map<string, any>, {key}: Path): void {\n if (!values.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const k of values.keys()) {\n if (k.startsWith(stem)) values.delete(k);\n }\n}\n\n/**\n * Writing a value revives its whole branch: drop any removal tombstone for\n * the path itself, its ancestors, or its descendants (a remounted field\n * overwrites its own tombstone; rewriting a parent array supersedes the\n * tombstones of shifted child paths).\n */\nfunction reviveBranch(deleted: Set<string>, {key}: Path): void {\n if (!deleted.size) return;\n for (const tombstone of deleted) {\n if (\n tombstone === key ||\n tombstone.startsWith(`${key.slice(0, -1)},`) ||\n key.startsWith(`${tombstone.slice(0, -1)},`)\n ) {\n deleted.delete(tombstone);\n }\n }\n}\n\n/**\n * Set form initialValues\n *\n * Content-based early return: a new reference with equal content (the\n * re-rendered inline literal) is a no-op, so committed edits survive, while\n * genuinely changed content swaps the baseline and re-seeds — live values\n * and tombstones are cleared, touched flags and errors survive.\n * @param form\n * @param initialValues\n */\nexport function setInitialValues(form: Form, initialValues: any): void {\n if (\n form.initialValues === initialValues ||\n isEqual(form.initialValues, initialValues)\n ) {\n return;\n }\n form.initialValues = initialValues;\n // A new baseline invalidates the previous schema parse.\n form.parsedValues = undefined;\n form.values.clear();\n form.deleted.clear();\n // ...and every baseline committed against the old one.\n clearDirtyBaselines(form);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/** Options accepted by {@link reset}. Every flag defaults to `false` —\n * omitting the object (or any flag) keeps the plain full-reset behavior.\n * Names mirror react-hook-form's reset options to ease migration. */\nexport type ResetOptions = {\n /** Keep the current values of fields that are dirty — differ from the\n * pre-reset initialValues (the same rule {@link getDirtyFields} applies).\n * Clean fields fall back to the new initialValues as usual. */\n keepDirtyValues?: boolean;\n /** Keep every field's current live value instead of returning to the\n * baseline (react-hook-form's `keepValues` — a strict superset of\n * `keepDirtyValues`, which only preserves dirty fields' values).\n * Dirtiness is recomputed against the post-reset baseline, so kept\n * values that differ from a newly provided baseline count as dirty. */\n keepValues?: boolean;\n /** Ignore a newly provided `initialValues` argument and keep the current\n * baseline — fields still return to it (react-hook-form's\n * `keepDefaultValues`). */\n keepDefaultValues?: boolean;\n /** Keep the touched set instead of clearing it. */\n keepTouched?: boolean;\n /** Keep field errors instead of clearing them. */\n keepErrors?: boolean;\n /** Keep the submitted flag (`isSubmitSuccessful`) instead of clearing\n * it. */\n keepIsSubmitted?: boolean;\n /** Keep `submitCount` instead of resetting it to 0. */\n keepSubmitCount?: boolean;\n /** Keep `isSubmitting` instead of resetting it to false. */\n keepIsSubmitting?: boolean;\n};\n\n/** Collect every leaf path of the merged values tree into `out` —\n * structured segments (numeric for array indexes) so each leaf can be\n * written back with setValueByPath. Objects with no enumerable keys\n * (Date, File, plain empty objects) are leaves themselves. */\nfunction collectValueLeaves(\n node: any,\n segments: PathSegments,\n out: {segments: PathSegments; value: any}[]\n): void {\n if (node !== null && typeof node === 'object') {\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectValueLeaves(node[i], [...segments, i], out);\n }\n return;\n }\n const keys = Object.keys(node);\n if (keys.length > 0) {\n for (const k of keys) {\n collectValueLeaves(node[k], [...segments, k], out);\n }\n return;\n }\n }\n out.push({segments, value: node});\n}\n\n/**\n * Reset form\n * @param form\n * @param initialValues new baseline — omitted (or undefined), the form\n * keeps its current initialValues and fields simply return to them\n * (react-hook-form's reset-without-values semantics)\n * @param options keep-flags to preserve slices of state through the reset\n */\nexport function reset(\n form: Form,\n initialValues?: any,\n options?: ResetOptions\n): void {\n // Snapshot the live values being preserved before the wipe: dirtiness\n // is measured against the pre-reset initialValues, so capture must\n // happen before form.values and form.initialValues are touched. The\n // snapshot carries structured segments, not dotted strings — a name\n // segment may itself contain '.' or quotes, and the dotted spelling does\n // not round-trip through the parser (dotted keys stay display-only, like\n // getDirtyFields' output). keepValues keeps every live value; the older\n // keepDirtyValues narrows the same snapshot to fields whose value\n // differs from their effective baseline.\n const keptValues: {segments: PathSegments; value: any}[] = [];\n if (options?.keepValues) {\n // Every leaf of the CURRENT merged tree — live edits and clean\n // baseline fields alike — is written back after the wipe, so a field\n // that never had a live edit keeps its pre-reset value instead of\n // adopting the new baseline's.\n collectValueLeaves(getValues(form), [], keptValues);\n } else if (options?.keepDirtyValues) {\n for (const [key, value] of form.values) {\n const segments = JSON.parse(key) as PathSegments;\n // Same predicate as getDirtyFields/forEachDirtyField: a live value\n // differing from its effective baseline (committed baselines read\n // clean and are not kept).\n if (getDirtyBaseline(form, key, segments) !== value) {\n keptValues.push({segments, value});\n }\n }\n }\n // Omitting values is a return-to-initialValues reset, not a wipe: an\n // undefined baseline would make getValues() return undefined (and every\n // consumer of it crash), so the current baseline survives when no new\n // one is provided.\n form.initialValues = options?.keepDefaultValues\n ? form.initialValues\n : (initialValues ?? form.initialValues);\n // The fresh baseline drops any schema parse from the previous cycle.\n form.parsedValues = undefined;\n if (!options?.keepErrors) clearErrors(form);\n const {emitter, touched, values, deleted, validating} = form;\n values.clear();\n deleted.clear();\n clearDirtyBaselines(form);\n if (!options?.keepTouched) touched.clear();\n validating.clear();\n if (!options?.keepIsSubmitting) form.isSubmitting = false;\n if (!options?.keepSubmitCount) form.submitCount = 0;\n if (!options?.keepIsSubmitted) form.isSubmitSuccessful = undefined;\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n // Write the kept values back over the fresh baseline: plain\n // setValueByPath, so no validation fires and nothing is marked touched.\n for (const {segments, value} of keptValues) {\n setValueByPath(form, createPath(segments), value);\n }\n emit(emitter, 'change');\n emit(emitter, 'touched');\n emit(emitter, 'validating');\n emit(emitter, 'submitting');\n emit(emitter, 'submitCount');\n emit(emitter, 'submitSuccessful');\n emit(emitter, 'reset');\n}\n\n/** Options accepted by {@link resetField}. The flags default to `false`;\n * `value` has no default — omitted, the field falls back to initialValues;\n * provided, the explicit value becomes the live value with no fallback at\n * all. Mirrors react-hook-form's resetField options (`value` plays their\n * `defaultValue`'s role) to ease migration. */\nexport type ResetFieldOptions = {\n /** Keep the field's touched flag instead of clearing it. */\n keepTouched?: boolean;\n /** Keep the field's errors instead of clearing them. */\n keepErrors?: boolean;\n /** Explicit post-reset value for the field — never falls back to\n * initialValues. */\n value?: any;\n};\n\n/**\n * Reset a single field: drop its live value (reads fall back to the\n * baseline — initialValues, or the schema's parsed output when one\n * exists, in which case the path is removed from parsedValues and the\n * initial value pinned back so the field reads initialValues again),\n * clear its touched flag and errors, and revive the path's removal\n * tombstones — the inverse of {@link removeFieldByPath}. Other fields\n * and the submission flags are untouched; see {@link reset} for the\n * form-wide counterpart.\n *\n * @param form\n * @param name\n * @param options\n */\nexport function resetField<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P, options?: ResetFieldOptions): void {\n const path = createPath(name);\n const {emitter, values, touched, errors, deleted} = form;\n values.delete(path.key);\n // The field returns to its baseline; commits from before the reset no\n // longer shadow the comparison.\n clearDirtyBaselines(form, path.key);\n // A parse baseline wholesale-shadows initialValues in reads (see\n // getValues), so unset alone would read the path as undefined. Remove\n // the path from the tree (immutable — parsedValues shares branches with\n // the schema's own output) and pin the initial value back as the live\n // value: equal to initialValues, so the field stays clean.\n if (form.parsedValues !== undefined) {\n form.parsedValues = unset(form.parsedValues, path.value);\n const initial = get(form.initialValues, path.value);\n if (initial !== undefined) values.set(path.key, initial);\n }\n if (options && 'value' in options) {\n values.set(path.key, options.value);\n }\n // A reset re-registers the branch, same as a write: tombstones on the\n // path or around it stop applying.\n reviveBranch(deleted, path);\n // Payload-less by design (unlike removeFieldByPath, whose mutations are\n // key-bounded): reviveBranch can un-tombstone ancestor or descendant\n // paths, whose readers must re-sync too.\n emit(emitter, 'change');\n if (!options?.keepTouched && touched.delete(path.key)) {\n emit(emitter, 'touched', path);\n }\n if (!options?.keepErrors && errors.delete(path.key)) {\n emit(emitter, 'errors', path);\n }\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n}\n\n/**\n * @param form\n */\n","import type {PathSegments} from '../path';\nimport type {Form} from '../form';\nimport {dirtyFieldsCaches, getDirtyBaseline} from './internals';\n\n/**\n * Is dirty -- any value differs from initialValues\n * @param form\n */\nexport function isDirty(form: Form): boolean {\n let dirty = false;\n forEachDirtyField(form, () => {\n dirty = true;\n });\n return dirty;\n}\n\nfunction forEachDirtyField(form: Form, fn: (dottedKey: string) => void): void {\n for (const [key, value] of form.values) {\n const path = JSON.parse(key) as PathSegments;\n if (getDirtyBaseline(form, key, path) !== value) fn(path.join('.'));\n }\n}\n\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\n\nfunction computeDirtyFields(form: Form): Record<string, boolean> {\n const dirtyFields: Record<string, boolean> = {};\n forEachDirtyField(form, key => {\n dirtyFields[key] = true;\n });\n return dirtyFields;\n}\n\n/** Dirty entries only ever map to `true`, so equal key sets mean shallow\n * equal results. */\nfunction sameDirtyKeys(\n a: Record<string, boolean>,\n b: Record<string, boolean>\n): boolean {\n const aKeys = Object.keys(a);\n if (aKeys.length !== Object.keys(b).length) return false;\n return aKeys.every(key => b[key] === true);\n}\n\n/**\n * Get dirty fields -- fields whose current value differs from initialValues.\n * Keys are user-facing dotted paths ('a.b', 'a.0.c'), unlike the JSON array\n * keys stored in the values Map.\n * @param form\n * @return object mapping each dirty field's dotted path to true; the same\n * reference is returned until the dirty set actually changes\n */\nexport function getDirtyFields(form: Form): Record<string, boolean> {\n let cache = dirtyFieldsCaches.get(form);\n if (!cache) {\n cache = {version: 0, result: computeDirtyFields(form)};\n dirtyFieldsCaches.set(form, cache);\n } else if (cache.version > 0) {\n const result = computeDirtyFields(form);\n // Keep the old reference when the dirty set is unchanged (values always\n // map to true) so subscribers see identity-stable snapshots.\n if (!sameDirtyKeys(cache.result, result)) cache.result = result;\n cache.version = 0;\n }\n return cache.result;\n}\n\n/**\n * Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'), unlike\n * the JSON array keys stored in the touched Set.\n * @param form\n * @return array of touched fields' dotted paths\n */\n","import {emit} from '@for-fun/event-emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport {isIndex, isPromise, normalizePath, waitUntil} from '../util';\nimport type {\n FieldError,\n FieldErrorEntry,\n Form,\n ValidationMode,\n ValidateResult,\n ValidationOutcome\n} from '../form';\nimport {\n VALIDATION_OUTCOME,\n getErrors,\n getFirstError,\n hasErrors,\n setError,\n setErrorByPath\n} from './errors';\nimport {hasTouchedByPath, setTouchedByPath} from './touched';\nimport {getValueByPath, getValues} from './values';\nimport {isFieldError, isSegmentsPath, setParsedValues} from './internals';\n\nexport function unsetValidatingByPath(\n {emitter, validating}: Form,\n path: Path\n): void {\n validating.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'validating', path);\n}\n\nexport function setValidatingByPath(\n {emitter, validating}: Form,\n path: Path\n): void {\n validating.add(path.key);\n emit(emitter, 'validating', path);\n}\n\n/**\n * Field validator. Returns an error (a string, a FieldError, or an array\n * mixing both) or undefined when valid; may return a Promise for async\n * validation.\n *\n * The second argument carries the validation context. `meta.signal` is\n * aborted as soon as the round is superseded — a newer round started, or\n * the field unregistered — so async validators can cancel their underlying\n * work (fetch, timers) instead of racing a stale result home. Stale\n * results are dropped independently by the registration's lock\n * ({@link registerValidatorByPath}), so validators that ignore the signal\n * stay correct too. Validators written against the older two-argument\n * signature keep working.\n */\nexport type Validator = (\n value: any,\n meta: {form: Form; path: Path; signal: AbortSignal}\n) =>\n | string\n | FieldError\n | (string | FieldError)[]\n | undefined\n | Promise<string | FieldError | (string | FieldError)[] | undefined>;\n\n/**\n * Synchronous pre-validator for {@link registerValidatorByPath}'s `sync`\n * accessor — declarative `required` rules compiled by `rulesToValidator`\n * in practice, but any sync-only check works. Runs on every kick, never\n * debounced: its errors land immediately and, while present,\n * short-circuit the debounced validator for that kick (the expensive\n * check never sees a value the gate already rejects). Must be synchronous\n * — unlike a {@link Validator} it may not return a Promise — and its meta\n * carries no `signal`: there is nothing to abort in a synchronous check.\n */\nexport type SyncValidator = (\n value: any,\n meta: {form: Form; path: Path}\n) => string | FieldError | (string | FieldError)[] | undefined;\n\n/** Live options for {@link registerValidatorByPath}: read at every kick\n * through accessors, so callers (React's `useValidate`) can swap the\n * validator/debounce/sync-gate per render without re-subscribing the\n * registration mid-flight. */\nexport type ValidatorRegistration = {\n /** Current debounced validator (or undefined — a sync-only\n * registration). */\n validate: () => Validator | undefined;\n /** Debounce delay in milliseconds; 0 (default) runs immediately. */\n debounce: () => number;\n /** Synchronous pre-validator, run on every kick (never debounced). */\n sync: () => SyncValidator | undefined;\n};\n\n/**\n * Register a field validator's kick at `path` in {@link Form.validators}\n * — the framework-free machinery behind `useValidate`. Returns a\n * disposer that drops the registration and cancels any pending debounce\n * window or in-flight round (its signal aborts and its validating mark\n * is released).\n *\n * Contract of the registered kick (the same contract `trigger` /\n * `ensureValidate` rely on when they run every entry, and the\n * user-change gate relies on when it runs the changed path's entry):\n * - the `sync` gate runs immediately on every kick — never debounced —\n * and while it returns errors, the debounced validator is skipped for\n * that kick and any pending window or in-flight round is superseded;\n * - a positive `debounce` merges kicks inside the window: only the last\n * one runs the validator, and while the timer is pending the field\n * counts as validating so `trigger`/`ensureValidate` wait it out;\n * - async results land under a lock: a superseded round's outcome —\n * rejection included — is dropped, and only the owning round releases\n * the validating mark;\n * - a synchronous throw inside the validator propagates to the caller\n * (the validating mark is not left stuck behind it).\n *\n * Registering at a path already registered by another mount replaces it\n * (last-wins, the historical `useValidate` behavior); the disposer drops\n * its own registration unconditionally.\n *\n * @param form\n * @param path\n * @param registration live validator/debounce/sync accessors\n * @return disposer: unregister and cancel pending work\n */\nexport function registerValidatorByPath(\n form: Form,\n path: Path,\n registration: ValidatorRegistration\n): () => void {\n // The pending debounce timer and the current round's controller live in\n // this closure so the disposer below can cancel them.\n let timer: ReturnType<typeof setTimeout> | null = null;\n let controller: AbortController | null = null;\n // Whether this registration currently holds the path's slot in\n // form.validating. The mark is taken when a debounce window opens or an\n // async round starts, and released by whichever round settles last —\n // including a later sync round that supersedes an in-flight async one\n // (its own .finally is lock-gated out by then).\n let marked = false;\n // The async-round lock: only the latest round may land its result or\n // release the mark; a superseded round's outcome is dropped wholesale.\n let lock: object | null = null;\n // Which source wrote the error currently on display — the sync gate or\n // the debounced validator. Tracked so a passing sync check can clear\n // its own stale error immediately instead of leaving it on screen until\n // the debounced round lands. External writers (setError, form-level\n // validate) are invisible here; a passing round clearing them matches\n // the long-standing \"a field validator owns its whole key\" contract.\n let errorSource: 'sync' | 'validator' | null = null;\n /** Does a validator result land errors? `[]` normalizes away exactly\n * like undefined in setErrorByPath. */\n const hasErrors = (errors: any): boolean =>\n errors !== undefined && !(Array.isArray(errors) && errors.length === 0);\n const mark = () => {\n if (marked) return;\n marked = true;\n setValidatingByPath(form, path);\n };\n const unmark = () => {\n if (!marked) return;\n marked = false;\n unsetValidatingByPath(form, path);\n };\n\n /** Run the synchronous gate on the field's current value. Its errors\n * land immediately — the gate is never debounced. Returns true when\n * errors landed (the kick's whole outcome for the debounced validator).\n * A passing gate clears the field's errors when they were its own from\n * an earlier kick, or when no debounced validator exists to own the\n * round. */\n const runSync = (): boolean => {\n const sync = registration.sync();\n if (!sync) return false;\n const errors = sync(getValueByPath(form, path), {form, path});\n if (!hasErrors(errors)) {\n // A stale error the gate itself wrote is answered by the gate\n // alone; a rules-only registration's passing check is the whole\n // round. With a debounced validator registered, its upcoming round\n // owns the outcome and lands it later.\n if (!registration.validate() || errorSource === 'sync') {\n setErrorByPath(form, path, undefined);\n errorSource = null;\n }\n return false;\n }\n setErrorByPath(form, path, errors);\n errorSource = 'sync';\n return true;\n };\n\n /** Drop any pending window or in-flight round without landing it: the\n * sync gate now owns the outcome, so the debounced validator must not\n * run for this value. */\n const supersede = () => {\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n controller?.abort();\n lock = {};\n };\n\n /** Run the debounced validator on the field's current value and land\n * its result — the sync gate has already passed. */\n const runValidator = () => {\n const fn = registration.validate();\n if (!fn) {\n unmark();\n return;\n }\n // Abort the superseded round's signal: a listening validator should\n // stop its underlying work. The lock refresh below independently\n // drops any result that still arrives, signal or not.\n controller?.abort();\n controller = new AbortController();\n const round = (lock = {});\n let result;\n try {\n result = fn(getValueByPath(form, path), {\n form,\n path,\n signal: controller.signal\n });\n } catch (e) {\n // A throwing sync validator propagates to the caller as it always\n // has; just don't leave the validating mark stuck behind it.\n unmark();\n throw e;\n }\n if (!isPromise(result)) {\n setErrorByPath(form, path, result);\n errorSource = hasErrors(result) ? 'validator' : null;\n // Error first, then release the mark: 'validating' subscribers\n // (trigger) re-read state on wake and must see the landed error.\n unmark();\n return;\n }\n mark();\n result\n .then(\n (error: string | FieldError | (string | FieldError)[] | undefined) => {\n if (lock === round) {\n setErrorByPath(form, path, error);\n errorSource = hasErrors(error) ? 'validator' : null;\n }\n }\n )\n // A rejected round is the normal way a signal-listening validator\n // gives up (fetch throws AbortError once aborted); swallow it and\n // let the owning round write the outcome.\n .catch(() => {})\n .finally(() => {\n if (lock === round) {\n unmark();\n lock = null;\n }\n });\n };\n\n /** A debounce window fired: the value may have drifted since the last\n * kick (programmatic writes do not kick validators), so re-run the\n * sync gate before spending the debounced validator on a value the\n * gate already rejects. */\n const run = () => {\n timer = null;\n if (runSync()) {\n supersede();\n unmark();\n return;\n }\n runValidator();\n };\n\n const kick = () => {\n if (runSync()) {\n supersede();\n unmark();\n return;\n }\n if (!registration.validate()) return;\n const debounce = registration.debounce();\n if (debounce > 0) {\n // Only the last kick inside the window runs: restart the timer on\n // every kick. The mark keeps trigger/ensureValidate's\n // validating-set wait covering the pending timer, not just\n // in-flight promises.\n if (timer !== null) clearTimeout(timer);\n else mark();\n timer = setTimeout(run, debounce);\n return;\n }\n runValidator();\n };\n\n form.validators.set(path.key, kick);\n return () => {\n form.validators.delete(path.key);\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n unmark();\n controller?.abort();\n };\n}\n\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n */\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\nexport type TriggerOptions = {\n /** Mark every path in the triggered scope as touched — even when\n * validation fails — once the round settles. Mirrors react-hook-form's\n * trigger `shouldTouch`. Defaults to `false`. */\n shouldTouch?: boolean;\n /**\n * Focus the first errored field in the triggered scope once the round\n * settles (and only when the round left errors) — react-hook-form's\n * trigger `shouldFocus` counterpart. Rides the 'focusError' event\n * channel like a failed submit's auto-focus: only mounted bound fields\n * react, unmounted ones are silent no-ops. Without `name` the first key\n * of the errors Map wins (the same rule handleSubmit applies); with\n * `name` the first errored triggered key does. Defaults to `false`.\n */\n shouldFocus?: boolean;\n};\n\n/**\n * Trigger field validation.\n *\n * Without `name` every registered field validator runs. A single `name` —\n * dotted string or segments array — runs only that field's validator, and\n * an array of names runs each one in order. An empty array is a no-op, as\n * is any name with no registered validator. An array argument counts as\n * one segments path only when it mixes in numbers (`['items', 0]`); pure\n * string arrays are name lists, so `['a', 'b']` triggers fields `a` and\n * `b`, not the nested path `a.b`.\n *\n * `options.shouldTouch` marks the triggered scope — the given names, or\n * every registered field when `name` is omitted — as touched after the\n * round settles, whether validation passed or failed. The wait/settle\n * logic is untouched: the marking rides on top of the settled round, so\n * subscribers observe errors and touched together rather than mid-flight.\n *\n * The returned promise waits for the triggered validation to settle —\n * async validators included — so their errors have already landed in\n * `form.errors` when it resolves. It never rejects: landing errors is the\n * expected outcome here, not a failure. Resolves `true` when the triggered\n * scope is error-free, `false` otherwise. Without `name` the scope is all\n * fields plus the form-level `validate` result (which runs after field\n * validators settle, same pipeline as {@link ensureValidate}); with `name`\n * only those fields' own errors count and form-level `validate` is\n * skipped (RHF semantics).\n *\n * Fire-and-forget callers may ignore the promise: the validator kicks\n * still happen synchronously, matching the pre-promise behavior.\n *\n * @param form\n * @param name field name(s) to trigger, or all fields when omitted\n * @param options extra behavior toggles ({@link TriggerOptions}); omitted,\n * validation alone runs — no touched marking\n * @return whether the triggered scope is error-free once validation settles\n */\nexport async function trigger(\n form: Form,\n name?: Name | Name[],\n options?: TriggerOptions\n): Promise<boolean> {\n // Never reject (an error landing is a normal outcome, not a failure), so\n // waitUntil's isReject is permanently false. Without a name the wait is\n // deliberately conservative — every FIELD validator, unrelated in-flight\n // ones included, because the round covers the whole form (and the\n // form-level validate's own window is excluded via fieldsSettled —\n // callers wait that out through the kick's promise instead, so a pending\n // window never gates the next kick). With a name the wait narrows to the\n // triggered keys only: a slow async validator on field B must not hold\n // trigger('a') hostage when the round never reads B.\n const settle = (keys?: string[]) =>\n waitUntil(\n form.emitter,\n 'validating',\n () =>\n keys === undefined\n ? fieldsSettled(form)\n : keys.every(key => !form.validating.has(key)),\n () => false\n );\n\n if (name === undefined) {\n form.validators.forEach(validator => validator());\n await settle();\n if (form.validate) await runFormValidate(form);\n // shouldTouch marks the whole registered scope — every key the round\n // could have validated — pass or fail alike.\n if (options?.shouldTouch) touchKeys(form, [...form.validators.keys()]);\n // First error across the errors Map — the same rule a failed submit's\n // auto-focus applies (a form-level error may land first; it has no\n // element, so it is a silent no-op like every unbound path).\n if (options?.shouldFocus) {\n const firstKey = form.errors.keys().next().value;\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n return !hasErrors(form);\n }\n\n const keys: string[] =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name).key]\n : name.map(one => createPath(one).key);\n keys.forEach(key => form.validators.get(key)?.());\n await settle(keys);\n if (options?.shouldTouch) touchKeys(form, keys);\n // Focus the first errored key among the triggered scope — trigger('a')\n // never focuses B's pre-existing error.\n if (options?.shouldFocus) {\n const firstKey = keys.find(key => form.errors.has(key));\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n return keys.every(key => !form.errors.has(key));\n}\n\n/** trigger's `shouldTouch` marking: touch every key in the triggered scope\n * through {@link setTouchedByPath}, which no-ops on already-touched keys\n * and emits the path-carrying 'touched' event per newly touched one. Keys\n * are the stored JSON-stringified segments shape, so parse them back into\n * Path — normalizePath passes segment arrays through untouched, making the\n * key round-trip exact. */\nfunction touchKeys(form: Form, keys: string[]): void {\n keys.forEach(key => setTouchedByPath(form, createPath(JSON.parse(key))));\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n */\nfunction setFormErrors(\n form: Form,\n result: Record<string, any>,\n segments: PathSegments = [],\n footprint?: Map<string, FieldError[]>\n): void {\n Object.entries(result).forEach(([key, value]) => {\n // Error-tree keys are explicit object keys, not path expressions:\n // a numeric key ('0' — Standard Schema issue paths stringify array\n // indices) stays a literal string segment instead of feeding the\n // path parser, whose dotted-numeric rule governs path strings only.\n const path: PathSegments = [\n ...segments,\n ...(isIndex(key) ? [key] : normalizePath(key))\n ];\n if (typeof value === 'string') {\n if (value) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n }\n } else if (Array.isArray(value)) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n } else if (isFieldError(value)) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n } else if (value && typeof value === 'object') {\n setFormErrors(form, value, path, footprint);\n }\n });\n}\n\n/** Record one leaf write of a form-level validate round: the path key and\n * the exact array now stored there. Nothing is recorded when the write\n * normalized away (all-empty arrays) — there is no error to own. The\n * stored array is read back from the errors Map because setErrorByPath\n * owns normalization. */\nfunction recordFootprint(\n form: Form,\n segments: PathSegments,\n footprint: Map<string, FieldError[]> | undefined\n): void {\n if (!footprint) return;\n const path = createPath(segments);\n const stored = form.errors.get(path.key);\n if (stored) footprint.set(path.key, stored);\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\nfunction applyValidateResult(\n form: Form,\n result: ValidateResult<any> | undefined\n): void {\n const footprint = form.validateDeps ? getFormErrorFootprint(form) : undefined;\n if (footprint) {\n clearFormValidateErrors(form, footprint);\n footprint.clear();\n }\n if (!result) return;\n if (typeof result === 'object' && VALIDATION_OUTCOME in result) {\n const outcome = result as ValidationOutcome<any>;\n if (outcome.errors) setFormErrors(form, outcome.errors, [], footprint);\n setParsedValues(form, outcome.values);\n return;\n }\n setFormErrors(form, result as Record<string, any>, [], footprint);\n}\n\n/** Per-form error footprint of the last form-level validate round: every\n * path key it flattened onto, with the exact array instance it stored.\n * Tracked only for forms that opted into `validateDeps` — held in a\n * WeakMap so the Form shape and the non-opted pipeline stay untouched. */\nconst formErrorFootprints = new WeakMap<Form, Map<string, FieldError[]>>();\n\nfunction getFormErrorFootprint(form: Form): Map<string, FieldError[]> {\n let footprint = formErrorFootprints.get(form);\n if (!footprint) {\n footprint = new Map();\n formErrorFootprints.set(form, footprint);\n }\n return footprint;\n}\n\n/** Does the form still show an error the last form-level round wrote?\n * Compared by identity, not key membership: once a field validator,\n * `setServerErrors`, a manual `setError` or `clearErrors` replaces the\n * stored array, that error is no longer the round's to own — neither the\n * dep-change gate nor the next round's clearing may touch it. */\nfunction hasFormValidateErrors(form: Form): boolean {\n const footprint = formErrorFootprints.get(form);\n if (!footprint) return false;\n for (const [key, written] of footprint) {\n if (form.errors.get(key) === written) return true;\n }\n return false;\n}\n\n/** Drop the last form-level round's errors before the next round lands.\n * Per key the stored array is identity-checked — an error overwritten or\n * cleared by anyone else in between survives — and each drop emits the\n * same path-payload 'errors' event {@link setErrorByPath} would, so\n * subscribed fields re-render exactly like on any error write. */\nfunction clearFormValidateErrors(\n form: Form,\n footprint: Map<string, FieldError[]>\n): void {\n for (const [key, written] of footprint) {\n const stored = form.errors.get(key);\n if (stored !== written) continue;\n form.errors.delete(key);\n emit(form.emitter, 'errors', createPath(JSON.parse(key)));\n }\n}\n\n/** Key the form-level validate round reserves in `form.validating` while\n * its debounce window is pending or its async round is in flight. Real\n * path keys are JSON-stringified segments (always bracketed), so a bare\n * word can never collide. */\nconst FORM_VALIDATING_KEY = '__form_validate__';\n\n/** Are all FIELD validation rounds drained? trigger/ensureValidate wait on\n * this before kicking the form-level validate (its errors gate whether the\n * form-level round may run at all). The form validate's own reserved key\n * is deliberately excluded: its window is waited out through the kick's\n * returned promise instead, so a pending window or in-flight form round\n * never gates the next kick — a kick during an in-flight round opens a\n * new window and the newer round supersedes, mirroring the per-field\n * `validateDebounce` contract. */\nfunction fieldsSettled(form: Form): boolean {\n for (const key of form.validating) {\n if (key !== FORM_VALIDATING_KEY) return false;\n }\n return true;\n}\n\n/** Sentinel telling {@link settleFormValidate} the round landed cleanly —\n * distinct from every rejection payload, including `undefined`. */\nconst SETTLED = Symbol('form-validate-settled');\n\n/** Per-form bookkeeping for the debounced form-level validate: the\n * pending window timer, the in-flight round, and the waiters merged into\n * the current window group. Held in a WeakMap so the Form instance shape\n * is untouched for forms that never set `validateDebounce`. */\ntype FormValidateState = {\n timer: ReturnType<typeof setTimeout> | null;\n controller: AbortController | null;\n /** Identity of the in-flight round; a superseded round's outcome\n * (rejection included) is dropped by comparing against it. */\n round: object | null;\n /** Whether this state currently holds FORM_VALIDATING_KEY in\n * form.validating. */\n marked: boolean;\n waiters: Array<{resolve: () => void; reject: (error: unknown) => void}>;\n};\n\nconst formValidateStates = new WeakMap<Form, FormValidateState>();\n\nfunction getFormValidateState(form: Form): FormValidateState {\n let state = formValidateStates.get(form);\n if (!state) {\n state = {\n timer: null,\n controller: null,\n round: null,\n marked: false,\n waiters: []\n };\n formValidateStates.set(form, state);\n }\n return state;\n}\n\n/**\n * Run the form-level `validate` and land its result, honoring the form's\n * `validateDebounce` option.\n *\n * Undebounced (`0`/undefined) the caller's await *is* the validate call —\n * the long-standing pipeline, unchanged: no validating mark, no round\n * gating, immediate values snapshot, rejection propagating to the caller.\n *\n * Debounced, the kick opens (or restarts — kicks inside the window merge)\n * a window during which the form counts as validating, so `trigger` /\n * `ensureValidate` / submit wait the window out exactly like a field's\n * `validateDebounce` window. When the timer fires, the round reads the\n * then-current values, supersedes (aborts) any in-flight round, and lands\n * its result. The returned promise settles once the window group's final\n * round has landed — rejecting when that round's validate callback threw\n * or its promise rejected, mirroring the undebounced propagation — so\n * merged callers all observe the same outcome.\n *\n * Only called under `if (form.validate)`.\n */\nfunction runFormValidate(form: Form): Promise<void> {\n const validate = form.validate;\n if (!validate) return Promise.resolve();\n const debounce = form.validateDebounce ?? 0;\n if (debounce <= 0) {\n // Standalone controller: nothing supersedes an undebounced call, so\n // its signal never fires — it exists for argument-shape parity with\n // the debounced rounds (and with field-level meta.signal).\n const controller = new AbortController();\n return Promise.resolve(\n validate(getValues(form), {form, signal: controller.signal})\n ).then(result => {\n applyValidateResult(form, result);\n });\n }\n const state = getFormValidateState(form);\n // (Re)open the window: a kick while the timer is pending restarts it\n // (only the last kick's values run); one while a round is in flight\n // keeps the validating mark held and defers to the new window's round.\n if (state.timer !== null) clearTimeout(state.timer);\n else {\n state.marked = true;\n form.validating.add(FORM_VALIDATING_KEY);\n emit(form.emitter, 'validating');\n }\n state.timer = setTimeout(() => {\n state.timer = null;\n const round = (state.round = {});\n runFormValidateRound(form, state, round).then(\n () => settleFormValidate(form, state, round, SETTLED),\n error => settleFormValidate(form, state, round, error)\n );\n }, debounce);\n return new Promise<void>((resolve, reject) => {\n state.waiters.push({resolve, reject});\n });\n}\n\n/** Run one form-level validate round with the form's current values.\n * Aborts the previous in-flight round's signal; a superseded round's\n * outcome — rejection included — is dropped by the round gate, exactly\n * like the field-level lock. */\nfunction runFormValidateRound(\n form: Form,\n state: FormValidateState,\n round: object\n): Promise<void> {\n const validate = form.validate;\n if (!validate) return Promise.resolve();\n state.controller?.abort();\n const controller = (state.controller = new AbortController());\n let outcome: Promise<any>;\n try {\n outcome = Promise.resolve(\n validate(getValues(form), {form, signal: controller.signal})\n );\n } catch (error) {\n outcome = Promise.reject(error);\n }\n return outcome.then(\n result => {\n if (state.round === round) applyValidateResult(form, result);\n },\n error => {\n if (state.round === round) throw error;\n }\n );\n}\n\n/** Land the window group's outcome: release the validating mark — after\n * the round's errors/values have already landed, because 'validating'\n * subscribers (trigger, ensureValidate) re-read state on wake — and\n * settle every merged waiter. A superseded round never lands here (the\n * newer round owns the release), and a window that re-opened while the\n * round was in flight defers: the mark and the waiters carry over to the\n * pending timer's round. */\nfunction settleFormValidate(\n form: Form,\n state: FormValidateState,\n round: object,\n outcome: unknown\n): void {\n if (state.round !== round) return;\n state.round = null;\n if (state.timer !== null) return;\n if (state.marked) {\n state.marked = false;\n form.validating.delete(FORM_VALIDATING_KEY);\n emit(form.emitter, 'validating');\n }\n const waiters = state.waiters;\n state.waiters = [];\n for (const waiter of waiters) {\n if (outcome === SETTLED) waiter.resolve();\n else waiter.reject(outcome);\n }\n}\n\n/**\n * Form-level twin of the gated validator kick in `useField`'s onChange:\n * re-run the form-level `validate` after a user change to a field listed\n * in `validateDeps`. Called from the field's own change pipeline (typing\n * and `changeValue` alike — both route through the mounted field's\n * onChange), so programmatic `setValue` writes do not re-run it, exactly\n * like they do not re-run field validators.\n *\n * The gate mirrors the per-field matrix with the *changed field's*\n * effective `mode` (a per-field override governs when its changes may\n * fire validation) and the form-level `reValidateMode` against the last\n * round's error footprint ({@link hasFormValidateErrors} — field\n * validators' errors never arm this kick):\n * - `mode` `'onChange'`/`'all'` — every dep change re-runs;\n * - `mode` `'onTouched'` — dep changes re-run once the field was touched;\n * - otherwise the re-run waits for `reValidateMode: 'onChange'` (the\n * default) while the last round's error is still live — the\n * submit-then-fix flow: the mismatch lands on submit, editing the\n * dependency re-runs the validate and clears it.\n * `reValidateMode: 'onBlur'`/`'onSubmit'` never re-run on a change (a\n * change is not a blur; submit re-runs are the submit pipeline's job).\n *\n * The kick is fire-and-forget: async round rejections are swallowed\n * (nothing in an event handler can await them), while a synchronous\n * throw inside the validate callback propagates to the caller exactly\n * like a field validator's does.\n *\n * A no-op unless the form set `validateDeps` listing `path` — forms\n * without the option pay one property check here.\n */\nexport function revalidateFormOnChange(\n form: Form,\n path: Path,\n mode: ValidationMode\n): void {\n if (!form.validateDeps?.has(path.key) || !form.validate) return;\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (form.reValidateMode === 'onChange' && hasFormValidateErrors(form))\n ) {\n runFormValidate(form).catch(() => {});\n }\n}\n\n/** Per-form registry of field-level `validateDeps` declarations ({@link\n * revalidateDependentsOnChange}): dep path key -> every dependent field key\n * that listed it. Held in a WeakMap so the Form shape is untouched for\n * forms whose fields never declare deps. */\nconst fieldValidateDeps = new WeakMap<Form, Map<string, Set<string>>>();\n\n/** Register one field's validateDeps declaration: `key` re-validates when\n * any path in `depKeys` takes a user change. Idempotent per (key, dep)\n * pair, so StrictMode's double effect is harmless. */\nexport function registerFieldValidateDeps(\n form: Form,\n key: string,\n depKeys: string[]\n): void {\n let deps = fieldValidateDeps.get(form);\n if (!deps) {\n deps = new Map();\n fieldValidateDeps.set(form, deps);\n }\n for (const depKey of depKeys) {\n let dependents = deps.get(depKey);\n if (!dependents) {\n dependents = new Set();\n deps.set(depKey, dependents);\n }\n dependents.add(key);\n }\n}\n\n/** Drop one field's validateDeps registration ({@link\n * registerFieldValidateDeps}). Entries nobody lists anymore are removed so\n * the registry never outlives its fields. */\nexport function unregisterFieldValidateDeps(\n form: Form,\n key: string,\n depKeys: string[]\n): void {\n const deps = fieldValidateDeps.get(form);\n if (!deps) return;\n for (const depKey of depKeys) {\n const dependents = deps.get(depKey);\n if (!dependents?.delete(key)) continue;\n if (!dependents.size) deps.delete(depKey);\n }\n}\n\n/**\n * Field-level twin of {@link revalidateFormOnChange}: after a user change\n * to `path`, re-run every field validator that declared `path` in its\n * `validateDeps` (useField option). Same channel, same gate: the kick\n * rides the changed field's own onChange pipeline (typing and\n * `changeValue` alike), so programmatic `setValue` writes never fire it —\n * exactly like field validators and the form-level `validateDeps`.\n *\n * The gate mirrors the form-level matrix with the *changed field's*\n * effective `mode` and the form-level `reValidateMode` against each\n * dependent's live error:\n * - `mode` `'onChange'`/`'all'` — every dep change re-runs the dependent;\n * - `mode` `'onTouched'` — once the changed field was touched;\n * - otherwise the re-run waits for `reValidateMode: 'onChange'` (the\n * default) while the dependent still shows an error — the\n * submit-then-fix flow: the mismatch lands on submit, editing the\n * dependency re-validates the dependent and a passing round clears it\n * (a field validator owns its whole key, so the re-run's result\n * replaces whatever the previous round wrote — the field-level shape\n * of the form-level footprint reclaim).\n *\n * The kick is an ordinary validator kick: the dependent's own\n * `validateDebounce` window applies, and a synchronous throw inside its\n * validate propagates to the caller like any field validator's would.\n *\n * A no-op unless some field declared `path` as a dep — forms without any\n * field-level `validateDeps` pay one property check here.\n */\nexport function revalidateDependentsOnChange(\n form: Form,\n path: Path,\n mode: ValidationMode\n): void {\n const dependents = fieldValidateDeps.get(form)?.get(path.key);\n if (!dependents?.size) return;\n for (const dependent of dependents) {\n // A self-dep changes nothing: the field's own onChange above already\n // validated it under the same gate.\n if (dependent === path.key) continue;\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (form.reValidateMode === 'onChange' && form.errors.has(dependent))\n ) {\n form.validators.get(dependent)?.();\n }\n }\n}\n\n/** The Error {@link ensureValidate} rejects with: `message` is the first\n * error's display text ({@link getFirstError}) — the long-standing shape\n * — and `.errors` carries the complete flattened error list ({@link\n * getErrors}: `{path, type, message}` entries, dotted display paths) so\n * catchers can branch on types and locate fields without re-reading the\n * form. */\nexport type FormValidationError = Error & {errors: FieldErrorEntry[]};\n\n/** Build {@link ensureValidate}'s rejection: first error's message, every\n * error attached. */\nfunction validationError(form: Form): FormValidationError {\n const error = new Error(getFirstError(form)) as FormValidationError;\n error.errors = getErrors(form);\n return error;\n}\n\n/**\n * Validate and throw if any field error.\n * @param form\n * @return resolve if no error; reject and stop validate if has an error\n */\nexport async function ensureValidate(form: Form): Promise<void> {\n form.validators.forEach(validator => validator());\n\n await waitUntil(\n form.emitter,\n 'validating',\n () => fieldsSettled(form),\n () => hasErrors(form)\n ).catch(() => {\n throw validationError(form);\n });\n\n if (form.validate) {\n await runFormValidate(form);\n if (hasErrors(form)) throw validationError(form);\n }\n}\n\n/**\n * Validate and return if any field error.\n * @param form\n * @return error message string or void\n */\nexport async function validate(form: Form): Promise<void | string> {\n return ensureValidate(form).catch(e => e.message);\n}\n","import createPath from '../path';\nimport type {Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport type {Form, ValidationMode} from '../form';\nimport {setValueByPath} from './values';\nimport type {SetFieldOptions} from './values';\nimport {revalidateFormOnChange, revalidateDependentsOnChange} from './validate';\nimport {hasTouchedByPath, setTouchedByPath} from './touched';\nimport {getFieldErrorsByPath} from './errors';\nimport {setDirtyBaseline} from './internals';\n\n/** Per-form registry of mounted fields' validation-mode overrides: path\n * key -> the field's `mode` option (undefined = follow {@link Form.mode})\n * plus an owner token so competing mounts at one path clean up safely.\n * Presence of an entry is the \"a field is mounted at this path\" signal\n * that routes {@link changeValueByPath} into the gated user-change\n * pipeline ({@link userChangeByPath}). Held in a WeakMap so the Form\n * shape carries only plain state fields. */\nconst fieldModes = new WeakMap<\n Form,\n Map<string, {mode: ValidationMode | undefined; token: object}>\n>();\n\n/**\n * Set a field value as a user change.\n *\n * The write rides the same gated user-change pipeline a user typing into\n * the field would fire when a field is mounted on the path (registered\n * through {@link registerFieldMode} — `useField` registers on mount): the\n * field's effective `mode` (per-field override included) and the form's\n * `reValidateMode` drive validation exactly as in {@link\n * userChangeByPath}. With no mounted field on the path it degrades to a\n * plain value set ({@link setValue}).\n *\n * This is the channel for component-library bridges that hand a control a\n * plain setter bound to a field — they cannot rebuild the gating from\n * public form state, because the per-field mode override and the\n * live-error view that gates `reValidateMode` live in the field\n * registration, not in public state.\n *\n * Contrast {@link setValue}: that is the imperative channel — its\n * `shouldValidate` option kicks the field's validator unconditionally,\n * ignoring any mode. Functional updaters are the caller's to evaluate\n * ({@link getValue}).\n *\n * `options` carries the same {@link SetFieldOptions}: on the fallback path\n * (no mounted field) they forward to {@link setValueByPath} wholesale,\n * while on the mounted-field path only `shouldDirty: false` applies — the\n * write lands as a commit while the field's own mode gating keeps driving\n * validation, which is the point of this channel.\n *\n * @param form\n * @param name\n * @param value\n * @param options\n */\nexport function changeValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n value: PathValueOf<T, P>,\n options?: SetFieldOptions\n): void {\n changeValueByPath(form, createPath(name), value, options);\n}\n\n/**\n * Set a field value as a user change, by parsed path\n * @param form\n * @param path\n * @param value\n * @param options\n */\nexport function changeValueByPath(\n form: Form,\n path: Path,\n value: any,\n options?: SetFieldOptions\n): void {\n // The baseline must land before the mounted field's change pipeline runs\n // — its write emits synchronously and subscribers read dirty state\n // inside the emission, so installing after the call would flash\n // dirty-then-clean.\n if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);\n if (fieldModes.get(form)?.get(path.key)) {\n // Mounted field: ride the gated user-change pipeline — the field's\n // own mode drives validation, so `shouldValidate`/`shouldTouch` have\n // no meaning here (forcing them would defeat the gating).\n userChangeByPath(form, path, value);\n } else {\n setValueByPath(form, path, value, options);\n }\n}\n\n/**\n * Register a mounted field's `mode` override at `path` for user-change\n * gating ({@link userChangeByPath} / {@link userBlur}). Returns the\n * registration token for {@link unregisterFieldMode} plus whether the\n * slot was already occupied — two fields mounted at one path is almost\n * always a bug: the latest mount's mode governs every user-change write\n * there, which the React layer warns about in DEV.\n *\n * @param form\n * @param path\n * @param mode the field's `mode` option, or undefined to follow\n * {@link Form.mode}\n * @return `token` to hand to {@link unregisterFieldMode}; `displaced`\n * true when a previous registration at the same path still owned\n * the slot\n */\nexport function registerFieldMode(\n form: Form,\n path: Path,\n mode: ValidationMode | undefined\n): {token: object; displaced: boolean} {\n let modes = fieldModes.get(form);\n if (!modes) {\n modes = new Map();\n fieldModes.set(form, modes);\n }\n const displaced = modes.has(path.key);\n const token = {};\n modes.set(path.key, {mode, token});\n return {token, displaced};\n}\n\n/** Drop a {@link registerFieldMode} registration. A later mount at the\n * same path keeps its slot: only the entry owned by `token` is removed. */\nexport function unregisterFieldMode(\n form: Form,\n path: Path,\n token: object\n): void {\n const modes = fieldModes.get(form);\n const entry = modes?.get(path.key);\n if (modes && entry && entry.token === token) modes.delete(path.key);\n}\n\n/** The user-change validation gate shared by a mounted field's onChange\n * and {@link changeValueByPath}: kick the field's validator, the\n * form-level `validateDeps` re-run and the field-level `validateDeps`\n * dependents under the mode/reValidateMode matrix. The live (stored)\n * error view arms the reValidate kick — an error hidden behind a render\n * layer's delayError window still counts, so typing can clear it before\n * it ever shows. */\nfunction runUserChangeGate(form: Form, path: Path, mode: ValidationMode): void {\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (getFieldErrorsByPath(form, path).length > 0 &&\n form.reValidateMode === 'onChange')\n )\n form.validators.get(path.key)?.();\n // Form-level validate deps: a user change to a listed field re-runs the\n // form-level validate under the same mode/reValidateMode gating above\n // (evaluated against the last round's own error footprint). No-op for\n // forms without validateDeps.\n revalidateFormOnChange(form, path, mode);\n // Field-level validate deps: fields that declared this path re-run their\n // own validators under the same gate. No-op when nobody declared it.\n revalidateDependentsOnChange(form, path, mode);\n}\n\n/**\n * Write a bound field's user change by path: the write plus the\n * mode/reValidateMode-gated validation pipeline — what a bound field's\n * onChange does when the user types. Reads the effective mode from the\n * field-mode registry (the latest mount's override governs), so a plain\n * write happens when no field is registered at `path`. Framework\n * adapters (React's `useField`, a Solid binding) forward their field\n * change events here.\n *\n * @param form\n * @param path\n * @param value\n */\nexport function userChangeByPath(form: Form, path: Path, value: any): void {\n setValueByPath(form, path, value);\n const entry = fieldModes.get(form)?.get(path.key);\n if (entry) runUserChangeGate(form, path, entry.mode ?? form.mode);\n}\n\n/**\n * A bound field's blur: mark the path touched, then kick its validator\n * under the blur-side gate (`mode` `'onBlur'`/`'onTouched'`/`'all'`, or\n * `reValidateMode: 'onBlur'` while the field carries a live error). The\n * touched marking is unconditional — a field counts as touched on blur\n * regardless of mode. Framework adapters forward field blur events here.\n *\n * @param form\n * @param path\n */\nexport function userBlur(form: Form, path: Path): void {\n setTouchedByPath(form, path);\n const entry = fieldModes.get(form)?.get(path.key);\n if (!entry) return;\n const mode = entry.mode ?? form.mode;\n if (\n mode === 'onBlur' ||\n mode === 'onTouched' ||\n mode === 'all' ||\n (getFieldErrorsByPath(form, path).length > 0 &&\n form.reValidateMode === 'onBlur')\n )\n form.validators.get(path.key)?.();\n}\n\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\n","import {emit} from '@for-fun/event-emitter';\nimport type {FieldErrorEntry, Form} from '../form';\nimport {getErrors} from './errors';\nimport {getValues} from './values';\nimport {validate} from './validate';\n\nexport function setIsSubmitting(form: Form, value: boolean): void {\n form.isSubmitting = value;\n emit(form.emitter, 'submitting');\n}\n\nexport function incrementSubmitCount(form: Form): void {\n form.submitCount++;\n emit(form.emitter, 'submitCount');\n}\n\nexport function setSubmitSuccessful(form: Form, value: boolean): void {\n form.isSubmitSuccessful = value;\n emit(form.emitter, 'submitSuccessful');\n}\n\n/**\n * Set the form-level disabled flag and emit a payload-less 'disabled'\n * event — subscribed fields (useField and the components built on it)\n * re-render with the merged disabled state: form flag || their own\n * `disabled` option.\n * @param form\n * @param value\n */\nexport function setDisabled(form: Form, value: boolean): void {\n form.disabled = value;\n emit(form.emitter, 'disabled');\n}\n\n/** Structural slice of a <form>-like element: an elements collection whose\n * controls expose the constraint-validation members we read. Matches the\n * DOM HTMLFormElement shape without coupling the core to DOM types. */\ntype NativeFormElement = {\n elements: ArrayLike<{\n name: string;\n checkValidity: () => boolean;\n validationMessage: string;\n }>;\n};\n\n/**\n * Converts a control's DOM name to the user-visible dotted path. Field\n * components render the path key (JSON.stringify'd segments, '[\"a\",\"0\"]')\n * as the name attribute, so JSON keys are parsed back and joined with\n * dots; any other name value is returned as-is.\n */\nfunction nameToPath(name: string): string {\n if (name.startsWith('[')) {\n try {\n const segments = JSON.parse(name);\n if (Array.isArray(segments)) return segments.join('.');\n } catch {\n // Not a JSON path key — fall through and use the raw name.\n }\n }\n return name;\n}\n\n/**\n * Collects the constraints failing native validation on a <form> as\n * {@link FieldErrorEntry} entries, in DOM order.\n *\n * Design note: native errors are deliberately NOT written into the form's\n * errors Map. That Map tracks custom validator state, while native\n * validity is transient DOM state owned by the browser (surfaced through\n * reportValidity); onInvalidSubmit receives this snapshot directly.\n */\nfunction getNativeErrors(formEl: NativeFormElement): FieldErrorEntry[] {\n const errors: FieldErrorEntry[] = [];\n const {elements} = formEl;\n for (let i = 0; i < elements.length; i++) {\n const el = elements[i];\n if (\n el.name &&\n typeof el.checkValidity === 'function' &&\n !el.checkValidity()\n ) {\n errors.push({\n path: nameToPath(el.name),\n type: 'native',\n message: el.validationMessage\n });\n }\n }\n return errors;\n}\n\n/** Submit callbacks for {@link handleSubmit}. All optional — a missing\n * callback is simply skipped, matching the <Form> component semantics. */\nexport type HandleSubmitOptions<T extends Record<string, any> = any> = {\n /** Called after validation passes, before onValidSubmit. */\n onSubmit?: (values: T, e?: any) => void | Promise<void>;\n /** Called after validation passes, following a successful onSubmit. */\n onValidSubmit?: (values: T, e?: any) => void | Promise<void>;\n /**\n * Called when validation fails.\n * @param errors array of {path, type, message} entries in insertion\n * order; path is the dotted field path ('a.b', 'list.0'), type is\n * the error kind ('custom' for plain string errors, 'native' for\n * failed DOM constraint validation), message is the display text\n * @param values current form values\n */\n onInvalidSubmit?: (errors: FieldErrorEntry[], values: T) => void;\n /**\n * Called after validation passes and the submit callbacks ran, with the\n * final (schema-coerced) values — the slot <Form>'s `action` prop uses\n * to dispatch React 19 server actions with FormData. Runs inside the\n * same isSubmitting window and is awaited like onSubmit/onValidSubmit.\n */\n onAction?: (values: T, e?: any) => void | Promise<void>;\n /**\n * Focus the first error field after a failed submit. Defaults to true —\n * only an explicit `false` disables it. When custom validation fails,\n * a 'focusError' event carrying the first error's path key is emitted\n * on the form (bound fields such as <Field> subscribe and focus their\n * input); when native constraint validation fails, the submitted\n * form's first ':invalid' control is focused directly.\n */\n shouldFocusError?: boolean;\n};\n\n/**\n * Create an async submit handler for `form` — the headless counterpart of\n * the <Form> component's onSubmit wiring.\n *\n * Behavior mirrors <Form> exactly: preventDefault when present, then the\n * submit state machine (isSubmitting/submitCount/isSubmitSuccessful) runs\n * around native constraint validation (via `e.currentTarget.checkValidity`,\n * skipped when the target has no checkValidity — e.g. React Native or\n * toolbar-button submits) and custom validators. Failed validation fires\n * onInvalidSubmit with the flattened error entries; a passing submit runs\n * onSubmit then onValidSubmit. Errors thrown by either are swallowed into\n * isSubmitSuccessful=false rather than rejecting the returned promise.\n * Failed validation also focuses the offending field (see\n * {@link HandleSubmitOptions.shouldFocusError}).\n *\n * @param form form instance\n * @param options submit callbacks\n * @return async event handler, callable without an event object\n */\nexport function handleSubmit<T extends Record<string, any> = any>(\n form: Form<T>,\n options?: HandleSubmitOptions<T>\n): (e?: {preventDefault?: () => void; currentTarget?: any}) => Promise<void> {\n const {\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n onAction,\n shouldFocusError = true\n } = options ?? {};\n return async e => {\n if (e && typeof e.preventDefault === 'function') {\n e.preventDefault();\n }\n const formEl = e?.currentTarget;\n setIsSubmitting(form, true);\n incrementSubmitCount(form);\n const values = getValues(form);\n\n if (\n formEl &&\n typeof formEl.checkValidity === 'function' &&\n formEl.checkValidity() === false\n ) {\n formEl.reportValidity();\n // Focus the first natively-invalid control directly off the DOM;\n // native failures never enter the errors Map (see below).\n if (shouldFocusError && typeof formEl.querySelector === 'function') {\n const invalid = formEl.querySelector(':invalid') as HTMLElement | null;\n if (invalid && typeof invalid.focus === 'function') invalid.focus();\n }\n setIsSubmitting(form, false);\n setSubmitSuccessful(form, false);\n // Native constraint failures are read from the DOM (not the errors\n // Map, which only holds custom validation state — see getNativeErrors).\n if (onInvalidSubmit) onInvalidSubmit(getNativeErrors(formEl), values);\n return;\n }\n\n const error = await validate(form);\n\n if (error) {\n setIsSubmitting(form, false);\n setSubmitSuccessful(form, false);\n // Notify bound fields (e.g. <Field>) so the first errored one can\n // focus its input; the payload is the errors Map's first key.\n if (shouldFocusError) {\n const firstKey = form.errors.keys().next().value;\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n if (onInvalidSubmit) onInvalidSubmit(getErrors(form), values);\n return;\n }\n\n try {\n // Re-read after validation: a schema validator's parsed output\n // (ValidationOutcome.values) landed in parsedValues during\n // validate(), and the submit callbacks must see the coerced /\n // transformed values, not the raw pre-validation snapshot.\n const submitted = getValues(form);\n if (onSubmit) await onSubmit(submitted, e);\n if (onValidSubmit) await onValidSubmit(submitted, e);\n if (onAction) await onAction(submitted, e);\n setSubmitSuccessful(form, true);\n } catch {\n setSubmitSuccessful(form, false);\n } finally {\n setIsSubmitting(form, false);\n }\n };\n}\n\n/** Options accepted by {@link setFocus}. All flags default to `false`. */\n","import {emit} from '@for-fun/event-emitter';\nimport createPath from '../path';\nimport type {Name} from '../path';\nimport type {Form} from '../form';\n\n/** Options accepted by {@link setFocus}. All flags default to `false`. */\nexport type SetFocusOptions = {\n /** Select the field's text after focusing it. Bound fields call\n * `select()` on their element; elements without one (custom `as`\n * components) just focus. */\n shouldSelect?: boolean;\n};\n\n/**\n * Programmatically focus a bound field's element (e.g. the <Field>'s\n * input).\n *\n * Rides the same 'focusError' event channel a failed handleSubmit uses to\n * focus the first errored field: the payload is the target's path key,\n * with the focus options as a second, backward-compatible argument (older\n * subscribers declared with a single `key` parameter simply ignore it).\n * Being event-driven, it is a silent no-op when the field is unmounted or\n * nothing subscribes — unknown names never throw.\n *\n * @param form form instance\n * @param name field name (dot path or segments path)\n * @param options focus options\n */\nexport function setFocus(\n form: Form,\n name: Name,\n options?: SetFocusOptions\n): void {\n const {key} = createPath(name);\n // Omit the options argument when absent so the payload is exactly the\n // shape handleSubmit emits after a failed submit.\n if (options) emit(form.emitter, 'focusError', key, options);\n else emit(form.emitter, 'focusError', key);\n}\n","import {\n create as createEmitter,\n emit,\n setMaxListeners\n} from '@for-fun/event-emitter';\nimport type {EventEmitter} from '@for-fun/event-emitter';\nimport createPath from './path';\nimport type {Name, Path} from './path';\nimport type {FieldPath} from './types';\nimport {isPromise} from './util';\nimport {setInitialValues} from './core/values';\nimport type {SetFocusOptions} from './core/focus';\nimport type {VALIDATION_OUTCOME} from './core/errors';\n\n// The implementation is split by concern under ./core (values, errors,\n// touched, dirty, validate, change, submit, focus; module-private shared\n// state lives in ./core/internals, which is deliberately not re-exported).\n// This file keeps the public types and the create factory, and re-exports\n// every public function — the single import surface the rest of the\n// package (hooks, components, server, persist, resolvers) consumes.\nexport type {Name};\nexport type {FieldPath, PathValue} from './types';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/** A field error: `type` identifies the error kind ('custom' for plain\n * string errors), `message` is the display text. */\nexport type FieldError = {type: string; message: string};\n\n/** A flattened entry from {@link getErrors}. */\nexport type FieldErrorEntry = {path: string; type: string; message: string};\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\nexport type ValidationMode =\n 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';\n\n/** When a field is re-validated after it already has an error:\n * - `'onChange'` (default): on every change\n * - `'onBlur'`: when the field loses focus\n * - `'onSubmit'`: only on submit (no live re-validation)\n */\nexport type ReValidateMode = 'onChange' | 'onBlur' | 'onSubmit';\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted.\n *\n * The brand constant itself lives in the errors module (the leaf module of\n * the core dependency graph — every consumer imports it from there) and is\n * re-exported below with `export *`. */\nexport type ValidationOutcome<T> = {\n [VALIDATION_OUTCOME]: true;\n errors?: Record<string, any>;\n values?: T;\n};\n\n/** What a form-level validate function may return: a plain nested error\n * record (flattened into field errors — the long-standing shape), or a\n * branded {@link ValidationOutcome} whose `values` become the form's\n * parsedValues baseline. */\nexport type ValidateResult<T> =\n | Record<string, any>\n | ValidationOutcome<T>\n | Promise<Record<string, any> | ValidationOutcome<T>>;\n\n/** Context passed to a form-level `validate` function's second argument.\n * `signal` aborts as soon as the round is superseded — a newer round\n * started (which only happens under a positive `validateDebounce`, where\n * kicks merge into windows) — so async validators can cancel their\n * underlying work instead of racing a stale result home. Stale results\n * are dropped independently by the round gate, so validators that ignore\n * the signal stay correct too; the same contract field-level validators\n * get through their own `meta`. */\nexport type FormValidateMeta<T extends Record<string, any> = any> = {\n form: Form<T>;\n signal: AbortSignal;\n};\n\n/** Form-level validator: receives all values (plus {@link\n * FormValidateMeta} as an optional second argument) and returns a\n * {@link ValidateResult} — sync or async — or `undefined`/nothing when\n * valid (the runtime skips falsy results, so implicit-return callbacks\n * type-check). */\nexport type FormValidateFn<T extends Record<string, any> = any> = (\n values: T,\n meta: FormValidateMeta<T>\n) => ValidateResult<T> | undefined;\n\n/**\n * The emitter event table for {@link Form.emitter}: each event's payload\n * tuple. Path-carrying events declare an optional single `Path` payload —\n * emit sites send it for single-field mutations and omit it for bulk\n * payload-less broadcasts (reset, setInitialValues, clear-all), both of\n * which subscribers handle. `focusError` carries the target's path key\n * plus optional {@link SetFocusOptions}.\n */\nexport type FormEvents =\n | ['change', [path?: Path]]\n | ['errors', [path?: Path]]\n | ['touched', [path?: Path]]\n | ['validating', [path?: Path]]\n | ['submitting', []]\n | ['submitCount', []]\n | ['submitSuccessful', []]\n | ['reset', []]\n | ['disabled', []]\n | ['loading', []]\n | ['focusError', [key: string, options?: SetFocusOptions]];\n\nexport type Form<T extends Record<string, any> = any> = {\n emitter: EventEmitter<FormEvents>;\n mode: ValidationMode;\n reValidateMode: ReValidateMode;\n initialValues: T;\n values: Map<string, any>;\n /** Tombstones of unregistered field paths (JSON path keys): reading or\n * merging values must not fall back to initialValues for these paths. */\n deleted: Set<string>;\n /** Every error registered for a field, as a non-empty array (the\n * write-side {@link setErrorByPath} normalizes to this invariant, so\n * readers never need to guard against an empty list). Readers wanting\n * the display error take the first entry ({@link getError}); readers\n * wanting all of them use {@link getFieldErrors}. */\n errors: Map<string, FieldError[]>;\n touched: Set<string>;\n /** Per-field validation kicks, registered by {@link\n * registerValidatorByPath} (`useValidate` is the React-side\n * registration): each is the field's debounce/lock-aware kick —\n * invoking it validates the field's current value. `trigger` /\n * `ensureValidate` run every entry; the user-change gate ({@link\n * userChangeByPath}) runs the entry at the changed path. */\n validators: Map<string, () => void>;\n validating: Set<string>;\n /** Parsed values from the last successful schema validation: the\n * schema's complete output tree (coerced/transformed values included).\n * Sits between initialValues and the values Map in {@link getValues}\n * until `reset`/`setInitialValues` clears it. Never affects dirty\n * state — that compares live edits against initialValues only. */\n parsedValues: T | undefined;\n /** Form-level validator, seeded from {@link Options.validate}. May\n * receive a second {@link FormValidateMeta} argument. */\n validate?: FormValidateFn<T>;\n /** Delay in milliseconds before the form-level `validate` runs; seeded\n * from {@link Options.validateDebounce} and fixed at create time. */\n validateDebounce?: number;\n /** Path keys (JSON-stringified segments) of the fields whose user\n * changes re-run the form-level `validate`; normalized from {@link\n * Options.validateDeps} at create time and fixed thereafter. */\n validateDeps?: ReadonlySet<string>;\n isSubmitting: boolean;\n submitCount: number;\n isSubmitSuccessful: boolean | undefined;\n /** True while an async {@link Options.initialValues} source (a Promise,\n * or a thunk returning one) is still pending — the form starts empty\n * and the resolved values become the baseline via setInitialValues when\n * it lands. Flips through the payload-less 'loading' event\n * (`useIsLoading` / `useFormState().isLoading`). */\n isLoading: boolean;\n /** Form-level default for a bound field's unmount behavior, seeded from\n * {@link Options.shouldUnregister}: `true` (the default) tombstones an\n * unmounted field, `false` keeps its value (react-hook-form's\n * `shouldUnregister` semantics). A field's own `shouldUnregister` option\n * overrides this. */\n shouldUnregister?: boolean;\n /** Form-level disabled flag, OR-ed into every bound field's `disabled`\n * (form flag || the field's own option). Seeded from\n * {@link Options}.disabled at create time and toggled at runtime with\n * {@link setDisabled}, which emits a payload-less 'disabled' event so\n * subscribed fields re-render. */\n disabled: boolean;\n};\n\nexport type Options<T extends Record<string, any> = any> = {\n /**\n * The values baseline. Sync objects seed immediately (SSR renders\n * them). Async sources — a Promise, or a thunk returning a value or\n * Promise (react-hook-form's async `defaultValues` shape) — start the\n * form empty with `isLoading: true` and land the resolved values as\n * the baseline via setInitialValues once they resolve: value\n * subscribers re-sync, dirty/touched state starts clean, and a later\n * `reset()` returns to the resolved baseline. A rejected source flips\n * isLoading back to false, keeps the form empty, and logs the error in\n * DEV — attach a `.catch` on the source itself to handle it. The thunk\n * runs at create time: keep its identity stable (module scope or\n * useMemo) when passing it inline, and note StrictMode double-invokes\n * it in development, like every render-phase call.\n */\n initialValues?: T | Promise<T> | (() => T | Promise<T>);\n /** When fields are validated. Defaults to `'onSubmit'`. See\n * {@link ValidationMode}. */\n mode?: ValidationMode;\n /** When a field is re-validated after it already has an error — it only\n * takes effect once the field has an error. Defaults to `'onChange'`. See\n * {@link ReValidateMode}. */\n reValidateMode?: ReValidateMode;\n /**\n * Form-level validator. Returns a record of errors keyed by field path;\n * nested objects are flattened ('a.b' style) and array values contribute\n * every non-empty string they hold as separate errors (zod `flatten()`\n * formErrors style). Schema adapters instead return a branded\n * {@link ValidationOutcome}: `errors` flattens the same way, `values`\n * (the schema's parsed output) becomes the form's parsedValues baseline\n * that {@link getValues} layers over initialValues.\n */\n validate?: FormValidateFn<T>;\n /**\n * Milliseconds to debounce the form-level `validate`: kicks from\n * `trigger`/`ensureValidate`/submit inside the window merge into one\n * run, and while the timer is pending the form counts as validating,\n * so `trigger` and submit wait the window out — the same contract the\n * per-field `validateDebounce` gives field validators. The merged run\n * reads the values current when its timer fires. Defaults to `0`\n * (validate runs immediately, exactly as before this option existed).\n */\n validateDebounce?: number;\n /** Fields whose user changes re-run the form-level `validate` — the\n * cross-field dependency list (password-confirm mismatch and friends).\n * Each entry is a field path ('password', 'user.email', 'items.0.qty');\n * a user change to a listed field re-runs the form-level `validate`\n * under the same mode/`reValidateMode` gating the field's own\n * validator gets. Omit it and the form-level `validate` only runs on\n * `trigger`/submit, exactly as before this option existed.\n *\n * Opting in also changes what a re-run may clear: each round first\n * drops the errors the previous round wrote (paths it flattened onto),\n * so a dep change that fixes the cross-field error makes it disappear.\n * Errors the round never wrote — field validators', `setServerErrors`,\n * manual `setError` — are never touched. TanStack Form's counterpart is\n * `onChangeListenTo` (v1) / validator `triggers` (v2 alpha). */\n validateDeps?: FieldPath<T>[];\n /**\n * Form-level default for a bound field's unmount behavior. `true` (the\n * default) tombstones an unmounted field — it drops out of\n * `getValues()` instead of reviving its initial value (this library's\n * historical default); `false` keeps the value, matching\n * react-hook-form's `shouldUnregister`. A field's own\n * `useField({shouldUnregister})` option overrides the form-level flag\n * in either direction.\n */\n shouldUnregister?: boolean;\n /** Start the form with every bound field disabled — the flag bound\n * fields OR with their own `disabled` option (a field cannot opt out\n * of a disabled form). Toggle later with {@link setDisabled}.\n * Defaults to `false`. */\n disabled?: boolean;\n};\n\n/**\n * Create form instance\n * @param options\n * @return form instance\n */\nexport default function create<T extends Record<string, any> = any>(\n options?: Options<T>\n): Form<T> {\n const emitter = createEmitter<FormEvents>();\n // A form legitimately accumulates one listener per mounted field per\n // event (useField subscribes change/errors/disabled/focusError…), so\n // the emitter's default max-listener warning would fire in DEV for any\n // form over ~10 fields. Field subscriptions are removed on unmount —\n // there is nothing to leak — so the warning would only be noise: raise\n // the cap to unlimited for form emitters.\n setMaxListeners(emitter, 0);\n // Async initialValues: a thunk is invoked here (create-time, like every\n // other option resolution); a promise-typed result starts the loading\n // cycle below instead of seeding.\n let source: any = options?.initialValues ?? {};\n if (typeof source === 'function') source = (source as () => unknown)();\n const form: Form<T> = {\n emitter,\n ...options,\n mode: options?.mode ?? 'onSubmit',\n reValidateMode: options?.reValidateMode ?? 'onChange',\n disabled: options?.disabled ?? false,\n validateDeps: options?.validateDeps\n ? new Set(options.validateDeps.map(dep => createPath(dep).key))\n : undefined,\n initialValues: {} as T,\n values: new Map(),\n deleted: new Set(),\n errors: new Map(),\n touched: new Set(),\n validators: new Map(),\n validating: new Set(),\n parsedValues: undefined,\n isSubmitting: false,\n submitCount: 0,\n isSubmitSuccessful: undefined,\n isLoading: false\n };\n if (isPromise(source)) {\n // The form starts empty; when the source resolves, its values become\n // the baseline through setInitialValues (payload-less 'change', so\n // every value subscriber re-syncs). The loading flag flips through\n // the 'loading' event before and after — no subscriber exists during\n // the first render, so the synchronous first emit is a safe no-op.\n form.isLoading = true;\n emit(emitter, 'loading');\n Promise.resolve(source).then(\n resolved => {\n form.isLoading = false;\n emit(emitter, 'loading');\n setInitialValues(form, resolved ?? {});\n },\n error => {\n form.isLoading = false;\n emit(emitter, 'loading');\n // The caller's own catch on the source sees the rejection;\n // rethrowing here would only duplicate it as an unhandled\n // promise rejection. Surface it in DEV instead.\n if (__DEV__) {\n // eslint-disable-next-line no-console -- dev-only diagnostics\n console.error('react-f0rm: async initialValues rejected', error);\n }\n }\n );\n } else {\n form.initialValues = source as T;\n }\n return form;\n}\n\nexport * from './core/values';\nexport * from './core/errors';\nexport * from './core/touched';\nexport * from './core/dirty';\nexport * from './core/validate';\nexport * from './core/change';\nexport * from './core/submit';\nexport * from './core/focus';\n","import type {FieldError} from './form';\nimport type {SyncValidator} from './hooks/validate';\n\n/** Type tag of a failed rule, as stored on the resulting FieldError. */\nexport type RuleType =\n 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern';\n\n/**\n * Declarative field rules — a subset of react-hook-form's `register` rules.\n *\n * Failed rules land in the form's error state as FieldErrors (`type` is the\n * rule name) instead of only surfacing through the browser's validity\n * bubble, so any design system can render the messages uniformly.\n */\nexport type FieldRules = {\n /**\n * Fails on empty values: `''`, `undefined` or `null` (`0` and `false`\n * count as filled). A string is the error message; `true` uses the\n * default. When it fails, the remaining rules are skipped — an empty\n * value reports only its required error.\n */\n required?: string | true;\n /** Fails when `Number(value)` is below this bound; `NaN` values skip. */\n min?: number;\n /** Fails when `Number(value)` is above this bound; `NaN` values skip. */\n max?: number;\n /** Fails when a string value is shorter than this; non-strings skip. */\n minLength?: number;\n /** Fails when a string value is longer than this; non-strings skip. */\n maxLength?: number;\n /** Fails when the value does not match `pattern.value`. */\n pattern?: {value: RegExp; message: string};\n /**\n * Overrides the message per rule type — `min`, `max`, `minLength`,\n * `maxLength` defaults and pattern's inline `message` alike — e.g. for\n * centralizing or localizing messages.\n */\n messages?: Partial<Record<Exclude<RuleType, 'required'>, string>>;\n};\n\n/** Default English messages, aligned with RHF's default-message style. */\nfunction defaultMessage(type: RuleType, bound?: number): string {\n switch (type) {\n case 'required':\n return 'This field is required';\n case 'min':\n return `Must be at least ${bound}`;\n case 'max':\n return `Must be at most ${bound}`;\n case 'minLength':\n return `Must be at least ${bound} characters`;\n case 'maxLength':\n return `Must be at most ${bound} characters`;\n case 'pattern':\n return 'Invalid format';\n default:\n return 'Invalid value';\n }\n}\n\n/**\n * Compile declarative {@link FieldRules} into a {@link SyncValidator}.\n *\n * `required` is checked first and, when it fails on an empty value,\n * short-circuits the rest. Every other failing rule is collected into one\n * FieldError[] in declaration order (min, max, minLength, maxLength,\n * pattern); a fully passing value yields undefined. Messages resolve to\n * the rule's own string (required), `rules.messages`, or the default.\n *\n * @param rules declarative constraints\n * @return synchronous validator producing FieldError[] | undefined\n */\nexport function rulesToValidator(rules: FieldRules): SyncValidator {\n return value => {\n if (rules.required) {\n if (value === '' || value === undefined || value === null) {\n return [\n {\n type: 'required',\n message:\n typeof rules.required === 'string'\n ? rules.required\n : defaultMessage('required')\n }\n ];\n }\n }\n const errors: FieldError[] = [];\n const message = (type: Exclude<RuleType, 'required'>, bound: number) =>\n rules.messages?.[type] ?? defaultMessage(type, bound);\n if (rules.min !== undefined) {\n const n = Number(value);\n if (!Number.isNaN(n) && n < rules.min) {\n errors.push({type: 'min', message: message('min', rules.min)});\n }\n }\n if (rules.max !== undefined) {\n const n = Number(value);\n if (!Number.isNaN(n) && n > rules.max) {\n errors.push({type: 'max', message: message('max', rules.max)});\n }\n }\n if (\n rules.minLength !== undefined &&\n typeof value === 'string' &&\n value.length < rules.minLength\n ) {\n errors.push({\n type: 'minLength',\n message: message('minLength', rules.minLength)\n });\n }\n if (\n rules.maxLength !== undefined &&\n typeof value === 'string' &&\n value.length > rules.maxLength\n ) {\n errors.push({\n type: 'maxLength',\n message: message('maxLength', rules.maxLength)\n });\n }\n if (rules.pattern && !rules.pattern.value.test(value)) {\n errors.push({\n type: 'pattern',\n // pattern.message is type-required but JS consumers may omit it.\n message:\n rules.messages?.pattern ??\n rules.pattern.message ??\n defaultMessage('pattern')\n });\n }\n return errors.length ? errors : undefined;\n };\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('../cjs/use-sync-external-store-shim.production.js');\n} else {\n module.exports = require('../cjs/use-sync-external-store-shim.development.js');\n}\n","/**\n * @license React\n * use-sync-external-store-shim.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar React = require(\"react\");\nfunction is(x, y) {\n return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);\n}\nvar objectIs = \"function\" === typeof Object.is ? Object.is : is,\n useState = React.useState,\n useEffect = React.useEffect,\n useLayoutEffect = React.useLayoutEffect,\n useDebugValue = React.useDebugValue;\nfunction useSyncExternalStore$2(subscribe, getSnapshot) {\n var value = getSnapshot(),\n _useState = useState({ inst: { value: value, getSnapshot: getSnapshot } }),\n inst = _useState[0].inst,\n forceUpdate = _useState[1];\n useLayoutEffect(\n function () {\n inst.value = value;\n inst.getSnapshot = getSnapshot;\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n },\n [subscribe, value, getSnapshot]\n );\n useEffect(\n function () {\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n return subscribe(function () {\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n });\n },\n [subscribe]\n );\n useDebugValue(value);\n return value;\n}\nfunction checkIfSnapshotChanged(inst) {\n var latestGetSnapshot = inst.getSnapshot;\n inst = inst.value;\n try {\n var nextValue = latestGetSnapshot();\n return !objectIs(inst, nextValue);\n } catch (error) {\n return !0;\n }\n}\nfunction useSyncExternalStore$1(subscribe, getSnapshot) {\n return getSnapshot();\n}\nvar shim =\n \"undefined\" === typeof window ||\n \"undefined\" === typeof window.document ||\n \"undefined\" === typeof window.document.createElement\n ? useSyncExternalStore$1\n : useSyncExternalStore$2;\nexports.useSyncExternalStore =\n void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;\n","/**\n * @license React\n * use-sync-external-store-shim.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function is(x, y) {\n return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);\n }\n function useSyncExternalStore$2(subscribe, getSnapshot) {\n didWarnOld18Alpha ||\n void 0 === React.startTransition ||\n ((didWarnOld18Alpha = !0),\n console.error(\n \"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release.\"\n ));\n var value = getSnapshot();\n if (!didWarnUncachedGetSnapshot) {\n var cachedValue = getSnapshot();\n objectIs(value, cachedValue) ||\n (console.error(\n \"The result of getSnapshot should be cached to avoid an infinite loop\"\n ),\n (didWarnUncachedGetSnapshot = !0));\n }\n cachedValue = useState({\n inst: { value: value, getSnapshot: getSnapshot }\n });\n var inst = cachedValue[0].inst,\n forceUpdate = cachedValue[1];\n useLayoutEffect(\n function () {\n inst.value = value;\n inst.getSnapshot = getSnapshot;\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n },\n [subscribe, value, getSnapshot]\n );\n useEffect(\n function () {\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n return subscribe(function () {\n checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });\n });\n },\n [subscribe]\n );\n useDebugValue(value);\n return value;\n }\n function checkIfSnapshotChanged(inst) {\n var latestGetSnapshot = inst.getSnapshot;\n inst = inst.value;\n try {\n var nextValue = latestGetSnapshot();\n return !objectIs(inst, nextValue);\n } catch (error) {\n return !0;\n }\n }\n function useSyncExternalStore$1(subscribe, getSnapshot) {\n return getSnapshot();\n }\n \"undefined\" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&\n \"function\" ===\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());\n var React = require(\"react\"),\n objectIs = \"function\" === typeof Object.is ? Object.is : is,\n useState = React.useState,\n useEffect = React.useEffect,\n useLayoutEffect = React.useLayoutEffect,\n useDebugValue = React.useDebugValue,\n didWarnOld18Alpha = !1,\n didWarnUncachedGetSnapshot = !1,\n shim =\n \"undefined\" === typeof window ||\n \"undefined\" === typeof window.document ||\n \"undefined\" === typeof window.document.createElement\n ? useSyncExternalStore$1\n : useSyncExternalStore$2;\n exports.useSyncExternalStore =\n void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;\n \"undefined\" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&\n \"function\" ===\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());\n })();\n","import {on} from '@for-fun/event-emitter';\nimport type {EventEmitter} from '@for-fun/event-emitter';\nimport createPath from './path';\nimport type {Name, Path} from './path';\nimport type {Form, FormEvents} from './form';\n\n/** Subscription granularity for {@link onPathEvent}.\n * - `'leaf'`: the subscriber reads exactly one key ({@link\n * useValueByPath}); only writes at that key or above it can change what\n * it reads.\n * - `'branch'`: the subscriber aggregates a whole subtree below a key\n * ({@link useFieldArray}); descendant writes matter too. */\nexport type WatchScope = 'leaf' | 'branch';\n\n/**\n * Is `key` a strict descendant of `ancestorKey`?\n *\n * Keys are JSON.stringify'd segment arrays ('[\"a\",\"b\"]'), so a descendant\n * key is the ancestor key minus its closing ']' followed by a ','\n * ('[\"a\",\"b\",'). The ',' separator is mandatory: a plain prefix match\n * would let the sibling '[\"tagsX\"]' pass as a descendant of '[\"tags\"]'.\n */\nfunction isDescendant(key: string, ancestorKey: string): boolean {\n return key.startsWith(`${ancestorKey.slice(0, -1)},`);\n}\n\n/**\n * Subscribe to `event`, invoking `cb` only when the emitted path is\n * relevant to `path`.\n *\n * Payload-less broadcasts (reset, setInitialValues) always invoke `cb` --\n * they are global syncs and the correctness fallback. (removeFieldByPath\n * emits with its path: its mutations are bounded to that key, so the path\n * matching below is exact.) When the emit carries a path P:\n * - `'leaf'`: P.key equals `path.key` or is one of its ancestors -- a leaf\n * read falls back to ancestor values (getValueByPath), so ancestor\n * writes must invalidate, while sibling and descendant writes cannot\n * change what the leaf reads.\n * - `'branch'`: `'leaf'` semantics plus P.key being a descendant of\n * `path.key` -- changed descendants re-aggregate the subtree.\n *\n * @param emitter emitter to subscribe to\n * @param event event name\n * @param path the watched path\n * @param scope which writes around `path` are relevant\n * @param cb listener, invoked with no arguments\n * @return unsubscribe function\n */\nexport function onPathEvent(\n emitter: EventEmitter<FormEvents>,\n event: SubscribeEvent,\n path: Path,\n scope: WatchScope,\n cb: () => void\n): () => void {\n const {key} = path;\n return on(emitter, event, (changed?: Path) => {\n if (\n changed === undefined ||\n changed.key === key ||\n isDescendant(key, changed.key) ||\n (scope === 'branch' && isDescendant(changed.key, key))\n ) {\n cb();\n }\n });\n}\n\n/**\n * Subscribe to `event`, invoking `cb` only when the emitted path's key is\n * exactly `key` (or the emit carries no payload -- a global sync).\n *\n * For state stored per exact key (errors, touched) no ancestor or\n * descendant matching is wanted: another field's key must not wake this\n * subscriber.\n *\n * @param emitter emitter to subscribe to\n * @param event event name\n * @param key exact path key to match\n * @param cb listener, invoked with no arguments\n * @return unsubscribe function\n */\nexport function onKeyEvent(\n emitter: EventEmitter<FormEvents>,\n event: SubscribeEvent,\n key: string,\n cb: () => void\n): () => void {\n return on(emitter, event, (changed?: Path) => {\n if (changed === undefined || changed.key === key) cb();\n });\n}\n\n/** Events {@link subscribe} can watch. `'errors'` and `'touched'` are\n * stored per exact key, so they match exact keys ({@link onKeyEvent});\n * `'change'`, `'validating'`, `'submitting'`, `'submitCount'`,\n * `'disabled'` and `'submitSuccessful'` go through\n * {@link onPathEvent}. `'validating'` carries paths (one per async\n * validator round) and matches by path exactly like `'change'`;\n * `'submitting'`, `'submitCount'`, `'disabled'` and\n * `'submitSuccessful'` are payload-less broadcasts, so `name` never\n * narrows them — every subscriber hears every emission. */\nexport type SubscribeEvent =\n | 'change'\n | 'errors'\n | 'touched'\n | 'validating'\n | 'submitting'\n | 'submitCount'\n | 'submitSuccessful'\n | 'disabled'\n | 'loading';\n\n/** Options accepted by {@link subscribe}. */\nexport type SubscribeOptions = {\n /** Path (or list of paths) to watch. Omit to receive every emission of\n * `event`, payload-less broadcasts included. A single segments path\n * (`['tags', 0]`) and a list of names (`['tags', 'user.name']`) are told\n * apart by the same rule `trigger` uses: only a segments path can hold\n * a number. */\n name?: Name | Name[];\n /** Event to watch. Defaults to `'change'`. */\n event?: SubscribeEvent;\n /** Which writes around `name` are relevant — `'leaf'` or `'branch'`.\n * Only meaningful for the path-carrying events `'change'` and\n * `'validating'`: `'errors'`/`'touched'` match exact keys and\n * `'submitting'`/`'submitCount'`/`'disabled'`/`'submitSuccessful'`\n * are payload-less. Defaults to `'branch'` — the intuitive linkage\n * semantics, where subscribing to `'tags'` means the whole branch. */\n scope?: WatchScope;\n /** Invoked with no arguments after each matching emission. Read fresh\n * state through the `get*` readers inside it. */\n callback: () => void;\n};\n\n/** Is `name` a list of names rather than one segments path? Numbers only\n * occur inside a segments path (`['a', 0]`), never as standalone names —\n * the same disambiguation `trigger` applies to its name argument. */\nfunction isNameList(name: Name | Name[]): name is Name[] {\n return (\n Array.isArray(name) &&\n (name as (number | unknown)[]).every(part => typeof part !== 'number')\n );\n}\n\n/**\n * Subscribe to form events imperatively — the non-render counterpart of\n * the `use*` hooks: linkages and side effects (province changed → clear\n * city, autosave, analytics) run without mounting a watching component.\n *\n * Without `name`, `callback` fires on every `event` emission, payload-less\n * broadcasts (reset, setInitialValues) included. With `name`, matching\n * follows the event's shape: `'errors'`/`'touched'` match the exact key\n * ({@link onKeyEvent}) — another field's error never wakes this\n * subscriber — while `'change'`/`'validating'`/`'submitting'`/\n * `'submitCount'`/`'disabled'`/`'submitSuccessful'` go through\n * {@link onPathEvent}, so the default `'branch'` scope wakes a `'tags'`\n * subscriber when any `tags.*` descendant is written. `'validating'`\n * carries a path per validator round and narrows by path like\n * `'change'`; `'disabled'`/`'submitSuccessful'` (like `'submitting'`)\n * are payload-less broadcasts that every named subscriber receives. A\n * `name` array builds one subscription per path and the returned\n * function unsubscribes them all.\n *\n * @param form the form to watch\n * @param options event, name(s), scope and callback\n * @return unsubscribe function\n */\nexport function subscribe(form: Form, options: SubscribeOptions): () => void {\n const {name, event = 'change', scope = 'branch', callback} = options;\n if (name === undefined) return on(form.emitter, event, callback);\n const names = isNameList(name) ? name : [name];\n const unsubscribes = names.map(one => {\n const path = createPath(one);\n return event === 'errors' || event === 'touched'\n ? onKeyEvent(form.emitter, event, path.key, callback)\n : onPathEvent(form.emitter, event, path, scope, callback);\n });\n return unsubscribes.length === 1\n ? unsubscribes[0]\n : () => unsubscribes.forEach(unsubscribe => unsubscribe());\n}\n","import {useState, useEffect, useCallback, useRef} from 'react';\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\nimport {on} from '@for-fun/event-emitter';\nimport type {EventEmitter} from '@for-fun/event-emitter';\nimport {onKeyEvent, onPathEvent} from '../subscribe';\nimport type {SubscribeEvent} from '../subscribe';\nimport createForm, {\n FORM_ERROR,\n getErrorByPath,\n getFieldErrorsByPath,\n getValueByPath,\n hasTouchedByPath,\n hasErrors,\n isDirty,\n getDirtyFields,\n getTouchedFields,\n setInitialValues\n} from '../form';\nimport type {FieldError, Form, FormEvents, Options} from '../form';\nimport type {FieldPath, PathValueOf} from '../types';\nimport createPath from '../path';\nimport type {PathSegments, Path} from '../path';\nimport {isEqual, isPromise} from '../util';\n\n/**\n * Create a form instance bound to this component.\n *\n * Beyond {@link Options}, the optional `values` object enables controlled\n * usage: when it genuinely changes it is re-synced into the form with\n * setInitialValues semantics -- uncommitted user edits are discarded\n * (master-detail semantics: selecting another record replaces the draft),\n * while touched flags and errors survive. Change detection is\n * reference-first with a structural fallback, so re-renders that pass an\n * inline literal with equal content never re-sync -- the user's\n * in-progress typing is never clobbered.\n */\nexport default function useForm<T extends Record<string, any> = any>(\n options?: Options<T> & {values?: T}\n): Form<T> {\n // Lazy initialization: createForm runs once per mount and the returned\n // instance is stable across re-renders (and StrictMode double renders),\n // without writing to refs during render. A provided `values` object is\n // seeded synchronously here (createForm does the same for initialValues)\n // so the first paint and SSR already reflect the controlled values.\n const [form] = useState(() => {\n const created = createForm<T>(options);\n if (options && options.values !== undefined) {\n setInitialValues(created, options.values);\n }\n return created;\n });\n const initialValues = options && options.initialValues;\n const values = options && options.values;\n\n // Track which initialValues source object the form was last seeded from.\n // Inline options create a fresh object every render, and re-seeding\n // clears the values Map (setInitialValues semantics), which would revert\n // every committed edit right after each re-render -- on the client and\n // after hydration alike. Memoized callers are covered by the reference\n // check; inline literals by the structural one, so only genuinely new\n // content re-seeds.\n const seededRef = useRef<{done: boolean; source: any} | null>(null);\n if (seededRef.current === null)\n seededRef.current = {done: false, source: undefined};\n\n useEffect(() => {\n // undefined = no baseline requested (createForm already defaulted to\n // {}): installing it would clear the values Map on mount for no\n // semantic gain — wiping any render-time useField initialValue seeds.\n // Async sources (Promise or thunk) are excluded too: createForm owns\n // their one-shot resolution, and a thunk's identity changes every\n // render, so re-seeding here would clobber the resolution cycle with\n // the raw function itself.\n if (initialValues === undefined) return;\n if (typeof initialValues === 'function' || isPromise(initialValues)) {\n return;\n }\n const seeded = seededRef.current!;\n if (\n seeded.done &&\n (seeded.source === initialValues || isEqual(seeded.source, initialValues))\n ) {\n return;\n }\n seeded.done = true;\n seeded.source = initialValues;\n setInitialValues(form, initialValues);\n }, [form, initialValues]);\n\n // Controlled values: re-sync only when the incoming object genuinely\n // differs from what the form was last seeded from. The reference check\n // is the fast path (memoized callers); inline literals get a fresh\n // object identity every render, so without the structural comparison\n // each re-render would clear the values Map (setInitialValues\n // semantics) and revert the user's uncommitted edits -- same hazard the\n // initialValues seed guard above protects against. Master-detail\n // semantics still apply whenever the content actually changed.\n const controlledRef = useRef<{done: boolean; source: any} | null>(null);\n if (controlledRef.current === null) {\n controlledRef.current = {done: false, source: undefined};\n }\n\n useEffect(() => {\n if (values === undefined) return;\n const seeded = controlledRef.current!;\n if (\n seeded.done &&\n (seeded.source === values || isEqual(seeded.source, values))\n ) {\n return;\n }\n seeded.done = true;\n seeded.source = values;\n setInitialValues(form, values);\n }, [form, values]);\n\n return form;\n}\n\n/** Per-hook snapshot cache for {@link useWatch}. */\ntype WatchCache<T> = {hasValue: boolean; value?: T};\n\n/**\n * Shared core of {@link useWatch} and the path-scoped hooks: a\n * useSyncExternalStore binding over a custom event subscription.\n * `subscribeFactory` receives the invalidate callback (drop the snapshot\n * cache, then notify React) and returns its unsubscribe function, so the\n * core stays identical whether the subscription is global or scoped to\n * one path.\n *\n * The optional `isEqual` comparator redirects `invalidate`: instead of\n * dropping the cache and waking React unconditionally, an event first\n * recomputes the getter and asks `isEqual` whether anything observable\n * changed — an equal verdict keeps the cached snapshot and skips the\n * notify entirely (no render at all), an unequal one stores the fresh\n * snapshot and notifies. Omitted, the historical drop-and-notify pipeline\n * runs byte-for-byte unchanged.\n */\nexport function useWatchCore<T>(\n subscribeFactory: (invalidate: () => void) => () => void,\n getter: () => T,\n isEqual?: (prev: T, next: T) => boolean\n): T {\n // useSyncExternalStore requires getSnapshot to return the same reference\n // until the store actually changed, otherwise React warns and loops.\n // Cache the snapshot per hook instance and recompute it only on the first\n // read and after the watched event fired.\n const cacheRef = useRef<WatchCache<T> | null>(null);\n if (cacheRef.current === null) cacheRef.current = {hasValue: false};\n const cache = cacheRef.current;\n\n // Hold the latest getter in a ref so getSnapshot keeps a stable identity\n // (callers pass a freshly bound function on every render) while still\n // recomputing with the most recent getter when the cache is invalid.\n const getterRef = useRef(getter);\n getterRef.current = getter;\n // Same freshness treatment for the comparator: invalidate is created once\n // per subscription, so it must read the latest isEqual through a ref\n // rather than capturing whichever instance the first render passed.\n const isEqualRef = useRef(isEqual);\n isEqualRef.current = isEqual;\n\n const getSnapshot = useCallback(() => {\n if (!cache.hasValue) {\n cache.value = getterRef.current();\n cache.hasValue = true;\n }\n return cache.value as T;\n }, [cache]);\n\n const subscribe = useCallback(\n (notify: () => void) => {\n // The form may have changed between render and this subscription, and\n // those events were missed: drop the cache. React's consistency check\n // right after subscribing recomputes and re-renders only when the\n // fresh value differs from the committed snapshot.\n cache.hasValue = false;\n const invalidate = () => {\n const compare = isEqualRef.current;\n if (compare && cache.hasValue) {\n // Custom comparator: decide before waking React. Equal means the\n // fresh getter result is observably the same — keep the cached\n // reference and return without notifying, so React never even\n // schedules a render. Unequal stores the fresh snapshot up front,\n // so React's own post-notify Object.is check reads it without\n // recomputing the getter.\n const next = getterRef.current();\n if (compare(cache.value as T, next)) return;\n cache.value = next;\n notify();\n return;\n }\n cache.hasValue = false;\n notify();\n };\n return subscribeFactory(invalidate);\n },\n [subscribeFactory, cache]\n );\n\n // Form state lives entirely in synchronously readable Map/Set structures\n // seeded from initialValues/values during the lazy useState initializer,\n // so the server snapshot is computed exactly like the client's first\n // render -- pass getSnapshot itself as getServerSnapshot and hydration\n // matches.\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Subscribe to a form event and keep the component's snapshot of `getter()`\n * in sync with the form state.\n *\n * Built on useSyncExternalStore, so snapshots taken while React renders are\n * guaranteed consistent (no tearing under concurrent rendering) and changes\n * emitted before the subscription effect runs are still picked up.\n *\n * The first argument is the form for the unified `fn(form, ...)` context\n * shape every hook shares; the raw emitter form remains accepted for\n * back-compat and for subscription sources that are not a full form.\n *\n * By default the re-render surface is the event's own scope: every emit\n * the subscription hears drops the snapshot cache and wakes React, which\n * then bails out when the recomputed snapshot is reference-identical\n * (Object.is) — the path/leaf scoping every built-in reader relies on.\n * The optional `isEqual` comparator exists for wide-scope getters that\n * return a fresh reference per call (a whole-values selector, say): each\n * event recomputes the getter and asks `isEqual` whether the result is\n * observably the same, and an equal verdict skips notifying React\n * altogether — no render, not even a bailed-out one. An unequal verdict\n * stores the new snapshot and re-renders. Same contract as TanStack's\n * `useSelector` compare. Omitted, behavior is unchanged.\n */\nexport function useWatch<T>(\n formOrEmitter: Form | EventEmitter<FormEvents>,\n event: SubscribeEvent,\n getter: () => T,\n isEqual?: (prev: T, next: T) => boolean\n): T {\n // A form carries an `emitter` field the opaque emitter instance never\n // has, so the duck test cleanly discriminates the two accepted shapes.\n const emitter =\n 'emitter' in formOrEmitter ? formOrEmitter.emitter : formOrEmitter;\n const subscribeFactory = useCallback(\n (invalidate: () => void) => on(emitter, event, invalidate),\n [emitter, event]\n );\n return useWatchCore(subscribeFactory, getter, isEqual);\n}\n\n/**\n * Get field value state\n */\nexport function useValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): PathValueOf<T, P> {\n return useValueByPath(form, createPath(name));\n}\n\n/**\n * Get field value state by path\n */\nexport function useValueByPath(form: Form, path: Path): any {\n const {emitter} = form;\n const {key} = path;\n // 'leaf' scope: a leaf read depends only on its own key and its\n // ancestors' (getValueByPath fallback chain), so writes elsewhere --\n // siblings, descendants, string-prefix lookalikes ('[\"a\",\"bX\"]') -- never\n // invalidate the snapshot. Payload-less broadcasts (reset,\n // setInitialValues) still sync everything; removeField matches by path.\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n onPathEvent(emitter, 'change', path, 'leaf', invalidate),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `key` on purpose: useValue creates a fresh Path per render, so the object must stay out of the deps while the key string pins the subscription\n [emitter, key]\n );\n return useWatchCore(subscribeFactory, getValueByPath.bind(null, form, path));\n}\n\n/**\n * Get field touched state\n */\nexport function useTouched<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): boolean {\n return useTouchedByPath(form, createPath(name));\n}\n\n/**\n * Get field touched state by path\n */\nexport function useTouchedByPath(form: Form, path: Path): boolean {\n const {emitter} = form;\n const {key} = path;\n // Touched is stored per exact key, so only this field's own setTouched\n // (now emitted with its path) matters; payload-less broadcasts (reset,\n // removeField) still sync everything.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'touched', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(\n subscribeFactory,\n hasTouchedByPath.bind(null, form, path)\n );\n}\n\n/**\n * Get field error message state\n * @return current error's message string (display text), or undefined\n */\nexport function useError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): string | undefined {\n return useErrorByPath(form, createPath(name))?.message;\n}\n\n/**\n * Get field error state by path\n * @return current FieldError object ({type, message}), or undefined\n */\nexport function useErrorByPath(form: Form, path: Path): FieldError | undefined {\n const {emitter} = form;\n const {key} = path;\n // Errors are stored per exact key, so only writes to this field's error\n // (setErrorByPath now emits with its path) matter; payload-less\n // broadcasts (clearErrors, reset, removeField) still sync everything.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'errors', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(subscribeFactory, getErrorByPath.bind(null, form, path));\n}\n\n/**\n * Get all field errors\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function useFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return useFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all field errors by path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function useFieldErrorsByPath(form: Form, path: Path): FieldError[] {\n const {emitter} = form;\n const {key} = path;\n // Same exact-key subscription and snapshot rules as useErrorByPath: the\n // getter returns the shared empty constant when clean and the stored\n // array by reference otherwise, so the useSyncExternalStore snapshot is\n // reference-stable between unrelated events.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'errors', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(\n subscribeFactory,\n getFieldErrorsByPath.bind(null, form, path)\n );\n}\n\nexport function useIsDirty(form: Form): boolean {\n // Dirty state is driven by value changes, not touch state: subscribe to\n // 'change' so typing flips this immediately, even before a blur.\n return useWatch(form, 'change', isDirty.bind(null, form));\n}\n\n/**\n * Get dirty fields state -- object mapping each dirty field's user-facing\n * dotted path ('a.b', 'a.0.c') to true; recalculated after 'change' events\n */\nexport function useDirtyFields(form: Form): Record<string, boolean> {\n return useWatch(form, 'change', getDirtyFields.bind(null, form));\n}\n\n/**\n * Get touched fields state -- array of touched fields' user-facing dotted\n * paths ('a.b', 'a.0.c'); recalculated after 'touched' events\n */\nexport function useTouchedFields(form: Form): string[] {\n return useWatch(form, 'touched', getTouchedFields.bind(null, form));\n}\n\n/**\n * Aggregate snapshot of the whole form's state flags — the one-subscription\n * counterpart of react-hook-form's `formState` object (no errors object;\n * per-field error state stays with `useError`/`useFieldErrors`, and\n * `hasErrors`/`isValid` cover the whole-form questions).\n *\n * Recomputed on every state-bearing event; the field-wise comparator keeps\n * the returned reference stable while nothing observably changed, so\n * `useFormState(form).isDirty` re-renders no more often than the dedicated\n * {@link useIsDirty}. Cheaper than calling the granular hooks one by one\n * (one subscription and one snapshot instead of one per flag).\n */\nexport type FormState = {\n /** Any live value differs from its baseline (see {@link isDirty}). */\n isDirty: boolean;\n /** Dirty fields keyed by user-facing dotted path ('a.b', 'a.0.c'). */\n dirtyFields: Record<string, boolean>;\n /** At least one field is touched. */\n isTouched: boolean;\n /** Touched fields' user-facing dotted paths. */\n touchedFields: string[];\n /** Any error registered (field or form level). */\n hasErrors: boolean;\n /** No errors are registered — react-hook-form's `isValid` semantics.\n * In-flight validation is NOT factored in ({@link isValidating} is the\n * separate signal; async rounds temporarily pass this flag like RHF's). */\n isValid: boolean;\n isSubmitting: boolean;\n /** Any validation round is running (field, form-level, or a pending\n * debounce window). */\n isValidating: boolean;\n isSubmitSuccessful: boolean | undefined;\n submitCount: number;\n /** Async initialValues still pending ({@link Form.isLoading}). */\n isLoading: boolean;\n /** The form-level disabled flag (fields OR their own `disabled`). */\n disabled: boolean;\n};\n\n/** Events any FormState field can react to: each recomputes the whole\n * snapshot — the comparator, not per-flag subscriptions, keeps the\n * re-render surface minimal. */\nconst FORM_STATE_EVENTS: readonly SubscribeEvent[] = [\n 'change',\n 'errors',\n 'touched',\n 'validating',\n 'submitting',\n 'submitCount',\n 'submitSuccessful',\n 'disabled',\n 'loading'\n];\n\nfunction getFormState(form: Form): FormState {\n return {\n isDirty: isDirty(form),\n dirtyFields: getDirtyFields(form),\n isTouched: form.touched.size > 0,\n touchedFields: getTouchedFields(form),\n hasErrors: hasErrors(form),\n isValid: !hasErrors(form),\n isSubmitting: form.isSubmitting,\n isValidating: form.validating.size > 0,\n isSubmitSuccessful: form.isSubmitSuccessful,\n submitCount: form.submitCount,\n isLoading: form.isLoading,\n disabled: form.disabled\n };\n}\n\n/** Field-wise equality: reference checks where the getter already memoizes\n * (dirtyFields), element-wise for the fresh array getTouchedFields builds,\n * value checks for the flags. */\nfunction isSameFormState(a: FormState, b: FormState): boolean {\n const sameTouched =\n a.touchedFields.length === b.touchedFields.length &&\n a.touchedFields.every((path, i) => path === b.touchedFields[i]);\n return (\n a.isDirty === b.isDirty &&\n a.dirtyFields === b.dirtyFields &&\n a.isTouched === b.isTouched &&\n sameTouched &&\n a.hasErrors === b.hasErrors &&\n a.isValid === b.isValid &&\n a.isSubmitting === b.isSubmitting &&\n a.isValidating === b.isValidating &&\n a.isSubmitSuccessful === b.isSubmitSuccessful &&\n a.submitCount === b.submitCount &&\n a.isLoading === b.isLoading &&\n a.disabled === b.disabled\n );\n}\n\nexport function useFormState(form: Form): FormState {\n const getter = useCallback(() => getFormState(form), [form]);\n const subscribeFactory = useCallback(\n (invalidate: () => void) => {\n const offs = FORM_STATE_EVENTS.map(event =>\n on(form.emitter, event, invalidate)\n );\n return () => {\n for (const off of offs) off();\n };\n },\n [form.emitter]\n );\n return useWatchCore(subscribeFactory, getter, isSameFormState);\n}\n\nexport function useHasErrors(form: Form): boolean {\n return useWatch(form, 'errors', hasErrors.bind(null, form));\n}\n\n/**\n * Get whether the form currently has no errors — react-hook-form's\n * `formState.isValid` counterpart. Subscribes to the `'errors'` event only;\n * in-flight validation does not flip it (see {@link useIsValidating}).\n */\nexport function useIsValid(form: Form): boolean {\n return useWatch(form, 'errors', () => !hasErrors(form));\n}\n\nexport function useIsSubmitting(form: Form): boolean {\n return useWatch(form, 'submitting', () => form.isSubmitting);\n}\n\n/**\n * Get whether an async {@link Options.initialValues} source is still\n * pending — the flag a loading skeleton or a disabled submit button gates\n * on until the resolved baseline lands. Subscribes to the 'loading' event\n * the core emits around the resolution cycle.\n */\nexport function useIsLoading(form: Form): boolean {\n return useWatch(form, 'loading', () => form.isLoading);\n}\n\n/**\n * Get whether the form accepts a submit right now:\n * `!isSubmitting && !hasErrors`. This is the single flag a submit\n * button's `disabled` prop wants — it is `false` for the whole async\n * `onSubmit` span (not just the validation pass) and whenever any field\n * holds an error (client validation or server backfill), replacing the\n * hand-rolled `useHasErrors(form) || useIsSubmitting(form)` pair.\n * Deliberately no dirty or validating semantics: an untouched-but-clean\n * form can submit.\n */\nexport function useCanSubmit(form: Form): boolean {\n const {emitter} = form;\n // canSubmit folds two events into one boolean: error writes\n // ('errors') and submit-state flips ('submitting'). useWatch subscribes\n // to a single event, so subscribe to both through useWatchCore — the\n // snapshot recomputes on either wake and re-renders only when the\n // boolean itself flips, so unrelated single-field error churn costs no\n // extra render (the same granularity useHasErrors already has).\n const subscribeFactory = useCallback(\n (invalidate: () => void) => {\n const offErrors = on(emitter, 'errors', invalidate);\n const offSubmitting = on(emitter, 'submitting', invalidate);\n return () => {\n offErrors();\n offSubmitting();\n };\n },\n [emitter]\n );\n return useWatchCore(\n subscribeFactory,\n () => !form.isSubmitting && !hasErrors(form)\n );\n}\n\nexport function useSubmitCount(form: Form): number {\n return useWatch(form, 'submitCount', () => form.submitCount);\n}\n\n/**\n * Get whether any validation round is currently running: a field\n * validator's pending `validateDebounce` window, an async field validator\n * still in flight, or the form-level validate's debounce window / in-flight\n * round — every one of them holds a key in `form.validating`, and the\n * 'validating' events they emit (field rounds with a path payload, the\n * form-level round as a payload-less broadcast) are what this subscribes\n * to. The boolean snapshot is Object.is-stable, so churn among the marks\n * (a second field opening while the first settles) costs no render while\n * the flag holds. This is the flag a submit button disables itself on, or\n * spins a spinner with, through the pre-submit validation pass — it flips\n * true the moment the first round opens and back false when the last one\n * settles.\n */\nexport function useIsValidating(form: Form): boolean {\n return useWatch(form, 'validating', () => form.validating.size > 0);\n}\n\n/**\n * Get whether the last submit succeeded: `true` once a submit's validation\n * and `onSubmit` completed without throwing, `false` after a failed submit\n * (validation rejection or a thrown callback) and before any submit ran —\n * the falsy reading of the undefined initial/reset state. Subscribes to\n * the 'submitSuccessful' event the core's setSubmitSuccessful emits, so\n * the flag flips in the same tick the outcome lands: the usual consumers\n * are a success banner and a redirect-on-success effect.\n */\nexport function useIsSubmitSuccessful(form: Form): boolean {\n return useWatch(\n form.emitter,\n 'submitSuccessful',\n () => !!form.isSubmitSuccessful\n );\n}\n\n/**\n * Get the form-level error message: the first error stored under the\n * reserved {@link FORM_ERROR} key, as display text — or undefined while\n * the slot is clean. That key is where a form-level `validate` record's\n * `_form` entry lands and where the Standard Schema adapter drops\n * path-less issues, so errors that belong to no single field still have a\n * reader. The classic usage renders it once above the submit button —\n * `useFormError(form) || null` — and the imperative twin is\n * `getError(form, FORM_ERROR)`.\n */\nexport function useFormError(form: Form): string | undefined {\n return useErrorByPath(form, createPath(FORM_ERROR))?.message;\n}\n\n/**\n * Get every form-level error: all errors stored under the reserved\n * {@link FORM_ERROR} key (insertion order), an empty array when the slot\n * is clean. The plural twin of {@link useFormError} for forms that stack\n * several form-level issues — each path-less Standard Schema issue lands\n * in this slot. The array reference is stable between unrelated events\n * (the stored array or a shared empty constant), so consumers can memo on\n * it; the imperative counterpart is `getFieldErrors(form, FORM_ERROR)`.\n */\nexport function useFormErrors(form: Form): FieldError[] {\n return useFieldErrorsByPath(form, createPath(FORM_ERROR));\n}\n","import {useMemo} from 'react';\nimport create from '../path';\nimport type {Name, Path} from '../path';\nimport {normalizePath} from '../util';\n\nexport default function usePath(name: Name): Path {\n const path = useMemo(() => create(normalizePath(name)), [name]);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: re-renders passing a fresh array for the same field name reuse the cached Path object (stable reference & Map key)\n return useMemo(() => path, [path.key]);\n}\n","import {useCallback, useRef, type MutableRefObject} from 'react';\n\nexport default function useStage<T>(value: T): MutableRefObject<T> {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n\nexport function useStageFn<T extends (...args: any[]) => any>(fn: T): T {\n const ref = useStage(fn);\n return useCallback(\n (...params: any[]) => ref.current(...params),\n [ref]\n ) as unknown as T;\n}\n","import {useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport type {Context} from 'react';\nimport {on} from '@for-fun/event-emitter';\nimport {FormContext} from '../context';\nimport {\n emitChangeByPath,\n getValueByPath,\n registerFieldMode,\n registerFieldValidateDeps,\n removeFieldByPath,\n seedValueByPath,\n unregisterFieldMode,\n unregisterFieldValidateDeps,\n userBlur,\n userChangeByPath\n} from '../form';\nimport type {FieldError, Form, ValidationMode} from '../form';\nimport createPath from '../path';\nimport type {Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport {rulesToValidator} from '../rules';\nimport type {FieldRules} from '../rules';\nimport {useFieldErrorsByPath, useWatch, useWatchCore} from './form';\nimport {onPathEvent} from '../subscribe';\nimport usePath from './path';\nimport useValidate from './validate';\nimport type {Validator} from './validate';\nimport {useStageFn} from './stage';\nimport {isPromise} from '../util';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\nexport type UseFieldOptions<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n form?: Form<TValues>;\n name: TPath;\n initialValue?: any;\n shouldUnregister?: boolean;\n validate?: Validator;\n /**\n * Declarative rules (required/min/max/minLength/maxLength/pattern),\n * compiled into a synchronous validator. `required` is special: it runs\n * immediately on every kick — never debounced — and while it fails,\n * `validate` is skipped (the expensive check never sees an empty value).\n * The other rules compose with `validate` — rules run first, then\n * `validate` (awaited when async), merging both sources' errors with\n * rules errors ahead. Failures land in the form's error state with the\n * given or default messages.\n */\n rules?: FieldRules;\n /**\n * Milliseconds to debounce this field's validation kicks. Defaults to 0\n * (validate immediately); while the timer is pending the field counts as\n * validating, so `trigger`/`ensureValidate` wait out the window. Only the\n * last kick inside the window runs the validator. The `required` rule is\n * exempt: it runs synchronously on every kick, so a required failure\n * shows immediately instead of waiting out the window.\n */\n validateDebounce?: number;\n /**\n * Milliseconds to delay showing a newly appearing error in the render\n * layer (`error`/`errorObject`/`errors` stay undefined/empty until the\n * window passes). The form's error state is never delayed — trigger,\n * submit and `getError` read it immediately. An error that clears inside\n * the window never shows; once an error is visible, later changes apply\n * immediately. Only the none → some transition waits.\n */\n delayError?: number;\n /**\n * Disable this field: OR-ed with the form-level flag\n * (`createForm({disabled})` / `setDisabled`) into the result's\n * `disabled`. A field cannot opt out of a disabled form.\n */\n disabled?: boolean;\n /**\n * Uncontrolled mode: the field never subscribes to its own value, so\n * typing re-renders nothing — the store still carries every write\n * (getValues/submit/validation read it), and errors/touched/disabled/\n * validating still re-render the field like react-hook-form's\n * `register`. The result's `value` is the mount-time snapshot (initial\n * value seed or baseline); reset/setInitialValues do not push into it\n * or into the DOM — read live values with useValue/getValues instead.\n * Attach the result with `<input defaultValue={field.value}>`-style\n * binding (no `value` prop), exactly like <Field uncontrolled /> does.\n */\n uncontrolled?: boolean;\n /**\n * Field-level validation mode override: when given, this field validates\n * on its own schedule instead of `form.mode` — every other field keeps\n * the form-level timing (e.g. a form that defaults to `'onSubmit'` with\n * one field declared `'onBlur'` shows that field's error on blur while\n * the rest wait for submit). `reValidateMode` stays form-level: once any\n * field has an error (after a failed submit, say), re-validation follows\n * the form's `reValidateMode` for every field, overriding this one too.\n * See {@link ValidationMode}.\n */\n mode?: ValidationMode;\n /**\n * Field paths whose **user changes re-run this field's validator** —\n * the field-level counterpart of the form-level `validateDeps` option\n * (cross-field linkage: `password` changed → re-check\n * `passwordConfirm`). TanStack Form's `onChangeListenTo` / RHF trigger\n * chains are the ecosystem analogues.\n *\n * The re-run rides the changed field's own onChange pipeline, so typing\n * and `changeValue` both fire it while programmatic `setValue` does\n * not, and its timing is gated by the same mode matrix as the form\n * level: the changed field's effective `mode` (per-field override\n * included) and the form's `reValidateMode` — under the default\n * `'onSubmit'`/`'onChange'` pair, a dep change re-validates this field\n * once this field already shows an error (the submit-then-fix flow: the\n * mismatch lands on submit, editing the password re-checks the confirm\n * and a passing round clears the error, because a field validator owns\n * its whole key).\n *\n * `validateDebounce` applies to the re-run like to any kick. Declaring\n * the field's own path is a no-op (its own change already validates it).\n */\n validateDeps?: FieldPath<TValues>[];\n};\n\n/**\n * The result of {@link useField}. Deliberately a closed shape: no index\n * signature, so a typo'd property access (`field.vlaue`) is a type error\n * instead of silently reading `undefined`.\n */\nexport type UseFieldResult<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n /** The form instance this field is bound to (explicit prop or context) —\n * handy for consumers that need direct access to the headless API. */\n form: Form<TValues>;\n value: PathValueOf<TValues, TPath>;\n /** Error message string (FieldError#message) for display, or undefined */\n error: string | undefined;\n /** Full FieldError object ({type, message}), or undefined */\n errorObject: FieldError | undefined;\n /** Every error registered for the field, in insertion order — `error`\n * and `errorObject` are its first entry. Empty (and reference-stable)\n * when the field has no errors. */\n errors: FieldError[];\n onChange: (v: any) => void;\n onBlur: () => void;\n name: string;\n /** Merged disabled flag: the form-level flag (`createForm({disabled})`\n * toggled by `setDisabled`) OR-ed with this field's own `disabled`\n * option, updated live through the form's event core. */\n disabled: boolean;\n /**\n * Callback ref carrying the focus channel: attach it to your input\n * element (`<input ref={field.focusRef} />`) so `setFocus` and a failed\n * submit's first-error auto-focus (`shouldFocusError`) can focus this\n * headless field — the same 'focusError' wiring `<Field>` performs for\n * its own input. Without it, focus requests aimed at this field are\n * silent no-ops, matching `setFocus`'s contract: focusing a field\n * whose element is not bound neither throws nor focuses anything.\n */\n focusRef: (el: any) => void;\n};\n\n/** Does `rules` declare any constraint? `messages` alone does not\n * validate anything, and a constraint-free object would otherwise compile\n * into a validator that always passes — which would still open debounce\n * windows and hold the validating mark for nothing. */\nfunction hasRuleConstraints(rules: FieldRules): boolean {\n return (\n rules.required !== undefined ||\n rules.min !== undefined ||\n rules.max !== undefined ||\n rules.minLength !== undefined ||\n rules.maxLength !== undefined ||\n rules.pattern !== undefined\n );\n}\n\n/**\n * Compose declarative rules with a user validator: rules run first, then\n * the user's validator (awaited when async), and the results merge into\n * one error list with rules errors ahead. Either side may be absent —\n * the other passes through untouched. Errors are returned as an array (or\n * undefined when both sides pass), which setErrorByPath stores as-is.\n */\nfunction combineRulesAndValidate(\n rules: FieldRules | undefined,\n validate: Validator | undefined\n): Validator | undefined {\n if (!rules || !hasRuleConstraints(rules)) return validate;\n const ruleValidator = rulesToValidator(rules);\n if (!validate) return ruleValidator;\n return (value, meta) => {\n // rulesToValidator's contract is FieldError[] | undefined; the wider\n // Validator union here is only its declared type.\n const ruleErrors = ruleValidator(value, meta) as FieldError[] | undefined;\n const merge = (\n other: string | FieldError | (string | FieldError)[] | undefined\n ): (string | FieldError)[] | undefined => {\n const list: (string | FieldError)[] = [...(ruleErrors ?? [])];\n if (Array.isArray(other)) list.push(...other);\n else if (other) list.push(other);\n return list.length ? list : undefined;\n };\n const result = validate(value, meta);\n return isPromise(result) ? result.then(merge) : merge(result);\n };\n}\n\n/**\n * Render-layer gating for {@link UseFieldOptions}.delayError: hold a newly\n * appearing error back for `delay` ms while the form's error state stays\n * immediate. Only the none → some transition waits — an error that clears\n * inside the window never shows, and once an error is visible, later\n * changes (a new message, entries added or removed) apply immediately.\n * With `delay === undefined` the subscription value passes through\n * untouched: no timers and no state writes, so fields that do not opt in\n * pay nothing beyond the hook calls themselves.\n */\nfunction useDelayedErrors(\n errors: FieldError[],\n delay: number | undefined\n): FieldError[] {\n const [shown, setShown] = useState<FieldError[]>(errors);\n useEffect(() => {\n if (delay === undefined) return;\n // Clearing is always immediate: an error cleared inside the window is\n // cancelled before ever showing, a shown one hides at once (errors is\n // the shared empty constant on this branch).\n if (errors.length === 0) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- 取消窗口是设计行为:清空必须立刻生效\n setShown(errors);\n return;\n }\n // Already showing an error: swaps and list changes apply at once.\n if (shown.length > 0) {\n setShown(errors);\n return;\n }\n // Appearing from none: wait out the window. The cleanup clears the\n // timer when errors change again or the field unmounts.\n const timer = setTimeout(() => setShown(errors), delay);\n return () => clearTimeout(timer);\n }, [errors, delay, shown]);\n return delay === undefined ? errors : shown;\n}\n\n/**\n * Value snapshot for {@link useFieldCore}. Controlled fields subscribe to\n * 'change' at their own path (leaf scope) and track the store live.\n * Uncontrolled fields instead pin the value read at mount: no change\n * subscription, so typing re-renders nothing while the store still carries\n * every write (getValues/submit/validation read it). Errors, touched,\n * disabled and validating stay subscribed, so state-driven re-renders\n * behave like react-hook-form's `register`. The pinned snapshot is\n * deliberately never refreshed — reset/setInitialValues do not push into\n * it (or into a `defaultValue`-bound DOM element).\n */\nfunction useFieldValue(form: Form, path: Path, uncontrolled: boolean): any {\n const snapshotRef = useRef<{has: boolean; value: any}>({\n has: false,\n value: undefined\n });\n const getter = useCallback(() => {\n if (!uncontrolled) return getValueByPath(form, path);\n if (!snapshotRef.current.has) {\n snapshotRef.current = {has: true, value: getValueByPath(form, path)};\n }\n return snapshotRef.current.value;\n }, [uncontrolled, form, path]);\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n uncontrolled\n ? () => {}\n : onPathEvent(form.emitter, 'change', path, 'leaf', invalidate),\n [uncontrolled, form.emitter, path]\n );\n return useWatchCore(subscribeFactory, getter);\n}\n\n/**\n * Shared core of {@link useField} and the per-instance hooks returned by\n * `createFormContext()`: identical behavior, but the form is resolved from\n * whichever Context instance is passed in instead of the module-level one.\n *\n * `form` is always handed to `useValidate` explicitly, and an explicit form\n * wins over `useValidate`'s own context read — so scoped contexts need no\n * changes there.\n */\nexport function useFieldCore<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>(\n {\n form: f1,\n name,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateDeps,\n delayError,\n disabled,\n uncontrolled,\n mode: modeOption\n }: UseFieldOptions<TValues, TPath>,\n Context: Context<Form<any> | null>\n): UseFieldResult<TValues, TPath> {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = f1 || contextForm;\n if (!form) throw new Error('no form provided');\n const path = usePath(name);\n\n // Seed initialValue during render, not in an effect: the first paint\n // (SSR included — effects never run on the server) must already carry\n // the value, so the write lands here — before the value subscription\n // below takes its first snapshot. The write is emit-free (see\n // seedValueByPath) because emitting while rendering is illegal; the\n // post-commit effect announces it. The `=== undefined` guard keeps user\n // input and committed values safe across re-renders and remounts.\n const seededRef = useRef(false);\n const seeded =\n initialValue !== undefined && getValueByPath(form, path) === undefined;\n if (seeded) {\n seedValueByPath(form, path, initialValue);\n // Sticky until the announce effect consumes it, so StrictMode's second\n // render (which sees the value already seeded) still announces once.\n seededRef.current = true;\n }\n useEffect(() => {\n // Dep-less on purpose: the seed can land on a later render too (a\n // setInitialValues/reset wiped it; the guard re-seeds), and the\n // announcement must follow every actual seed. The flag makes the\n // steady state a cheap check.\n if (!seededRef.current) return;\n seededRef.current = false;\n // Wake path-scoped subscribers that rendered before this field in an\n // earlier commit — their snapshots predate the seed. Same-commit\n // subscribers self-heal through useSyncExternalStore's post-subscribe\n // snapshot check, and subscribers that already saw the seeded value\n // re-read an unchanged snapshot and bail out.\n emitChangeByPath(form, path);\n });\n\n // Undeclared options are dropped on purpose: the return value carries\n // only the fields declared on UseFieldResult, so nothing rides it back\n // onto DOM elements through a component's prop spread.\n //\n // `required` splits off into useValidate's synchronous gate: it runs\n // immediately on every kick (never debounced) and, while it fails, the\n // debounced validator is skipped — the other rules and `validate` never\n // see an empty value. The remaining rules still compose with `validate`\n // inside the debounced validator.\n const restRules: FieldRules | undefined = rules\n ? {...rules, required: undefined}\n : undefined;\n useValidate(combineRulesAndValidate(restRules, validate), path, form, {\n debounce: validateDebounce,\n sync:\n rules && rules.required !== undefined\n ? rulesToValidator({required: rules.required})\n : undefined\n });\n\n // All errors of the field through one subscription; the array reference\n // is stable (stored array or shared empty constant), so consumers can\n // memo on it. delayError gates only this render-layer view of the list;\n // the stored list keeps driving the reValidateMode kicks inside the\n // core's user-change gate.\n const liveErrors = useFieldErrorsByPath(form, path);\n const errors = useDelayedErrors(liveErrors, delayError);\n const errorObject = errors[0];\n const error = errorObject?.message;\n const value = useFieldValue(form, path, !!uncontrolled);\n\n // The form-level disabled flag, subscribed so setDisabled re-renders\n // this field; the field's own option is OR-ed in on every render.\n const formDisabled = useWatch(form, 'disabled', () => form.disabled);\n\n // The user-change pipeline lives in the core: onChange forwards to\n // userChangeByPath (write + mode/reValidateMode-gated validation, the\n // matrix registered below through registerFieldMode), onBlur to\n // userBlur (touched marking + blur-side gate). The stage keeps the\n // handler identities stable across re-renders.\n const onChange = useStageFn((v: any) => userChangeByPath(form, path, v));\n const onBlur = useStageFn(() => userBlur(form, path));\n\n // Register this field's validation-mode override so path-based\n // user-change writes (changeValue / changeValueByPath) route through\n // the same gated core pipeline as a user typing into the field.\n // Two fields mounted at the same path compete for the slot last-wins:\n // from here on every user-change write gates on the latest mount's\n // mode. That is almost always a bug (a stray duplicate name, a remount\n // racing the old instance) — say so in DEV.\n useEffect(() => {\n const {token, displaced} = registerFieldMode(form, path, modeOption);\n if (__DEV__ && displaced) {\n // eslint-disable-next-line no-console -- the whole point of this branch\n console.warn(\n `react-f0rm: two fields are mounted at the same path ${path.key}. ` +\n `The latest mount's mode registration owns the slot, so changeValue ` +\n `writes gate on it and the earlier field's validation mode no ` +\n `longer applies. Use distinct names if both must stay mounted.`\n );\n }\n return () => unregisterFieldMode(form, path, token);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath memoizes the Path per key, so re-registering on key (not object identity) is enough\n }, [form, path.key, modeOption]);\n\n // Publish this field's validateDeps declaration so the dep fields'\n // change pipelines can find it (revalidateDependentsOnChange). Keyed on\n // the serialized dep list, so a re-render passing an equal inline array\n // does not churn the registry; a genuinely changed list re-registers.\n const depsKey = validateDeps?.length ? validateDeps.join('\\n') : undefined;\n useEffect(() => {\n if (!depsKey) return;\n const depKeys = validateDeps!.map(dep => createPath(dep).key);\n registerFieldValidateDeps(form, path.key, depKeys);\n return () => unregisterFieldValidateDeps(form, path.key, depKeys);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `depsKey` on purpose: depKeys derive from the same option value the key serializes\n }, [form, path.key, depsKey]);\n\n // The focus channel. 'focusError' carries the target's path key —\n // emitted by handleSubmit's failed round (the first error's key, gated\n // by shouldFocusError) and by setFocus (with an optional\n // {shouldSelect} second argument). Subscribing here rather than inside\n // <Field> means headless useField consumers get focus support by\n // attaching focusRef; <Field> merely forwards it through its merged\n // ref. The callback ref is identity-stable, so re-renders never detach\n // the element, and the null guard keeps unbound fields silent no-ops.\n const elementRef = useRef<any>(null);\n const focusRef = useCallback((el: any) => {\n elementRef.current = el;\n }, []);\n useEffect(\n () =>\n on(\n form.emitter,\n 'focusError',\n (key: string, options?: {shouldSelect?: boolean}) => {\n if (key !== path.key) return;\n const el = elementRef.current;\n if (!el || typeof el.focus !== 'function') return;\n el.focus();\n if (options?.shouldSelect && typeof el.select === 'function') {\n el.select();\n }\n }\n ),\n [form, path.key]\n );\n\n useEffect(\n () => () => {\n // Effective unmount behavior: the field's own option, falling back\n // to the form-level default, then to this library's historical\n // default (tombstone).\n if ((shouldUnregister ?? form.shouldUnregister) !== false) {\n removeFieldByPath(form, path);\n }\n },\n [path, form, shouldUnregister]\n );\n\n return {\n form,\n value,\n error,\n errorObject,\n errors,\n onChange,\n onBlur,\n name: path.key,\n disabled: formDisabled || !!disabled,\n focusRef\n };\n}\n\nexport default function useField<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>(options: UseFieldOptions<TValues, TPath>): UseFieldResult<TValues, TPath> {\n return useFieldCore(options, FormContext);\n}\n","import {useContext, useEffect, useRef} from 'react';\nimport {FormContext} from '../context';\nimport {registerValidatorByPath} from '../form';\nimport type {Form, SyncValidator, Validator} from '../form';\nimport type {Path} from '../path';\nimport {useStageFn} from './stage';\n\n// The validator contract itself is framework-free and lives in the core\n// (`src/form.ts`); re-exported here so historical imports keep working.\nexport type {SyncValidator, Validator};\n\n/**\n * Options for {@link useValidate} — the React-side registration of a field\n * validator. The registration machinery (debounce window, async-round\n * lock, signal abort, validating mark) lives in the core's\n * {@link registerValidatorByPath}; this hook only wires its React\n * lifecycle around it: register on mount, dispose on unmount, and read\n * the validator/debounce/sync-gate live through refs so re-renders never\n * re-subscribe the registration mid-flight.\n */\nexport type UseValidateOptions = {\n /**\n * Delay in milliseconds before a validation kick actually runs the\n * debounced validator. `0` (default) runs immediately; a positive value\n * debounces rapid kicks (e.g. typing) so only the last one executes.\n * While the timer is pending the field counts as validating, so\n * `trigger` / `ensureValidate` wait out the window. The `sync`\n * pre-validator is exempt: it runs immediately on every kick and never\n * waits out the window.\n */\n debounce?: number;\n /**\n * Synchronous pre-validator run immediately on every kick — never\n * debounced. While it returns errors, the debounced `validate` is\n * skipped for that kick (its errors land and the expensive check never\n * runs), and any pending debounce window or in-flight round is\n * superseded. When it passes, a stale error it produced earlier clears\n * at once, and a registration with no `validate` treats the passing\n * check as the whole round and clears the field's errors.\n */\n sync?: SyncValidator;\n};\n\n/**\n * Register a field validator with the form and return its kick — a stable\n * function that validates the field's current value (debounce and sync\n * gate applied). The returned function is the one stored in\n * `form.validators`; `trigger`/`ensureValidate` run every stored kick,\n * and the field's user-change gate runs the changed path's kick. This is\n * the old \"useValidate\" behavior — the same public shape with the\n * machinery moved into the core, so non-React adapters can register\n * validators directly through `registerValidatorByPath`.\n */\nexport default function useValidate(\n validate: Validator | undefined,\n path: Path,\n formProp?: Form,\n options?: UseValidateOptions\n): () => void {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(FormContext);\n const form = formProp || contextForm;\n if (!form) throw new Error('no form provided');\n // Live accessors: the registration must always see the latest\n // validator/debounce/sync-gate, so swapping them per render (inline\n // validators, recompiled rules) never re-subscribes the registration\n // mid-flight.\n const validateRef = useRef(validate);\n validateRef.current = validate;\n const debounceRef = useRef(options?.debounce ?? 0);\n debounceRef.current = options?.debounce ?? 0;\n const syncRef = useRef(options?.sync);\n syncRef.current = options?.sync;\n\n useEffect(\n () =>\n registerValidatorByPath(form, path, {\n validate: () => validateRef.current,\n debounce: () => debounceRef.current,\n sync: () => syncRef.current\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath returns a stable Path per key, so re-subscribing on key (not object identity) is enough\n [form, path.key]\n );\n\n return useStageFn(() => form.validators.get(path.key)?.());\n}\n","import {useCallback, useContext, useEffect, useReducer, useRef} from 'react';\nimport type {Context} from 'react';\nimport {FormContext} from '../context';\nimport {getValueByPath, setValueByPath} from '../form';\nimport type {FieldError, Form, Name} from '../form';\nimport {onPathEvent} from '../subscribe';\nimport {useFieldErrorsByPath} from './form';\nimport usePath from './path';\nimport useStage, {useStageFn} from './stage';\n\n/** Per-form row-id counter. A module-level counter would grow across\n * every form on the page — and, on the server, across requests (ids like\n * `_4701` after a day of SSR). Keyed weakly so it dies with the form. */\nconst idCounters = new WeakMap<Form, number>();\n\nfunction generateId(form: Form): string {\n const next = (idCounters.get(form) ?? 0) + 1;\n idCounters.set(form, next);\n return `_${next}`;\n}\n\n/**\n * Live `id -> index` tables shared between {@link useFieldArray} and\n * {@link useFieldArrayItem}: one ids array per (form, array key), keyed\n * weakly so it dies with the form. The array is the hook's own `idsRef`\n * reference (mutated in place by the movers), so items always read the\n * latest order without owning a subscription of their own.\n */\nconst arrayIdsRegistry = new WeakMap<Form, Map<string, string[]>>();\n\nfunction getArrayIds(form: Form, key: string): string[] | undefined {\n return arrayIdsRegistry.get(form)?.get(key);\n}\n\nfunction registerArrayIds(form: Form, key: string, ids: string[]): void {\n let registry = arrayIdsRegistry.get(form);\n if (!registry) {\n registry = new Map();\n arrayIdsRegistry.set(form, registry);\n }\n registry.set(key, ids);\n}\n\n/** Stable identity for the render-count reducer below: never recreated,\n * so the dispatch path stays referentially clean. */\nfunction bumpReducer(count: number): number {\n return count + 1;\n}\n\ntype FieldArrayItem = {id: string; index: number};\n\nexport type UseFieldArrayResult = {\n fields: FieldArrayItem[];\n append: (value: any) => void;\n prepend: (value: any) => void;\n insert: (index: number, value: any) => void;\n remove: (index: number) => void;\n swap: (from: number, to: number) => void;\n move: (from: number, to: number) => void;\n replace: (values: any[]) => void;\n update: (index: number, value: any) => void;\n};\n\n/**\n * Shared core of {@link useFieldArray} and the per-instance hook returned by\n * `createFormContext()`: identical behavior, but the form is resolved from\n * whichever Context instance is passed in instead of the module-level one.\n */\nexport function useFieldArrayCore(\n options: {name: Name; form?: Form},\n Context: Context<Form<any> | null>\n): UseFieldArrayResult {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = options.form || contextForm;\n if (!form) throw new Error('no form provided');\n const path = usePath(options.name);\n const idsRef = useRef<string[]>([]);\n\n const getArray = useCallback(\n (): any[] => getValueByPath(form, path) || [],\n [form, path]\n );\n\n const setArray = useCallback(\n (arr: any[]) => {\n setValueByPath(form, path, arr);\n },\n [form, path]\n );\n\n const computeFields = useCallback(() => {\n const arr = getArray();\n while (idsRef.current.length < arr.length) {\n idsRef.current.push(generateId(form));\n }\n while (idsRef.current.length > arr.length) {\n idsRef.current.pop();\n }\n return idsRef.current.map((id, index) => ({id, index}));\n }, [getArray, form]);\n\n // Subscribe to 'change' events scoped to this array's branch: the array\n // key itself, its ancestors (an ancestor write replaces what the leaf\n // read falls back to) and its descendants (item edits), so typing into\n // unrelated fields does not re-render the array component. Payload-less\n // 'change' emits (reset, setInitialValues) always sync, and a field\n // unmounting inside the branch fires through the descendant match. The\n // comma-separated key prefix comparison lives in onPathEvent,\n // which keeps lookalike sibling keys ('[\"tagsX\"]') from matching.\n const [fields, syncFields] = useReducer(\n computeFields,\n undefined,\n computeFields\n );\n useEffect(\n () => onPathEvent(form.emitter, 'change', path, 'branch', syncFields),\n [form.emitter, path]\n );\n\n // Publish the live ids array so per-item hooks (useFieldArrayItem) can\n // resolve id -> index. Registered during render — not only in an effect —\n // so items rendered in the same first paint, and on the server, already\n // resolve; the set is idempotent (same reference every render, the\n // movers mutate it in place, `replace` swaps it and the next render\n // re-registers). The effect mirrors the registration because StrictMode\n // exercises the cleanup path on mount (unsubscribe, un-register, re-run)\n // without a fresh render in between — without it the table would stay\n // empty and every item would resolve to -1. Unmount drops the entry\n // only while this hook still owns it; a second useFieldArray at the\n // same path competes for the slot last-wins, same as the field-mode\n // registration in useField.\n registerArrayIds(form, path.key, idsRef.current);\n useEffect(() => {\n registerArrayIds(form, path.key, idsRef.current);\n return () => {\n const registry = arrayIdsRegistry.get(form);\n if (registry?.get(path.key) === idsRef.current) registry.delete(path.key);\n };\n }, [form, path.key]);\n\n const append = useStageFn((value: any) => {\n const arr = getArray();\n idsRef.current.push(generateId(form));\n setArray([...arr, value]);\n });\n\n const prepend = useStageFn((value: any) => {\n const arr = getArray();\n idsRef.current.unshift(generateId(form));\n setArray([value, ...arr]);\n });\n\n const insert = useStageFn((index: number, value: any) => {\n const arr = getArray();\n idsRef.current.splice(index, 0, generateId(form));\n const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];\n setArray(newArr);\n });\n\n const remove = useStageFn((index: number) => {\n const arr = getArray();\n idsRef.current.splice(index, 1);\n const newArr = arr.filter((_: any, i: number) => i !== index);\n setArray(newArr);\n });\n\n const swap = useStageFn((from: number, to: number) => {\n const arr = getArray();\n [idsRef.current[from], idsRef.current[to]] = [\n idsRef.current[to],\n idsRef.current[from]\n ];\n const newArr = [...arr];\n [newArr[from], newArr[to]] = [newArr[to], newArr[from]];\n setArray(newArr);\n });\n\n const move = useStageFn((from: number, to: number) => {\n const arr = getArray();\n const [id] = idsRef.current.splice(from, 1);\n idsRef.current.splice(to, 0, id);\n const newArr = [...arr];\n const [item] = newArr.splice(from, 1);\n newArr.splice(to, 0, item);\n setArray(newArr);\n });\n\n // replace is a full swap (length may change), so every row is conceptually\n // a new row: regenerate all ids to remount them, mirroring how reset works.\n const replace = useStageFn((values: any[]) => {\n idsRef.current = values.map(() => generateId(form));\n setArray([...values]);\n });\n\n // update only overwrites one value, so the id at that index is kept and the\n // row does not remount. Out-of-bounds indices are a silent no-op — plain\n // assignment would instead punch sparse-array holes into the form state.\n const update = useStageFn((index: number, value: any) => {\n const arr = getArray();\n if (index < 0 || index >= arr.length) return;\n const newArr = [...arr];\n newArr[index] = value;\n setArray(newArr);\n });\n\n return {fields, append, prepend, insert, remove, swap, move, replace, update};\n}\n\nexport default function useFieldArray(options: {\n name: Name;\n form?: Form;\n}): UseFieldArrayResult {\n return useFieldArrayCore(options, FormContext);\n}\n\n/**\n * The result of {@link useFieldArrayItem}. Mirrors the {@link useField}\n * return shape (`value`/`errors`/`error`) plus the row's `index` and\n * `name` (path key) so nested fields can build on it —\n * `useField({name: ['tags', item.index, 'label']})`.\n */\nexport type UseFieldArrayItemResult<TValue = any> = {\n value: TValue;\n /** Overwrite this row's value in place (same array-layer write as\n * `update(index, value)`: the row's id and position are kept). */\n setValue: (value: TValue) => void;\n /** Every error registered for the row's path, insertion order; the\n * shared empty constant while clean, so consumers can memo on it. */\n errors: FieldError[];\n /** First error's message — the display text — or undefined. */\n error: string | undefined;\n /** The row's current path key (JSON-stringified segments, e.g.\n * `[\"tags\",0]`); moves with the row across reorder/remove. */\n name: string;\n /** The row's current position in the array. `-1` while the row is being\n * removed (or when no useFieldArray is mounted at `name`): reads return\n * undefined and nothing writes the dangling path. */\n index: number;\n form: Form;\n};\n\n/**\n * Shared core of {@link useFieldArrayItem} and the per-instance hook\n * returned by `createFormContext()`: identical behavior, but the form is\n * resolved from whichever Context instance is passed in instead of the\n * module-level one.\n */\nexport function useFieldArrayItemCore<TValue = any>(\n options: {name: Name; id: string; form?: Form},\n Context: Context<Form<any> | null>\n): UseFieldArrayItemResult<TValue> {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = options.form || contextForm;\n if (!form) throw new Error('no form provided');\n const {id} = options;\n const arrayPath = usePath(options.name);\n\n // --- snapshots: locate the row by its stable id through the array's\n // published ids table, then read its value from the array layer — the\n // same layer every useFieldArray operation and `setValue` below write,\n // so `value` and update/append/swap/… always agree with each other.\n const computeIndex = useCallback(\n () => getArrayIds(form, arrayPath.key)?.indexOf(id) ?? -1,\n [form, arrayPath.key, id]\n );\n const computeValue = useCallback(\n (index: number) => {\n const arr = getValueByPath(form, arrayPath);\n return Array.isArray(arr) ? arr[index] : undefined;\n },\n [form, arrayPath]\n );\n\n // Both are read synchronously during render (SSR included: no effect is\n // involved), and the last-rendered pair is mirrored into refs for the\n // subscription below. Writing own refs during render follows the same\n // pattern as `useStage`.\n const index = computeIndex();\n const value = computeValue(index) as TValue;\n const lastRef = useRef({index, value});\n lastRef.current = {index, value};\n\n // A render is scheduled only when the row's own view would change. The\n // subscription is 'leaf'-scoped on the array key: every useFieldArray\n // operation rewrites that key (payload-less broadcasts — reset,\n // setInitialValues — always fire), so this fires exactly when the row\n // order or the array can have moved, while a write to one item's leaf\n // path (`['tags', 1]`) never fires it. The comparison happens in the\n // listener — not through React's equal-state bailout, which act/test\n // environments do not honor — so an unchanged row never dispatches at\n // all and its component function never runs: append, update and\n // single-row edits leave untouched rows completely quiet, and a\n // whole-array rewrite re-renders only rows whose value reference (or\n // index) actually changed — the shallow copies keep untouched items'\n // references stable. Rows whose index migrates (remove/move/swap/\n // insert) re-render by design; computing `next` with the fresh index\n // means a row that moved but kept its value still bumps.\n const computeRef = useStage({computeIndex, computeValue});\n const [, bump] = useReducer(bumpReducer, 0);\n useEffect(\n () =>\n onPathEvent(form.emitter, 'change', arrayPath, 'leaf', () => {\n const {computeIndex: idx, computeValue: val} = computeRef.current;\n const nextIndex = idx();\n if (\n nextIndex !== lastRef.current.index ||\n !Object.is(val(nextIndex), lastRef.current.value)\n )\n bump();\n }),\n [form.emitter, arrayPath, computeRef]\n );\n\n // --- errors: stored per exact key, so this is the one place the row's\n // indexed path is needed. A removed row resolves to index -1: the\n // parent is about to unmount this component (its key left `fields`),\n // and until that commit lands the dangling key is inert — reads return\n // undefined/no errors and the `setValue` guard refuses to write. -1\n // also surfaces when no useFieldArray is mounted at `name`; pairing\n // the two hooks is the documented contract.\n const itemPath = usePath([...arrayPath.value, index]);\n const errors = useFieldErrorsByPath(form, itemPath);\n\n const setValue = useStageFn((v: TValue) => {\n if (index < 0) return;\n const arr = [...(getValueByPath(form, arrayPath) ?? [])];\n if (index >= arr.length) return;\n arr[index] = v;\n setValueByPath(form, arrayPath, arr);\n });\n\n return {\n value,\n setValue,\n errors,\n error: errors[0]?.message,\n name: itemPath.key,\n index,\n form\n };\n}\n\n/**\n * Subscribe to a single row of a {@link useFieldArray} field — the\n * per-item counterpart `useFieldArray` alone cannot offer. `useFieldArray`\n * subscribes to the whole branch, so any row's edit re-renders the\n * component holding the array (and, without memoization, every row);\n * `useFieldArrayItem` scopes what re-renders to one row identified by its\n * stable id: editing row K re-renders only row K's component, and a\n * whole-array rewrite re-renders only rows whose value reference actually\n * changed. Pair it with a `React.memo` row component that takes stable\n * props (`form`, `id`) so the array component's own re-render cannot drag\n * the rows along.\n *\n * Rows whose index migrates — remove/move/swap/insert reshuffles —\n * re-render by design: the row's path contains the index, exactly like\n * TanStack Form's per-field api. The win is single-row edits staying\n * single-row.\n *\n * Value reads and writes live on the array layer — the same layer every\n * `useFieldArray` operation touches — so `value`, `setValue` and\n * `update`/`append`/… always agree with each other.\n *\n * @param options `name` of the array (a useFieldArray must be mounted at\n * the same path — it publishes the id table), the row's `id` from\n * `fields[i].id`, and optionally an explicit `form`\n */\nexport function useFieldArrayItem<TValue = any>(options: {\n name: Name;\n id: string;\n form?: Form;\n}): UseFieldArrayItemResult<TValue> {\n return useFieldArrayItemCore(options, FormContext);\n}\n","import {createContext, createElement, useContext, type ReactNode} from 'react';\nimport {\n useFieldCore,\n type UseFieldOptions,\n type UseFieldResult\n} from './hooks/field';\nimport {\n useFieldArrayCore,\n useFieldArrayItemCore,\n type UseFieldArrayResult,\n type UseFieldArrayItemResult\n} from './hooks/fieldArray';\nimport type {Form} from './form';\nimport type {Name, PathSegments} from './path';\nimport type {FieldPath} from './types';\n\nexport const FormContext = createContext<Form<any> | null>(null);\n\nexport const FormProvider = FormContext.Provider;\n\n/**\n * Read the form from the module-level {@link FormContext}. Pass the values\n * shape — `useFormContext<Values>()` — to get a fully typed `Form<Values>`\n * headless API; the `any` default keeps untyped call sites compiling.\n *\n * For multiple forms in one subtree use {@link createFormContext} instead.\n *\n * @throws when no `<FormProvider>` is mounted above the call site.\n */\nexport function useFormContext<T extends Record<string, any> = any>(): Form<T> {\n const form = useContext(FormContext);\n if (!form) throw new Error('no form provided');\n return form;\n}\n\n/**\n * Create an isolated bundle of form-context bindings: its own React context\n * plus `useField` / `useFieldArray` / `useFieldArrayItem` /\n * `useFormContext` hooks that resolve their form from it.\n *\n * Why: the module-level {@link FormContext} works fine for a single form per\n * subtree, but nesting two forms (or reusing a component inside a different\n * form) makes them fight over one context. Calling this factory once per app\n * area — `const Ctx = createFormContext<Values>()` — fixes the value shape\n * (`Ctx.useField({name: 'user.name'})` gets its `name` constrained by\n * `FieldPath<Values>` and its `value` typed accordingly), so call sites stop\n * hand-writing generics, and each instance's Provider scopes a strictly\n * separate form. The bundle also carries its raw React context\n * (`Ctx.context`) so `<Form context={Ctx.context}>` can provide into it.\n */\nexport function createFormContext<TValues extends Record<string, any> = any>() {\n const Context = createContext<Form<TValues> | null>(null);\n\n // A `form`-prop wrapper instead of exposing Context.Provider directly:\n // callers shouldn't have to know about the raw `value` prop shape.\n function FormProvider({\n form,\n children\n }: {\n form: Form<TValues>;\n children: ReactNode;\n }): ReactNode {\n return createElement(Context.Provider, {value: form}, children);\n }\n\n function useFormContext(): Form<TValues> {\n const form = useContext(Context);\n if (!form) throw new Error('no form provided');\n return form;\n }\n\n function useField<\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n // The bare `{name: TPath}` member keeps `name` a direct inference site\n // for TPath instead of routing it through the mapped Omit type.\n // `form` is omitted on purpose — the form always comes from this\n // factory's own Context.\n options: {name: TPath} & Omit<UseFieldOptions<TValues, TPath>, 'form'>\n ): UseFieldResult<TValues, TPath> {\n return useFieldCore(options as UseFieldOptions<TValues, TPath>, Context);\n }\n\n function useFieldArray(options: {\n name: FieldPath<TValues> | Name;\n }): UseFieldArrayResult {\n return useFieldArrayCore(options as {name: Name}, Context);\n }\n\n function useFieldArrayItem<TValue = any>(options: {\n name: FieldPath<TValues> | Name;\n id: string;\n }): UseFieldArrayItemResult<TValue> {\n return useFieldArrayItemCore(options as {name: Name; id: string}, Context);\n }\n\n // The raw React context, for `<Form context={...}>`: the component keeps\n // its submit machinery while providing into this instance's private\n // context, so the bound hooks above resolve the form it manages.\n return {\n context: Context,\n FormProvider,\n useFormContext,\n useField,\n useFieldArray,\n useFieldArrayItem\n };\n}\n\nexport const CheckboxGroupContext = createContext<any>(null);\n\nexport const CheckboxGroupProvider = CheckboxGroupContext.Provider;\n\nexport function useCheckboxGroupContext(): any {\n const group = useContext(CheckboxGroupContext);\n if (!group) throw new Error('no group provided');\n return group;\n}\n","/**\n * Server-side validation entry — `react-f0rm/server`.\n *\n * The core (`./form`) is pure TypeScript with zero React imports, so it\n * already runs anywhere Node does; what the server lacked is an entry\n * that never pulls React into the module graph at all — the main entry\n * re-exports the hooks/components, and a Server Action or RSC that only\n * wants to check a payload should not have to depend on them. This module\n * is that entry: values in, one whole-form validation round, structured\n * result out.\n *\n * It plays the role TanStack Form gives `createServerValidate`, minus the\n * action prop: their API wraps validation inside a generated server\n * action, while react-f0rm keeps the values store the single source of\n * truth — {@link validateValues} is a plain function over values (the\n * same contract the client-side `trigger` has over a form instance), so\n * it composes into any server framework's handler instead of owning it.\n *\n * Like the resolvers and devtools it is intentionally NOT re-exported\n * from the main entry: importing `react-f0rm/server` is the only way this\n * code reaches a bundle, so client builds that never validate on the\n * server stay at baseline size.\n */\nimport createForm, {getErrors, getValues, trigger} from './form';\nimport type {FieldErrorEntry, Options, ValidationOutcome} from './form';\n\n// Building a branded ValidationOutcome server-side (schema adapters, or a\n// hand-written validate that returns parsed values) needs the brand symbol\n// itself; importing it from the package root would drag the React graph\n// back in, so it is re-exported here together with its result type.\nexport {VALIDATION_OUTCOME} from './form';\nexport type {ValidationOutcome};\n\n/** The outcome of {@link validateValues}: the error-free flag, the values\n * once the round has landed (schema-coerced where the validator produced\n * parsed values), and every error the round wrote as flat entries. */\nexport type ValidateValuesResult<T extends Record<string, any> = any> = {\n /** Whether the round landed no errors — `trigger`'s boolean. An invalid\n * payload is a normal outcome, never a rejection: unlike\n * `ensureValidate`, server callers learn validity from data instead of\n * catching, because both branches are interesting on the server\n * (persist vs. bounce back to the client). */\n valid: boolean;\n /** The values after the round. When the validator returned a branded\n * {@link ValidationOutcome} with `values`, those parsed values are the\n * baseline `getValues` layers over the input — schema coerce/transform\n * output included — so this is the tree to persist or feed onward, not\n * necessarily the object passed in. Deep-equals the input otherwise. */\n values: T;\n /** Every error the round landed, flattened to `{path, type, message}`\n * entries — the same list {@link getErrors} hands out on the client.\n * Feed it to `setServerErrors` to land a failed round back on the\n * client form (the Server Actions bridge; see the docs' Server Actions\n * guide). */\n errors: FieldErrorEntry[];\n};\n\n/** Append one value under `key` into `fd`. Arrays and FileLists flatten\n * to one entry per item (FormData's multi-entry convention); Files keep\n * their name; Dates become ISO strings; other objects JSON.stringify;\n * booleans/numbers/strings String() as a native form submit would. */\nfunction appendFormDataValue(fd: FormData, key: string, value: any): void {\n if (value == null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendFormDataValue(fd, key, item);\n return;\n }\n if (typeof FileList !== 'undefined' && value instanceof FileList) {\n for (let i = 0; i < value.length; i++) fd.append(key, value.item(i)!);\n return;\n }\n if (typeof File !== 'undefined' && value instanceof File) {\n fd.append(key, value, value.name);\n return;\n }\n if (typeof Blob !== 'undefined' && value instanceof Blob) {\n fd.append(key, value);\n return;\n }\n if (value instanceof Date) {\n fd.append(key, value.toISOString());\n return;\n }\n fd.append(\n key,\n typeof value === 'object' ? JSON.stringify(value) : String(value)\n );\n}\n\n/**\n * Convert a values object into FormData — the transport shape React 19\n * Server Actions and multipart handlers expect. Built to pair with the\n * `<Form action>` prop and `validateValues`: the validated (schema-coerced)\n * values tree lands in the server action as FormData, files included.\n *\n * Array values become multiple entries under the same key (FormData's\n * native multi-value convention); File values keep their name; Dates\n * become ISO strings; plain objects JSON.stringify; null/undefined are\n * skipped.\n */\nexport function formDataFromValues(values: Record<string, any>): FormData {\n const fd = new FormData();\n for (const key of Object.keys(values)) {\n appendFormDataValue(fd, key, values[key]);\n }\n return fd;\n}\n\n/**\n * Validate a payload of values on the server — no form instance, no\n * React.\n *\n * Spins up a throwaway form from `options` (with `initialValues` forced\n * to `values`), runs one whole-form `trigger`, and reads the outcome\n * back. `trigger` never rejects and waits out async validators and any\n * `validateDebounce` window, so a single `await` drains the whole round —\n * the returned `valid`/`errors` are final, not a snapshot mid-flight.\n *\n * Validation comes from `options.validate` — the form-level validator.\n * Field validators register through mounted fields (`useField`), and\n * nothing is mounted on the server, so they cannot participate by\n * construction; pass a schema-backed form validator\n * (`standardSchemaFormValidator(schema)` from\n * `react-f0rm/resolvers/standard-schema`) or a hand-written `validate`\n * instead. `mode`/`reValidateMode` are equally inert here — there are no\n * field events to gate — and may be omitted.\n *\n * When the validator returns a branded {@link ValidationOutcome} whose\n * `values` carry the schema's output, those parsed values become the\n * form's parsedValues baseline, so `result.values` flows coercion and\n * transforms forward (`z.coerce.number()` turning `'42'` into `42`, and\n * friends). Persist that tree; on the client the same schema round runs\n * again on submit, keeping one validation source across the boundary.\n *\n * Safe to call from Node, Server Actions and RSC — the module graph is\n * this file plus the pure core, zero React.\n *\n * @param values the payload to validate; becomes the form's initialValues\n * @param options form options; `validate` is where the rules come from\n * @return the settled round: `valid`, the (possibly parsed) values, and\n * the flat error entries\n */\nexport async function validateValues<T extends Record<string, any> = any>(\n values: T,\n options?: Options<T>\n): Promise<ValidateValuesResult<T>> {\n const form = createForm({...options, initialValues: values});\n const valid = await trigger(form);\n return {valid, values: getValues(form), errors: getErrors(form)};\n}\n","import * as React from 'react';\nimport {handleSubmit} from '../form';\n// 别名规避 rollup-plugin-dts 对「type import 与本地 default export 同名」\n// 的 Identifier already declared 误报(类型引用语义不变)。\nimport type {Form as FormApi} from '../form';\nimport {formDataFromValues} from '../server';\nimport {FormContext} from '../context';\nimport useForm from '../hooks/form';\n\n/**\n * Props for <Form>.\n *\n * Native validation behavior: the rendered <form> always sets noValidate,\n * which suppresses the browser's built-in blocked-submit UI. However, native\n * constraint validation still gates submission — the form element's\n * checkValidity() runs before custom validators, and when it fails,\n * reportValidity() surfaces the offending constraints as native bubbles and\n * submission stops (onInvalidSubmit fires). onSubmit/onValidSubmit only run\n * once every native constraint (required, type=email, minLength, ...) passes.\n *\n * The submit flow itself lives in the headless `handleSubmit` (see form.ts);\n * this component is a thin wrapper that binds it to the rendered <form>.\n */\ntype FormProps<T extends Record<string, any> = any> = Omit<\n React.FormHTMLAttributes<HTMLFormElement>,\n 'onSubmit'\n> & {\n form?: FormApi<T>;\n /**\n * Provide into an isolated context from `createFormContext()` instead of\n * the module-level one — `<Form context={ProfileForm.context}>` keeps the\n * component's full submit machinery while the factory's bound hooks\n * (`ProfileForm.useField`, `ProfileForm.useFormContext`, ...) resolve this\n * form from their private context. The module-level `useFormContext()` /\n * `useField` do not see it; that is the point of the isolation. Omitted,\n * the form lands in the module-level FormContext as before.\n */\n context?: React.Context<FormApi<any> | null>;\n /**\n * The values baseline — a sync object, a Promise, or a thunk returning\n * either ({@link Options.initialValues}). Async sources render the form\n * empty and gate on `form.isLoading` until they resolve.\n */\n initialValues?: T | Promise<T> | (() => T | Promise<T>);\n /**\n * Form-level default for a bound field's unmount behavior\n * ({@link Options.shouldUnregister}): `true` (the default) tombstones\n * unmounted fields, `false` keeps their values.\n */\n shouldUnregister?: boolean;\n /**\n * Controlled external values. When the `values` reference changes, the\n * new object is synced into the form (via setInitialValues semantics):\n * uncommitted user edits are discarded -- master-detail semantics, where\n * selecting another record replaces the draft -- while touched flags and\n * errors are kept. Sync is reference-based: re-renders that pass the same\n * `values` reference never clobber what the user is typing.\n */\n values?: T;\n /** May be async — the submit flow awaits it, so form.isSubmitting\n * covers the entire flight. */\n onSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;\n /** May be async, same as onSubmit. */\n onValidSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;\n /**\n * React 19 Server Action target: after validation passes (and after\n * onSubmit/onValidSubmit), the validated, schema-coerced values are\n * converted to FormData ({@link formDataFromValues} — files, arrays and\n * nested objects included) and dispatched to this callback, e.g.\n * `action={createUser}` for a server action or\n * `action={formData => startTransition(() => dispatch(formData))}` in a\n * useActionState bridge. `isSubmitting` covers the whole flight.\n */\n action?: (formData: FormData) => void | Promise<void>;\n /**\n * Called when validation fails.\n * @param errors array of {path, type, message} entries in insertion\n * order; path is the dotted field path ('a.b', 'list.0'), type is\n * the error kind ('custom' for plain string errors, 'native' for\n * failed DOM constraint validation), message is the display text\n * @param values current form values\n */\n onInvalidSubmit?: (\n errors: {path: string; type: string; message: string}[],\n values: T\n ) => void;\n /**\n * Focus the first field with an error after a failed submit: custom\n * validation failures focus the first errored field, native constraint\n * failures focus the first ':invalid' control. Defaults to true; pass\n * false to disable.\n */\n shouldFocusError?: boolean;\n};\n\nexport default function Form<T extends Record<string, any> = any>({\n form: f1,\n context,\n initialValues,\n values,\n shouldUnregister,\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n action,\n shouldFocusError,\n ...props\n}: FormProps<T>) {\n const f2 = useForm<T>({initialValues, values, shouldUnregister});\n const form = f1 || f2;\n\n const submit = handleSubmit(form, {\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n shouldFocusError,\n onAction: action ? values => action(formDataFromValues(values)) : undefined\n });\n\n // Route the form into the caller's isolated context (createFormContext)\n // or the module-level default, whichever Provider we ended up with.\n const {Provider} = context ?? FormContext;\n\n return (\n <Provider value={form}>\n <form {...props} noValidate onSubmit={submit} />\n </Provider>\n );\n}\n","import * as React from 'react';\nimport useField from '../hooks/field';\nimport type {UseFieldOptions, UseFieldResult} from '../hooks/field';\nimport type {FieldPath} from '../types';\nimport type {PathSegments} from '../path';\n\n/**\n * Props for {@link FormField}: every {@link UseFieldOptions} option plus a\n * render-prop `children` receiving the bound field result.\n */\nexport type FormFieldProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n children: (field: UseFieldResult<TValues, TPath>) => React.ReactNode;\n};\n\n/**\n * Headless field bound through a render prop — the non-hook counterpart of\n * {@link useField} for class components, callback-style consumers and\n * library bridges where a hook cannot be called (Formik `<Field>` /\n * TanStack `form.Field` shape).\n *\n * The child function receives the full {@link UseFieldResult} — value,\n * error(s), onChange/onBlur, `disabled`, `focusRef`, the bound `form` —\n * and renders whatever UI it wants; nothing is rendered when it returns\n * null/undefined, so it can also gate conditional layout. Resolves its\n * form from the module-level `FormContext` or the explicit `form` option\n * (per-instance contexts from `createFormContext()` keep using their own\n * `useField` hook).\n */\nexport default function FormField<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>({children, ...options}: FormFieldProps<TValues, TPath>): React.ReactNode {\n const field = useField<TValues, TPath>(options);\n return children(field);\n}\n","import * as React from 'react';\nimport useField from '../hooks/field';\nimport type {Validator} from '../hooks/validate';\nimport type {Form, ValidationMode} from '../form';\nimport type {FieldRules} from '../rules';\nimport type {Name, Path, PathSegments} from '../path';\nimport createPath from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\n\n/**\n * Props shared by Field/Checkbox/Select. Generic so a typed form flows into\n * the `validate` callback: with `form` (a `Form<Values>`) and `name`\n * (a `FieldPath<Values>`) provided, `validate` receives the value at that\n * path — `PathValueOf<Values, P>` — instead of `any`. The defaults keep the\n * bare `<Field name=\"x\" />` (context-resolved, untyped) call sites exactly\n * as permissive as before.\n */\ntype UseFieldOptions<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n form?: Form<TValues>;\n name?: TPath;\n initialValue?: any;\n shouldUnregister?: boolean;\n /**\n * Field-level validator. The value argument is typed when the field is\n * tied to a typed form (via the `form` prop); the return shape mirrors\n * {@link Validator} — an error (string / FieldError / mixed array) or\n * undefined when valid, possibly a Promise for async validation. The\n * second argument carries the validation context (`meta.signal` aborts\n * when the round is superseded).\n */\n validate?: (\n value: PathValueOf<TValues, TPath>,\n meta: {form: Form; path: Path; signal: AbortSignal}\n ) => ReturnType<Validator>;\n /**\n * Declarative rules (required/min/max/minLength/maxLength/pattern),\n * compiled into a validator that runs before `validate`; failures land\n * in the form's error state. Passed through to useField — like\n * validateDebounce it is never spread onto the DOM element.\n */\n rules?: FieldRules;\n /**\n * Milliseconds to debounce this field's validation kicks. Defaults to 0\n * (validate immediately); only the last kick inside the window runs the\n * validator, and `trigger` waits the window out. Passed through to\n * useField/useValidate.\n */\n validateDebounce?: number;\n /**\n * Disable this field's control: OR-ed with the form-level flag\n * (`createForm({disabled})` / `setDisabled`) — a field cannot opt out\n * of a disabled form. Passed through to useField, like every option,\n * never spread onto the DOM element from props.\n */\n disabled?: boolean;\n /**\n * Milliseconds to delay showing a newly appearing error (render layer\n * only — `aria-invalid`/`renderError` wait out the window while the\n * form's error state stays immediate for trigger/submit). An error\n * that clears inside the window never shows; once visible, error\n * changes apply immediately. Passed through to useField.\n */\n delayError?: number;\n /**\n * Field-level validation mode override: this field validates on its own\n * schedule instead of the form's `mode` (other fields are unaffected);\n * the form's `reValidateMode` still governs re-validation once the\n * field has an error. Passed through to useField, never spread onto\n * the DOM element.\n */\n mode?: ValidationMode;\n /**\n * Uncontrolled mode: render the element with `defaultValue` instead of\n * `value` — typing re-renders nothing (the store still carries every\n * write; errors/touched/disabled still re-render the field). The\n * snapshot is pinned at mount; reset does not clear the DOM element\n * (read live values with useValue/getValues). Passed through to\n * useField, never spread onto the DOM element.\n */\n uncontrolled?: boolean;\n [key: string]: any;\n};\n\ntype FieldProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n as?: React.ComponentType<any>;\n asProps?: Record<string, any>;\n eventToValue?: (e: any) => any;\n valueToProps?: (value: any) => Record<string, any>;\n /**\n * Optional error renderer. When provided and the field has an error,\n * Field renders `<span id={id} role=\"alert\">{renderError(error, id)}</span>`\n * next to the input. The input's aria-describedby points at that span's\n * id (the same `fieldErrorId(name)` derivation) whenever the field has\n * an error — with or without renderError — so custom error components\n * that render the element themselves (using `fieldErrorId`) get the\n * wiring for free.\n */\n renderError?: (error: string, id: string) => React.ReactNode;\n};\n\nfunction setRef<T>(ref: React.Ref<T> | undefined, value: T | null) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref) {\n (ref as React.MutableRefObject<T | null>).current = value;\n }\n}\n\n/**\n * Converts a path key (the JSON.stringify'd path segments, e.g. '[\"a\",\"0\"]')\n * into a valid HTML id ('a-0'): quotes, brackets, commas and whitespace\n * become hyphens; leading/trailing hyphens are trimmed. Falls back to\n * 'field' if nothing remains.\n */\nfunction errorIdFromKey(key: string): string {\n const id = key.replace(/[\"'[\\],\\s]+/g, '-').replace(/^-+|-+$/g, '');\n return id || 'field';\n}\n\n/**\n * The aria wiring every bound field shares: `aria-invalid` when the field\n * has an error, and `aria-describedby` pointing at the error-message\n * element id derived from the field key — the same id `fieldErrorId(name)`\n * derives (the key is what useField returns as `name`). User-provided ids\n * survive, joined ahead of the error id.\n */\nfunction ariaProps(\n error: string | undefined,\n fieldKey: string,\n props: Record<string, any>\n) {\n return {\n 'aria-invalid': error ? true : props['aria-invalid'],\n 'aria-describedby': error\n ? [props['aria-describedby'], errorIdFromKey(fieldKey)]\n .filter(Boolean)\n .join(' ')\n : props['aria-describedby']\n };\n}\n\n/**\n * The error-message element id a field's `aria-describedby` points at —\n * `fieldErrorId('a[0].b')` is `'a-0-b'`, the same id `Field`'s built-in\n * `renderError` span carries. This is the library-level wiring convention:\n * whenever a bound field (Field/Checkbox/Select) has an error it sets\n * `aria-invalid` and describes the element with this id, so a custom error\n * component only needs `<span id={fieldErrorId(name)} role=\"alert\">` to\n * complete the accessible-name chain for screen readers.\n * @param name the same field name passed to the bound component\n */\nexport function fieldErrorId(name: Name): string {\n return errorIdFromKey(createPath(name).key);\n}\n\n/**\n * The callable shape of {@link Field}: `form` + `name` flow their generics\n * into `validate`'s value argument (`PathValueOf<TValues, TPath>`). A named\n * interface rather than an inline `as <TValues, ...>() => ...` signature —\n * same types, and the inline form trips no-use-before-define on the type\n * parameters.\n */\ntype FieldComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: FieldProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>\n ): React.ReactElement | null;\n};\n\nexport const Field = React.forwardRef<HTMLInputElement, FieldProps>(\n (\n {\n validate,\n eventToValue,\n initialValue,\n name,\n asProps,\n renderError,\n as,\n valueToProps,\n form: formProp,\n shouldUnregister,\n rules,\n validateDebounce,\n disabled,\n delayError,\n mode,\n uncontrolled,\n ...props\n },\n ref\n ) => {\n const innerRef = React.useRef<HTMLInputElement | null>(null);\n const [nativeInvalidCount, setNativeInvalidCount] = React.useState(0);\n // Only declared options go into the hook; DOM props stay in `props` and\n // are spread onto the element below — useField no longer echoes unknown\n // options back, so `as`/`valueToProps`/DOM props are destructured here\n // instead of being fished out of its result.\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled,\n focusRef\n } = useField({\n name: name!,\n form: formProp,\n initialValue,\n shouldUnregister,\n rules,\n validateDebounce,\n delayError,\n disabled,\n mode,\n // File inputs cannot be value-controlled at all — force the\n // uncontrolled path so no `value` prop ever reaches the element.\n uncontrolled: uncontrolled || props.type === 'file',\n validate: (...params: [any, any]) => {\n const el = innerRef.current;\n if (el && typeof el.checkValidity === 'function') {\n el.setCustomValidity('');\n if (el.checkValidity() === false) {\n setNativeInvalidCount(count => count + 1);\n return undefined;\n }\n }\n if (validate) return validate(...params);\n }\n });\n // One merged ref, three duties: the private innerRef (validate's\n // setCustomValidity above), the focus channel (useField's focusRef —\n // setFocus and a failed submit's shouldFocusError focus through it),\n // and the user's forwarded ref. focusRef is identity-stable, so the\n // deps behave exactly as the previous [ref] did.\n const mergedRef = React.useCallback(\n (node: HTMLInputElement | null) => {\n innerRef.current = node;\n focusRef(node);\n setRef(ref, node);\n },\n [ref, focusRef]\n );\n const Component = as || 'input';\n\n React.useEffect(() => {\n const el = innerRef.current;\n if (!el || typeof el.setCustomValidity !== 'function') return;\n if (typeof error === 'string') {\n el.setCustomValidity(error);\n el.reportValidity();\n } else {\n el.setCustomValidity('');\n }\n }, [error]);\n\n React.useEffect(() => {\n if (nativeInvalidCount > 0) innerRef.current?.reportValidity();\n }, [nativeInvalidCount]);\n\n const isFile = props.type === 'file';\n const toValue =\n eventToValue ??\n (isFile ? (e: any) => e.target.files : (e: any) => e.target.value);\n\n // file inputs never receive a value/defaultValue prop (they cannot be\n // value-controlled); uncontrolled renders defaultValue, controlled\n // renders value.\n const valueProps = valueToProps\n ? valueToProps(value)\n : isFile\n ? {}\n : uncontrolled\n ? {defaultValue: value}\n : {value};\n\n // fieldKey is the field's path key (set by useField), e.g. '[\"a\",\"0\"]'.\n const errorId = errorIdFromKey(fieldKey);\n\n return (\n <>\n <Component\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n {...asProps}\n {...valueProps}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: any) => onChange(toValue(e))}\n ref={mergedRef}\n />\n {error && renderError ? (\n <span id={errorId} role=\"alert\">\n {renderError(error, errorId)}\n </span>\n ) : null}\n </>\n );\n }\n) as FieldComponent;\n\ntype CheckboxProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath>;\n\n/**\n * Callable shape of {@link Checkbox}: the same form-typed `validate`\n * inference contract as {@link FieldComponent}.\n */\ntype CheckboxComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: CheckboxProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>\n ): React.ReactElement | null;\n};\n\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n name,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n disabled,\n delayError,\n mode,\n ...props\n },\n ref\n ) => {\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled\n } = useField({\n name: name!,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n delayError,\n disabled,\n mode\n });\n // Same error-id convention as Field: the checkbox describes the\n // fieldErrorId(name) element whenever it has an error.\n return (\n <input\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n type=\"checkbox\"\n checked={!!value}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n onChange(e.target.checked)\n }\n ref={ref}\n />\n );\n }\n) as CheckboxComponent;\n\ntype SelectProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n multiple?: boolean;\n children?: React.ReactNode;\n};\n\n/**\n * Controlled <select>. Options are passed as children (<option> elements).\n * Single-select stores the selected option's value as a string, matching\n * Field's default event-to-value behavior; a multiple select stores the\n * values of all selected options as a string array.\n */\n/** Normalize a field value for a <select>: multiple wants a string array,\n * single-select wants a string. */\nfunction toSelectValue(\n multiple: boolean | undefined,\n value: any\n): string | string[] {\n if (multiple) return Array.isArray(value) ? value : [];\n return value ?? '';\n}\n\n/**\n * Callable shape of {@link Select}: the same form-typed `validate`\n * inference contract as {@link FieldComponent}.\n */\ntype SelectComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: SelectProps<TValues, TPath> & React.RefAttributes<HTMLSelectElement>\n ): React.ReactElement | null;\n};\n\nexport const Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n (\n {\n name,\n multiple,\n children,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n disabled,\n delayError,\n mode,\n ...props\n },\n ref\n ) => {\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled\n } = useField({\n name: name!,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n delayError,\n disabled,\n mode\n });\n // Same error-id convention as Field: the select describes the\n // fieldErrorId(name) element whenever it has an error.\n return (\n <select\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n multiple={multiple}\n value={toSelectValue(multiple, value)}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>\n onChange(\n multiple\n ? Array.from(e.target.selectedOptions, option => option.value)\n : e.target.value\n )\n }\n ref={ref}\n >\n {children}\n </select>\n );\n }\n) as SelectComponent;\n"],"names":["pathCache","Map","normalizePath","path","Array","isArray","cached","get","value","result","identifier","flushIdentifier","isIndex","dotted","map","String","join","bracket","reduce","acc","seg","TypeError","push","i","length","char","quote","close","indexOf","slice","content","Number","parsePath","size","oldest","keys","next","done","delete","set","segment","test","values","current","p","unset","prop","props","arr","copy","index","setOwned","root","owned","container","parent","parentProp","has","add","isPromise","then","isEqual","a","b","Object","is","Date","getTime","proto","getPrototypeOf","prototype","keysA","keysB","key","waitUntil","emitter","event","isResolve","isReject","Promise","resolve","reject","off","on","create","name","JSON","stringify","valuesCaches","WeakMap","bumpValuesVersion","form","cache","version","dirtyBaselines","getDirtyBaseline","segments","baselines","initialValues","setDirtyBaseline","pruneDirtyBaselines","stem","baselineKey","startsWith","clearDirtyBaselines","clear","dirtyFieldsCaches","bumpDirtyVersion","isSegmentsPath","some","part","isFieldError","type","message","FORM_ERROR","VALIDATION_OUTCOME","getError","getErrorByPath","createPath","errors","NO_ERRORS","getFieldErrors","getFieldErrorsByPath","getErrors","entries","list","parse","getFirstError","setError","error","setErrorByPath","forEach","item","normalizeErrors","emit","clearErrors","paths","one","setServerErrors","options","keepExisting","hasErrors","setTouched","setTouchedByPath","touched","hasTouched","hasTouchedByPath","getTouchedFields","from","isTouched","getValues","computeValues","parsedValues","deleted","Set","merged","getValue","getValueByPath","ancestorKey","setValue","setValueByPath","pruneDescendantKeys","reviveBranch","shouldDirty","shouldTouch","shouldValidate","validators","seedValueByPath","emitChangeByPath","getFieldState","validating","live","isDirty","isValidating","removeField","removeFieldByPath","keepValue","keepDirty","hasLiveBranch","keepTouched","keepError","k","tombstone","setInitialValues","collectValueLeaves","node","out","reset","keptValues","keepValues","keepDirtyValues","keepDefaultValues","keepErrors","keepIsSubmitting","isSubmitting","keepSubmitCount","submitCount","keepIsSubmitted","isSubmitSuccessful","resetField","initial","dirty","forEachDirtyField","fn","computeDirtyFields","dirtyFields","getDirtyFields","aKeys","every","sameDirtyKeys","unsetValidatingByPath","setValidatingByPath","registerValidatorByPath","registration","timer","controller","marked","lock","errorSource","mark","unmark","runSync","sync","validate","supersede","clearTimeout","abort","runValidator","AbortController","round","signal","e","catch","finally","run","debounce","setTimeout","async","trigger","settle","fieldsSettled","validator","runFormValidate","touchKeys","shouldFocus","firstKey","find","setFormErrors","footprint","recordFootprint","stored","applyValidateResult","validateDeps","formErrorFootprints","getFormErrorFootprint","written","clearFormValidateErrors","outcome","setParsedValues","FORM_VALIDATING_KEY","SETTLED","formValidateStates","validateDebounce","state","waiters","getFormValidateState","runFormValidateRound","settleFormValidate","waiter","revalidateFormOnChange","mode","reValidateMode","hasFormValidateErrors","fieldValidateDeps","registerFieldValidateDeps","depKeys","deps","depKey","dependents","unregisterFieldValidateDeps","revalidateDependentsOnChange","dependent","validationError","Error","ensureValidate","fieldModes","changeValue","changeValueByPath","userChangeByPath","registerFieldMode","modes","displaced","token","unregisterFieldMode","entry","runUserChangeGate","userBlur","setIsSubmitting","incrementSubmitCount","setSubmitSuccessful","setDisabled","disabled","nameToPath","handleSubmit","onSubmit","onValidSubmit","onInvalidSubmit","onAction","shouldFocusError","preventDefault","formEl","currentTarget","checkValidity","reportValidity","querySelector","invalid","focus","elements","el","validationMessage","getNativeErrors","submitted","setFocus","createEmitter","setMaxListeners","source","dep","isLoading","resolved","defaultMessage","bound","rulesToValidator","rules","required","messages","min","n","isNaN","max","minLength","maxLength","pattern","process","env","NODE_ENV","shimModule","exports","React","require$$0","objectIs","x","y","useState","useEffect","useLayoutEffect","useDebugValue","checkIfSnapshotChanged","inst","latestGetSnapshot","getSnapshot","nextValue","shim","window","document","createElement","subscribe","_useState","forceUpdate","useSyncExternalStoreShim_production","useSyncExternalStore","__REACT_DEVTOOLS_GLOBAL_HOOK__","registerInternalModuleStart","didWarnOld18Alpha","didWarnUncachedGetSnapshot","startTransition","console","cachedValue","useSyncExternalStoreShim_development","registerInternalModuleStop","isDescendant","onPathEvent","scope","cb","changed","onKeyEvent","callback","names","isNameList","unsubscribes","unsubscribe","useForm","created","createForm","seededRef","useRef","seeded","controlledRef","useWatchCore","subscribeFactory","getter","cacheRef","hasValue","getterRef","isEqualRef","useCallback","notify","compare","useWatch","formOrEmitter","invalidate","useValue","useValueByPath","bind","useTouched","useTouchedByPath","useError","useErrorByPath","useFieldErrors","useFieldErrorsByPath","useIsDirty","useDirtyFields","useTouchedFields","FORM_STATE_EVENTS","isSameFormState","sameTouched","touchedFields","isValid","useFormState","getFormState","offs","useHasErrors","useIsValid","useIsSubmitting","useIsLoading","useCanSubmit","offErrors","offSubmitting","useSubmitCount","useIsValidating","useIsSubmitSuccessful","useFormError","useFormErrors","usePath","useMemo","useStage","ref","useStageFn","params","useFieldCore","f1","initialValue","shouldUnregister","delayError","uncontrolled","modeOption","Context","contextForm","useContext","formProp","FormContext","validateRef","debounceRef","syncRef","useValidate","hasRuleConstraints","ruleValidator","meta","ruleErrors","merge","other","combineRulesAndValidate","delay","shown","setShown","useDelayedErrors","errorObject","snapshotRef","useFieldValue","formDisabled","onChange","v","onBlur","depsKey","elementRef","focusRef","shouldSelect","select","useField","idCounters","generateId","arrayIdsRegistry","registerArrayIds","ids","registry","bumpReducer","count","useFieldArrayCore","idsRef","getArray","setArray","computeFields","pop","id","fields","syncFields","useReducer","append","prepend","unshift","insert","splice","newArr","remove","filter","_","swap","to","move","replace","update","useFieldArray","useFieldArrayItemCore","arrayPath","computeIndex","getArrayIds","computeValue","lastRef","computeRef","bump","idx","val","nextIndex","itemPath","useFieldArrayItem","createContext","FormProvider","Provider","useFormContext","createFormContext","context","children","CheckboxGroupContext","CheckboxGroupProvider","useCheckboxGroupContext","group","appendFormDataValue","fd","FileList","File","Blob","toISOString","Form","action","f2","submit","FormData","formDataFromValues","noValidate","FormField","errorIdFromKey","ariaProps","fieldKey","Boolean","fieldErrorId","Field","forwardRef","eventToValue","asProps","renderError","as","valueToProps","innerRef","nativeInvalidCount","setNativeInvalidCount","isDisabled","setCustomValidity","mergedRef","setRef","Component","isFile","toValue","target","files","valueProps","defaultValue","errorId","Fragment","role","Checkbox","checked","toSelectValue","multiple","Select","selectedOptions","option"],"mappings":"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","x_google_ignoreList":[13,14,15]}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/util.ts","../src/path.ts","../src/core/internals.ts","../src/core/errors.ts","../src/core/dirty.ts","../src/core/touched.ts","../src/core/values.ts","../src/core/validate.ts","../src/core/change.ts","../src/core/submit.ts","../src/core/focus.ts","../src/form.ts","../src/rules.ts","../src/subscribe.ts","../src/hooks/form.tsx","../src/hooks/path.ts","../src/hooks/stage.ts","../src/hooks/validate.ts","../src/core/unmount.ts","../src/hooks/field.tsx","../src/hooks/fieldArray.ts","../src/context.ts","../src/hooks/transform.ts","../src/server.ts","../src/components/Form.tsx","../src/components/FormField.tsx","../src/components/Field.tsx"],"sourcesContent":["import {on} from './emitter';\nimport type {EventEmitter} from './emitter';\n\n/** FIFO bound for {@link pathCache}. Static field names ('user.email')\n * number in the dozens per app, so the cache barely grows in practice;\n * the cap is only a backstop for dynamic keys ('items[' + id + ']'\n * style — array inputs skip the cache entirely), where long-lived forms\n * would otherwise accumulate entries forever. Map preserves insertion\n * order, so eviction drops the oldest entry; a dropped string only\n * costs a re-parse the next time normalizePath sees it — results are\n * deterministic, so eviction affects performance, never behavior. */\nconst PATH_CACHE_LIMIT = 1e4;\n\nconst pathCache = new Map<string, (string | number)[]>();\n\n/** Test-only view of the path cache size. Not re-exported from the\n * package entry — tests import this module directly to assert the\n * FIFO bound above. */\nexport const pathCacheSize = () => pathCache.size;\n\nexport function normalizePath(\n path: string | (string | number)[]\n): (string | number)[] {\n if (Array.isArray(path)) return path;\n const cached = pathCache.get(path);\n if (cached) return cached;\n const value = parsePath(path);\n if (pathCache.size >= PATH_CACHE_LIMIT) {\n // Insertion order is FIFO order; the cache is non-empty here\n // because size >= 1e4.\n const oldest = pathCache.keys().next();\n if (!oldest.done) pathCache.delete(oldest.value);\n }\n pathCache.set(path, value);\n return value;\n}\n\n/** Does a segment string denote an integer array index (optionally\n * negative)? The parser feeds it bracket contents ('items[0]' → number)\n * and rejects dotted numerics outright ('items.0' throws), so parsed\n * paths never carry index-looking strings. Its remaining duty is\n * defending programmatic segments: normalizePath also accepts raw\n * (string | number)[] arrays, and index-shaped strings can still arrive\n * from internal callers (error-tree keys) or array containers met\n * during set/setOwned walks. */\nexport const isIndex = (segment: string) => /^-?\\d+$/.test(segment);\n\nfunction parsePath(path: string): (string | number)[] {\n const result: (string | number)[] = [];\n let identifier = '';\n const flushIdentifier = () => {\n if (isIndex(identifier)) {\n // Rebuild both spellings for an actionable message: the dotted\n // form the caller wrote vs. the bracket form the parser accepts.\n const dotted = [...result.map(String), identifier].join('.');\n const bracket = result.reduce(\n (acc: string, seg: string | number) =>\n acc +\n (typeof seg === 'number' ? `[${seg}]` : `${acc ? '.' : ''}${seg}`),\n ''\n );\n throw new TypeError(\n `Numeric path segment must use bracket notation: \"${dotted}\" → \"${bracket}[${identifier}]\" (path: ${path})`\n );\n }\n result.push(identifier);\n identifier = '';\n };\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n if (char === '.') {\n if (identifier !== '') flushIdentifier();\n } else if (char === '[') {\n if (identifier !== '') flushIdentifier();\n const quote = path[i + 1];\n if (quote === '\"' || quote === \"'\") {\n const close = path.indexOf(quote, i + 2);\n if (close === -1) {\n throw new TypeError(`Unterminated quote in path: ${path}`);\n }\n if (path[close + 1] !== ']') {\n throw new TypeError(\n `Expected \"]\" after quoted segment in path: ${path}`\n );\n }\n result.push(path.slice(i + 2, close));\n i = close + 1;\n } else {\n const close = path.indexOf(']', i + 1);\n if (close === -1) {\n throw new TypeError(`Unterminated bracket in path: ${path}`);\n }\n const content = path.slice(i + 1, close);\n result.push(isIndex(content) ? Number(content) : content);\n i = close;\n }\n } else {\n identifier += char;\n }\n }\n if (identifier !== '' || result.length === 0) flushIdentifier();\n return result;\n}\n\nexport function get(values: any, path: (string | number)[]): any {\n return path.reduce((current: any, p: string | number) => {\n if (current == null) return undefined;\n return current[p];\n }, values);\n}\n\n/**\n * Immutable counterpart of {@link set}: removes the path from the value\n * tree, copying only along the touched branch (untouched branches stay\n * shared with the source, like set). Deletes the key entirely rather than\n * writing undefined, so the result carries no `a: undefined` entries.\n */\nexport function unset(values: any, path: (string | number)[]): any {\n if (!path.length || values == null) return values;\n const [prop, ...props] = path;\n if (props.length) {\n const next = unset(values[prop], props);\n // Reattach the pruned child at its parent key — NOT at the full path,\n // which would write the pruned subtree back under the removed key.\n return next === values[prop] ? values : set(values, [prop], next);\n }\n if (Array.isArray(values)) {\n if (!(prop in values)) return values;\n const arr = values.slice();\n delete arr[prop as number];\n return arr;\n }\n if (typeof values !== 'object' || !(prop in values)) return values;\n const copy = {...values};\n delete copy[prop as string];\n return copy;\n}\n\nexport function set(values: any, path: (string | number)[], value: any): any {\n if (!path.length) return value;\n\n const [prop, ...props] = path;\n // A numeric segment lands with the array copy rule — numbers, and the\n // string form dotted paths parse to ('a.0'), on an array container: an\n // object spread there would corrupt the array into {'0': ...}.\n const index =\n typeof prop === 'number'\n ? prop\n : Array.isArray(values) && typeof prop === 'string' && isIndex(prop)\n ? Number(prop)\n : undefined;\n if (index !== undefined) {\n const arr = Array.isArray(values) ? values.slice() : [];\n arr[index] = set(arr[index], props, value);\n return arr;\n }\n return {...values, [prop]: set(values && values[prop], props, value)};\n}\n\n/**\n * Ownership-tracked {@link set}: merge many paths into one tree without\n * re-copying containers the merge itself already created.\n *\n * Containers present in `owned` (freshly created by an earlier call of the\n * same merge) are mutated in place; every other container -- nodes borrowed\n * from the seed tree and user leaf values -- is copied first with the exact\n * copy rules `set` applies (numeric prop: array slice, or a fresh array\n * when the node is not one; string prop: object spread). Chaining\n * `setOwned` over a list of paths therefore produces the tree chaining\n * `set` would, in the same insertion order, but allocates each distinct\n * container once (O(distinct path prefixes)) instead of re-copying the\n * whole branch for every path (O(paths x depth)).\n *\n * Use a fresh `owned` set per merge and thread the returned root (a copied\n * replacement when the seed root itself had to be copied) into the next\n * call. Borrowed containers are never mutated.\n */\nexport function setOwned(\n root: any,\n path: (string | number)[],\n value: any,\n owned: Set<object>\n): any {\n if (!path.length) return value;\n let container = root;\n let parent: any = null;\n let parentProp: string | number = '';\n for (let i = 0; i < path.length; i++) {\n const prop = path[i];\n if (!owned.has(container)) {\n let copy: any;\n if (\n typeof prop === 'number' ||\n (Array.isArray(container) && typeof prop === 'string' && isIndex(prop))\n ) {\n copy = Array.isArray(container) ? container.slice() : [];\n } else {\n copy = {...container};\n }\n owned.add(copy);\n if (i === 0) root = copy;\n else parent[parentProp] = copy;\n container = copy;\n }\n if (i === path.length - 1) {\n container[prop] = value;\n } else {\n parent = container;\n parentProp = prop;\n container = container[prop];\n }\n }\n return root;\n}\n\nexport function isEmpty(value: any): boolean {\n if (value == null) return true;\n if (typeof value !== 'object') return false;\n\n const values = Object.values(value);\n return values.length === 0 || values.every(isEmpty);\n}\n\nexport function isPromise(value: any): value is Promise<any> {\n return value && typeof value.then === 'function';\n}\n\n/** Structural equality for form default data (primitives, arrays, plain\n * objects, Dates). Class instances and other exotic objects compare as\n * unequal, which errs on the side of re-seeding when {@link\n * setInitialValues} uses it to tell a re-rendered inline literal from\n * genuinely changed content. */\nexport function isEqual(a: any, b: any): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return false;\n const isArray = Array.isArray(a);\n if (isArray !== Array.isArray(b)) return false;\n if (isArray) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!isEqual(a[i], b[i])) return false;\n }\n return true;\n }\n const proto = Object.getPrototypeOf(a);\n if (proto !== Object.prototype && proto !== null) return false;\n if (Object.getPrototypeOf(b) !== proto) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if (!isEqual(a[key], b[key])) return false;\n }\n return true;\n}\n\nexport function waitUntil(\n emitter: EventEmitter<any>,\n event: string,\n isResolve: () => boolean,\n isReject: () => boolean\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (isReject()) return void reject();\n if (isResolve()) return void resolve();\n\n const off = on(emitter, event as any, () => {\n if (isReject()) {\n off();\n reject();\n return;\n }\n // Condition not reached yet — stay subscribed and keep waiting. (The\n // previous `if (isResolve()) return` was inverted: it hung forever\n // once the condition held and resolved prematurely while it didn't.)\n if (!isResolve()) return;\n off();\n resolve();\n });\n });\n}\n\n/**\n * DEV-only snapshot guard for {@link getValues}: deep-clones and freezes\n * plain objects and arrays so a consumer mutating the returned tree throws\n * immediately instead of silently corrupting the shared memoized result\n * (getValues hands the same cached reference to every reader between\n * writes). Non-plain values (Date, File, Blob, class instances, Map/Set)\n * pass through by reference, unfrozen — cloning would strip their\n * prototypes and freezing would break legitimate methods like\n * Date#setHours. Callers gate the call behind `__DEV__` so production\n * builds pay nothing.\n */\nexport function freezeValues(value: any): any {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) {\n return Object.freeze(value.map(freezeValues));\n }\n if (Object.getPrototypeOf(value) !== Object.prototype) return value;\n const clone: Record<string, any> = {};\n for (const key of Object.keys(value)) clone[key] = freezeValues(value[key]);\n return Object.freeze(clone);\n}\n","import {normalizePath} from './util';\n\nexport type PathSegments = (string | number)[];\nexport type Name = string | PathSegments;\nexport type Path = {value: PathSegments; key: string};\n\nexport default function create(name: Name): Path {\n const value = normalizePath(name);\n return {value, key: JSON.stringify(value)};\n}\n","import {emit} from '../emitter';\nimport {get} from '../util';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldError, Form} from '../form';\n\n/** Per-form memoization of {@link getValues}, the same version-bump/read\n * pattern {@link dirtyFieldsCaches} gives {@link getDirtyFields}. */\ntype ValuesCache = {version: number; result: any};\n\nexport const valuesCaches = new WeakMap<Form, ValuesCache>();\n\n/**\n * Invalidate `form`'s cached {@link getValues} result. Called at every\n * point that can change values, parsedValues or initialValues\n * (setValueByPath, removeFieldByPath, setInitialValues, reset, resetField,\n * setParsedValues) so repeated reads hand back a stable reference until\n * the next write.\n */\nexport function bumpValuesVersion(form: Form): void {\n const cache = valuesCaches.get(form);\n if (cache) cache.version++;\n}\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\nconst dirtyBaselines = new WeakMap<Form, Map<string, any>>();\n\n/** The value a field's dirtiness is measured against: its committed\n * baseline when one exists, initialValues at the path otherwise. */\nexport function getDirtyBaseline(\n form: Form,\n key: string,\n segments: PathSegments\n): any {\n const baselines = dirtyBaselines.get(form);\n if (baselines?.has(key)) return baselines.get(key);\n return get(form.initialValues, segments);\n}\n\n/** Install a committed baseline for a `shouldDirty: false` write: the\n * field reads clean until a later write diverges from the new baseline. */\nexport function setDirtyBaseline(form: Form, {key}: Path, value: any): void {\n let baselines = dirtyBaselines.get(form);\n if (!baselines) {\n baselines = new Map();\n dirtyBaselines.set(form, baselines);\n }\n baselines.set(key, value);\n}\n\n/** A wholesale write at a path replaces the subtree below it, so baselines\n * committed under the branch die with the data they were committed against\n * (array movers rewrite the parent path, re-aligning row indices). Called\n * from every write — a no-op unless the form ever opted in. */\nexport function pruneDirtyBaselines(form: Form, {key}: Path): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines?.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const baselineKey of baselines.keys()) {\n if (baselineKey.startsWith(stem)) baselines.delete(baselineKey);\n }\n}\n\n/** Drop committed baselines at one path ({@link removeFieldByPath} /\n * {@link resetField}) or all of them ({@link setInitialValues} /\n * {@link reset}) — the state they were measured against is gone. */\nexport function clearDirtyBaselines(form: Form, key?: string): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines) return;\n if (key === undefined) baselines.clear();\n else baselines.delete(key);\n}\n\n/** Per-form memoization of {@link getDirtyFields}. `version` counts value\n * mutations since the cached `result` was computed: bump points increment\n * it, reads reset it, so a non-zero version means the cache is stale. */\ntype DirtyFieldsCache = {version: number; result: Record<string, boolean>};\n\nexport const dirtyFieldsCaches = new WeakMap<Form, DirtyFieldsCache>();\n\n/**\n * Invalidate `form`'s cached {@link getDirtyFields} result. Called at every\n * point that can change values or initialValues (setValueByPath,\n * removeFieldByPath, setInitialValues, reset) so repeated reads hand out a\n * stable reference and useWatch's Object.is snapshot check can skip\n * re-renders.\n */\nexport function bumpDirtyVersion(form: Form): void {\n const cache = dirtyFieldsCaches.get(form);\n if (cache) cache.version++;\n}\n/** Numbers only occur inside a segments path (`['a', 0]`), never as\n * standalone names, so a top-level number marks `name` as one single path\n * rather than a list of names. */\nexport function isSegmentsPath(\n name: PathSegments | Name[]\n): name is PathSegments {\n return (name as (number | unknown)[]).some(part => typeof part === 'number');\n}\n\nexport function isFieldError(value: any): value is FieldError {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof value.type === 'string' &&\n typeof value.message === 'string'\n );\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n/** Store a schema validator's parsed output as the getValues baseline\n * layer above initialValues. Payload-less 'change' notifies value\n * watchers (useValue, useDirtyFields, ...); dirty state is untouched —\n * it only compares live edits against initialValues, and parsing is not\n * an edit. */\nexport function setParsedValues(form: Form, values: any): void {\n if (values === undefined || values === form.parsedValues) return;\n form.parsedValues = values;\n // parsedValues is a getValues layer above initialValues, so a new parse\n // invalidates the cached merge (dirty state is untouched — parsing is\n // not an edit, hence no bumpDirtyVersion here).\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {FieldError, FieldErrorEntry, Form} from '../form';\nimport {isFieldError, isSegmentsPath} from './internals';\n\n/** Reserved top-level path segment for form-level errors. The Standard\n * Schema form-level adapter lands path-less issues under this key; the\n * exported constant replaces the magic string, and readers consume it via\n * getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */\nexport const FORM_ERROR = '_form';\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\n/** Brand marking a form-level validate result as a structured\n * {@link ValidationOutcome} (parsed values and/or errors) rather than a\n * plain nested error record. Symbols cannot collide with user error\n * records, so detection is an exact `VALIDATION_OUTCOME in result`. */\nexport const VALIDATION_OUTCOME: unique symbol = Symbol('validation-outcome');\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted. */\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\nexport function getError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError | undefined {\n return getErrorByPath(form, createPath(name));\n}\n\n/**\n * Get field error by path\n * @param form\n * @param path\n * @return first FieldError of the field, or undefined\n */\nexport function getErrorByPath(\n {errors}: Form,\n path: Path\n): FieldError | undefined {\n return errors.get(path.key)?.[0];\n}\n\n/** Shared empty result for {@link getFieldErrorsByPath}: a fresh `[]` per\n * call would allocate on the hot no-error path, and the stored arrays are\n * handed out by reference too, so callers must treat results as read-only. */\nconst NO_ERRORS: FieldError[] = [];\n\n/**\n * Get all errors of a field\n * @param form\n * @param name\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return getFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all errors of a field by path\n * @param form\n * @param path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrorsByPath({errors}: Form, path: Path): FieldError[] {\n return errors.get(path.key) ?? NO_ERRORS;\n}\n\n/**\n * Get all errors\n * @param form\n * @return array of {path, type, message} entries, in insertion order; path\n * is the user-facing dotted field path ('a.b', 'list.0'), and a\n * field holding several errors contributes one entry per error\n */\nexport function getErrors({errors}: Form): FieldErrorEntry[] {\n const entries: FieldErrorEntry[] = [];\n for (const [key, list] of errors) {\n const path = (JSON.parse(key) as PathSegments).join('.');\n for (const {type, message} of list) entries.push({path, type, message});\n }\n return entries;\n}\n\n/**\n * Get first error message\n * @param form\n * @return first error's message string, or undefined when there are no errors\n */\nexport function getFirstError({errors}: Form): string | undefined {\n return errors.values().next().value?.[0]?.message;\n}\n\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\n/** Options accepted by {@link setError}. */\nexport type SetErrorOptions = {\n /**\n * Focus the named field's element after the error lands (react-hook-form's\n * `setError` `shouldFocus`). Rides the same 'focusError' channel\n * `setFocus` and a failed submit's auto-focus use: only mounted bound\n * fields react, unmounted ones are silent no-ops.\n */\n shouldFocus?: boolean;\n};\n\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n setErrorByPath(form, createPath(name), error, options);\n}\n\n/**\n * Set field error\n * @param form\n * @param path\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setErrorByPath(\n form: Form,\n path: Path,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n const {emitter, errors} = form;\n const list = normalizeErrors(error);\n // An empty result (undefined, '', or an array of only falsy items) clears\n // the key: the errors Map never stores an empty list, so hasErrors stays\n // a plain size check and readers can index [0] unguarded.\n if (list) errors.set(path.key, list);\n else errors.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'errors', path);\n if (options?.shouldFocus) emit(emitter, 'focusError', path.key);\n}\n\n/** Normalize any {@link setErrorByPath} input into the stored non-empty\n * FieldError[] shape, or undefined when there is nothing to store. */\nfunction normalizeErrors(\n error: string | FieldError | (string | FieldError)[] | undefined\n): FieldError[] | undefined {\n if (typeof error === 'string') {\n return error ? [{type: 'custom', message: error}] : undefined;\n }\n if (isFieldError(error)) return [error];\n if (!error) return undefined;\n // Falsy items drop out before normalization, so '' never becomes a\n // stored {type: 'custom', message: ''} placeholder.\n const list: FieldError[] = [];\n error.forEach(item => {\n if (typeof item === 'string' && item) {\n list.push({type: 'custom', message: item});\n } else if (isFieldError(item)) {\n list.push(item);\n }\n });\n return list.length ? list : undefined;\n}\n\n/**\n * Clear errors\n * @param form\n * @param name a single path or a list of paths; omit to clear every error\n */\nexport function clearErrors(form: Form, name?: Name | Name[]): void {\n const {emitter, errors} = form;\n if (name === undefined) {\n errors.clear();\n // Payload-less broadcast: every error subscriber re-syncs.\n emit(emitter, 'errors');\n return;\n }\n // Same single-path vs list discrimination as trigger: a segment array\n // holding a number is one path ('a.0' shape), not a list of names.\n const paths =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name)]\n : name.map(one => createPath(one));\n for (const {key} of paths) errors.delete(key);\n // Path-payload emits — the setErrorByPath scoping — wake exactly the\n // affected fields' subscribers.\n for (const path of paths) emit(emitter, 'errors', path);\n}\n\n/** Options accepted by {@link setServerErrors}. */\nexport type SetServerErrorsOptions = {\n /** Keep existing field errors instead of clearing them first. Defaults\n * to `false`: a fresh server response replaces the prior error state. */\n keepExisting?: boolean;\n};\n\n/**\n * Land a server-side error response on the form: each entry becomes the\n * named field's error(s) with `type: 'server'`, ready for the same\n * renderError/`useError` channel client-side validation uses. Takes the\n * flat `Record<string, string | string[]>` shape REST APIs commonly\n * return (RealWorld: `422 {errors: {email: ['has already been taken']}}`)\n * without a hand-rolled `Object.entries` + `setError` loop.\n *\n * A string value lands as one error, a string array as several (first one\n * is what `getError`/`error` expose); an empty array clears that field's\n * errors. By default every existing error is cleared first — a fresh\n * response describes the current state, not a patch onto stale client\n * errors; pass `keepExisting: true` to layer instead.\n * @param form\n * @param errors field errors keyed by name\n * @param options\n */\nexport function setServerErrors(\n form: Form,\n errors: Record<string, string | string[]>,\n options?: SetServerErrorsOptions\n): void {\n if (!options?.keepExisting) clearErrors(form);\n for (const [name, error] of Object.entries(errors)) {\n setError(\n form,\n name,\n (Array.isArray(error) ? error : [error]).map(message => ({\n type: 'server',\n message\n }))\n );\n }\n}\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\n/**\n * @param form\n */\nexport function hasErrors({errors}: Form): boolean {\n return errors.size > 0;\n}\n\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\n","import type {Path, PathSegments} from '../path';\nimport type {Form} from '../form';\nimport {dirtyFieldsCaches, getDirtyBaseline} from './internals';\n\n/**\n * Is one field dirty — the per-field rule behind `getFieldState`'s\n * `isDirty` and {@link useIsFieldDirty}: a live value exists at the path\n * and differs from the field's effective baseline (committed\n * `shouldDirty: false` baselines included). A leaf under a wholesale\n * ancestor write reports clean — dirtiness belongs to the branch that\n * actually diverged, the same attribution {@link getDirtyFields} applies.\n */\nexport function isFieldDirtyByPath(form: Form, path: Path): boolean {\n const live = form.values.get(path.key);\n return (\n form.values.has(path.key) &&\n getDirtyBaseline(form, path.key, path.value) !== live\n );\n}\n\n/**\n * Is dirty -- any value differs from initialValues\n * @param form\n */\nexport function isDirty(form: Form): boolean {\n let dirty = false;\n forEachDirtyField(form, () => {\n dirty = true;\n });\n return dirty;\n}\n\nfunction forEachDirtyField(form: Form, fn: (dottedKey: string) => void): void {\n for (const [key, value] of form.values) {\n const path = JSON.parse(key) as PathSegments;\n if (getDirtyBaseline(form, key, path) !== value) fn(path.join('.'));\n }\n}\n\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\n\nfunction computeDirtyFields(form: Form): Record<string, boolean> {\n const dirtyFields: Record<string, boolean> = {};\n forEachDirtyField(form, key => {\n dirtyFields[key] = true;\n });\n return dirtyFields;\n}\n\n/** Dirty entries only ever map to `true`, so equal key sets mean shallow\n * equal results. */\nfunction sameDirtyKeys(\n a: Record<string, boolean>,\n b: Record<string, boolean>\n): boolean {\n const aKeys = Object.keys(a);\n if (aKeys.length !== Object.keys(b).length) return false;\n return aKeys.every(key => b[key] === true);\n}\n\n/**\n * Get dirty fields -- fields whose current value differs from initialValues.\n * Keys are user-facing dotted paths ('a.b', 'a.0.c'), unlike the JSON array\n * keys stored in the values Map.\n * @param form\n * @return object mapping each dirty field's dotted path to true; the same\n * reference is returned until the dirty set actually changes\n */\nexport function getDirtyFields(form: Form): Record<string, boolean> {\n let cache = dirtyFieldsCaches.get(form);\n if (!cache) {\n cache = {version: 0, result: computeDirtyFields(form)};\n dirtyFieldsCaches.set(form, cache);\n } else if (cache.version > 0) {\n const result = computeDirtyFields(form);\n // Keep the old reference when the dirty set is unchanged (values always\n // map to true) so subscribers see identity-stable snapshots.\n if (!sameDirtyKeys(cache.result, result)) cache.result = result;\n cache.version = 0;\n }\n return cache.result;\n}\n\n/**\n * Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'), unlike\n * the JSON array keys stored in the touched Set.\n * @param form\n * @return array of touched fields' dotted paths\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {Form} from '../form';\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\nexport function setTouched(form: Form, name: Name): void {\n setTouchedByPath(form, createPath(name));\n}\n\n/**\n * Set field touched state\n * @param form\n * @param path\n */\nexport function setTouchedByPath({emitter, touched}: Form, path: Path): void {\n if (touched.has(path.key)) return;\n touched.add(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'touched', path);\n}\n\n/**\n * Check if field has been touched\n * @param form\n * @param name\n */\nexport function hasTouched<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): boolean {\n return hasTouchedByPath(form, createPath(name));\n}\n\n/**\n * Check if field has been touched\n * @param form\n * @param path\n */\nexport function hasTouchedByPath({touched}: Form, path: Path): boolean {\n return touched.has(path.key);\n}\n\n/**\n * Is dirty -- any value differs from initialValues\n * @param form\n */\n/**\n * Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'), unlike\n * the JSON array keys stored in the touched Set.\n * @param form\n * @return array of touched fields' dotted paths\n */\nexport function getTouchedFields({touched}: Form): string[] {\n return Array.from(touched, key =>\n (JSON.parse(key) as PathSegments).join('.')\n );\n}\n\n/**\n * Is touched -- any field has been touched\n * @param form\n */\nexport function isTouched({touched}: Form): boolean {\n return touched.size > 0;\n}\n\n/**\n * Remove a field: by default its live value drops out of reads and\n * `getValues()` (the path is tombstoned, so it never falls back to\n * initialValues), its dirty baseline, touched flag and errors are cleared.\n * The keep-flags preserve slices of that state instead.\n *\n * @param form\n * @param name\n */\n/**\n * Options accepted by {@link removeField}. All flags default to `false` —\n * the historical remove semantics (value dropped, path tombstoned, dirty\n * baseline/touched/errors cleared). Names mirror react-hook-form's\n * `unregister` options to ease migration; RHF's `shouldValidate` and\n * `keepDefaultValue` have no counterparts (removal never validates, and\n * the tombstone is exactly the \"do not revive from initialValues\" choice).\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport {freezeValues, get, isEqual, setOwned, unset} from '../util';\nimport type {FieldError, Form} from '../form';\nimport {clearErrors, getErrorByPath, getFieldErrorsByPath} from './errors';\nimport {isFieldDirtyByPath} from './dirty';\nimport {setTouchedByPath} from './touched';\nimport {\n bumpDirtyVersion,\n bumpValuesVersion,\n clearDirtyBaselines,\n getDirtyBaseline,\n pruneDirtyBaselines,\n setDirtyBaseline,\n valuesCaches\n} from './internals';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\nexport function getValues<T extends Record<string, any> = any>(\n form: Form<T>\n): T {\n let cache = valuesCaches.get(form);\n if (!cache) {\n cache = {version: 0, result: computeValues(form)};\n valuesCaches.set(form, cache);\n } else if (cache.version > 0) {\n cache.result = computeValues(form);\n cache.version = 0;\n }\n return cache.result as T;\n}\n\nfunction computeValues(form: Form): any {\n const {initialValues, parsedValues, values, deleted} = form;\n const owned = new Set<object>();\n let merged = parsedValues ?? initialValues;\n for (const [key, value] of values) {\n merged = setOwned(merged, JSON.parse(key), value, owned);\n }\n // Unregistered fields leave a tombstone in `deleted`; remove those paths\n // from the merged result so they don't fall back to initialValues. unset\n // is immutable (set() shares untouched branches with initialValues, so a\n // mutating delete would corrupt them) and deletes the key outright rather\n // than writing undefined, which would leave `a: undefined` entries behind\n // in anything that spreads getValues().\n for (const key of deleted) {\n merged = unset(merged, JSON.parse(key));\n }\n // DEV-only: hand back a frozen snapshot (a clone — freezing the merged\n // tree in place would also freeze the initialValues/parsedValues\n // containers it borrows from). Consumer mutations then throw at the\n // offending site instead of silently corrupting the shared cache.\n return __DEV__ ? freezeValues(merged) : merged;\n}\n\n/**\n * Get field value\n * @param form\n * @param name\n */\nexport function getValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): PathValueOf<T, P> {\n return getValueByPath(form, createPath(name));\n}\n\n/**\n * Get field value by path\n * @param form\n * @param path\n */\nexport function getValueByPath(\n {initialValues, parsedValues, values, deleted}: Form,\n path: Path\n): any {\n const {key, value: segments} = path;\n if (values.has(key)) return values.get(key);\n // Unregistered path: the tombstone blocks the initialValues fallback.\n if (deleted.has(key)) return undefined;\n // A live ancestor key is a whole-branch write (setValue at a parent\n // path, every useFieldArray operation): it replaces the subtree below\n // it, the same way getValues' merge layers it over the baseline, so\n // reads under it resolve from that stored value instead of falling\n // back to the pre-edit initialValues snapshot. Nearest ancestor first:\n // a finer write is layered over a coarser one (setValueByPath drops the\n // superseded descendant keys), so the closest live ancestor is the\n // newest generation. Paths the ancestor's value does not carry read\n // undefined — the baseline must not fill holes inside a replaced\n // branch.\n for (let i = segments.length - 1; i > 0; i--) {\n const ancestorKey = JSON.stringify(segments.slice(0, i));\n if (values.has(ancestorKey)) {\n return get(values.get(ancestorKey), segments.slice(i));\n }\n }\n // Same layering as getValues: parsed values (when present) are the\n // baseline above initialValues.\n return get(parsedValues ?? initialValues, segments);\n}\n\n/** Options accepted by {@link setValue} / {@link setValueByPath} / {@link\n * changeValue} / {@link changeValueByPath}. `shouldValidate`/`shouldTouch`\n * default to `false`; omitting the options object entirely keeps the plain\n * set-value behavior (no validation, no touched marking, dirty stays\n * derived). */\nexport type SetFieldOptions = {\n /** Run the field's registered validator (if any) after the value lands,\n * same as triggering that single field. Defaults to `false`. */\n shouldValidate?: boolean;\n /** Mark the field as touched. Defaults to `false`. */\n shouldTouch?: boolean;\n /** Land the value as a commit instead of an edit: the value becomes the\n * field's dirty-comparison baseline, so `getDirtyFields`/`isDirty`/\n * `getFieldState().isDirty` read the field as clean, and a later write\n * dirties it only by differing from the new baseline. `true` (or\n * omitting the flag) keeps the default derived behavior — dirty while\n * the live value differs from initialValues. */\n shouldDirty?: boolean;\n};\n\n/**\n * Set field value. The value may also be an updater function receiving\n * the field's current value and returning the next one (TanStack Form's\n * `setFieldValue` contract) — handy for increments and array transforms:\n * `setValue(form, 'count', c => c + 1)`. The tradeoff: a function can\n * never itself be stored as a field value through this function.\n * @param form\n * @param name\n * @param value\n * @param options\n */\nexport function setValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n value: PathValueOf<T, P> | ((prev: PathValueOf<T, P>) => PathValueOf<T, P>),\n options?: SetFieldOptions\n): void {\n setValueByPath(form, createPath(name), value, options);\n}\n\n/**\n * Set field value. The value may also be an updater function receiving\n * the field's current value and returning the next one (TanStack Form's\n * `setFieldValue` contract) — note that a function can therefore never\n * itself be stored as a field value through this function.\n * @param form\n * @param path\n * @param value\n * @param options\n */\nexport function setValueByPath(\n form: Form,\n path: Path,\n value: any | ((prev: any) => any),\n options?: SetFieldOptions\n): void {\n const {emitter, values, deleted} = form;\n const next =\n typeof value === 'function' ? value(getValueByPath(form, path)) : value;\n values.set(path.key, next);\n // The write replaces the whole subtree below it, so descendant keys in\n // the values Map belong to an older generation of that subtree: without\n // this prune they would shadow the new value on exact-key reads and\n // double-apply over it in getValues' insertion-ordered merge (a stale\n // `a.b` would survive a fresh `a` write, or corrupt an array branch\n // into an object when applied later).\n pruneDescendantKeys(values, path);\n reviveBranch(deleted, path);\n // Baselines under the replaced subtree die with it — before the emit, so\n // subscribers reading dirty state inside the emission never see a stale\n // commit suppressing the write they are being told about.\n pruneDirtyBaselines(form, path);\n if (options?.shouldDirty === false) setDirtyBaseline(form, path, next);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n if (options?.shouldTouch) setTouchedByPath(form, path);\n if (options?.shouldValidate) form.validators.get(path.key)?.();\n emit(emitter, 'change', path);\n}\n\n/**\n * The write of {@link setValueByPath} minus the `'change'` emit: the\n * render-time {@link useField} `initialValue` seed. The field's first\n * paint (SSR included — effects never run on the server) must already\n * carry the value, so the write happens during render where emitting is\n * illegal; the seeding field announces it from its post-commit effect\n * through {@link emitChangeByPath} instead.\n *\n * Everything else matches a plain write: descendant keys of the seeded\n * path are pruned, the branch's tombstones and committed baselines are\n * revived/dropped, and both memo caches are invalidated. Like the effect\n * seed it replaces, the caller guards it to paths with no value yet.\n */\nexport function seedValueByPath(form: Form, path: Path, value: any): void {\n const {values, deleted} = form;\n values.set(path.key, value);\n pruneDescendantKeys(values, path);\n reviveBranch(deleted, path);\n pruneDirtyBaselines(form, path);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n}\n\n/** Announce a {@link seedValueByPath} that happened during render: the\n * payload-carrying `'change'` emit {@link setValueByPath} would have\n * fired, split out so it can run post-commit where emitting is safe.\n * Subscribers that rendered after the seed re-read an unchanged snapshot\n * and bail; subscribers from earlier commits resync. */\nexport function emitChangeByPath({emitter}: Form, path: Path): void {\n emit(emitter, 'change', path);\n}\n\n/** Per-form registry of mounted fields' validation-mode overrides: path\n * key -> the field's `mode` option (undefined = follow {@link Form.mode})\n * plus an owner token so competing mounts at one path clean up safely.\n * Presence of an entry is the \"a field is mounted at this path\" signal\n * that routes {@link changeValueByPath} into the gated user-change\n * pipeline ({@link userChangeByPath}). Held in a WeakMap so the Form\n * shape carries only plain state fields. */\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\nexport type FieldState<T = any> = {\n value: T;\n error: FieldError | undefined;\n errors: FieldError[];\n isDirty: boolean;\n isTouched: boolean;\n isValidating: boolean;\n};\n\n/**\n * Get one field's aggregated state: the layered value ({@link getValue}),\n * the first error ({@link getError}) and every error ({@link\n * getFieldErrors}), dirtiness, the touched flag, and whether a validator\n * is in flight. `isDirty` applies the same per-field rule as {@link\n * getDirtyFields}: a live value exists and differs from initialValues at\n * that path (parsedValues never counts — parsing is not an edit).\n *\n * @param form\n * @param name\n */\nexport function getFieldState<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldState<PathValueOf<T, P>> {\n const path = createPath(name);\n const {touched, validating} = form;\n return {\n value: getValueByPath(form, path),\n error: getErrorByPath(form, path),\n errors: getFieldErrorsByPath(form, path),\n // The shared per-field rule (committed baselines included): the field\n // is dirty while its live value differs from its effective baseline.\n isDirty: isFieldDirtyByPath(form, path),\n isTouched: touched.has(path.key),\n isValidating: validating.has(path.key)\n };\n}\n\n/**\n * Remove a field: by default its live value drops out of reads and\n * `getValues()` (the path is tombstoned, so it never falls back to\n * initialValues), its dirty baseline, touched flag and errors are cleared.\n * The keep-flags preserve slices of that state instead.\n *\n * @param form\n * @param name\n */\n/**\n * Options accepted by {@link removeField}. All flags default to `false` —\n * the historical remove semantics (value dropped, path tombstoned, dirty\n * baseline/touched/errors cleared). Names mirror react-hook-form's\n * `unregister` options to ease migration; RHF's `shouldValidate` and\n * `keepDefaultValue` have no counterparts (removal never validates, and\n * the tombstone is exactly the \"do not revive from initialValues\" choice).\n */\nexport type RemoveFieldOptions = {\n /** Keep the field's live value and dirty baseline instead of\n * tombstoning: reads and `getValues()` keep returning the value, submit\n * includes it, and dirtiness against initialValues is preserved. */\n keepValue?: boolean;\n /** Keep the field's dirty baseline. Implies `keepValue` — a removed\n * value has nothing to be dirty about. */\n keepDirty?: boolean;\n /** Keep the field's touched flag instead of clearing it. */\n keepTouched?: boolean;\n /** Keep the field's errors instead of clearing them. */\n keepError?: boolean;\n};\n\nexport function removeField(\n form: Form,\n name: Name,\n options?: RemoveFieldOptions\n): void {\n removeFieldByPath(form, createPath(name), options);\n}\n\n/**\n * Remove field\n * @param form\n * @param path\n * @param options keep-flags to preserve slices of state through the removal\n */\nexport function removeFieldByPath(\n form: Form,\n path: Path,\n options?: RemoveFieldOptions\n): void {\n const {key, value: segments} = path;\n const {emitter, values, touched, errors, validating, deleted} = form;\n if (!options?.keepValue && !options?.keepDirty) {\n values.delete(key);\n // The field is gone; a remount starts fresh rather than inheriting a\n // baseline committed by the previous incarnation.\n clearDirtyBaselines(form, key);\n // Tombstone the unregistered path so later reads do not fall back to\n // initialValues and \"revive\" the field's old initial value. A tombstone\n // never shadows live values: skip it when the branch is already covered\n // by a live ancestor key (e.g. a FieldArray rewrite stored the whole\n // array at the parent path) or a still-mounted descendant key.\n if (!hasLiveBranch(values, segments)) deleted.add(key);\n }\n if (!options?.keepTouched) touched.delete(key);\n if (!options?.keepError) errors.delete(key);\n validating.delete(key);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n // Path-payload emits, scoped exactly like the writes above: every\n // mutation is bounded to this path's key (exact deletes in the four\n // stores, an exact-key tombstone), so the same matching the write sites\n // use decides who re-syncs. Leaf watchers on the path and BELOW it wake\n // (their reads fall back through the removed key), branch watchers on\n // ancestors wake (their subtree lost a leaf — the wizard/tab unmount\n // case), and global listeners (`on`, useWatch aggregates like\n // useDirtyFields/getValues readers) wake regardless — an emit with a\n // payload still reaches every plain listener. Sibling fields stay\n // asleep: unmounting one tab's fields no longer re-renders every other\n // field's subscriber.\n emit(emitter, 'change', path);\n emit(emitter, 'touched', path);\n emit(emitter, 'errors', path);\n emit(emitter, 'validating', path);\n}\n\n/**\n * Does a live value cover the branch at `segments` -- either at an ancestor\n * key or below it at a descendant key?\n */\nfunction hasLiveBranch(\n values: Map<string, any>,\n segments: PathSegments\n): boolean {\n for (let i = 1; i < segments.length; i++) {\n if (values.has(JSON.stringify(segments.slice(0, i)))) return true;\n }\n const stem = `${JSON.stringify(segments).slice(0, -1)},`;\n for (const key of values.keys()) {\n if (key.startsWith(stem)) return true;\n }\n return false;\n}\n\n/**\n * Writing a value replaces the subtree below the written path, so drop the\n * values Map keys under it: they were set against an older generation of\n * that subtree and would otherwise shadow the fresh value (exact-key reads\n * in {@link getValueByPath}) or re-apply over it (getValues' merge).\n * Deleting while iterating `keys()` is safe for a Map.\n */\nfunction pruneDescendantKeys(values: Map<string, any>, {key}: Path): void {\n if (!values.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const k of values.keys()) {\n if (k.startsWith(stem)) values.delete(k);\n }\n}\n\n/**\n * Writing a value revives its whole branch: drop any removal tombstone for\n * the path itself, its ancestors, or its descendants (a remounted field\n * overwrites its own tombstone; rewriting a parent array supersedes the\n * tombstones of shifted child paths).\n */\nfunction reviveBranch(deleted: Set<string>, {key}: Path): void {\n if (!deleted.size) return;\n for (const tombstone of deleted) {\n if (\n tombstone === key ||\n tombstone.startsWith(`${key.slice(0, -1)},`) ||\n key.startsWith(`${tombstone.slice(0, -1)},`)\n ) {\n deleted.delete(tombstone);\n }\n }\n}\n\n/**\n * Set form initialValues\n *\n * Content-based early return: a new reference with equal content (the\n * re-rendered inline literal) is a no-op, so committed edits survive, while\n * genuinely changed content swaps the baseline and re-seeds — live values\n * and tombstones are cleared, touched flags and errors survive.\n * @param form\n * @param initialValues\n */\nexport function setInitialValues(form: Form, initialValues: any): void {\n if (\n form.initialValues === initialValues ||\n isEqual(form.initialValues, initialValues)\n ) {\n return;\n }\n form.initialValues = initialValues;\n // A new baseline invalidates the previous schema parse.\n form.parsedValues = undefined;\n form.values.clear();\n form.deleted.clear();\n // ...and every baseline committed against the old one.\n clearDirtyBaselines(form);\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/** Options accepted by {@link reset}. Every flag defaults to `false` —\n * omitting the object (or any flag) keeps the plain full-reset behavior.\n * Names mirror react-hook-form's reset options to ease migration. */\nexport type ResetOptions = {\n /** Keep the current values of fields that are dirty — differ from the\n * pre-reset initialValues (the same rule {@link getDirtyFields} applies).\n * Clean fields fall back to the new initialValues as usual. */\n keepDirtyValues?: boolean;\n /** Keep every field's current live value instead of returning to the\n * baseline (react-hook-form's `keepValues` — a strict superset of\n * `keepDirtyValues`, which only preserves dirty fields' values).\n * Dirtiness is recomputed against the post-reset baseline, so kept\n * values that differ from a newly provided baseline count as dirty. */\n keepValues?: boolean;\n /** Ignore a newly provided `initialValues` argument and keep the current\n * baseline — fields still return to it (react-hook-form's\n * `keepDefaultValues`). */\n keepDefaultValues?: boolean;\n /** Keep the touched set instead of clearing it. */\n keepTouched?: boolean;\n /** Keep field errors instead of clearing them. */\n keepErrors?: boolean;\n /** Keep the submitted flag (`isSubmitted`) instead of clearing it —\n * react-hook-form's `keepIsSubmitted`. */\n keepIsSubmitted?: boolean;\n /** Keep the last submit's success flag (`isSubmitSuccessful`) instead of\n * clearing it. */\n keepIsSubmitSuccessful?: boolean;\n /** Keep `submitCount` instead of resetting it to 0. */\n keepSubmitCount?: boolean;\n /** Keep `isSubmitting` instead of resetting it to false. */\n keepIsSubmitting?: boolean;\n};\n\n/** Collect every leaf path of the merged values tree into `out` —\n * structured segments (numeric for array indexes) so each leaf can be\n * written back with setValueByPath. Objects with no enumerable keys\n * (Date, File, plain empty objects) are leaves themselves. */\nfunction collectValueLeaves(\n node: any,\n segments: PathSegments,\n out: {segments: PathSegments; value: any}[]\n): void {\n if (node !== null && typeof node === 'object') {\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectValueLeaves(node[i], [...segments, i], out);\n }\n return;\n }\n const keys = Object.keys(node);\n if (keys.length > 0) {\n for (const k of keys) {\n collectValueLeaves(node[k], [...segments, k], out);\n }\n return;\n }\n }\n out.push({segments, value: node});\n}\n\n/**\n * Reset form\n * @param form\n * @param initialValues new baseline — omitted (or undefined), the form\n * keeps its current initialValues and fields simply return to them\n * (react-hook-form's reset-without-values semantics)\n * @param options keep-flags to preserve slices of state through the reset\n */\nexport function reset(\n form: Form,\n initialValues?: any,\n options?: ResetOptions\n): void {\n // Snapshot the live values being preserved before the wipe: dirtiness\n // is measured against the pre-reset initialValues, so capture must\n // happen before form.values and form.initialValues are touched. The\n // snapshot carries structured segments, not dotted strings — a name\n // segment may itself contain '.' or quotes, and the dotted spelling does\n // not round-trip through the parser (dotted keys stay display-only, like\n // getDirtyFields' output). keepValues keeps every live value; the older\n // keepDirtyValues narrows the same snapshot to fields whose value\n // differs from their effective baseline.\n const keptValues: {segments: PathSegments; value: any}[] = [];\n if (options?.keepValues) {\n // Every leaf of the CURRENT merged tree — live edits and clean\n // baseline fields alike — is written back after the wipe, so a field\n // that never had a live edit keeps its pre-reset value instead of\n // adopting the new baseline's.\n collectValueLeaves(getValues(form), [], keptValues);\n } else if (options?.keepDirtyValues) {\n for (const [key, value] of form.values) {\n const segments = JSON.parse(key) as PathSegments;\n // Same predicate as getDirtyFields/forEachDirtyField: a live value\n // differing from its effective baseline (committed baselines read\n // clean and are not kept).\n if (getDirtyBaseline(form, key, segments) !== value) {\n keptValues.push({segments, value});\n }\n }\n }\n // Omitting values is a return-to-initialValues reset, not a wipe: an\n // undefined baseline would make getValues() return undefined (and every\n // consumer of it crash), so the current baseline survives when no new\n // one is provided.\n form.initialValues = options?.keepDefaultValues\n ? form.initialValues\n : (initialValues ?? form.initialValues);\n // The fresh baseline drops any schema parse from the previous cycle.\n form.parsedValues = undefined;\n if (!options?.keepErrors) clearErrors(form);\n const {emitter, touched, values, deleted, validating} = form;\n values.clear();\n deleted.clear();\n clearDirtyBaselines(form);\n if (!options?.keepTouched) touched.clear();\n validating.clear();\n if (!options?.keepIsSubmitting) form.isSubmitting = false;\n if (!options?.keepSubmitCount) form.submitCount = 0;\n if (!options?.keepIsSubmitted) form.isSubmitted = false;\n if (!options?.keepIsSubmitSuccessful) form.isSubmitSuccessful = undefined;\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n // Write the kept values back over the fresh baseline: plain\n // setValueByPath, so no validation fires and nothing is marked touched.\n for (const {segments, value} of keptValues) {\n setValueByPath(form, createPath(segments), value);\n }\n emit(emitter, 'change');\n emit(emitter, 'touched');\n emit(emitter, 'validating');\n emit(emitter, 'submitting');\n emit(emitter, 'submitCount');\n emit(emitter, 'submitSuccessful');\n emit(emitter, 'reset');\n}\n\n/** Options accepted by {@link resetField}. The flags default to `false`;\n * `value` has no default — omitted, the field falls back to initialValues;\n * provided, the explicit value becomes the live value with no fallback at\n * all. Mirrors react-hook-form's resetField options (`value` plays their\n * `defaultValue`'s role) to ease migration. */\nexport type ResetFieldOptions = {\n /** Keep the field's touched flag instead of clearing it. */\n keepTouched?: boolean;\n /** Keep the field's errors instead of clearing them. */\n keepErrors?: boolean;\n /** Explicit post-reset value for the field — never falls back to\n * initialValues. */\n value?: any;\n};\n\n/**\n * Reset a single field: drop its live value (reads fall back to the\n * baseline — initialValues, or the schema's parsed output when one\n * exists, in which case the path is removed from parsedValues and the\n * initial value pinned back so the field reads initialValues again),\n * clear its touched flag and errors, and revive the path's removal\n * tombstones — the inverse of {@link removeFieldByPath}. Other fields\n * and the submission flags are untouched; see {@link reset} for the\n * form-wide counterpart.\n *\n * @param form\n * @param name\n * @param options\n */\nexport function resetField<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P, options?: ResetFieldOptions): void {\n const path = createPath(name);\n const {emitter, values, touched, errors, deleted} = form;\n values.delete(path.key);\n // The field returns to its baseline; commits from before the reset no\n // longer shadow the comparison.\n clearDirtyBaselines(form, path.key);\n // A parse baseline wholesale-shadows initialValues in reads (see\n // getValues), so unset alone would read the path as undefined. Remove\n // the path from the tree (immutable — parsedValues shares branches with\n // the schema's own output) and pin the initial value back as the live\n // value: equal to initialValues, so the field stays clean.\n if (form.parsedValues !== undefined) {\n form.parsedValues = unset(form.parsedValues, path.value);\n const initial = get(form.initialValues, path.value);\n if (initial !== undefined) values.set(path.key, initial);\n }\n if (options && 'value' in options) {\n values.set(path.key, options.value);\n }\n // A reset re-registers the branch, same as a write: tombstones on the\n // path or around it stop applying.\n reviveBranch(deleted, path);\n // Payload-less by design (unlike removeFieldByPath, whose mutations are\n // key-bounded): reviveBranch can un-tombstone ancestor or descendant\n // paths, whose readers must re-sync too.\n emit(emitter, 'change');\n if (!options?.keepTouched && touched.delete(path.key)) {\n emit(emitter, 'touched', path);\n }\n if (!options?.keepErrors && errors.delete(path.key)) {\n emit(emitter, 'errors', path);\n }\n bumpDirtyVersion(form);\n bumpValuesVersion(form);\n}\n\n/**\n * @param form\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport {isIndex, isPromise, normalizePath, waitUntil} from '../util';\nimport type {\n FieldError,\n FieldErrorEntry,\n Form,\n ValidationMode,\n ValidateResult,\n ValidationOutcome\n} from '../form';\nimport {\n VALIDATION_OUTCOME,\n getErrors,\n getFirstError,\n hasErrors,\n setError,\n setErrorByPath\n} from './errors';\nimport {hasTouchedByPath, setTouchedByPath} from './touched';\nimport {getValueByPath, getValues} from './values';\nimport {isFieldError, isSegmentsPath, setParsedValues} from './internals';\n\nexport function unsetValidatingByPath(\n {emitter, validating}: Form,\n path: Path\n): void {\n validating.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'validating', path);\n}\n\nexport function setValidatingByPath(\n {emitter, validating}: Form,\n path: Path\n): void {\n validating.add(path.key);\n emit(emitter, 'validating', path);\n}\n\n/**\n * Field validator. Returns an error (a string, a FieldError, or an array\n * mixing both) or undefined when valid; may return a Promise for async\n * validation.\n *\n * The second argument carries the validation context. `meta.signal` is\n * aborted as soon as the round is superseded — a newer round started, or\n * the field unregistered — so async validators can cancel their underlying\n * work (fetch, timers) instead of racing a stale result home. Stale\n * results are dropped independently by the registration's lock\n * ({@link registerValidatorByPath}), so validators that ignore the signal\n * stay correct too. Validators written against the older two-argument\n * signature keep working.\n */\nexport type Validator = (\n value: any,\n meta: {form: Form; path: Path; signal: AbortSignal}\n) =>\n | string\n | FieldError\n | (string | FieldError)[]\n | undefined\n | Promise<string | FieldError | (string | FieldError)[] | undefined>;\n\n/**\n * Synchronous pre-validator for {@link registerValidatorByPath}'s `sync`\n * accessor — declarative `required` rules compiled by `rulesToValidator`\n * in practice, but any sync-only check works. Runs on every kick, never\n * debounced: its errors land immediately and, while present,\n * short-circuit the debounced validator for that kick (the expensive\n * check never sees a value the gate already rejects). Must be synchronous\n * — unlike a {@link Validator} it may not return a Promise — and its meta\n * carries no `signal`: there is nothing to abort in a synchronous check.\n */\nexport type SyncValidator = (\n value: any,\n meta: {form: Form; path: Path}\n) => string | FieldError | (string | FieldError)[] | undefined;\n\n/** Live options for {@link registerValidatorByPath}: read at every kick\n * through accessors, so callers (React's `useValidate`) can swap the\n * validator/debounce/sync-gate per render without re-subscribing the\n * registration mid-flight. */\nexport type ValidatorRegistration = {\n /** Current debounced validator (or undefined — a sync-only\n * registration). */\n validate: () => Validator | undefined;\n /** Debounce delay in milliseconds; 0 (default) runs immediately. */\n debounce: () => number;\n /** Synchronous pre-validator, run on every kick (never debounced). */\n sync: () => SyncValidator | undefined;\n /** Whether the debounced validator still runs when the sync gate\n * failed — TanStack Form's `asyncAlways`: the gate's errors land\n * immediately (never debounced), then the validator's own result lands\n * alongside them (per-source semantics) instead of the gate\n * short-circuiting the whole kick. Optional — absent means false\n * (gate failure owns the kick's outcome), so pre-existing\n * framework-free registrations keep working unchanged. */\n asyncAlways?: () => boolean;\n};\n\n/**\n * Register a field validator's kick at `path` in {@link Form.validators}\n * — the framework-free machinery behind `useValidate`. Returns a\n * disposer that drops the registration and cancels any pending debounce\n * window or in-flight round (its signal aborts and its validating mark\n * is released).\n *\n * Contract of the registered kick (the same contract `trigger` /\n * `ensureValidate` rely on when they run every entry, and the\n * user-change gate relies on when it runs the changed path's entry):\n * - the `sync` gate runs immediately on every kick — never debounced —\n * and while it returns errors, the debounced validator is skipped for\n * that kick and any pending window or in-flight round is superseded —\n * unless `asyncAlways` is set, in which case the validator still runs\n * and its result lands alongside the gate's errors (per-source);\n * - a positive `debounce` merges kicks inside the window: only the last\n * one runs the validator, and while the timer is pending the field\n * counts as validating so `trigger`/`ensureValidate` wait it out;\n * - async results land under a lock: a superseded round's outcome —\n * rejection included — is dropped, and only the owning round releases\n * the validating mark;\n * - a synchronous throw inside the validator propagates to the caller\n * (the validating mark is not left stuck behind it).\n *\n * Registering at a path already registered by another mount replaces it\n * (last-wins, the historical `useValidate` behavior); the disposer drops\n * its own registration unconditionally.\n *\n * @param form\n * @param path\n * @param registration live validator/debounce/sync accessors\n * @return disposer: unregister and cancel pending work\n */\nexport function registerValidatorByPath(\n form: Form,\n path: Path,\n registration: ValidatorRegistration\n): () => void {\n // The pending debounce timer and the current round's controller live in\n // this closure so the disposer below can cancel them.\n let timer: ReturnType<typeof setTimeout> | null = null;\n let controller: AbortController | null = null;\n // Whether this registration currently holds the path's slot in\n // form.validating. The mark is taken when a debounce window opens or an\n // async round starts, and released by whichever round settles last —\n // including a later sync round that supersedes an in-flight async one\n // (its own .finally is lock-gated out by then).\n let marked = false;\n // The async-round lock: only the latest round may land its result or\n // release the mark; a superseded round's outcome is dropped wholesale.\n let lock: object | null = null;\n // Which source wrote the error currently on display — the sync gate or\n // the debounced validator. Tracked so a passing sync check can clear\n // its own stale error immediately instead of leaving it on screen until\n // the debounced round lands. External writers (setError, form-level\n // validate) are invisible here; a passing round clearing them matches\n // the long-standing \"a field validator owns its whole key\" contract.\n let errorSource: 'sync' | 'validator' | null = null;\n /** Does a validator result land errors? `[]` normalizes away exactly\n * like undefined in setErrorByPath. */\n const hasErrors = (errors: any): boolean =>\n errors !== undefined && !(Array.isArray(errors) && errors.length === 0);\n const mark = () => {\n if (marked) return;\n marked = true;\n setValidatingByPath(form, path);\n };\n const unmark = () => {\n if (!marked) return;\n marked = false;\n unsetValidatingByPath(form, path);\n };\n\n /** Run the synchronous gate on the field's current value. Its errors\n * land immediately — the gate is never debounced. Returns true when\n * errors landed (the kick's whole outcome for the debounced validator).\n * A passing gate clears the field's errors when they were its own from\n * an earlier kick, or when no debounced validator exists to own the\n * round. */\n const runSync = (): boolean => {\n const sync = registration.sync();\n if (!sync) return false;\n const errors = sync(getValueByPath(form, path), {form, path});\n if (!hasErrors(errors)) {\n // A stale error the gate itself wrote is answered by the gate\n // alone; a rules-only registration's passing check is the whole\n // round. With a debounced validator registered, its upcoming round\n // owns the outcome and lands it later.\n if (!registration.validate() || errorSource === 'sync') {\n setErrorByPath(form, path, undefined);\n errorSource = null;\n }\n return false;\n }\n setErrorByPath(form, path, errors);\n errorSource = 'sync';\n return true;\n };\n\n /** Re-run the sync gate purely for its error list — no store write.\n * asyncAlways landings merge it with the validator's result so each\n * source keeps its own errors on display (TanStack's per-source\n * errorMap shape); the non-asyncAlways path never calls this. */\n const collectSyncErrors = (): (string | FieldError)[] | null => {\n const sync = registration.sync();\n if (!sync) return null;\n const errors = sync(getValueByPath(form, path), {form, path});\n if (errors === undefined) return null;\n const list = Array.isArray(errors) ? errors : [errors];\n return list.length ? list : null;\n };\n\n /** Land a validator result. asyncAlways merges the gate's current\n * verdict (re-collected — the value may have drifted since the round\n * started) ahead of the validator's errors, so a still-failing gate\n * keeps its own errors on screen; the default path stays the\n * historical \"validator owns the whole key\" write. */\n const land = (\n result: string | FieldError | (string | FieldError)[] | undefined\n ): void => {\n if (registration.asyncAlways?.()) {\n const gate = collectSyncErrors();\n const own =\n result === undefined ? [] : Array.isArray(result) ? result : [result];\n setErrorByPath(form, path, [...(gate ?? []), ...own]);\n errorSource = hasErrors(result) ? 'validator' : gate ? 'sync' : null;\n } else {\n setErrorByPath(form, path, result);\n errorSource = hasErrors(result) ? 'validator' : null;\n }\n };\n\n /** Drop any pending window or in-flight round without landing it: the\n * sync gate now owns the outcome, so the debounced validator must not\n * run for this value. */\n const supersede = () => {\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n controller?.abort();\n lock = {};\n };\n\n /** Run the debounced validator on the field's current value and land\n * its result — the sync gate has already passed. */\n const runValidator = () => {\n const fn = registration.validate();\n if (!fn) {\n unmark();\n return;\n }\n // Abort the superseded round's signal: a listening validator should\n // stop its underlying work. The lock refresh below independently\n // drops any result that still arrives, signal or not.\n controller?.abort();\n controller = new AbortController();\n const round = (lock = {});\n let result;\n try {\n result = fn(getValueByPath(form, path), {\n form,\n path,\n signal: controller.signal\n });\n } catch (e) {\n // A throwing sync validator propagates to the caller as it always\n // has; just don't leave the validating mark stuck behind it.\n unmark();\n throw e;\n }\n if (!isPromise(result)) {\n land(result);\n // Error first, then release the mark: 'validating' subscribers\n // (trigger) re-read state on wake and must see the landed error.\n unmark();\n return;\n }\n mark();\n result\n .then(\n (error: string | FieldError | (string | FieldError)[] | undefined) => {\n if (lock === round) {\n land(error);\n }\n }\n )\n // A rejected round is the normal way a signal-listening validator\n // gives up (fetch throws AbortError once aborted); swallow it and\n // let the owning round write the outcome.\n .catch(() => {})\n .finally(() => {\n if (lock === round) {\n unmark();\n lock = null;\n }\n });\n };\n\n /** A debounce window fired: the value may have drifted since the last\n * kick (programmatic writes do not kick validators), so re-run the\n * sync gate before spending the debounced validator on a value the\n * gate already rejects. Under asyncAlways a failing gate does not own\n * the outcome — the validator still runs and both verdicts land. */\n const run = () => {\n timer = null;\n if (runSync() && !registration.asyncAlways?.()) {\n supersede();\n unmark();\n return;\n }\n runValidator();\n };\n\n const kick = () => {\n if (runSync() && !registration.asyncAlways?.()) {\n supersede();\n unmark();\n return;\n }\n if (!registration.validate()) return;\n const debounce = registration.debounce();\n if (debounce > 0) {\n // Only the last kick inside the window runs: restart the timer on\n // every kick. The mark keeps trigger/ensureValidate's\n // validating-set wait covering the pending timer, not just\n // in-flight promises.\n if (timer !== null) clearTimeout(timer);\n else mark();\n timer = setTimeout(run, debounce);\n return;\n }\n runValidator();\n };\n\n form.validators.set(path.key, kick);\n return () => {\n form.validators.delete(path.key);\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n unmark();\n controller?.abort();\n };\n}\n\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n */\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\nexport type TriggerOptions = {\n /** Mark every path in the triggered scope as touched — even when\n * validation fails — once the round settles. Mirrors react-hook-form's\n * trigger `shouldTouch`. Defaults to `false`. */\n shouldTouch?: boolean;\n /**\n * Focus the first errored field in the triggered scope once the round\n * settles (and only when the round left errors) — react-hook-form's\n * trigger `shouldFocus` counterpart. Rides the 'focusError' event\n * channel like a failed submit's auto-focus: only mounted bound fields\n * react, unmounted ones are silent no-ops. Without `name` the first key\n * of the errors Map wins (the same rule handleSubmit applies); with\n * `name` the first errored triggered key does. Defaults to `false`.\n */\n shouldFocus?: boolean;\n};\n\n/**\n * Trigger field validation.\n *\n * Without `name` every registered field validator runs. A single `name` —\n * dotted string or segments array — runs only that field's validator, and\n * an array of names runs each one in order. An empty array is a no-op, as\n * is any name with no registered validator. An array argument counts as\n * one segments path only when it mixes in numbers (`['items', 0]`); pure\n * string arrays are name lists, so `['a', 'b']` triggers fields `a` and\n * `b`, not the nested path `a.b`.\n *\n * `options.shouldTouch` marks the triggered scope — the given names, or\n * every registered field when `name` is omitted — as touched after the\n * round settles, whether validation passed or failed. The wait/settle\n * logic is untouched: the marking rides on top of the settled round, so\n * subscribers observe errors and touched together rather than mid-flight.\n *\n * The returned promise waits for the triggered validation to settle —\n * async validators included — so their errors have already landed in\n * `form.errors` when it resolves. It never rejects: landing errors is the\n * expected outcome here, not a failure. Resolves `true` when the triggered\n * scope is error-free, `false` otherwise. Without `name` the scope is all\n * fields plus the form-level `validate` result (which runs after field\n * validators settle, same pipeline as {@link ensureValidate}); with `name`\n * only those fields' own errors count and form-level `validate` is\n * skipped (RHF semantics).\n *\n * Fire-and-forget callers may ignore the promise: the validator kicks\n * still happen synchronously, matching the pre-promise behavior.\n *\n * @param form\n * @param name field name(s) to trigger, or all fields when omitted\n * @param options extra behavior toggles ({@link TriggerOptions}); omitted,\n * validation alone runs — no touched marking\n * @return whether the triggered scope is error-free once validation settles\n */\nexport async function trigger(\n form: Form,\n name?: Name | Name[],\n options?: TriggerOptions\n): Promise<boolean> {\n // Never reject (an error landing is a normal outcome, not a failure), so\n // waitUntil's isReject is permanently false. Without a name the wait is\n // deliberately conservative — every FIELD validator, unrelated in-flight\n // ones included, because the round covers the whole form (and the\n // form-level validate's own window is excluded via fieldsSettled —\n // callers wait that out through the kick's promise instead, so a pending\n // window never gates the next kick). With a name the wait narrows to the\n // triggered keys only: a slow async validator on field B must not hold\n // trigger('a') hostage when the round never reads B.\n const settle = (keys?: string[]) =>\n waitUntil(\n form.emitter,\n 'validating',\n () =>\n keys === undefined\n ? fieldsSettled(form)\n : keys.every(key => !form.validating.has(key)),\n () => false\n );\n\n if (name === undefined) {\n form.validators.forEach(validator => validator());\n await settle();\n if (form.validate) await runFormValidate(form);\n // shouldTouch marks the whole registered scope — every key the round\n // could have validated — pass or fail alike.\n if (options?.shouldTouch) touchKeys(form, [...form.validators.keys()]);\n // First error across the errors Map — the same rule a failed submit's\n // auto-focus applies (a form-level error may land first; it has no\n // element, so it is a silent no-op like every unbound path).\n if (options?.shouldFocus) {\n const firstKey = form.errors.keys().next().value;\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n return !hasErrors(form);\n }\n\n const keys: string[] =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name).key]\n : name.map(one => createPath(one).key);\n keys.forEach(key => form.validators.get(key)?.());\n await settle(keys);\n if (options?.shouldTouch) touchKeys(form, keys);\n // Focus the first errored key among the triggered scope — trigger('a')\n // never focuses B's pre-existing error.\n if (options?.shouldFocus) {\n const firstKey = keys.find(key => form.errors.has(key));\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n return keys.every(key => !form.errors.has(key));\n}\n\n/** trigger's `shouldTouch` marking: touch every key in the triggered scope\n * through {@link setTouchedByPath}, which no-ops on already-touched keys\n * and emits the path-carrying 'touched' event per newly touched one. Keys\n * are the stored JSON-stringified segments shape, so parse them back into\n * Path — normalizePath passes segment arrays through untouched, making the\n * key round-trip exact. */\nfunction touchKeys(form: Form, keys: string[]): void {\n keys.forEach(key => setTouchedByPath(form, createPath(JSON.parse(key))));\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n */\nfunction setFormErrors(\n form: Form,\n result: Record<string, any>,\n segments: PathSegments = [],\n footprint?: Map<string, FieldError[]>\n): void {\n Object.entries(result).forEach(([key, value]) => {\n // Error-tree keys are explicit object keys, not path expressions:\n // a numeric key ('0' — Standard Schema issue paths stringify array\n // indices) stays a literal string segment instead of feeding the\n // path parser, whose dotted-numeric rule governs path strings only.\n const path: PathSegments = [\n ...segments,\n ...(isIndex(key) ? [key] : normalizePath(key))\n ];\n if (typeof value === 'string') {\n if (value) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n }\n } else if (Array.isArray(value)) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n } else if (isFieldError(value)) {\n setError(form, path, value);\n recordFootprint(form, path, footprint);\n } else if (value && typeof value === 'object') {\n setFormErrors(form, value, path, footprint);\n }\n });\n}\n\n/** Record one leaf write of a form-level validate round: the path key and\n * the exact array now stored there. Nothing is recorded when the write\n * normalized away (all-empty arrays) — there is no error to own. The\n * stored array is read back from the errors Map because setErrorByPath\n * owns normalization. */\nfunction recordFootprint(\n form: Form,\n segments: PathSegments,\n footprint: Map<string, FieldError[]> | undefined\n): void {\n if (!footprint) return;\n const path = createPath(segments);\n const stored = form.errors.get(path.key);\n if (stored) footprint.set(path.key, stored);\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\nfunction applyValidateResult(\n form: Form,\n result: ValidateResult<any> | undefined\n): void {\n const footprint = form.validateDeps ? getFormErrorFootprint(form) : undefined;\n if (footprint) {\n clearFormValidateErrors(form, footprint);\n footprint.clear();\n }\n if (!result) return;\n if (typeof result === 'object' && VALIDATION_OUTCOME in result) {\n const outcome = result as ValidationOutcome<any>;\n if (outcome.errors) setFormErrors(form, outcome.errors, [], footprint);\n setParsedValues(form, outcome.values);\n return;\n }\n setFormErrors(form, result as Record<string, any>, [], footprint);\n}\n\n/** Per-form error footprint of the last form-level validate round: every\n * path key it flattened onto, with the exact array instance it stored.\n * Tracked only for forms that opted into `validateDeps` — held in a\n * WeakMap so the Form shape and the non-opted pipeline stay untouched. */\nconst formErrorFootprints = new WeakMap<Form, Map<string, FieldError[]>>();\n\nfunction getFormErrorFootprint(form: Form): Map<string, FieldError[]> {\n let footprint = formErrorFootprints.get(form);\n if (!footprint) {\n footprint = new Map();\n formErrorFootprints.set(form, footprint);\n }\n return footprint;\n}\n\n/** Does the form still show an error the last form-level round wrote?\n * Compared by identity, not key membership: once a field validator,\n * `setServerErrors`, a manual `setError` or `clearErrors` replaces the\n * stored array, that error is no longer the round's to own — neither the\n * dep-change gate nor the next round's clearing may touch it. */\nfunction hasFormValidateErrors(form: Form): boolean {\n const footprint = formErrorFootprints.get(form);\n if (!footprint) return false;\n for (const [key, written] of footprint) {\n if (form.errors.get(key) === written) return true;\n }\n return false;\n}\n\n/** Drop the last form-level round's errors before the next round lands.\n * Per key the stored array is identity-checked — an error overwritten or\n * cleared by anyone else in between survives — and each drop emits the\n * same path-payload 'errors' event {@link setErrorByPath} would, so\n * subscribed fields re-render exactly like on any error write. */\nfunction clearFormValidateErrors(\n form: Form,\n footprint: Map<string, FieldError[]>\n): void {\n for (const [key, written] of footprint) {\n const stored = form.errors.get(key);\n if (stored !== written) continue;\n form.errors.delete(key);\n emit(form.emitter, 'errors', createPath(JSON.parse(key)));\n }\n}\n\n/** Key the form-level validate round reserves in `form.validating` while\n * its debounce window is pending or its async round is in flight. Real\n * path keys are JSON-stringified segments (always bracketed), so a bare\n * word can never collide. */\nconst FORM_VALIDATING_KEY = '__form_validate__';\n\n/** Are all FIELD validation rounds drained? trigger/ensureValidate wait on\n * this before kicking the form-level validate (its errors gate whether the\n * form-level round may run at all). The form validate's own reserved key\n * is deliberately excluded: its window is waited out through the kick's\n * returned promise instead, so a pending window or in-flight form round\n * never gates the next kick — a kick during an in-flight round opens a\n * new window and the newer round supersedes, mirroring the per-field\n * `validateDebounce` contract. */\nfunction fieldsSettled(form: Form): boolean {\n for (const key of form.validating) {\n if (key !== FORM_VALIDATING_KEY) return false;\n }\n return true;\n}\n\n/** Sentinel telling {@link settleFormValidate} the round landed cleanly —\n * distinct from every rejection payload, including `undefined`. */\nconst SETTLED = Symbol('form-validate-settled');\n\n/** Per-form bookkeeping for the debounced form-level validate: the\n * pending window timer, the in-flight round, and the waiters merged into\n * the current window group. Held in a WeakMap so the Form instance shape\n * is untouched for forms that never set `validateDebounce`. */\ntype FormValidateState = {\n timer: ReturnType<typeof setTimeout> | null;\n controller: AbortController | null;\n /** Identity of the in-flight round; a superseded round's outcome\n * (rejection included) is dropped by comparing against it. */\n round: object | null;\n /** Whether this state currently holds FORM_VALIDATING_KEY in\n * form.validating. */\n marked: boolean;\n waiters: Array<{resolve: () => void; reject: (error: unknown) => void}>;\n};\n\nconst formValidateStates = new WeakMap<Form, FormValidateState>();\n\nfunction getFormValidateState(form: Form): FormValidateState {\n let state = formValidateStates.get(form);\n if (!state) {\n state = {\n timer: null,\n controller: null,\n round: null,\n marked: false,\n waiters: []\n };\n formValidateStates.set(form, state);\n }\n return state;\n}\n\n/**\n * Run the form-level `validate` and land its result, honoring the form's\n * `validateDebounce` option.\n *\n * Undebounced (`0`/undefined) the caller's await *is* the validate call —\n * the long-standing pipeline, unchanged: no validating mark, no round\n * gating, immediate values snapshot, rejection propagating to the caller.\n *\n * Debounced, the kick opens (or restarts — kicks inside the window merge)\n * a window during which the form counts as validating, so `trigger` /\n * `ensureValidate` / submit wait the window out exactly like a field's\n * `validateDebounce` window. When the timer fires, the round reads the\n * then-current values, supersedes (aborts) any in-flight round, and lands\n * its result. The returned promise settles once the window group's final\n * round has landed — rejecting when that round's validate callback threw\n * or its promise rejected, mirroring the undebounced propagation — so\n * merged callers all observe the same outcome.\n *\n * Only called under `if (form.validate)`. Public: the form-level-only\n * round (field validators excluded) — `useForm`'s `validateOnMount` run\n * and cross-cutting re-checks use it; `trigger`/`ensureValidate` compose\n * it after the field validators settle.\n */\nexport function runFormValidate(form: Form): Promise<void> {\n const validate = form.validate;\n if (!validate) return Promise.resolve();\n const debounce = form.validateDebounce ?? 0;\n if (debounce <= 0) {\n // Standalone controller: nothing supersedes an undebounced call, so\n // its signal never fires — it exists for argument-shape parity with\n // the debounced rounds (and with field-level meta.signal).\n const controller = new AbortController();\n return Promise.resolve(\n validate(getValues(form), {form, signal: controller.signal})\n ).then(result => {\n applyValidateResult(form, result);\n });\n }\n const state = getFormValidateState(form);\n // (Re)open the window: a kick while the timer is pending restarts it\n // (only the last kick's values run); one while a round is in flight\n // keeps the validating mark held and defers to the new window's round.\n if (state.timer !== null) clearTimeout(state.timer);\n else {\n state.marked = true;\n form.validating.add(FORM_VALIDATING_KEY);\n emit(form.emitter, 'validating');\n }\n state.timer = setTimeout(() => {\n state.timer = null;\n const round = (state.round = {});\n runFormValidateRound(form, state, round).then(\n () => settleFormValidate(form, state, round, SETTLED),\n error => settleFormValidate(form, state, round, error)\n );\n }, debounce);\n return new Promise<void>((resolve, reject) => {\n state.waiters.push({resolve, reject});\n });\n}\n\n/** Run one form-level validate round with the form's current values.\n * Aborts the previous in-flight round's signal; a superseded round's\n * outcome — rejection included — is dropped by the round gate, exactly\n * like the field-level lock. */\nfunction runFormValidateRound(\n form: Form,\n state: FormValidateState,\n round: object\n): Promise<void> {\n const validate = form.validate;\n if (!validate) return Promise.resolve();\n state.controller?.abort();\n const controller = (state.controller = new AbortController());\n let outcome: Promise<any>;\n try {\n outcome = Promise.resolve(\n validate(getValues(form), {form, signal: controller.signal})\n );\n } catch (error) {\n outcome = Promise.reject(error);\n }\n return outcome.then(\n result => {\n if (state.round === round) applyValidateResult(form, result);\n },\n error => {\n if (state.round === round) throw error;\n }\n );\n}\n\n/** Land the window group's outcome: release the validating mark — after\n * the round's errors/values have already landed, because 'validating'\n * subscribers (trigger, ensureValidate) re-read state on wake — and\n * settle every merged waiter. A superseded round never lands here (the\n * newer round owns the release), and a window that re-opened while the\n * round was in flight defers: the mark and the waiters carry over to the\n * pending timer's round. */\nfunction settleFormValidate(\n form: Form,\n state: FormValidateState,\n round: object,\n outcome: unknown\n): void {\n if (state.round !== round) return;\n state.round = null;\n if (state.timer !== null) return;\n if (state.marked) {\n state.marked = false;\n form.validating.delete(FORM_VALIDATING_KEY);\n emit(form.emitter, 'validating');\n }\n const waiters = state.waiters;\n state.waiters = [];\n for (const waiter of waiters) {\n if (outcome === SETTLED) waiter.resolve();\n else waiter.reject(outcome);\n }\n}\n\n/**\n * Form-level twin of the gated validator kick in `useField`'s onChange:\n * re-run the form-level `validate` after a user change to a field listed\n * in `validateDeps`. Called from the field's own change pipeline (typing\n * and `changeValue` alike — both route through the mounted field's\n * onChange), so programmatic `setValue` writes do not re-run it, exactly\n * like they do not re-run field validators.\n *\n * The gate mirrors the per-field matrix with the *changed field's*\n * effective `mode` (a per-field override governs when its changes may\n * fire validation) and the form-level `reValidateMode` against the last\n * round's error footprint ({@link hasFormValidateErrors} — field\n * validators' errors never arm this kick):\n * - `mode` `'onChange'`/`'all'` — every dep change re-runs;\n * - `mode` `'onTouched'` — dep changes re-run once the field was touched;\n * - otherwise the re-run waits for `reValidateMode: 'onChange'` (the\n * default) while the last round's error is still live — the\n * submit-then-fix flow: the mismatch lands on submit, editing the\n * dependency re-runs the validate and clears it.\n * `reValidateMode: 'onBlur'`/`'onSubmit'` never re-run on a change (a\n * change is not a blur; submit re-runs are the submit pipeline's job).\n *\n * The kick is fire-and-forget: async round rejections are swallowed\n * (nothing in an event handler can await them), while a synchronous\n * throw inside the validate callback propagates to the caller exactly\n * like a field validator's does.\n *\n * A no-op unless the form set `validateDeps` listing `path` — forms\n * without the option pay one property check here.\n */\nexport function revalidateFormOnChange(\n form: Form,\n path: Path,\n mode: ValidationMode\n): void {\n if (!form.validateDeps?.has(path.key) || !form.validate) return;\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (form.reValidateMode === 'onChange' && hasFormValidateErrors(form))\n ) {\n runFormValidate(form).catch(() => {});\n }\n}\n\n/** Per-form registry of field-level `validateDeps` declarations ({@link\n * revalidateDependentsOnChange}): dep path key -> every dependent field key\n * that listed it. Held in a WeakMap so the Form shape is untouched for\n * forms whose fields never declare deps. */\nconst fieldValidateDeps = new WeakMap<Form, Map<string, Set<string>>>();\n\n/** Register one field's validateDeps declaration: `key` re-validates when\n * any path in `depKeys` takes a user change. Idempotent per (key, dep)\n * pair, so StrictMode's double effect is harmless. */\nexport function registerFieldValidateDeps(\n form: Form,\n key: string,\n depKeys: string[]\n): void {\n let deps = fieldValidateDeps.get(form);\n if (!deps) {\n deps = new Map();\n fieldValidateDeps.set(form, deps);\n }\n for (const depKey of depKeys) {\n let dependents = deps.get(depKey);\n if (!dependents) {\n dependents = new Set();\n deps.set(depKey, dependents);\n }\n dependents.add(key);\n }\n}\n\n/** Drop one field's validateDeps registration ({@link\n * registerFieldValidateDeps}). Entries nobody lists anymore are removed so\n * the registry never outlives its fields. */\nexport function unregisterFieldValidateDeps(\n form: Form,\n key: string,\n depKeys: string[]\n): void {\n const deps = fieldValidateDeps.get(form);\n if (!deps) return;\n for (const depKey of depKeys) {\n const dependents = deps.get(depKey);\n if (!dependents?.delete(key)) continue;\n if (!dependents.size) deps.delete(depKey);\n }\n}\n\n/**\n * Field-level twin of {@link revalidateFormOnChange}: after a user change\n * to `path`, re-run every field validator that declared `path` in its\n * `validateDeps` (useField option). Same channel, same gate: the kick\n * rides the changed field's own onChange pipeline (typing and\n * `changeValue` alike), so programmatic `setValue` writes never fire it —\n * exactly like field validators and the form-level `validateDeps`.\n *\n * The gate mirrors the form-level matrix with the *changed field's*\n * effective `mode` and the form-level `reValidateMode` against each\n * dependent's live error:\n * - `mode` `'onChange'`/`'all'` — every dep change re-runs the dependent;\n * - `mode` `'onTouched'` — once the changed field was touched;\n * - otherwise the re-run waits for `reValidateMode: 'onChange'` (the\n * default) while the dependent still shows an error — the\n * submit-then-fix flow: the mismatch lands on submit, editing the\n * dependency re-validates the dependent and a passing round clears it\n * (a field validator owns its whole key, so the re-run's result\n * replaces whatever the previous round wrote — the field-level shape\n * of the form-level footprint reclaim).\n *\n * The kick is an ordinary validator kick: the dependent's own\n * `validateDebounce` window applies, and a synchronous throw inside its\n * validate propagates to the caller like any field validator's would.\n *\n * A no-op unless some field declared `path` as a dep — forms without any\n * field-level `validateDeps` pay one property check here.\n */\nexport function revalidateDependentsOnChange(\n form: Form,\n path: Path,\n mode: ValidationMode\n): void {\n const dependents = fieldValidateDeps.get(form)?.get(path.key);\n if (!dependents?.size) return;\n for (const dependent of dependents) {\n // A self-dep changes nothing: the field's own onChange above already\n // validated it under the same gate.\n if (dependent === path.key) continue;\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (form.reValidateMode === 'onChange' && form.errors.has(dependent))\n ) {\n form.validators.get(dependent)?.();\n }\n }\n}\n\n/** The Error {@link ensureValidate} rejects with: `message` is the first\n * error's display text ({@link getFirstError}) — the long-standing shape\n * — and `.errors` carries the complete flattened error list ({@link\n * getErrors}: `{path, type, message}` entries, dotted display paths) so\n * catchers can branch on types and locate fields without re-reading the\n * form. */\nexport type FormValidationError = Error & {errors: FieldErrorEntry[]};\n\n/** Build {@link ensureValidate}'s rejection: first error's message, every\n * error attached. */\nfunction validationError(form: Form): FormValidationError {\n const error = new Error(getFirstError(form)) as FormValidationError;\n error.errors = getErrors(form);\n return error;\n}\n\n/**\n * Validate and throw if any field error.\n * @param form\n * @return resolve if no error; reject and stop validate if has an error\n */\nexport async function ensureValidate(form: Form): Promise<void> {\n form.validators.forEach(validator => validator());\n\n await waitUntil(\n form.emitter,\n 'validating',\n () => fieldsSettled(form),\n () => hasErrors(form)\n ).catch(() => {\n throw validationError(form);\n });\n\n if (form.validate) {\n await runFormValidate(form);\n if (hasErrors(form)) throw validationError(form);\n }\n}\n\n/**\n * Validate and return if any field error.\n * @param form\n * @return error message string or void\n */\nexport async function validate(form: Form): Promise<void | string> {\n return ensureValidate(form).catch(e => e.message);\n}\n","import createPath from '../path';\nimport type {Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport type {Form, ValidationMode} from '../form';\nimport {setValueByPath} from './values';\nimport type {SetFieldOptions} from './values';\nimport {revalidateFormOnChange, revalidateDependentsOnChange} from './validate';\nimport {hasTouchedByPath, setTouchedByPath} from './touched';\nimport {getFieldErrorsByPath} from './errors';\nimport {setDirtyBaseline} from './internals';\n\n/** Per-form registry of mounted fields' validation-mode overrides: path\n * key -> the field's `mode` option (undefined = follow {@link Form.mode})\n * plus an owner token so competing mounts at one path clean up safely.\n * Presence of an entry is the \"a field is mounted at this path\" signal\n * that routes {@link changeValueByPath} into the gated user-change\n * pipeline ({@link userChangeByPath}). Held in a WeakMap so the Form\n * shape carries only plain state fields. */\nconst fieldModes = new WeakMap<\n Form,\n Map<string, {mode: ValidationMode | undefined; token: object}>\n>();\n\n/**\n * Set a field value as a user change.\n *\n * The write rides the same gated user-change pipeline a user typing into\n * the field would fire when a field is mounted on the path (registered\n * through {@link registerFieldMode} — `useField` registers on mount): the\n * field's effective `mode` (per-field override included) and the form's\n * `reValidateMode` drive validation exactly as in {@link\n * userChangeByPath}. With no mounted field on the path it degrades to a\n * plain value set ({@link setValue}).\n *\n * This is the channel for component-library bridges that hand a control a\n * plain setter bound to a field — they cannot rebuild the gating from\n * public form state, because the per-field mode override and the\n * live-error view that gates `reValidateMode` live in the field\n * registration, not in public state.\n *\n * Contrast {@link setValue}: that is the imperative channel — its\n * `shouldValidate` option kicks the field's validator unconditionally,\n * ignoring any mode. Functional updaters are the caller's to evaluate\n * ({@link getValue}).\n *\n * `options` carries the same {@link SetFieldOptions}: on the fallback path\n * (no mounted field) they forward to {@link setValueByPath} wholesale,\n * while on the mounted-field path only `shouldDirty: false` applies — the\n * write lands as a commit while the field's own mode gating keeps driving\n * validation, which is the point of this channel.\n *\n * @param form\n * @param name\n * @param value\n * @param options\n */\nexport function changeValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n value: PathValueOf<T, P>,\n options?: SetFieldOptions\n): void {\n changeValueByPath(form, createPath(name), value, options);\n}\n\n/**\n * Set a field value as a user change, by parsed path\n * @param form\n * @param path\n * @param value\n * @param options\n */\nexport function changeValueByPath(\n form: Form,\n path: Path,\n value: any,\n options?: SetFieldOptions\n): void {\n // The baseline must land before the mounted field's change pipeline runs\n // — its write emits synchronously and subscribers read dirty state\n // inside the emission, so installing after the call would flash\n // dirty-then-clean.\n if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);\n if (fieldModes.get(form)?.get(path.key)) {\n // Mounted field: ride the gated user-change pipeline — the field's\n // own mode drives validation, so `shouldValidate`/`shouldTouch` have\n // no meaning here (forcing them would defeat the gating).\n userChangeByPath(form, path, value);\n } else {\n setValueByPath(form, path, value, options);\n }\n}\n\n/**\n * Register a mounted field's `mode` override at `path` for user-change\n * gating ({@link userChangeByPath} / {@link userBlur}). Returns the\n * registration token for {@link unregisterFieldMode} plus whether the\n * slot was already occupied — two fields mounted at one path is almost\n * always a bug: the latest mount's mode governs every user-change write\n * there, which the React layer warns about in DEV.\n *\n * @param form\n * @param path\n * @param mode the field's `mode` option, or undefined to follow\n * {@link Form.mode}\n * @return `token` to hand to {@link unregisterFieldMode}; `displaced`\n * true when a previous registration at the same path still owned\n * the slot\n */\nexport function registerFieldMode(\n form: Form,\n path: Path,\n mode: ValidationMode | undefined\n): {token: object; displaced: boolean} {\n let modes = fieldModes.get(form);\n if (!modes) {\n modes = new Map();\n fieldModes.set(form, modes);\n }\n const displaced = modes.has(path.key);\n const token = {};\n modes.set(path.key, {mode, token});\n return {token, displaced};\n}\n\n/** Drop a {@link registerFieldMode} registration. A later mount at the\n * same path keeps its slot: only the entry owned by `token` is removed. */\nexport function unregisterFieldMode(\n form: Form,\n path: Path,\n token: object\n): void {\n const modes = fieldModes.get(form);\n const entry = modes?.get(path.key);\n if (modes && entry && entry.token === token) modes.delete(path.key);\n}\n\n/** The user-change validation gate shared by a mounted field's onChange\n * and {@link changeValueByPath}: kick the field's validator, the\n * form-level `validateDeps` re-run and the field-level `validateDeps`\n * dependents under the mode/reValidateMode matrix. The live (stored)\n * error view arms the reValidate kick — an error hidden behind a render\n * layer's delayError window still counts, so typing can clear it before\n * it ever shows. */\nfunction runUserChangeGate(form: Form, path: Path, mode: ValidationMode): void {\n if (\n mode === 'onChange' ||\n mode === 'all' ||\n (mode === 'onTouched' && hasTouchedByPath(form, path)) ||\n (getFieldErrorsByPath(form, path).length > 0 &&\n form.reValidateMode === 'onChange')\n )\n form.validators.get(path.key)?.();\n // Form-level validate deps: a user change to a listed field re-runs the\n // form-level validate under the same mode/reValidateMode gating above\n // (evaluated against the last round's own error footprint). No-op for\n // forms without validateDeps.\n revalidateFormOnChange(form, path, mode);\n // Field-level validate deps: fields that declared this path re-run their\n // own validators under the same gate. No-op when nobody declared it.\n revalidateDependentsOnChange(form, path, mode);\n}\n\n/**\n * Write a bound field's user change by path: the write plus the\n * mode/reValidateMode-gated validation pipeline — what a bound field's\n * onChange does when the user types. Reads the effective mode from the\n * field-mode registry (the latest mount's override governs), so a plain\n * write happens when no field is registered at `path`. Framework\n * adapters (React's `useField`, a Solid binding) forward their field\n * change events here.\n *\n * @param form\n * @param path\n * @param value\n */\nexport function userChangeByPath(form: Form, path: Path, value: any): void {\n setValueByPath(form, path, value);\n const entry = fieldModes.get(form)?.get(path.key);\n if (entry) runUserChangeGate(form, path, entry.mode ?? form.mode);\n}\n\n/**\n * A bound field's blur: mark the path touched, then kick its validator\n * under the blur-side gate (`mode` `'onBlur'`/`'onTouched'`/`'all'`, or\n * `reValidateMode: 'onBlur'` while the field carries a live error). The\n * touched marking is unconditional — a field counts as touched on blur\n * regardless of mode. Framework adapters forward field blur events here.\n *\n * @param form\n * @param path\n */\nexport function userBlur(form: Form, path: Path): void {\n setTouchedByPath(form, path);\n const entry = fieldModes.get(form)?.get(path.key);\n if (!entry) return;\n const mode = entry.mode ?? form.mode;\n if (\n mode === 'onBlur' ||\n mode === 'onTouched' ||\n mode === 'all' ||\n (getFieldErrorsByPath(form, path).length > 0 &&\n form.reValidateMode === 'onBlur')\n )\n form.validators.get(path.key)?.();\n}\n\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\n","import {emit} from '../emitter';\nimport type {FieldErrorEntry, Form} from '../form';\nimport {getErrors} from './errors';\nimport {getValues} from './values';\nimport {validate} from './validate';\n\nexport function setIsSubmitting(form: Form, value: boolean): void {\n form.isSubmitting = value;\n emit(form.emitter, 'submitting');\n}\n\nexport function incrementSubmitCount(form: Form): void {\n form.submitCount++;\n emit(form.emitter, 'submitCount');\n}\n\nexport function setSubmitSuccessful(form: Form, value: boolean): void {\n form.isSubmitSuccessful = value;\n emit(form.emitter, 'submitSuccessful');\n}\n\n/**\n * Set the form-level disabled flag and emit a payload-less 'disabled'\n * event — subscribed fields (useField and the components built on it)\n * re-render with the merged disabled state: form flag || their own\n * `disabled` option.\n * @param form\n * @param value\n */\nexport function setDisabled(form: Form, value: boolean): void {\n form.disabled = value;\n emit(form.emitter, 'disabled');\n}\n\n/**\n * Set the form's user-owned metadata slot (Formik's `status` role): the\n * payload-less 'status' event wakes {@link useStatus} and any imperative\n * `subscribe(form, {event: 'status'})` listeners. Nothing else reads or\n * interprets the value — server session flags, step state, non-field\n * errors of any shape are all fair game. Starts `undefined`.\n * @param form\n * @param value\n */\nexport function setStatus(form: Form, value: any): void {\n form.status = value;\n emit(form.emitter, 'status');\n}\n\n/** Structural slice of a <form>-like element: an elements collection whose\n * controls expose the constraint-validation members we read. Matches the\n * DOM HTMLFormElement shape without coupling the core to DOM types. */\ntype NativeFormElement = {\n elements: ArrayLike<{\n name: string;\n checkValidity: () => boolean;\n validationMessage: string;\n }>;\n};\n\n/**\n * Converts a control's DOM name to the user-visible dotted path. Field\n * components render the path key (JSON.stringify'd segments, '[\"a\",\"0\"]')\n * as the name attribute, so JSON keys are parsed back and joined with\n * dots; any other name value is returned as-is.\n */\nfunction nameToPath(name: string): string {\n if (name.startsWith('[')) {\n try {\n const segments = JSON.parse(name);\n if (Array.isArray(segments)) return segments.join('.');\n } catch {\n // Not a JSON path key — fall through and use the raw name.\n }\n }\n return name;\n}\n\n/**\n * Collects the constraints failing native validation on a <form> as\n * {@link FieldErrorEntry} entries, in DOM order.\n *\n * Design note: native errors are deliberately NOT written into the form's\n * errors Map. That Map tracks custom validator state, while native\n * validity is transient DOM state owned by the browser (surfaced through\n * reportValidity); onInvalidSubmit receives this snapshot directly.\n */\nfunction getNativeErrors(formEl: NativeFormElement): FieldErrorEntry[] {\n const errors: FieldErrorEntry[] = [];\n const {elements} = formEl;\n for (let i = 0; i < elements.length; i++) {\n const el = elements[i];\n if (\n el.name &&\n typeof el.checkValidity === 'function' &&\n !el.checkValidity()\n ) {\n errors.push({\n path: nameToPath(el.name),\n type: 'native',\n message: el.validationMessage\n });\n }\n }\n return errors;\n}\n\n/** Submit callbacks for {@link handleSubmit}. All optional — a missing\n * callback is simply skipped, matching the <Form> component semantics. */\nexport type HandleSubmitOptions<T extends Record<string, any> = any> = {\n /** Called after validation passes, before onValidSubmit. */\n onSubmit?: (values: T, e?: any) => void | Promise<void>;\n /** Called after validation passes, following a successful onSubmit. */\n onValidSubmit?: (values: T, e?: any) => void | Promise<void>;\n /**\n * Called when validation fails.\n * @param errors array of {path, type, message} entries in insertion\n * order; path is the dotted field path ('a.b', 'list.0'), type is\n * the error kind ('custom' for plain string errors, 'native' for\n * failed DOM constraint validation), message is the display text\n * @param values current form values\n */\n onInvalidSubmit?: (errors: FieldErrorEntry[], values: T) => void;\n /**\n * Called after validation passes and the submit callbacks ran, with the\n * final (schema-coerced) values — the slot <Form>'s `action` prop uses\n * to dispatch React 19 server actions with FormData. Runs inside the\n * same isSubmitting window and is awaited like onSubmit/onValidSubmit.\n */\n onAction?: (values: T, e?: any) => void | Promise<void>;\n /**\n * Focus the first error field after a failed submit. Defaults to true —\n * only an explicit `false` disables it. When custom validation fails,\n * a 'focusError' event carrying the first error's path key is emitted\n * on the form (bound fields such as <Field> subscribe and focus their\n * input); when native constraint validation fails, the submitted\n * form's first ':invalid' control is focused directly.\n */\n shouldFocusError?: boolean;\n};\n\n/**\n * Create an async submit handler for `form` — the headless counterpart of\n * the <Form> component's onSubmit wiring.\n *\n * Behavior mirrors <Form> exactly: preventDefault when present, then the\n * submit state machine (isSubmitting/submitCount/isSubmitSuccessful) runs\n * around native constraint validation (via `e.currentTarget.checkValidity`,\n * skipped when the target has no checkValidity — e.g. React Native or\n * toolbar-button submits) and custom validators. Failed validation fires\n * onInvalidSubmit with the flattened error entries; a passing submit runs\n * onSubmit then onValidSubmit. Errors thrown by either are swallowed into\n * isSubmitSuccessful=false rather than rejecting the returned promise.\n * Failed validation also focuses the offending field (see\n * {@link HandleSubmitOptions.shouldFocusError}).\n *\n * @param form form instance\n * @param options submit callbacks\n * @return async event handler, callable without an event object\n */\nexport function handleSubmit<T extends Record<string, any> = any>(\n form: Form<T>,\n options?: HandleSubmitOptions<T>\n): (e?: {preventDefault?: () => void; currentTarget?: any}) => Promise<void> {\n const {\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n onAction,\n shouldFocusError = true\n } = options ?? {};\n return async e => {\n if (e && typeof e.preventDefault === 'function') {\n e.preventDefault();\n }\n const formEl = e?.currentTarget;\n // Land the submitted flag before the isSubmitting flip: the single\n // 'submitting' emit setIsSubmitting fires carries both state changes\n // to FormState subscribers.\n form.isSubmitted = true;\n setIsSubmitting(form, true);\n incrementSubmitCount(form);\n const values = getValues(form);\n\n if (\n formEl &&\n typeof formEl.checkValidity === 'function' &&\n formEl.checkValidity() === false\n ) {\n formEl.reportValidity();\n // Focus the first natively-invalid control directly off the DOM;\n // native failures never enter the errors Map (see below).\n if (shouldFocusError && typeof formEl.querySelector === 'function') {\n const invalid = formEl.querySelector(':invalid') as HTMLElement | null;\n if (invalid && typeof invalid.focus === 'function') invalid.focus();\n }\n setIsSubmitting(form, false);\n setSubmitSuccessful(form, false);\n // Native constraint failures are read from the DOM (not the errors\n // Map, which only holds custom validation state — see getNativeErrors).\n if (onInvalidSubmit) onInvalidSubmit(getNativeErrors(formEl), values);\n return;\n }\n\n const error = await validate(form);\n\n if (error) {\n setIsSubmitting(form, false);\n setSubmitSuccessful(form, false);\n // Notify bound fields (e.g. <Field>) so the first errored one can\n // focus its input; the payload is the errors Map's first key.\n if (shouldFocusError) {\n const firstKey = form.errors.keys().next().value;\n if (firstKey !== undefined) emit(form.emitter, 'focusError', firstKey);\n }\n if (onInvalidSubmit) onInvalidSubmit(getErrors(form), values);\n return;\n }\n\n try {\n // Re-read after validation: a schema validator's parsed output\n // (ValidationOutcome.values) landed in parsedValues during\n // validate(), and the submit callbacks must see the coerced /\n // transformed values, not the raw pre-validation snapshot.\n const submitted = getValues(form);\n if (onSubmit) await onSubmit(submitted, e);\n if (onValidSubmit) await onValidSubmit(submitted, e);\n if (onAction) await onAction(submitted, e);\n setSubmitSuccessful(form, true);\n } catch {\n setSubmitSuccessful(form, false);\n } finally {\n setIsSubmitting(form, false);\n }\n };\n}\n\n/** Options accepted by {@link setFocus}. All flags default to `false`. */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name} from '../path';\nimport type {Form} from '../form';\n\n/** Options accepted by {@link setFocus}. All flags default to `false`. */\nexport type SetFocusOptions = {\n /** Select the field's text after focusing it. Bound fields call\n * `select()` on their element; elements without one (custom `as`\n * components) just focus. */\n shouldSelect?: boolean;\n};\n\n/**\n * Programmatically focus a bound field's element (e.g. the <Field>'s\n * input).\n *\n * Rides the same 'focusError' event channel a failed handleSubmit uses to\n * focus the first errored field: the payload is the target's path key,\n * with the focus options as a second, backward-compatible argument (older\n * subscribers declared with a single `key` parameter simply ignore it).\n * Being event-driven, it is a silent no-op when the field is unmounted or\n * nothing subscribes — unknown names never throw.\n *\n * @param form form instance\n * @param name field name (dot path or segments path)\n * @param options focus options\n */\nexport function setFocus(\n form: Form,\n name: Name,\n options?: SetFocusOptions\n): void {\n const {key} = createPath(name);\n // Omit the options argument when absent so the payload is exactly the\n // shape handleSubmit emits after a failed submit.\n if (options) emit(form.emitter, 'focusError', key, options);\n else emit(form.emitter, 'focusError', key);\n}\n","import {create as createEmitter, emit, setMaxListeners} from './emitter';\nimport type {EventEmitter} from './emitter';\nimport createPath from './path';\nimport type {Name, Path} from './path';\nimport type {FieldPath} from './types';\nimport {isPromise} from './util';\nimport {setInitialValues} from './core/values';\nimport type {SetFocusOptions} from './core/focus';\nimport type {VALIDATION_OUTCOME} from './core/errors';\n\n// The implementation is split by concern under ./core (values, errors,\n// touched, dirty, validate, change, submit, focus; module-private shared\n// state lives in ./core/internals, which is deliberately not re-exported).\n// This file keeps the public types and the create factory, and re-exports\n// every public function — the single import surface the rest of the\n// package (hooks, components, server, persist, resolvers) consumes.\nexport type {Name};\nexport type {FieldPath, PathValue} from './types';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/** A field error: `type` identifies the error kind ('custom' for plain\n * string errors), `message` is the display text. */\nexport type FieldError = {type: string; message: string};\n\n/** A flattened entry from {@link getErrors}. */\nexport type FieldErrorEntry = {path: string; type: string; message: string};\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\nexport type ValidationMode =\n 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';\n\n/** When a field is re-validated after it already has an error:\n * - `'onChange'` (default): on every change\n * - `'onBlur'`: when the field loses focus\n * - `'onSubmit'`: only on submit (no live re-validation)\n */\nexport type ReValidateMode = 'onChange' | 'onBlur' | 'onSubmit';\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted.\n *\n * The brand constant itself lives in the errors module (the leaf module of\n * the core dependency graph — every consumer imports it from there) and is\n * re-exported below with `export *`. */\nexport type ValidationOutcome<T> = {\n [VALIDATION_OUTCOME]: true;\n errors?: Record<string, any>;\n values?: T;\n};\n\n/** What a form-level validate function may return: a plain nested error\n * record (flattened into field errors — the long-standing shape), or a\n * branded {@link ValidationOutcome} whose `values` become the form's\n * parsedValues baseline. */\nexport type ValidateResult<T> =\n | Record<string, any>\n | ValidationOutcome<T>\n | Promise<Record<string, any> | ValidationOutcome<T>>;\n\n/** Context passed to a form-level `validate` function's second argument.\n * `signal` aborts as soon as the round is superseded — a newer round\n * started (which only happens under a positive `validateDebounce`, where\n * kicks merge into windows) — so async validators can cancel their\n * underlying work instead of racing a stale result home. Stale results\n * are dropped independently by the round gate, so validators that ignore\n * the signal stay correct too; the same contract field-level validators\n * get through their own `meta`. */\nexport type FormValidateMeta<T extends Record<string, any> = any> = {\n form: Form<T>;\n signal: AbortSignal;\n};\n\n/** Form-level validator: receives all values (plus {@link\n * FormValidateMeta} as an optional second argument) and returns a\n * {@link ValidateResult} — sync or async — or `undefined`/nothing when\n * valid (the runtime skips falsy results, so implicit-return callbacks\n * type-check). */\nexport type FormValidateFn<T extends Record<string, any> = any> = (\n values: T,\n meta: FormValidateMeta<T>\n) => ValidateResult<T> | undefined;\n\n/**\n * The emitter event table for {@link Form.emitter}: each event's payload\n * tuple. Path-carrying events declare an optional single `Path` payload —\n * emit sites send it for single-field mutations and omit it for bulk\n * payload-less broadcasts (reset, setInitialValues, clear-all), both of\n * which subscribers handle. `focusError` carries the target's path key\n * plus optional {@link SetFocusOptions}.\n */\nexport type FormEvents =\n | ['change', [path?: Path]]\n | ['errors', [path?: Path]]\n | ['touched', [path?: Path]]\n | ['validating', [path?: Path]]\n | ['submitting', []]\n | ['submitCount', []]\n | ['submitSuccessful', []]\n | ['reset', []]\n | ['disabled', []]\n | ['status', []]\n | ['loading', []]\n | ['focusError', [key: string, options?: SetFocusOptions]];\n\nexport type Form<T extends Record<string, any> = any> = {\n emitter: EventEmitter<FormEvents>;\n mode: ValidationMode;\n reValidateMode: ReValidateMode;\n initialValues: T;\n values: Map<string, any>;\n /** Tombstones of unregistered field paths (JSON path keys): reading or\n * merging values must not fall back to initialValues for these paths. */\n deleted: Set<string>;\n /** Every error registered for a field, as a non-empty array (the\n * write-side {@link setErrorByPath} normalizes to this invariant, so\n * readers never need to guard against an empty list). Readers wanting\n * the display error take the first entry ({@link getError}); readers\n * wanting all of them use {@link getFieldErrors}. */\n errors: Map<string, FieldError[]>;\n touched: Set<string>;\n /** Per-field validation kicks, registered by {@link\n * registerValidatorByPath} (`useValidate` is the React-side\n * registration): each is the field's debounce/lock-aware kick —\n * invoking it validates the field's current value. `trigger` /\n * `ensureValidate` run every entry; the user-change gate ({@link\n * userChangeByPath}) runs the entry at the changed path. */\n validators: Map<string, () => void>;\n validating: Set<string>;\n /** Parsed values from the last successful schema validation: the\n * schema's complete output tree (coerced/transformed values included).\n * Sits between initialValues and the values Map in {@link getValues}\n * until `reset`/`setInitialValues` clears it. Never affects dirty\n * state — that compares live edits against initialValues only. */\n parsedValues: T | undefined;\n /** Form-level validator, seeded from {@link Options.validate}. May\n * receive a second {@link FormValidateMeta} argument. */\n validate?: FormValidateFn<T>;\n /** Delay in milliseconds before the form-level `validate` runs; seeded\n * from {@link Options.validateDebounce} and fixed at create time. */\n validateDebounce?: number;\n /** Path keys (JSON-stringified segments) of the fields whose user\n * changes re-run the form-level `validate`; normalized from {@link\n * Options.validateDeps} at create time and fixed thereafter. */\n validateDeps?: ReadonlySet<string>;\n isSubmitting: boolean;\n /** Whether a submit has been attempted — set by `handleSubmit` on every\n * attempt (validation outcome aside), cleared by `reset`.\n * `useFormState().isSubmitted` reads it (react-hook-form's\n * `formState.isSubmitted` semantics). */\n isSubmitted: boolean;\n submitCount: number;\n isSubmitSuccessful: boolean | undefined;\n /** True while an async {@link Options.initialValues} source (a Promise,\n * or a thunk returning one) is still pending — the form starts empty\n * and the resolved values become the baseline via setInitialValues when\n * it lands. Flips through the payload-less 'loading' event\n * (`useIsLoading` / `useFormState().isLoading`). */\n isLoading: boolean;\n /** Form-level default for a bound field's unmount behavior, seeded from\n * {@link Options.shouldUnregister}: `true` (the default) tombstones an\n * unmounted field, `false` keeps its value (react-hook-form's\n * `shouldUnregister` semantics). A field's own `shouldUnregister` option\n * overrides this. */\n shouldUnregister?: boolean;\n /** Form-level disabled flag, OR-ed into every bound field's `disabled`\n * (form flag || the field's own option). Seeded from\n * {@link Options}.disabled at create time and toggled at runtime with\n * {@link setDisabled}, which emits a payload-less 'disabled' event so\n * subscribed fields re-render. */\n disabled: boolean;\n /** Form-level default for mount validation, seeded from\n * {@link Options.validateOnMount}: `true` makes every mounted field\n * with a validator kick once after mount (deferred until an async\n * {@link Options.initialValues} source lands), and makes `useForm` run\n * the form-level `validate` once. A field's own `validateOnMount`\n * option overrides this flag in either direction. */\n validateOnMount: boolean;\n /** Form-level default for {@link UseValidateOptions.asyncAlways}:\n * whether a field's debounced validator still runs when its `required`\n * gate failed. A field's own `asyncAlways` option overrides this flag\n * in either direction. Seeded from {@link Options.asyncAlways}. */\n asyncAlways: boolean;\n /**\n * User-owned metadata slot for non-field state — session flags, server\n * backfill that belongs to no field, step indices (Formik's `status`\n * role). Written with {@link setStatus}, which emits the payload-less\n * 'status' event; read directly or reactively through {@link useStatus}.\n * Starts `undefined`.\n */\n status: any;\n};\n\nexport type Options<T extends Record<string, any> = any> = {\n /**\n * The values baseline. Sync objects seed immediately (SSR renders\n * them). Async sources — a Promise, or a thunk returning a value or\n * Promise (react-hook-form's async `defaultValues` shape) — start the\n * form empty with `isLoading: true` and land the resolved values as\n * the baseline via setInitialValues once they resolve: value\n * subscribers re-sync, dirty/touched state starts clean, and a later\n * `reset()` returns to the resolved baseline. A rejected source flips\n * isLoading back to false, keeps the form empty, and logs the error in\n * DEV — attach a `.catch` on the source itself to handle it. The thunk\n * runs at create time: keep its identity stable (module scope or\n * useMemo) when passing it inline, and note StrictMode double-invokes\n * it in development, like every render-phase call.\n */\n initialValues?: T | Promise<T> | (() => T | Promise<T>);\n /** When fields are validated. Defaults to `'onSubmit'`. See\n * {@link ValidationMode}. */\n mode?: ValidationMode;\n /** When a field is re-validated after it already has an error — it only\n * takes effect once the field has an error. Defaults to `'onChange'`. See\n * {@link ReValidateMode}. */\n reValidateMode?: ReValidateMode;\n /**\n * Form-level validator. Returns a record of errors keyed by field path;\n * nested objects are flattened ('a.b' style) and array values contribute\n * every non-empty string they hold as separate errors (zod `flatten()`\n * formErrors style). Schema adapters instead return a branded\n * {@link ValidationOutcome}: `errors` flattens the same way, `values`\n * (the schema's parsed output) becomes the form's parsedValues baseline\n * that {@link getValues} layers over initialValues.\n */\n validate?: FormValidateFn<T>;\n /**\n * Milliseconds to debounce the form-level `validate`: kicks from\n * `trigger`/`ensureValidate`/submit inside the window merge into one\n * run, and while the timer is pending the form counts as validating,\n * so `trigger` and submit wait the window out — the same contract the\n * per-field `validateDebounce` gives field validators. The merged run\n * reads the values current when its timer fires. Defaults to `0`\n * (validate runs immediately, exactly as before this option existed).\n */\n validateDebounce?: number;\n /** Fields whose user changes re-run the form-level `validate` — the\n * cross-field dependency list (password-confirm mismatch and friends).\n * Each entry is a field path ('password', 'user.email', 'items.0.qty');\n * a user change to a listed field re-runs the form-level `validate`\n * under the same mode/`reValidateMode` gating the field's own\n * validator gets. Omit it and the form-level `validate` only runs on\n * `trigger`/submit, exactly as before this option existed.\n *\n * Opting in also changes what a re-run may clear: each round first\n * drops the errors the previous round wrote (paths it flattened onto),\n * so a dep change that fixes the cross-field error makes it disappear.\n * Errors the round never wrote — field validators', `setServerErrors`,\n * manual `setError` — are never touched. TanStack Form's counterpart is\n * `onChangeListenTo` (v1) / validator `triggers` (v2 alpha). */\n validateDeps?: FieldPath<T>[];\n /**\n * Form-level default for a bound field's unmount behavior. `true` (the\n * default) tombstones an unmounted field — it drops out of\n * `getValues()` instead of reviving its initial value (this library's\n * historical default); `false` keeps the value, matching\n * react-hook-form's `shouldUnregister`. A field's own\n * `useField({shouldUnregister})` option overrides the form-level flag\n * in either direction.\n */\n shouldUnregister?: boolean;\n /** Start the form with every bound field disabled — the flag bound\n * fields OR with their own `disabled` option (a field cannot opt out\n * of a disabled form). Toggle later with {@link setDisabled}.\n * Defaults to `false`. */\n disabled?: boolean;\n /**\n * Form-level default for field validation's `asyncAlways`: when true,\n * a field whose `required` gate failed still runs its debounced\n * validator (the gate's errors land immediately, the validator's own\n * result lands alongside them per-source). TanStack Form's\n * `asyncAlways` counterpart. A field's own\n * `useField({asyncAlways})` option overrides the form-level flag in\n * either direction. Defaults to `false`.\n */\n asyncAlways?: boolean;\n /**\n * Validate on mount: `true` makes every mounted field with a validator\n * (declarative `rules` or a `validate` callback) run it once after\n * mount, instead of waiting for the first submit/change — errors show\n * immediately for an untouched form (Formik's `validateOnMount` /\n * TanStack Form's per-field `validateOnMount`). The form-level\n * `validate` also runs once after mount. Mount kicks are deferred\n * while an async `initialValues` source is still pending: validating\n * the empty shell would land spurious required errors, so the kicks\n * fire after the resolved baseline lands instead. A field's own\n * `useField({validateOnMount})` option overrides the form-level flag\n * in either direction. Defaults to `false`.\n */\n validateOnMount?: boolean;\n};\n\n/**\n * Create form instance\n * @param options\n * @return form instance\n */\nexport default function create<T extends Record<string, any> = any>(\n options?: Options<T>\n): Form<T> {\n const emitter = createEmitter<FormEvents>();\n // A form legitimately accumulates one listener per mounted field per\n // event (useField subscribes change/errors/disabled/focusError…), so\n // the emitter's default max-listener warning would fire in DEV for any\n // form over ~10 fields. Field subscriptions are removed on unmount —\n // there is nothing to leak — so the warning would only be noise: raise\n // the cap to unlimited for form emitters.\n setMaxListeners(emitter, 0);\n // Async initialValues: a thunk is invoked here (create-time, like every\n // other option resolution); a promise-typed result starts the loading\n // cycle below instead of seeding.\n let source: any = options?.initialValues ?? {};\n if (typeof source === 'function') source = (source as () => unknown)();\n const form: Form<T> = {\n emitter,\n ...options,\n mode: options?.mode ?? 'onSubmit',\n reValidateMode: options?.reValidateMode ?? 'onChange',\n disabled: options?.disabled ?? false,\n validateOnMount: options?.validateOnMount ?? false,\n asyncAlways: options?.asyncAlways ?? false,\n validateDeps: options?.validateDeps\n ? new Set(options.validateDeps.map(dep => createPath(dep).key))\n : undefined,\n initialValues: {} as T,\n values: new Map(),\n deleted: new Set(),\n errors: new Map(),\n touched: new Set(),\n validators: new Map(),\n validating: new Set(),\n parsedValues: undefined,\n isSubmitting: false,\n isSubmitted: false,\n submitCount: 0,\n isSubmitSuccessful: undefined,\n isLoading: false,\n status: undefined\n };\n if (isPromise(source)) {\n // The form starts empty; when the source resolves, its values become\n // the baseline through setInitialValues (payload-less 'change', so\n // every value subscriber re-syncs). The loading flag flips through\n // the 'loading' event before and after — no subscriber exists during\n // the first render, so the synchronous first emit is a safe no-op.\n form.isLoading = true;\n emit(emitter, 'loading');\n Promise.resolve(source).then(\n resolved => {\n // Values land first, then the flag flips and 'loading' fires —\n // subscribers waking on the event read the resolved baseline, not\n // the empty shell (mount-validation deferral among them).\n setInitialValues(form, resolved ?? {});\n form.isLoading = false;\n emit(emitter, 'loading');\n },\n error => {\n form.isLoading = false;\n emit(emitter, 'loading');\n // The caller's own catch on the source sees the rejection;\n // rethrowing here would only duplicate it as an unhandled\n // promise rejection. Surface it in DEV instead.\n if (__DEV__) {\n // eslint-disable-next-line no-console -- dev-only diagnostics\n console.error('react-f0rm: async initialValues rejected', error);\n }\n }\n );\n } else {\n form.initialValues = source as T;\n }\n return form;\n}\n\nexport * from './core/values';\nexport * from './core/errors';\nexport * from './core/touched';\nexport * from './core/dirty';\nexport * from './core/validate';\nexport * from './core/change';\nexport * from './core/submit';\nexport * from './core/focus';\n","import type {FieldError} from './form';\nimport type {SyncValidator} from './hooks/validate';\n\n/** Type tag of a failed rule, as stored on the resulting FieldError. */\nexport type RuleType =\n 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern';\n\n/**\n * Declarative field rules — a subset of react-hook-form's `register` rules.\n *\n * Failed rules land in the form's error state as FieldErrors (`type` is the\n * rule name) instead of only surfacing through the browser's validity\n * bubble, so any design system can render the messages uniformly.\n */\nexport type FieldRules = {\n /**\n * Fails on empty values: `''`, `undefined`, `null` or an empty array\n * (`0` and `false` count as filled) — react-hook-form's `required`\n * semantics. A string is the error message; `true` uses the default.\n * When it fails, the remaining rules are skipped — an empty value\n * reports only its required error.\n */\n required?: string | true;\n /** Fails when `Number(value)` is below this bound; `NaN` values skip. */\n min?: number;\n /** Fails when `Number(value)` is above this bound; `NaN` values skip. */\n max?: number;\n /** Fails when a string value is shorter than this, or an array has\n * fewer entries; other values skip. */\n minLength?: number;\n /** Fails when a string value is longer than this, or an array has more\n * entries; other values skip. */\n maxLength?: number;\n /** Fails when the value does not match `pattern.value`. */\n pattern?: {value: RegExp; message: string};\n /**\n * Custom rule callbacks — react-hook-form's `register({validate})`\n * shape: one function, or a record of named functions. Each runs after\n * the declarative checks, and only when they passed (`required` failing\n * short-circuits the rest, RHF's first-error semantics). A returned\n * error keeps its message; its `type` becomes the record key\n * (`'validate'` for the single-function form) so consumers can switch\n * on `error.type`. Sync-only — async checks belong in the field's\n * `validate` option.\n */\n validate?: SyncValidator | Record<string, SyncValidator>;\n /**\n * Overrides the message per rule type — `min`, `max`, `minLength`,\n * `maxLength` defaults and pattern's inline `message` alike — e.g. for\n * centralizing or localizing messages.\n */\n messages?: Partial<Record<Exclude<RuleType, 'required'>, string>>;\n};\n\n/** Default English messages, aligned with RHF's default-message style. */\nfunction defaultMessage(type: RuleType, bound?: number): string {\n switch (type) {\n case 'required':\n return 'This field is required';\n case 'min':\n return `Must be at least ${bound}`;\n case 'max':\n return `Must be at most ${bound}`;\n case 'minLength':\n return `Must be at least ${bound} characters`;\n case 'maxLength':\n return `Must be at most ${bound} characters`;\n case 'pattern':\n return 'Invalid format';\n default:\n return 'Invalid value';\n }\n}\n\n/**\n * Compile declarative {@link FieldRules} into a {@link SyncValidator}.\n *\n * `required` is checked first and, when it fails on an empty value,\n * short-circuits the rest. Every other failing rule is collected into one\n * FieldError[] in declaration order (min, max, minLength, maxLength,\n * pattern); a fully passing value yields undefined. Messages resolve to\n * the rule's own string (required), `rules.messages`, or the default.\n *\n * @param rules declarative constraints\n * @return synchronous validator producing FieldError[] | undefined\n */\nexport function rulesToValidator(rules: FieldRules): SyncValidator {\n return (value, meta) => {\n if (rules.required) {\n if (\n value === '' ||\n value === undefined ||\n value === null ||\n (Array.isArray(value) && value.length === 0)\n ) {\n return [\n {\n type: 'required',\n message:\n typeof rules.required === 'string'\n ? rules.required\n : defaultMessage('required')\n }\n ];\n }\n }\n const errors: FieldError[] = [];\n const message = (type: Exclude<RuleType, 'required'>, bound: number) =>\n rules.messages?.[type] ?? defaultMessage(type, bound);\n if (rules.min !== undefined) {\n const n = Number(value);\n if (!Number.isNaN(n) && n < rules.min) {\n errors.push({type: 'min', message: message('min', rules.min)});\n }\n }\n if (rules.max !== undefined) {\n const n = Number(value);\n if (!Number.isNaN(n) && n > rules.max) {\n errors.push({type: 'max', message: message('max', rules.max)});\n }\n }\n const isSized = typeof value === 'string' || Array.isArray(value);\n if (\n rules.minLength !== undefined &&\n isSized &&\n value.length < rules.minLength\n ) {\n errors.push({\n type: 'minLength',\n message: message('minLength', rules.minLength)\n });\n }\n if (\n rules.maxLength !== undefined &&\n isSized &&\n value.length > rules.maxLength\n ) {\n errors.push({\n type: 'maxLength',\n message: message('maxLength', rules.maxLength)\n });\n }\n if (rules.pattern && !rules.pattern.value.test(value)) {\n errors.push({\n type: 'pattern',\n // pattern.message is type-required but JS consumers may omit it.\n message:\n rules.messages?.pattern ??\n rules.pattern.message ??\n defaultMessage('pattern')\n });\n }\n if (rules.validate !== undefined) {\n const fns =\n typeof rules.validate === 'function'\n ? {validate: rules.validate}\n : rules.validate;\n for (const [type, fn] of Object.entries(fns)) {\n const result = fn(value, meta);\n if (result === undefined) continue;\n // Each custom rule owns its `type`: the record key (or\n // 'validate' for the single-function form), so consumers can\n // switch on error.type like with every declarative rule.\n for (const entry of Array.isArray(result) ? result : [result]) {\n errors.push(\n typeof entry === 'string'\n ? {type, message: entry}\n : {...entry, type}\n );\n }\n }\n }\n return errors.length ? errors : undefined;\n };\n}\n\n/**\n * Map declarative {@link FieldRules} onto native HTML constraint\n * attributes — the subset the platform exposes: `required`, `min`,\n * `max`, `minLength`, `maxLength`, `pattern`. Rendered onto a bound\n * control they give browsers and assistive tech the native hints\n * (`:invalid`/`:user-invalid` styling, screen-reader announcements,\n * mobile input modes) while the store-based pipeline stays the source of\n * truth for messages: `rulesToValidator` still lands errors in the form\n * state and `renderError`/`aria-invalid` keep working. `validate`\n * callbacks have no native counterpart and are skipped. Native `min`/\n * `max` only constrain numeric/date inputs; the store checks apply\n * regardless of input type — render hints, not the validation gate.\n */\nexport function rulesToConstraintAttrs(rules: FieldRules): Record<string, any> {\n const attrs: Record<string, any> = {};\n if (rules.required) attrs.required = true;\n if (rules.min !== undefined) attrs.min = rules.min;\n if (rules.max !== undefined) attrs.max = rules.max;\n if (rules.minLength !== undefined) attrs.minLength = rules.minLength;\n if (rules.maxLength !== undefined) attrs.maxLength = rules.maxLength;\n if (rules.pattern) attrs.pattern = rules.pattern.value.source;\n return attrs;\n}\n","import {on} from './emitter';\nimport type {EventEmitter} from './emitter';\nimport createPath from './path';\nimport type {Name, Path} from './path';\nimport type {Form, FormEvents} from './form';\n\n/** Subscription granularity for {@link onPathEvent}.\n * - `'leaf'`: the subscriber reads exactly one key ({@link\n * useValueByPath}); only writes at that key or above it can change what\n * it reads.\n * - `'branch'`: the subscriber aggregates a whole subtree below a key\n * ({@link useFieldArray}); descendant writes matter too. */\nexport type WatchScope = 'leaf' | 'branch';\n\n/**\n * Is `key` a strict descendant of `ancestorKey`?\n *\n * Keys are JSON.stringify'd segment arrays ('[\"a\",\"b\"]'), so a descendant\n * key is the ancestor key minus its closing ']' followed by a ','\n * ('[\"a\",\"b\",'). The ',' separator is mandatory: a plain prefix match\n * would let the sibling '[\"tagsX\"]' pass as a descendant of '[\"tags\"]'.\n */\nfunction isDescendant(key: string, ancestorKey: string): boolean {\n return key.startsWith(`${ancestorKey.slice(0, -1)},`);\n}\n\n/**\n * Subscribe to `event`, invoking `cb` only when the emitted path is\n * relevant to `path`.\n *\n * Payload-less broadcasts (reset, setInitialValues) always invoke `cb` --\n * they are global syncs and the correctness fallback. (removeFieldByPath\n * emits with its path: its mutations are bounded to that key, so the path\n * matching below is exact.) When the emit carries a path P:\n * - `'leaf'`: P.key equals `path.key` or is one of its ancestors -- a leaf\n * read falls back to ancestor values (getValueByPath), so ancestor\n * writes must invalidate, while sibling and descendant writes cannot\n * change what the leaf reads.\n * - `'branch'`: `'leaf'` semantics plus P.key being a descendant of\n * `path.key` -- changed descendants re-aggregate the subtree.\n *\n * @param emitter emitter to subscribe to\n * @param event event name\n * @param path the watched path\n * @param scope which writes around `path` are relevant\n * @param cb listener, invoked with no arguments\n * @return unsubscribe function\n */\nexport function onPathEvent(\n emitter: EventEmitter<FormEvents>,\n event: SubscribeEvent,\n path: Path,\n scope: WatchScope,\n cb: () => void\n): () => void {\n const {key} = path;\n return on(emitter, event, (changed?: Path) => {\n if (\n changed === undefined ||\n changed.key === key ||\n isDescendant(key, changed.key) ||\n (scope === 'branch' && isDescendant(changed.key, key))\n ) {\n cb();\n }\n });\n}\n\n/**\n * Subscribe to `event`, invoking `cb` only when the emitted path's key is\n * exactly `key` (or the emit carries no payload -- a global sync).\n *\n * For state stored per exact key (errors, touched) no ancestor or\n * descendant matching is wanted: another field's key must not wake this\n * subscriber.\n *\n * @param emitter emitter to subscribe to\n * @param event event name\n * @param key exact path key to match\n * @param cb listener, invoked with no arguments\n * @return unsubscribe function\n */\nexport function onKeyEvent(\n emitter: EventEmitter<FormEvents>,\n event: SubscribeEvent,\n key: string,\n cb: () => void\n): () => void {\n return on(emitter, event, (changed?: Path) => {\n if (changed === undefined || changed.key === key) cb();\n });\n}\n\n/** Events {@link subscribe} can watch. `'errors'` and `'touched'` are\n * stored per exact key, so they match exact keys ({@link onKeyEvent});\n * `'change'`, `'validating'`, `'submitting'`, `'submitCount'`,\n * `'disabled'`, `'status'` and `'submitSuccessful'` go through\n * {@link onPathEvent}. `'validating'` carries paths (one per async\n * validator round) and matches by path exactly like `'change'`;\n * `'submitting'`, `'submitCount'`, `'disabled'`, `'status'` and\n * `'submitSuccessful'` are payload-less broadcasts, so `name` never\n * narrows them — every subscriber hears every emission. */\nexport type SubscribeEvent =\n | 'change'\n | 'errors'\n | 'touched'\n | 'validating'\n | 'submitting'\n | 'submitCount'\n | 'submitSuccessful'\n | 'disabled'\n | 'status'\n | 'loading';\n\n/** Options accepted by {@link subscribe}. */\nexport type SubscribeOptions = {\n /** Path (or list of paths) to watch. Omit to receive every emission of\n * `event`, payload-less broadcasts included. A single segments path\n * (`['tags', 0]`) and a list of names (`['tags', 'user.name']`) are told\n * apart by the same rule `trigger` uses: only a segments path can hold\n * a number. */\n name?: Name | Name[];\n /** Event to watch. Defaults to `'change'`. */\n event?: SubscribeEvent;\n /** Which writes around `name` are relevant — `'leaf'` or `'branch'`.\n * Only meaningful for the path-carrying events `'change'` and\n * `'validating'`: `'errors'`/`'touched'` match exact keys and\n * `'submitting'`/`'submitCount'`/`'disabled'`/`'status'`/\n * `'submitSuccessful'` are payload-less. Defaults to `'branch'` — the\n * intuitive linkage semantics, where subscribing to `'tags'` means the\n * whole branch. */\n scope?: WatchScope;\n /** Invoked with no arguments after each matching emission. Read fresh\n * state through the `get*` readers inside it. */\n callback: () => void;\n};\n\n/** Is `name` a list of names rather than one segments path? Numbers only\n * occur inside a segments path (`['a', 0]`), never as standalone names —\n * the same disambiguation `trigger` applies to its name argument. */\nfunction isNameList(name: Name | Name[]): name is Name[] {\n return (\n Array.isArray(name) &&\n (name as (number | unknown)[]).every(part => typeof part !== 'number')\n );\n}\n\n/**\n * Subscribe to form events imperatively — the non-render counterpart of\n * the `use*` hooks: linkages and side effects (province changed → clear\n * city, autosave, analytics) run without mounting a watching component.\n *\n * Without `name`, `callback` fires on every `event` emission, payload-less\n * broadcasts (reset, setInitialValues) included. With `name`, matching\n * follows the event's shape: `'errors'`/`'touched'` match the exact key\n * ({@link onKeyEvent}) — another field's error never wakes this\n * subscriber — while `'change'`/`'validating'`/`'submitting'`/\n * `'submitCount'`/`'disabled'`/`'submitSuccessful'` go through\n * {@link onPathEvent}, so the default `'branch'` scope wakes a `'tags'`\n * subscriber when any `tags.*` descendant is written. `'validating'`\n * carries a path per validator round and narrows by path like\n * `'change'`; `'disabled'`/`'submitSuccessful'` (like `'submitting'`)\n * are payload-less broadcasts that every named subscriber receives. A\n * `name` array builds one subscription per path and the returned\n * function unsubscribes them all.\n *\n * @param form the form to watch\n * @param options event, name(s), scope and callback\n * @return unsubscribe function\n */\nexport function subscribe(form: Form, options: SubscribeOptions): () => void {\n const {name, event = 'change', scope = 'branch', callback} = options;\n if (name === undefined) return on(form.emitter, event, callback);\n const names = isNameList(name) ? name : [name];\n const unsubscribes = names.map(one => {\n const path = createPath(one);\n return event === 'errors' || event === 'touched'\n ? onKeyEvent(form.emitter, event, path.key, callback)\n : onPathEvent(form.emitter, event, path, scope, callback);\n });\n return unsubscribes.length === 1\n ? unsubscribes[0]\n : () => unsubscribes.forEach(unsubscribe => unsubscribe());\n}\n","import {\n useState,\n useEffect,\n useCallback,\n useRef,\n useSyncExternalStore\n} from 'react';\nimport {on} from '../emitter';\nimport type {EventEmitter} from '../emitter';\nimport {onKeyEvent, onPathEvent} from '../subscribe';\nimport type {SubscribeEvent, WatchScope} from '../subscribe';\nimport createForm, {\n FORM_ERROR,\n getErrorByPath,\n getFieldErrorsByPath,\n getValueByPath,\n getValues,\n hasTouchedByPath,\n hasErrors,\n isDirty,\n isFieldDirtyByPath,\n getDirtyFields,\n getTouchedFields,\n setInitialValues,\n runFormValidate\n} from '../form';\nimport type {FieldError, Form, FormEvents, Options} from '../form';\nimport type {FieldPath, PathValueOf} from '../types';\nimport createPath from '../path';\nimport type {PathSegments, Path} from '../path';\nimport {get, isEqual, isPromise} from '../util';\n\n/**\n * Create a form instance bound to this component.\n *\n * Beyond {@link Options}, the optional `values` object enables controlled\n * usage: when it genuinely changes it is re-synced into the form with\n * setInitialValues semantics -- uncommitted user edits are discarded\n * (master-detail semantics: selecting another record replaces the draft),\n * while touched flags and errors survive. Change detection is\n * reference-first with a structural fallback, so re-renders that pass an\n * inline literal with equal content never re-sync -- the user's\n * in-progress typing is never clobbered.\n */\nexport default function useForm<T extends Record<string, any> = any>(\n options?: Options<T> & {values?: T}\n): Form<T> {\n // Lazy initialization: createForm runs once per mount and the returned\n // instance is stable across re-renders (and StrictMode double renders),\n // without writing to refs during render. A provided `values` object is\n // seeded synchronously here (createForm does the same for initialValues)\n // so the first paint and SSR already reflect the controlled values.\n const [form] = useState(() => {\n const created = createForm<T>(options);\n if (options && options.values !== undefined) {\n setInitialValues(created, options.values);\n }\n return created;\n });\n const initialValues = options && options.initialValues;\n const values = options && options.values;\n\n // Track which initialValues source object the form was last seeded from.\n // Inline options create a fresh object every render, and re-seeding\n // clears the values Map (setInitialValues semantics), which would revert\n // every committed edit right after each re-render -- on the client and\n // after hydration alike. Memoized callers are covered by the reference\n // check; inline literals by the structural one, so only genuinely new\n // content re-seeds.\n const seededRef = useRef<{done: boolean; source: any} | null>(null);\n if (seededRef.current === null)\n seededRef.current = {done: false, source: undefined};\n\n useEffect(() => {\n // undefined = no baseline requested (createForm already defaulted to\n // {}): installing it would clear the values Map on mount for no\n // semantic gain — wiping any render-time useField initialValue seeds.\n // Async sources (Promise or thunk) are excluded too: createForm owns\n // their one-shot resolution, and a thunk's identity changes every\n // render, so re-seeding here would clobber the resolution cycle with\n // the raw function itself.\n if (initialValues === undefined) return;\n if (typeof initialValues === 'function' || isPromise(initialValues)) {\n return;\n }\n const seeded = seededRef.current!;\n if (\n seeded.done &&\n (seeded.source === initialValues || isEqual(seeded.source, initialValues))\n ) {\n return;\n }\n seeded.done = true;\n seeded.source = initialValues;\n setInitialValues(form, initialValues);\n }, [form, initialValues]);\n\n // Controlled values: re-sync only when the incoming object genuinely\n // differs from what the form was last seeded from. The reference check\n // is the fast path (memoized callers); inline literals get a fresh\n // object identity every render, so without the structural comparison\n // each re-render would clear the values Map (setInitialValues\n // semantics) and revert the user's uncommitted edits -- same hazard the\n // initialValues seed guard above protects against. Master-detail\n // semantics still apply whenever the content actually changed.\n const controlledRef = useRef<{done: boolean; source: any} | null>(null);\n if (controlledRef.current === null) {\n controlledRef.current = {done: false, source: undefined};\n }\n\n useEffect(() => {\n if (values === undefined) return;\n const seeded = controlledRef.current!;\n if (\n seeded.done &&\n (seeded.source === values || isEqual(seeded.source, values))\n ) {\n return;\n }\n seeded.done = true;\n seeded.source = values;\n setInitialValues(form, values);\n }, [form, values]);\n\n // Mount validation: the form-level `validate` runs once after mount when\n // the form opted into `validateOnMount` (field kicks are the fields' own\n // — useValidate schedules them per registration). Children's effects run\n // before the parent's, so field registrations are in place by the time\n // this fires. While an async initialValues source is pending, defer to\n // the 'loading' event — it fires after the resolved baseline has landed.\n // The run is fire-and-forget: a rejected validator is the submit path's\n // business, and a sync throw propagates exactly like trigger's.\n useEffect(() => {\n if (!form.validateOnMount || !form.validate) return;\n const run = () => {\n void runFormValidate(form).catch(() => undefined);\n };\n if (!form.isLoading) {\n run();\n return;\n }\n return on(form.emitter, 'loading', () => {\n run();\n });\n }, [form]);\n\n return form;\n}\n\n/** Per-hook snapshot cache for {@link useWatch}. */\ntype WatchCache<T> = {hasValue: boolean; value?: T};\n\n/**\n * Shared core of {@link useWatch} and the path-scoped hooks: a\n * useSyncExternalStore binding over a custom event subscription.\n * `subscribeFactory` receives the invalidate callback (drop the snapshot\n * cache, then notify React) and returns its unsubscribe function, so the\n * core stays identical whether the subscription is global or scoped to\n * one path.\n *\n * The optional `isEqual` comparator redirects `invalidate`: instead of\n * dropping the cache and waking React unconditionally, an event first\n * recomputes the getter and asks `isEqual` whether anything observable\n * changed — an equal verdict keeps the cached snapshot and skips the\n * notify entirely (no render at all), an unequal one stores the fresh\n * snapshot and notifies. Omitted, the historical drop-and-notify pipeline\n * runs byte-for-byte unchanged.\n */\nexport function useWatchCore<T>(\n subscribeFactory: (invalidate: () => void) => () => void,\n getter: () => T,\n isEqual?: (prev: T, next: T) => boolean\n): T {\n // useSyncExternalStore requires getSnapshot to return the same reference\n // until the store actually changed, otherwise React warns and loops.\n // Cache the snapshot per hook instance and recompute it only on the first\n // read and after the watched event fired.\n const cacheRef = useRef<WatchCache<T> | null>(null);\n if (cacheRef.current === null) cacheRef.current = {hasValue: false};\n const cache = cacheRef.current;\n\n // Hold the latest getter in a ref so getSnapshot keeps a stable identity\n // (callers pass a freshly bound function on every render) while still\n // recomputing with the most recent getter when the cache is invalid.\n const getterRef = useRef(getter);\n getterRef.current = getter;\n // Same freshness treatment for the comparator: invalidate is created once\n // per subscription, so it must read the latest isEqual through a ref\n // rather than capturing whichever instance the first render passed.\n const isEqualRef = useRef(isEqual);\n isEqualRef.current = isEqual;\n\n const getSnapshot = useCallback(() => {\n if (!cache.hasValue) {\n cache.value = getterRef.current();\n cache.hasValue = true;\n }\n return cache.value as T;\n }, [cache]);\n\n const subscribe = useCallback(\n (notify: () => void) => {\n // The form may have changed between render and this subscription, and\n // those events were missed: drop the cache. React's consistency check\n // right after subscribing recomputes and re-renders only when the\n // fresh value differs from the committed snapshot.\n cache.hasValue = false;\n const invalidate = () => {\n const compare = isEqualRef.current;\n if (compare && cache.hasValue) {\n // Custom comparator: decide before waking React. Equal means the\n // fresh getter result is observably the same — keep the cached\n // reference and return without notifying, so React never even\n // schedules a render. Unequal stores the fresh snapshot up front,\n // so React's own post-notify Object.is check reads it without\n // recomputing the getter.\n const next = getterRef.current();\n if (compare(cache.value as T, next)) return;\n cache.value = next;\n notify();\n return;\n }\n cache.hasValue = false;\n notify();\n };\n return subscribeFactory(invalidate);\n },\n [subscribeFactory, cache]\n );\n\n // Form state lives entirely in synchronously readable Map/Set structures\n // seeded from initialValues/values during the lazy useState initializer,\n // so the server snapshot is computed exactly like the client's first\n // render -- pass getSnapshot itself as getServerSnapshot and hydration\n // matches.\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Subscribe to a form event and keep the component's snapshot of `getter()`\n * in sync with the form state.\n *\n * Built on useSyncExternalStore, so snapshots taken while React renders are\n * guaranteed consistent (no tearing under concurrent rendering) and changes\n * emitted before the subscription effect runs are still picked up.\n *\n * The first argument is the form for the unified `fn(form, ...)` context\n * shape every hook shares; the raw emitter form remains accepted for\n * back-compat and for subscription sources that are not a full form.\n *\n * By default the re-render surface is the event's own scope: every emit\n * the subscription hears drops the snapshot cache and wakes React, which\n * then bails out when the recomputed snapshot is reference-identical\n * (Object.is) — the path/leaf scoping every built-in reader relies on.\n * The optional `isEqual` comparator exists for wide-scope getters that\n * return a fresh reference per call (a whole-values selector, say): each\n * event recomputes the getter and asks `isEqual` whether the result is\n * observably the same, and an equal verdict skips notifying React\n * altogether — no render, not even a bailed-out one. An unequal verdict\n * stores the new snapshot and re-renders. Same contract as TanStack's\n * `useSelector` compare. Omitted, behavior is unchanged.\n */\nexport function useWatch<T>(\n formOrEmitter: Form | EventEmitter<FormEvents>,\n event: SubscribeEvent,\n getter: () => T,\n isEqual?: (prev: T, next: T) => boolean\n): T {\n // A form carries an `emitter` field the opaque emitter instance never\n // has, so the duck test cleanly discriminates the two accepted shapes.\n const emitter =\n 'emitter' in formOrEmitter ? formOrEmitter.emitter : formOrEmitter;\n const subscribeFactory = useCallback(\n (invalidate: () => void) => on(emitter, event, invalidate),\n [emitter, event]\n );\n return useWatchCore(subscribeFactory, getter, isEqual);\n}\n\n/** Options for {@link useValue} and {@link useValueByPath}. */\nexport type UseValueOptions<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n> = {\n /** Value to return while the field reads undefined — react-hook-form's\n * `useWatch` `defaultValue`: an untouched, never-seeded field reads\n * this instead of `undefined`. */\n defaultValue?: PathValueOf<T, P>;\n /** Watch descendants too (react-hook-form's `exact: false`): a write\n * to `a.b` invalidates a `useValue(form, 'a')` read, and the read\n * resolves the merged subtree (the copy-on-write `getValues` tree) so\n * descendant edits show up in the result. Defaults to true — the leaf\n * scope, where only the exact key and its ancestors invalidate (the\n * long-standing behavior). */\n exact?: boolean;\n};\n\n/**\n * Get field value state\n */\nexport function useValue<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P, options?: UseValueOptions<T, P>): PathValueOf<T, P> {\n return useValueByPath(form, createPath(name), options);\n}\n\n/**\n * Get field value state by path\n */\nexport function useValueByPath(\n form: Form,\n path: Path,\n options?: {defaultValue?: any; exact?: boolean}\n): any {\n const {emitter} = form;\n const {key} = path;\n const scope: WatchScope = options?.exact === false ? 'branch' : 'leaf';\n // 'leaf' scope: a leaf read depends only on its own key and its\n // ancestors' (getValueByPath fallback chain), so writes elsewhere --\n // siblings, descendants, string-prefix lookalikes ('[\"a\",\"bX\"]') -- never\n // invalidate the snapshot. 'branch' (exact: false) additionally wakes on\n // descendant writes and resolves the merged subtree through `getValues`\n // (getValueByPath only walks live ancestors, so a descendant edit would\n // otherwise read back a stale reference). Payload-less broadcasts\n // (reset, setInitialValues) still sync everything; removeField matches\n // by path.\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n onPathEvent(emitter, 'change', path, scope, invalidate),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `key` on purpose: useValue creates a fresh Path per render, so the object must stay out of the deps while the key string pins the subscription\n [emitter, key, scope]\n );\n return useWatchCore(subscribeFactory, () => {\n if (options?.exact === false) {\n return get(getValues(form), path.value);\n }\n const value = getValueByPath(form, path);\n return value === undefined ? options?.defaultValue : value;\n });\n}\n\n/**\n * Get field touched state\n */\nexport function useTouched<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): boolean {\n return useTouchedByPath(form, createPath(name));\n}\n\n/**\n * Get field touched state by path\n */\nexport function useTouchedByPath(form: Form, path: Path): boolean {\n const {emitter} = form;\n const {key} = path;\n // Touched is stored per exact key, so only this field's own setTouched\n // (now emitted with its path) matters; payload-less broadcasts (reset,\n // removeField) still sync everything.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'touched', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(\n subscribeFactory,\n hasTouchedByPath.bind(null, form, path)\n );\n}\n\n/**\n * Get field error message state\n * @return current error's message string (display text), or undefined\n */\nexport function useError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): string | undefined {\n return useErrorByPath(form, createPath(name))?.message;\n}\n\n/**\n * Get field error state by path\n * @return current FieldError object ({type, message}), or undefined\n */\nexport function useErrorByPath(form: Form, path: Path): FieldError | undefined {\n const {emitter} = form;\n const {key} = path;\n // Errors are stored per exact key, so only writes to this field's error\n // (setErrorByPath now emits with its path) matter; payload-less\n // broadcasts (clearErrors, reset, removeField) still sync everything.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'errors', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(subscribeFactory, getErrorByPath.bind(null, form, path));\n}\n\n/**\n * Get all field errors\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function useFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return useFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all field errors by path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function useFieldErrorsByPath(form: Form, path: Path): FieldError[] {\n const {emitter} = form;\n const {key} = path;\n // Same exact-key subscription and snapshot rules as useErrorByPath: the\n // getter returns the shared empty constant when clean and the stored\n // array by reference otherwise, so the useSyncExternalStore snapshot is\n // reference-stable between unrelated events.\n const subscribeFactory = useCallback(\n (invalidate: () => void) => onKeyEvent(emitter, 'errors', key, invalidate),\n [emitter, key]\n );\n return useWatchCore(\n subscribeFactory,\n getFieldErrorsByPath.bind(null, form, path)\n );\n}\n\nexport function useIsDirty(form: Form): boolean {\n // Dirty state is driven by value changes, not touch state: subscribe to\n // 'change' so typing flips this immediately, even before a blur.\n return useWatch(form, 'change', isDirty.bind(null, form));\n}\n\n/**\n * Get whether one field is dirty: its live value exists and differs from\n * the field's effective baseline — the same per-field rule\n * `getFieldState(form, name).isDirty` applies (committed\n * `shouldDirty: false` baselines included). Subscribes to 'change' at\n * leaf scope like {@link useValue}: own-key and ancestor writes re-check\n * the flag, payload-less broadcasts (reset, setInitialValues) always\n * sync, and writes elsewhere never re-render it.\n */\nexport function useIsFieldDirty<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): boolean {\n return useIsFieldDirtyByPath(form, createPath(name));\n}\n\n/**\n * Get whether one field is dirty, by parsed path. See {@link\n * useIsFieldDirty}.\n */\nexport function useIsFieldDirtyByPath(form: Form, path: Path): boolean {\n const {emitter} = form;\n const {key} = path;\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n onPathEvent(emitter, 'change', path, 'leaf', invalidate),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- same key-pinning convention as useValueByPath\n [emitter, key]\n );\n return useWatchCore(subscribeFactory, () => isFieldDirtyByPath(form, path));\n}\n\n/**\n * Get dirty fields state -- object mapping each dirty field's user-facing\n * dotted path ('a.b', 'a.0.c') to true; recalculated after 'change' events\n */\nexport function useDirtyFields(form: Form): Record<string, boolean> {\n return useWatch(form, 'change', getDirtyFields.bind(null, form));\n}\n\n/**\n * Get touched fields state -- array of touched fields' user-facing dotted\n * paths ('a.b', 'a.0.c'); recalculated after 'touched' events\n */\nexport function useTouchedFields(form: Form): string[] {\n return useWatch(form, 'touched', getTouchedFields.bind(null, form));\n}\n\n/**\n * Aggregate snapshot of the whole form's state flags — the one-subscription\n * counterpart of react-hook-form's `formState` object (no errors object;\n * per-field error state stays with `useError`/`useFieldErrors`, and\n * `hasErrors`/`isValid` cover the whole-form questions).\n *\n * Recomputed on every state-bearing event; the field-wise comparator keeps\n * the returned reference stable while nothing observably changed, so\n * `useFormState(form).isDirty` re-renders no more often than the dedicated\n * {@link useIsDirty}. Cheaper than calling the granular hooks one by one\n * (one subscription and one snapshot instead of one per flag).\n */\nexport type FormState = {\n /** Any live value differs from its baseline (see {@link isDirty}). */\n isDirty: boolean;\n /** Dirty fields keyed by user-facing dotted path ('a.b', 'a.0.c'). */\n dirtyFields: Record<string, boolean>;\n /** At least one field is touched. */\n isTouched: boolean;\n /** Touched fields' user-facing dotted paths. */\n touchedFields: string[];\n /** Any error registered (field or form level). */\n hasErrors: boolean;\n /** No errors are registered — react-hook-form's `isValid` semantics.\n * In-flight validation is NOT factored in ({@link isValidating} is the\n * separate signal; async rounds temporarily pass this flag like RHF's). */\n isValid: boolean;\n isSubmitting: boolean;\n /**\n * Whether a submit has been attempted on this form — set on the first\n * `handleSubmit` call (validation outcome aside) and cleared by\n * `reset`, react-hook-form's `formState.isSubmitted` semantics. Read\n * after a failed submit to render a \"fix the errors below\" panel.\n */\n isSubmitted: boolean;\n /** Any validation round is running (field, form-level, or a pending\n * debounce window). */\n isValidating: boolean;\n isSubmitSuccessful: boolean | undefined;\n submitCount: number;\n /** Async initialValues still pending ({@link Form.isLoading}). */\n isLoading: boolean;\n /** The form-level disabled flag (fields OR their own `disabled`). */\n disabled: boolean;\n};\n\n/** Events any FormState field can react to: each recomputes the whole\n * snapshot — the comparator, not per-flag subscriptions, keeps the\n * re-render surface minimal. */\nconst FORM_STATE_EVENTS: readonly SubscribeEvent[] = [\n 'change',\n 'errors',\n 'touched',\n 'validating',\n 'submitting',\n 'submitCount',\n 'submitSuccessful',\n 'disabled',\n 'loading'\n];\n\nfunction getFormState(form: Form): FormState {\n return {\n isDirty: isDirty(form),\n dirtyFields: getDirtyFields(form),\n isTouched: form.touched.size > 0,\n touchedFields: getTouchedFields(form),\n hasErrors: hasErrors(form),\n isValid: !hasErrors(form),\n isSubmitting: form.isSubmitting,\n isSubmitted: form.isSubmitted,\n isValidating: form.validating.size > 0,\n isSubmitSuccessful: form.isSubmitSuccessful,\n submitCount: form.submitCount,\n isLoading: form.isLoading,\n disabled: form.disabled\n };\n}\n\n/** Field-wise equality: reference checks where the getter already memoizes\n * (dirtyFields), element-wise for the fresh array getTouchedFields builds,\n * value checks for the flags. */\nfunction isSameFormState(a: FormState, b: FormState): boolean {\n const sameTouched =\n a.touchedFields.length === b.touchedFields.length &&\n a.touchedFields.every((path, i) => path === b.touchedFields[i]);\n return (\n a.isDirty === b.isDirty &&\n a.dirtyFields === b.dirtyFields &&\n a.isTouched === b.isTouched &&\n sameTouched &&\n a.hasErrors === b.hasErrors &&\n a.isValid === b.isValid &&\n a.isSubmitting === b.isSubmitting &&\n a.isSubmitted === b.isSubmitted &&\n a.isValidating === b.isValidating &&\n a.isSubmitSuccessful === b.isSubmitSuccessful &&\n a.submitCount === b.submitCount &&\n a.isLoading === b.isLoading &&\n a.disabled === b.disabled\n );\n}\n\nexport function useFormState(form: Form): FormState {\n const getter = useCallback(() => getFormState(form), [form]);\n const subscribeFactory = useCallback(\n (invalidate: () => void) => {\n const offs = FORM_STATE_EVENTS.map(event =>\n on(form.emitter, event, invalidate)\n );\n return () => {\n for (const off of offs) off();\n };\n },\n [form.emitter]\n );\n return useWatchCore(subscribeFactory, getter, isSameFormState);\n}\n\nexport function useHasErrors(form: Form): boolean {\n return useWatch(form, 'errors', hasErrors.bind(null, form));\n}\n\n/**\n * Get whether the form currently has no errors — react-hook-form's\n * `formState.isValid` counterpart. Subscribes to the `'errors'` event only;\n * in-flight validation does not flip it (see {@link useIsValidating}).\n */\nexport function useIsValid(form: Form): boolean {\n return useWatch(form, 'errors', () => !hasErrors(form));\n}\n\nexport function useIsSubmitting(form: Form): boolean {\n return useWatch(form, 'submitting', () => form.isSubmitting);\n}\n\n/**\n * Get whether an async {@link Options.initialValues} source is still\n * pending — the flag a loading skeleton or a disabled submit button gates\n * on until the resolved baseline lands. Subscribes to the 'loading' event\n * the core emits around the resolution cycle.\n */\nexport function useIsLoading(form: Form): boolean {\n return useWatch(form, 'loading', () => form.isLoading);\n}\n\n/**\n * Get the form's user-owned metadata slot reactively (Formik's `status`\n * counterpart): any value the app stores through {@link setStatus} —\n * server session flags, wizard step state, non-field errors. Subscribes\n * to the payload-less 'status' event, so unrelated events never re-render\n * the caller, and the returned reference is stable between writes that\n * store an equal value (useSyncExternalStore's Object.is bailout).\n */\nexport function useStatus<T = any>(form: Form): T {\n return useWatch(form, 'status', () => form.status);\n}\n\n/**\n * Get whether the form accepts a submit right now:\n * `!isSubmitting && !hasErrors`. This is the single flag a submit\n * button's `disabled` prop wants — it is `false` for the whole async\n * `onSubmit` span (not just the validation pass) and whenever any field\n * holds an error (client validation or server backfill), replacing the\n * hand-rolled `useHasErrors(form) || useIsSubmitting(form)` pair.\n * Deliberately no dirty or validating semantics: an untouched-but-clean\n * form can submit.\n */\nexport function useCanSubmit(form: Form): boolean {\n const {emitter} = form;\n // canSubmit folds two events into one boolean: error writes\n // ('errors') and submit-state flips ('submitting'). useWatch subscribes\n // to a single event, so subscribe to both through useWatchCore — the\n // snapshot recomputes on either wake and re-renders only when the\n // boolean itself flips, so unrelated single-field error churn costs no\n // extra render (the same granularity useHasErrors already has).\n const subscribeFactory = useCallback(\n (invalidate: () => void) => {\n const offErrors = on(emitter, 'errors', invalidate);\n const offSubmitting = on(emitter, 'submitting', invalidate);\n return () => {\n offErrors();\n offSubmitting();\n };\n },\n [emitter]\n );\n return useWatchCore(\n subscribeFactory,\n () => !form.isSubmitting && !hasErrors(form)\n );\n}\n\nexport function useSubmitCount(form: Form): number {\n return useWatch(form, 'submitCount', () => form.submitCount);\n}\n\n/**\n * Get whether any validation round is currently running: a field\n * validator's pending `validateDebounce` window, an async field validator\n * still in flight, or the form-level validate's debounce window / in-flight\n * round — every one of them holds a key in `form.validating`, and the\n * 'validating' events they emit (field rounds with a path payload, the\n * form-level round as a payload-less broadcast) are what this subscribes\n * to. The boolean snapshot is Object.is-stable, so churn among the marks\n * (a second field opening while the first settles) costs no render while\n * the flag holds. This is the flag a submit button disables itself on, or\n * spins a spinner with, through the pre-submit validation pass — it flips\n * true the moment the first round opens and back false when the last one\n * settles.\n */\nexport function useIsValidating(form: Form): boolean {\n return useWatch(form, 'validating', () => form.validating.size > 0);\n}\n\n/**\n * Get whether the last submit succeeded: `true` once a submit's validation\n * and `onSubmit` completed without throwing, `false` after a failed submit\n * (validation rejection or a thrown callback) and before any submit ran —\n * the falsy reading of the undefined initial/reset state. Subscribes to\n * the 'submitSuccessful' event the core's setSubmitSuccessful emits, so\n * the flag flips in the same tick the outcome lands: the usual consumers\n * are a success banner and a redirect-on-success effect.\n */\nexport function useIsSubmitSuccessful(form: Form): boolean {\n return useWatch(\n form.emitter,\n 'submitSuccessful',\n () => !!form.isSubmitSuccessful\n );\n}\n\n/**\n * Get the form-level error message: the first error stored under the\n * reserved {@link FORM_ERROR} key, as display text — or undefined while\n * the slot is clean. That key is where a form-level `validate` record's\n * `_form` entry lands and where the Standard Schema adapter drops\n * path-less issues, so errors that belong to no single field still have a\n * reader. The classic usage renders it once above the submit button —\n * `useFormError(form) || null` — and the imperative twin is\n * `getError(form, FORM_ERROR)`.\n */\nexport function useFormError(form: Form): string | undefined {\n return useErrorByPath(form, createPath(FORM_ERROR))?.message;\n}\n\n/**\n * Get every form-level error: all errors stored under the reserved\n * {@link FORM_ERROR} key (insertion order), an empty array when the slot\n * is clean. The plural twin of {@link useFormError} for forms that stack\n * several form-level issues — each path-less Standard Schema issue lands\n * in this slot. The array reference is stable between unrelated events\n * (the stored array or a shared empty constant), so consumers can memo on\n * it; the imperative counterpart is `getFieldErrors(form, FORM_ERROR)`.\n */\nexport function useFormErrors(form: Form): FieldError[] {\n return useFieldErrorsByPath(form, createPath(FORM_ERROR));\n}\n","import {useMemo} from 'react';\nimport create from '../path';\nimport type {Name, Path} from '../path';\nimport {normalizePath} from '../util';\n\nexport default function usePath(name: Name): Path {\n const path = useMemo(() => create(normalizePath(name)), [name]);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: re-renders passing a fresh array for the same field name reuse the cached Path object (stable reference & Map key)\n return useMemo(() => path, [path.key]);\n}\n","import {useCallback, useEffect, useRef, type MutableRefObject} from 'react';\n\nexport default function useStage<T>(value: T): MutableRefObject<T> {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n\nexport function useStageFn<T extends (...args: any[]) => any>(fn: T): T {\n const ref = useStage(fn);\n return useCallback(\n (...params: any[]) => ref.current(...params),\n [ref]\n ) as unknown as T;\n}\n\n/**\n * Run destructive unmount `teardown` synchronously on every cleanup —\n * real unmounts behave exactly like a plain effect cleanup — and let a\n * setup that immediately follows a cleanup (`restore`) undo it.\n *\n * React 19's StrictMode double-invokes effects on the initial mount\n * (setup → cleanup → setup), so a plain cleanup would run the teardown\n * and then remount with the state gone. The cycle's second setup finds\n * the `removed` flag and calls `restore` before any render or event can\n * observe the gap; a real unmount has no following setup and the\n * teardown simply stands.\n *\n * `teardown`/`restore` must be referentially stable (build them with\n * {@link useStageFn}); the effect intentionally runs once per mount.\n */\nexport function useUnmountRestore(\n teardown: () => void,\n restore: () => void\n): void {\n const removedRef = useRef(false);\n useEffect(() => {\n // The previous cleanup ran the teardown — this setup is the StrictMode\n // remount: put the state back.\n if (removedRef.current) {\n removedRef.current = false;\n restore();\n }\n return () => {\n removedRef.current = true;\n teardown();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- teardown/restore are stage-stable; the effect must run exactly once per mount\n }, []);\n}\n","import {useContext, useEffect, useRef} from 'react';\nimport {on} from '../emitter';\nimport {FormContext} from '../context';\nimport {registerValidatorByPath} from '../form';\nimport type {Form, SyncValidator, Validator} from '../form';\nimport type {Path} from '../path';\nimport {useStageFn} from './stage';\n\n// The validator contract itself is framework-free and lives in the core\n// (`src/form.ts`); re-exported here so historical imports keep working.\nexport type {SyncValidator, Validator};\n\n/**\n * Options for {@link useValidate} — the React-side registration of a field\n * validator. The registration machinery (debounce window, async-round\n * lock, signal abort, validating mark) lives in the core's\n * {@link registerValidatorByPath}; this hook only wires its React\n * lifecycle around it: register on mount, dispose on unmount, and read\n * the validator/debounce/sync-gate live through refs so re-renders never\n * re-subscribe the registration mid-flight.\n */\nexport type UseValidateOptions = {\n /**\n * Delay in milliseconds before a validation kick actually runs the\n * debounced validator. `0` (default) runs immediately; a positive value\n * debounces rapid kicks (e.g. typing) so only the last one executes.\n * While the timer is pending the field counts as validating, so\n * `trigger` / `ensureValidate` wait out the window. The `sync`\n * pre-validator is exempt: it runs immediately on every kick and never\n * waits out the window.\n */\n debounce?: number;\n /**\n * Synchronous pre-validator run immediately on every kick — never\n * debounced. While it returns errors, the debounced `validate` is\n * skipped for that kick (its errors land and the expensive check never\n * runs), and any pending debounce window or in-flight round is\n * superseded. When it passes, a stale error it produced earlier clears\n * at once, and a registration with no `validate` treats the passing\n * check as the whole round and clears the field's errors.\n */\n sync?: SyncValidator;\n /**\n * Run the debounced validator even when the `sync` gate failed —\n * TanStack Form's `asyncAlways`. The gate's errors land immediately\n * (never debounced) and the validator's own result lands alongside\n * them, per-source: a passing async round clears only its own errors,\n * the gate's verdict stays until the gate itself passes. Defaults to\n * false (gate failure owns the kick's outcome).\n */\n asyncAlways?: boolean;\n /**\n * Validate on mount: kick the registration once after it lands (Formik's\n * `validateOnMount` / TanStack Form's per-field flag). Falls back to the\n * form-level `createForm({validateOnMount})` when omitted, so a field\n * opts out with `validateOnMount: false`. Validator-less registrations\n * never kick on mount — an empty kick would clear a server error that\n * landed before the field mounted. While an async `initialValues` source\n * is still pending the kick is deferred until the resolved baseline\n * lands (validating the empty shell would land spurious required\n * errors); a field unmounted in between never kicks.\n */\n validateOnMount?: boolean;\n};\n\n/**\n * Register a field validator with the form and return its kick — a stable\n * function that validates the field's current value (debounce and sync\n * gate applied). The returned function is the one stored in\n * `form.validators`; `trigger`/`ensureValidate` run every stored kick,\n * and the field's user-change gate runs the changed path's kick. This is\n * the old \"useValidate\" behavior — the same public shape with the\n * machinery moved into the core, so non-React adapters can register\n * validators directly through `registerValidatorByPath`.\n */\nexport default function useValidate(\n validate: Validator | undefined,\n path: Path,\n formProp?: Form,\n options?: UseValidateOptions\n): () => void {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(FormContext);\n const form = formProp || contextForm;\n if (!form) throw new Error('no form provided');\n // Live accessors: the registration must always see the latest\n // validator/debounce/sync-gate, so swapping them per render (inline\n // validators, recompiled rules) never re-subscribes the registration\n // mid-flight.\n const validateRef = useRef(validate);\n validateRef.current = validate;\n const debounceRef = useRef(options?.debounce ?? 0);\n debounceRef.current = options?.debounce ?? 0;\n const syncRef = useRef(options?.sync);\n syncRef.current = options?.sync;\n const asyncAlwaysRef = useRef(options?.asyncAlways ?? false);\n asyncAlwaysRef.current = options?.asyncAlways ?? false;\n\n useEffect(() => {\n const dispose = registerValidatorByPath(form, path, {\n validate: () => validateRef.current,\n debounce: () => debounceRef.current,\n sync: () => syncRef.current,\n asyncAlways: () => asyncAlwaysRef.current\n });\n // Mount validation: kick the registration once after it lands. The\n // field's own option wins over the form-level flag in either\n // direction. Validator-less registrations never kick — an empty kick\n // clears whatever error was already stored at the path (a server\n // backfill that landed before mount, say).\n const validateOnMount = options?.validateOnMount ?? form.validateOnMount;\n if (!validateOnMount || (!validateRef.current && !syncRef.current)) {\n return dispose;\n }\n // A deferred kick must never fire after this mount's registration was\n // disposed (unmount, or StrictMode's setup→cleanup→setup remount): the\n // flag drops it, and a remounted field's own setup schedules its kick.\n let disposed = false;\n const kick = () => {\n if (disposed) return;\n form.validators.get(path.key)?.();\n };\n if (!form.isLoading) {\n kick();\n } else {\n // Async initialValues pending: the 'loading' event fires after the\n // resolved baseline has landed (setInitialValues first), so the kick\n // validates real values instead of the empty shell.\n const off = on(form.emitter, 'loading', () => {\n off();\n kick();\n });\n }\n return () => {\n disposed = true;\n dispose();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath returns a stable Path per key, so re-subscribing on key (not object identity) is enough\n }, [form, path.key]);\n\n return useStageFn(() => form.validators.get(path.key)?.());\n}\n","/**\n * Unmount-removal helpers: the snapshot/remove pair and its restore.\n *\n * React 19's StrictMode double-invokes effects on the initial mount\n * (setup → cleanup → setup), so a plain effect cleanup that calls\n * {@link removeFieldByPath} runs during the mount cycle and wipes a field\n * the very next setup expects to be there. `useUnmountRestore` in\n * src/hooks/stage.ts runs the teardown synchronously on every cleanup\n * (real unmounts stay exactly as before) and hands the restore to the\n * setup that follows — which exists only in the StrictMode cycle, so the\n * removal is undone before any render or subscriber can observe the gap.\n *\n * This module is internal: hooks import it directly, the facade never\n * re-exports it.\n */\nimport {emit} from '../emitter';\nimport type {FieldError, Form} from '../form';\nimport type {Path} from '../path';\nimport {setErrorByPath} from './errors';\nimport {bumpValuesVersion} from './internals';\nimport {setTouchedByPath} from './touched';\nimport {removeFieldByPath, setValueByPath} from './values';\n\n/** Everything {@link removeFieldByPath} destroys, captured before it runs\n * so {@link restoreRemovedField} can put it back. */\nexport type RemovedFieldSnapshot = {\n /** Whether the values Map held the key — restores the exact entry,\n * including an explicit `undefined` value. */\n present: boolean;\n value: any;\n touched: boolean;\n errors: FieldError[] | undefined;\n};\n\n/**\n * Snapshot the field's state, then remove it — the teardown half of the\n * StrictMode-safe unmount removal.\n */\nexport function removeFieldForUnmount(\n form: Form,\n path: Path\n): RemovedFieldSnapshot {\n const {key} = path;\n const snapshot: RemovedFieldSnapshot = {\n present: form.values.has(key),\n value: form.values.get(key),\n touched: form.touched.has(key),\n errors: form.errors.get(key)\n };\n removeFieldByPath(form, path);\n return snapshot;\n}\n\n/**\n * Undo {@link removeFieldForUnmount} — the restore half, run only by a\n * setup that immediately follows the cleanup (the StrictMode remount).\n * Rebuilds the exact pre-removal state:\n * - a Map-backed value re-lands through {@link setValueByPath} with\n * `shouldDirty: false` (the removal cleared committed baselines; the\n * restored value becomes the baseline — identical dirty reads, since\n * the StrictMode cycle happens at mount before any edit exists)\n * - a baseline-derived value (absent from the Map) only needs its\n * tombstone undone — no write, so no entry materializes in the Map\n * - touched/errors re-add without re-validating\n */\nexport function restoreRemovedField(\n form: Form,\n path: Path,\n snapshot: RemovedFieldSnapshot\n): void {\n const {key} = path;\n if (snapshot.present) {\n setValueByPath(form, path, snapshot.value, {shouldDirty: false});\n } else {\n form.deleted.delete(key);\n bumpValuesVersion(form);\n // The removal emitted with a path payload; the restore must wake the\n // same subscribers so snapshots taken in the gap re-sync.\n emit(form.emitter, 'change', path);\n }\n if (snapshot.touched) setTouchedByPath(form, path);\n if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);\n}\n","import {useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport type {Context} from 'react';\nimport {on} from '../emitter';\nimport {FormContext} from '../context';\nimport {\n emitChangeByPath,\n getValueByPath,\n isFieldDirtyByPath,\n registerFieldMode,\n registerFieldValidateDeps,\n seedValueByPath,\n unregisterFieldMode,\n unregisterFieldValidateDeps,\n userBlur,\n userChangeByPath\n} from '../form';\nimport type {FieldError, Form, ValidationMode} from '../form';\nimport createPath from '../path';\nimport type {Path, PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport {rulesToValidator} from '../rules';\nimport type {FieldRules} from '../rules';\nimport {useFieldErrorsByPath, useWatch, useWatchCore} from './form';\nimport {onKeyEvent, onPathEvent} from '../subscribe';\nimport usePath from './path';\nimport useValidate from './validate';\nimport type {Validator} from './validate';\nimport {removeFieldForUnmount, restoreRemovedField} from '../core/unmount';\nimport type {RemovedFieldSnapshot} from '../core/unmount';\nimport {useStageFn, useUnmountRestore} from './stage';\nimport {isPromise} from '../util';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/** Module-private registry driving uncontrolled fields' DOM sync — one\n * 'change' listener per form (see the sync effect in {@link\n * useFieldCore}), the same module-scope registry pattern\n * `arrayIdsRegistry` uses in fieldArray.ts. Per-form cells map a field's\n * path key to a reader of its bound element and path; the shared listener\n * iterates them only on payload-less (bulk) emits. */\ntype UncontrolledSyncEntry = {\n cells: Map<string, () => {el: any; path: Path}>;\n off: () => void;\n};\nconst uncontrolledSyncRegistry = new WeakMap<Form, UncontrolledSyncEntry>();\n\nexport type UseFieldOptions<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n form?: Form<TValues>;\n name: TPath;\n initialValue?: any;\n shouldUnregister?: boolean;\n /**\n * Field-level validator. The value argument follows the path: with a\n * typed form the callback receives `PathValueOf<TValues, TPath>` (the\n * TanStack-parity inference — `name: 'age'` on a `{age: number}` shape\n * types `value` as `number`), and falls back to `any` for untyped call\n * sites (segment arrays, dynamic names). The return shape mirrors\n * {@link Validator} — an error (string / FieldError / mixed array) or\n * undefined when valid, possibly a Promise for async validation. The\n * second argument carries the validation context (`meta.signal` aborts\n * when the round is superseded).\n */\n validate?: (\n value: PathValueOf<TValues, TPath>,\n meta: {form: Form<TValues>; path: Path; signal: AbortSignal}\n ) => ReturnType<Validator>;\n /**\n * Declarative rules (required/min/max/minLength/maxLength/pattern),\n * compiled into a synchronous validator. `required` is special: it runs\n * immediately on every kick — never debounced — and while it fails,\n * `validate` is skipped (the expensive check never sees an empty value).\n * The other rules compose with `validate` — rules run first, then\n * `validate` (awaited when async), merging both sources' errors with\n * rules errors ahead. Failures land in the form's error state with the\n * given or default messages.\n */\n rules?: FieldRules;\n /**\n * Milliseconds to debounce this field's validation kicks. Defaults to 0\n * (validate immediately); while the timer is pending the field counts as\n * validating, so `trigger`/`ensureValidate` wait out the window. Only the\n * last kick inside the window runs the validator. The `required` rule is\n * exempt: it runs synchronously on every kick, so a required failure\n * shows immediately instead of waiting out the window.\n */\n validateDebounce?: number;\n /**\n * Run this field's debounced validator even when its `required` gate\n * failed — TanStack Form's `asyncAlways`. The gate's errors land\n * immediately (never debounced) and the validator's own result lands\n * alongside them, per-source: a passing async round clears only its\n * own errors while the gate's verdict stays. Falls back to the\n * form-level `createForm({asyncAlways})` flag when omitted, so a field\n * opts out with `asyncAlways: false`. The use case: the cheap format\n * check fails (gate) but the expensive backend check should still run\n * (\"not in the right shape — and the backend says taken, too\").\n */\n asyncAlways?: boolean;\n /**\n * Milliseconds to delay showing a newly appearing error in the render\n * layer (`error`/`errorObject`/`errors` stay undefined/empty until the\n * window passes). The form's error state is never delayed — trigger,\n * submit and `getError` read it immediately. An error that clears inside\n * the window never shows; once an error is visible, later changes apply\n * immediately. Only the none → some transition waits.\n */\n delayError?: number;\n /**\n * Disable this field: OR-ed with the form-level flag\n * (`createForm({disabled})` / `setDisabled`) into the result's\n * `disabled`. A field cannot opt out of a disabled form.\n */\n disabled?: boolean;\n /**\n * Uncontrolled mode: the field never subscribes to its own value, so\n * typing re-renders nothing — the store still carries every write\n * (getValues/submit/validation read it), and errors/touched/disabled/\n * validating still re-render the field like react-hook-form's\n * `register`. The result's `value` is the mount-time snapshot (initial\n * value seed or baseline); it never refreshes, and bulk operations\n * (reset/setInitialValues) sync the DOM element directly through the\n * `focusRef`-held element instead of a render — the register-style\n * contract, RHF's reset clears the input the same way. Attach the\n * result with `<input defaultValue={field.value} ref={field.focusRef}>`\n * -style binding (no `value` prop), exactly like <Field uncontrolled />\n * does. The DOM sync writes the raw stored value (file inputs are\n * skipped); read live values with useValue/getValues.\n */\n uncontrolled?: boolean;\n /**\n * Field-level validation mode override: when given, this field validates\n * on its own schedule instead of `form.mode` — every other field keeps\n * the form-level timing (e.g. a form that defaults to `'onSubmit'` with\n * one field declared `'onBlur'` shows that field's error on blur while\n * the rest wait for submit). `reValidateMode` stays form-level: once any\n * field has an error (after a failed submit, say), re-validation follows\n * the form's `reValidateMode` for every field, overriding this one too.\n * See {@link ValidationMode}.\n */\n mode?: ValidationMode;\n /**\n * Field paths whose **user changes re-run this field's validator** —\n * the field-level counterpart of the form-level `validateDeps` option\n * (cross-field linkage: `password` changed → re-check\n * `passwordConfirm`). TanStack Form's `onChangeListenTo` / RHF trigger\n * chains are the ecosystem analogues.\n *\n * The re-run rides the changed field's own onChange pipeline, so typing\n * and `changeValue` both fire it while programmatic `setValue` does\n * not, and its timing is gated by the same mode matrix as the form\n * level: the changed field's effective `mode` (per-field override\n * included) and the form's `reValidateMode` — under the default\n * `'onSubmit'`/`'onChange'` pair, a dep change re-validates this field\n * once this field already shows an error (the submit-then-fix flow: the\n * mismatch lands on submit, editing the password re-checks the confirm\n * and a passing round clears the error, because a field validator owns\n * its whole key).\n *\n * `validateDebounce` applies to the re-run like to any kick. Declaring\n * the field's own path is a no-op (its own change already validates it).\n */\n validateDeps?: FieldPath<TValues>[];\n /**\n * Validate this field once on mount instead of waiting for the first\n * submit/change — errors show immediately for an untouched field.\n * Overrides the form-level `createForm({validateOnMount})` flag in\n * either direction (`false` opts a field out of a validating form).\n * While an async `initialValues` source is still pending the kick waits\n * for the resolved baseline; a field unmounted in between never kicks.\n */\n validateOnMount?: boolean;\n};\n\n/**\n * The result of {@link useField}. Deliberately a closed shape: no index\n * signature, so a typo'd property access (`field.vlaue`) is a type error\n * instead of silently reading `undefined`.\n */\nexport type UseFieldResult<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n /** The form instance this field is bound to (explicit prop or context) —\n * handy for consumers that need direct access to the headless API. */\n form: Form<TValues>;\n value: PathValueOf<TValues, TPath>;\n /** Error message string (FieldError#message) for display, or undefined */\n error: string | undefined;\n /** Full FieldError object ({type, message}), or undefined */\n errorObject: FieldError | undefined;\n /** Every error registered for the field, in insertion order — `error`\n * and `errorObject` are its first entry. Empty (and reference-stable)\n * when the field has no errors. */\n errors: FieldError[];\n /**\n * Whether the field is dirty: its live value exists and differs from\n * the field's effective baseline (the same per-field rule\n * `getFieldState(form, name).isDirty` applies — committed\n * `shouldDirty: false` baselines included). Live in controlled mode;\n * pinned at mount in uncontrolled mode (like `value`) so typing never\n * re-renders the field — {@link useIsFieldDirty} is the live scoped\n * channel for either mode.\n */\n isDirty: boolean;\n /**\n * Whether a validator round for this field is currently in flight —\n * a pending debounce window or an unresolved async validator (the\n * `getFieldState(form, name).isValidating` reading, made reactive).\n */\n validating: boolean;\n onChange: (v: any) => void;\n onBlur: () => void;\n name: string;\n /** Merged disabled flag: the form-level flag (`createForm({disabled})`\n * toggled by `setDisabled`) OR-ed with this field's own `disabled`\n * option, updated live through the form's event core. */\n disabled: boolean;\n /**\n * Callback ref carrying the focus channel: attach it to your input\n * element (`<input ref={field.focusRef} />`) so `setFocus` and a failed\n * submit's first-error auto-focus (`shouldFocusError`) can focus this\n * headless field — the same 'focusError' wiring `<Field>` performs for\n * its own input. Without it, focus requests aimed at this field are\n * silent no-ops, matching `setFocus`'s contract: focusing a field\n * whose element is not bound neither throws nor focuses anything.\n */\n focusRef: (el: any) => void;\n};\n\n/** Does `rules` declare any constraint? `messages` alone does not\n * validate anything, and a constraint-free object would otherwise compile\n * into a validator that always passes — which would still open debounce\n * windows and hold the validating mark for nothing. `validate` callbacks\n * count: they are the only constraint a validate-only rules object\n * carries. */\nfunction hasRuleConstraints(rules: FieldRules): boolean {\n return (\n rules.required !== undefined ||\n rules.min !== undefined ||\n rules.max !== undefined ||\n rules.minLength !== undefined ||\n rules.maxLength !== undefined ||\n rules.pattern !== undefined ||\n rules.validate !== undefined\n );\n}\n\n/**\n * Compose declarative rules with a user validator: rules run first, then\n * the user's validator (awaited when async), and the results merge into\n * one error list with rules errors ahead. Either side may be absent —\n * the other passes through untouched. Errors are returned as an array (or\n * undefined when both sides pass), which setErrorByPath stores as-is.\n */\nfunction combineRulesAndValidate(\n rules: FieldRules | undefined,\n validate: Validator | undefined\n): Validator | undefined {\n if (!rules || !hasRuleConstraints(rules)) return validate;\n const ruleValidator = rulesToValidator(rules);\n if (!validate) return ruleValidator;\n return (value, meta) => {\n // rulesToValidator's contract is FieldError[] | undefined; the wider\n // Validator union here is only its declared type.\n const ruleErrors = ruleValidator(value, meta) as FieldError[] | undefined;\n const merge = (\n other: string | FieldError | (string | FieldError)[] | undefined\n ): (string | FieldError)[] | undefined => {\n const list: (string | FieldError)[] = [...(ruleErrors ?? [])];\n if (Array.isArray(other)) list.push(...other);\n else if (other) list.push(other);\n return list.length ? list : undefined;\n };\n const result = validate(value, meta);\n return isPromise(result) ? result.then(merge) : merge(result);\n };\n}\n\n/**\n * Render-layer gating for {@link UseFieldOptions}.delayError: hold a newly\n * appearing error back for `delay` ms while the form's error state stays\n * immediate. Only the none → some transition waits — an error that clears\n * inside the window never shows, and once an error is visible, later\n * changes (a new message, entries added or removed) apply immediately.\n * With `delay === undefined` the subscription value passes through\n * untouched: no timers and no state writes, so fields that do not opt in\n * pay nothing beyond the hook calls themselves.\n */\nfunction useDelayedErrors(\n errors: FieldError[],\n delay: number | undefined\n): FieldError[] {\n const [shown, setShown] = useState<FieldError[]>(errors);\n useEffect(() => {\n if (delay === undefined) return;\n // Clearing is always immediate: an error cleared inside the window is\n // cancelled before ever showing, a shown one hides at once (errors is\n // the shared empty constant on this branch).\n if (errors.length === 0) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- 取消窗口是设计行为:清空必须立刻生效\n setShown(errors);\n return;\n }\n // Already showing an error: swaps and list changes apply at once.\n if (shown.length > 0) {\n setShown(errors);\n return;\n }\n // Appearing from none: wait out the window. The cleanup clears the\n // timer when errors change again or the field unmounts.\n const timer = setTimeout(() => setShown(errors), delay);\n return () => clearTimeout(timer);\n }, [errors, delay, shown]);\n return delay === undefined ? errors : shown;\n}\n\n/**\n * Value snapshot for {@link useFieldCore}. Controlled fields subscribe to\n * 'change' at their own path (leaf scope) and track the store live.\n * Uncontrolled fields instead pin the value read at mount: no change\n * subscription, so typing re-renders nothing while the store still carries\n * every write (getValues/submit/validation read it). Errors, touched,\n * disabled and validating stay subscribed, so state-driven re-renders\n * behave like react-hook-form's `register`. The pinned snapshot is\n * deliberately never refreshed — reset/setInitialValues do not push into\n * it (or into a `defaultValue`-bound DOM element).\n */\nfunction useFieldValue(form: Form, path: Path, uncontrolled: boolean): any {\n const snapshotRef = useRef<{has: boolean; value: any}>({\n has: false,\n value: undefined\n });\n const getter = useCallback(() => {\n if (!uncontrolled) return getValueByPath(form, path);\n if (!snapshotRef.current.has) {\n snapshotRef.current = {has: true, value: getValueByPath(form, path)};\n }\n return snapshotRef.current.value;\n }, [uncontrolled, form, path]);\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n uncontrolled\n ? () => {}\n : onPathEvent(form.emitter, 'change', path, 'leaf', invalidate),\n [uncontrolled, form.emitter, path]\n );\n return useWatchCore(subscribeFactory, getter);\n}\n\n/**\n * Shared core of {@link useField} and the per-instance hooks returned by\n * `createFormContext()`: identical behavior, but the form is resolved from\n * whichever Context instance is passed in instead of the module-level one.\n *\n * `form` is always handed to `useValidate` explicitly, and an explicit form\n * wins over `useValidate`'s own context read — so scoped contexts need no\n * changes there.\n */\nexport function useFieldCore<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>(\n {\n form: f1,\n name,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateDeps,\n validateOnMount,\n delayError,\n disabled,\n uncontrolled,\n asyncAlways,\n mode: modeOption\n }: UseFieldOptions<TValues, TPath>,\n Context: Context<Form<any> | null>\n): UseFieldResult<TValues, TPath> {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = f1 || contextForm;\n if (!form) throw new Error('no form provided');\n const path = usePath(name);\n\n // Seed initialValue during render, not in an effect: the first paint\n // (SSR included — effects never run on the server) must already carry\n // the value, so the write lands here — before the value subscription\n // below takes its first snapshot. The write is emit-free (see\n // seedValueByPath) because emitting while rendering is illegal; the\n // post-commit effect announces it. The `=== undefined` guard keeps user\n // input and committed values safe across re-renders and remounts.\n const seededRef = useRef(false);\n const seeded =\n initialValue !== undefined && getValueByPath(form, path) === undefined;\n if (seeded) {\n seedValueByPath(form, path, initialValue);\n // Sticky until the announce effect consumes it, so StrictMode's second\n // render (which sees the value already seeded) still announces once.\n seededRef.current = true;\n }\n useEffect(() => {\n // Dep-less on purpose: the seed can land on a later render too (a\n // setInitialValues/reset wiped it; the guard re-seeds), and the\n // announcement must follow every actual seed. The flag makes the\n // steady state a cheap check.\n if (!seededRef.current) return;\n seededRef.current = false;\n // Wake path-scoped subscribers that rendered before this field in an\n // earlier commit — their snapshots predate the seed. Same-commit\n // subscribers self-heal through useSyncExternalStore's post-subscribe\n // snapshot check, and subscribers that already saw the seeded value\n // re-read an unchanged snapshot and bail out.\n emitChangeByPath(form, path);\n });\n\n // Undeclared options are dropped on purpose: the return value carries\n // only the fields declared on UseFieldResult, so nothing rides it back\n // onto DOM elements through a component's prop spread.\n //\n // `required` splits off into useValidate's synchronous gate: it runs\n // immediately on every kick (never debounced) and, while it fails, the\n // debounced validator is skipped — the other rules and `validate` never\n // see an empty value. The remaining rules still compose with `validate`\n // inside the debounced validator.\n const restRules: FieldRules | undefined = rules\n ? {...rules, required: undefined}\n : undefined;\n useValidate(combineRulesAndValidate(restRules, validate), path, form, {\n debounce: validateDebounce,\n validateOnMount,\n asyncAlways: asyncAlways ?? form.asyncAlways,\n sync:\n rules && rules.required !== undefined\n ? rulesToValidator({required: rules.required})\n : undefined\n });\n\n // All errors of the field through one subscription; the array reference\n // is stable (stored array or shared empty constant), so consumers can\n // memo on it. delayError gates only this render-layer view of the list;\n // the stored list keeps driving the reValidateMode kicks inside the\n // core's user-change gate.\n const liveErrors = useFieldErrorsByPath(form, path);\n const errors = useDelayedErrors(liveErrors, delayError);\n const errorObject = errors[0];\n const error = errorObject?.message;\n const value = useFieldValue(form, path, !!uncontrolled);\n // isDirty is a value-derived flag: like the value itself, it stays live\n // only in controlled mode. Uncontrolled fields pin it at mount — a live\n // subscription here would re-render the field on every keystroke and\n // break the register-parity contract (typing re-renders nothing). The\n // live scoped channel for either mode is useIsFieldDirty. `validating`\n // is a non-value flag: it stays subscribed in both modes (like errors/\n // touched/disabled), matching its exact key with payload-less\n // broadcasts still syncing everything.\n const isDirty = useWatchCore(\n useCallback(\n (invalidate: () => void) =>\n uncontrolled\n ? () => {}\n : onPathEvent(form.emitter, 'change', path, 'leaf', invalidate),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- usePath memoizes the Path per key, so key pins the subscription like every path-scoped hook\n [form.emitter, path.key, uncontrolled]\n ),\n () => isFieldDirtyByPath(form, path)\n );\n const validating = useWatchCore(\n useCallback(\n (invalidate: () => void) =>\n onKeyEvent(form.emitter, 'validating', path.key, invalidate),\n [form.emitter, path.key]\n ),\n () => form.validating.has(path.key)\n );\n\n // The form-level disabled flag, subscribed so setDisabled re-renders\n // this field; the field's own option is OR-ed in on every render.\n const formDisabled = useWatch(form, 'disabled', () => form.disabled);\n\n // The user-change pipeline lives in the core: onChange forwards to\n // userChangeByPath (write + mode/reValidateMode-gated validation, the\n // matrix registered below through registerFieldMode), onBlur to\n // userBlur (touched marking + blur-side gate). The stage keeps the\n // handler identities stable across re-renders.\n const onChange = useStageFn((v: any) => userChangeByPath(form, path, v));\n const onBlur = useStageFn(() => userBlur(form, path));\n\n // Register this field's validation-mode override so path-based\n // user-change writes (changeValue / changeValueByPath) route through\n // the same gated core pipeline as a user typing into the field.\n // Two fields mounted at the same path compete for the slot last-wins:\n // from here on every user-change write gates on the latest mount's\n // mode. That is almost always a bug (a stray duplicate name, a remount\n // racing the old instance) — say so in DEV.\n useEffect(() => {\n const {token, displaced} = registerFieldMode(form, path, modeOption);\n if (__DEV__ && displaced) {\n // eslint-disable-next-line no-console -- the whole point of this branch\n console.warn(\n `react-f0rm: two fields are mounted at the same path ${path.key}. ` +\n `The latest mount's mode registration owns the slot, so changeValue ` +\n `writes gate on it and the earlier field's validation mode no ` +\n `longer applies. Use distinct names if both must stay mounted.`\n );\n }\n return () => unregisterFieldMode(form, path, token);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath memoizes the Path per key, so re-registering on key (not object identity) is enough\n }, [form, path.key, modeOption]);\n\n // Publish this field's validateDeps declaration so the dep fields'\n // change pipelines can find it (revalidateDependentsOnChange). Keyed on\n // the serialized dep list, so a re-render passing an equal inline array\n // does not churn the registry; a genuinely changed list re-registers.\n const depsKey = validateDeps?.length ? validateDeps.join('\\n') : undefined;\n useEffect(() => {\n if (!depsKey) return;\n const depKeys = validateDeps!.map(dep => createPath(dep).key);\n registerFieldValidateDeps(form, path.key, depKeys);\n return () => unregisterFieldValidateDeps(form, path.key, depKeys);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `depsKey` on purpose: depKeys derive from the same option value the key serializes\n }, [form, path.key, depsKey]);\n\n // The focus channel. 'focusError' carries the target's path key —\n // emitted by handleSubmit's failed round (the first error's key, gated\n // by shouldFocusError) and by setFocus (with an optional\n // {shouldSelect} second argument). Subscribing here rather than inside\n // <Field> means headless useField consumers get focus support by\n // attaching focusRef; <Field> merely forwards it through its merged\n // ref. The callback ref is identity-stable, so re-renders never detach\n // the element, and the null guard keeps unbound fields silent no-ops.\n const elementRef = useRef<any>(null);\n const focusRef = useCallback((el: any) => {\n elementRef.current = el;\n }, []);\n useEffect(\n () =>\n on(\n form.emitter,\n 'focusError',\n (key: string, options?: {shouldSelect?: boolean}) => {\n if (key !== path.key) return;\n const el = elementRef.current;\n if (!el || typeof el.focus !== 'function') return;\n el.focus();\n if (options?.shouldSelect && typeof el.select === 'function') {\n el.select();\n }\n }\n ),\n [form, path.key]\n );\n\n // Uncontrolled DOM sync: a payload-less 'change' means a bulk operation\n // (reset, setInitialValues) rewrote values without a React render, and\n // an uncontrolled field deliberately never subscribes to its own value\n // — so its DOM element would keep stale text. Write the store's value\n // straight into the element held by the focus channel (register-style:\n // no re-render — exactly how RHF's reset clears uncontrolled inputs).\n //\n // One listener per form, not per field: a per-field subscription would\n // add O(mounted fields) handler calls to every keystroke — breaking the\n // O(affected-fields) change contract the uncontrolled parity bench\n // measures. The shared listener returns on the first check for\n // payload-carrying emits (typing, setValue), so bulk operations pay one\n // iteration over the registered cells and keystrokes pay one branch.\n useEffect(() => {\n if (!uncontrolled) return;\n let entry = uncontrolledSyncRegistry.get(form);\n if (!entry) {\n const cells = new Map<string, () => {el: any; path: Path}>();\n const off = on(form.emitter, 'change', (changed?: Path) => {\n if (changed) return;\n for (const read of cells.values()) {\n const {el, path} = read();\n // File inputs cannot be assigned a value at all.\n if (!el || el.type === 'file') continue;\n const next = getValueByPath(form, path);\n const asString = next == null ? '' : String(next);\n if (el.value !== asString) el.value = asString;\n }\n });\n entry = {cells, off};\n uncontrolledSyncRegistry.set(form, entry);\n }\n entry.cells.set(path.key, () => ({el: elementRef.current, path}));\n return () => {\n entry!.cells.delete(path.key);\n if (entry!.cells.size === 0) {\n entry!.off();\n uncontrolledSyncRegistry.delete(form);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath returns a stable Path per key, and the closure's `path` changes identity only when the key does\n }, [form, path.key, uncontrolled]);\n\n // Effective unmount behavior: the field's own option, falling back\n // to the form-level default, then to this library's historical\n // default (tombstone). The removal snapshots first and a setup that\n // immediately follows the cleanup (StrictMode's dev\n // setup→cleanup→setup cycle) restores it — see useUnmountRestore.\n const removalSnapshotRef = useRef<RemovedFieldSnapshot | null>(null);\n const teardownOnUnmount = useStageFn(() => {\n if ((shouldUnregister ?? form.shouldUnregister) === false) return;\n removalSnapshotRef.current = removeFieldForUnmount(form, path);\n });\n const restoreAfterStrictMode = useStageFn(() => {\n const snapshot = removalSnapshotRef.current;\n removalSnapshotRef.current = null;\n if (snapshot) restoreRemovedField(form, path, snapshot);\n });\n useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);\n\n return {\n form,\n value,\n error,\n errorObject,\n errors,\n isDirty,\n validating,\n onChange,\n onBlur,\n name: path.key,\n disabled: formDisabled || !!disabled,\n focusRef\n };\n}\n\nexport default function useField<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>(options: UseFieldOptions<TValues, TPath>): UseFieldResult<TValues, TPath> {\n return useFieldCore(options, FormContext);\n}\n","import {useCallback, useContext, useEffect, useReducer, useRef} from 'react';\nimport type {Context} from 'react';\nimport {FormContext} from '../context';\nimport {getValueByPath, setValueByPath} from '../form';\nimport type {FieldError, Form, Name} from '../form';\nimport {removeFieldForUnmount, restoreRemovedField} from '../core/unmount';\nimport type {RemovedFieldSnapshot} from '../core/unmount';\nimport {rulesToValidator} from '../rules';\nimport type {FieldRules} from '../rules';\nimport {onPathEvent} from '../subscribe';\nimport {useFieldErrorsByPath} from './form';\nimport usePath from './path';\nimport useStage, {useStageFn, useUnmountRestore} from './stage';\nimport useValidate from './validate';\n\n/** Per-form row-id counter. A module-level counter would grow across\n * every form on the page — and, on the server, across requests (ids like\n * `_4701` after a day of SSR). Keyed weakly so it dies with the form. */\nconst idCounters = new WeakMap<Form, number>();\n\nfunction generateId(form: Form): string {\n const next = (idCounters.get(form) ?? 0) + 1;\n idCounters.set(form, next);\n return `_${next}`;\n}\n\n/**\n * Live `id -> index` tables shared between {@link useFieldArray} and\n * {@link useFieldArrayItem}: one ids array per (form, array key), keyed\n * weakly so it dies with the form. The array is the hook's own `idsRef`\n * reference (mutated in place by the movers), so items always read the\n * latest order without owning a subscription of their own.\n */\nconst arrayIdsRegistry = new WeakMap<Form, Map<string, string[]>>();\n\nfunction getArrayIds(form: Form, key: string): string[] | undefined {\n return arrayIdsRegistry.get(form)?.get(key);\n}\n\nfunction registerArrayIds(form: Form, key: string, ids: string[]): void {\n let registry = arrayIdsRegistry.get(form);\n if (!registry) {\n registry = new Map();\n arrayIdsRegistry.set(form, registry);\n }\n registry.set(key, ids);\n}\n\n/** Stable identity for the render-count reducer below: never recreated,\n * so the dispatch path stays referentially clean. */\nfunction bumpReducer(count: number): number {\n return count + 1;\n}\n\ntype FieldArrayItem<K extends string> = {id: string; index: number} & Record<\n K,\n string\n>;\n\n/** Options accepted by {@link useFieldArray} and the per-instance hook\n * returned by `createFormContext()`. */\nexport type UseFieldArrayOptions<K extends string = 'id'> = {\n name: Name;\n form?: Form;\n /**\n * Property name the stable row key is exposed under on each `fields`\n * entry (react-hook-form's `keyName`): defaults to `'id'`, a custom\n * name (e.g. `'key'`) avoids clashing with a row data field of the\n * same name. The underlying id is unchanged.\n */\n keyName?: K;\n /**\n * Declarative rules validated against the whole array value\n * (react-hook-form's `useFieldArray` `rules`): `required` fails on an\n * empty array, `minLength`/`maxLength` read the array's length. Checked\n * on submit and `trigger`, like every registered validator.\n */\n rules?: FieldRules;\n /**\n * Whether unmounting this array removes its branch. Defaults to the\n * form-level `shouldUnregister` — tombstone (drop values) like a bound\n * field's unmount; pass `false` to keep the values.\n */\n shouldUnregister?: boolean;\n};\n\nexport type UseFieldArrayResult<K extends string = 'id'> = {\n fields: FieldArrayItem<K>[];\n append: (value: any) => void;\n prepend: (value: any) => void;\n insert: (index: number, value: any) => void;\n remove: (index: number) => void;\n swap: (from: number, to: number) => void;\n move: (from: number, to: number) => void;\n replace: (values: any[]) => void;\n update: (index: number, value: any) => void;\n};\n\n/**\n * Shared core of {@link useFieldArray} and the per-instance hook returned by\n * `createFormContext()`: identical behavior, but the form is resolved from\n * whichever Context instance is passed in instead of the module-level one.\n */\nexport function useFieldArrayCore<K extends string = 'id'>(\n options: UseFieldArrayOptions<K>,\n Context: Context<Form<any> | null>\n): UseFieldArrayResult<K> {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = options.form || contextForm;\n if (!form) throw new Error('no form provided');\n const keyName = (options.keyName ?? 'id') as K;\n const {rules, shouldUnregister} = options;\n const path = usePath(options.name);\n const idsRef = useRef<string[]>([]);\n\n const getArray = useCallback(\n (): any[] => getValueByPath(form, path) || [],\n [form, path]\n );\n\n const setArray = useCallback(\n (arr: any[]) => {\n setValueByPath(form, path, arr);\n },\n [form, path]\n );\n\n const computeFields = useCallback(() => {\n const arr = getArray();\n while (idsRef.current.length < arr.length) {\n idsRef.current.push(generateId(form));\n }\n while (idsRef.current.length > arr.length) {\n idsRef.current.pop();\n }\n return idsRef.current.map((id, index) => ({\n id,\n index,\n [keyName]: id\n })) as FieldArrayItem<K>[];\n }, [getArray, form, keyName]);\n\n // Subscribe to 'change' events scoped to this array's branch: the array\n // key itself, its ancestors (an ancestor write replaces what the leaf\n // read falls back to) and its descendants (item edits), so typing into\n // unrelated fields does not re-render the array component. Payload-less\n // 'change' emits (reset, setInitialValues) always sync, and a field\n // unmounting inside the branch fires through the descendant match. The\n // comma-separated key prefix comparison lives in onPathEvent,\n // which keeps lookalike sibling keys ('[\"tagsX\"]') from matching.\n const [fields, syncFields] = useReducer(\n computeFields,\n undefined,\n computeFields\n );\n useEffect(\n () => onPathEvent(form.emitter, 'change', path, 'branch', syncFields),\n [form.emitter, path]\n );\n\n // Publish the live ids array so per-item hooks (useFieldArrayItem) can\n // resolve id -> index. Registered during render — not only in an effect —\n // so items rendered in the same first paint, and on the server, already\n // resolve; the set is idempotent (same reference every render, the\n // movers mutate it in place, `replace` swaps it and the next render\n // re-registers). The effect mirrors the registration because StrictMode\n // exercises the cleanup path on mount (unsubscribe, un-register, re-run)\n // without a fresh render in between — without it the table would stay\n // empty and every item would resolve to -1. Unmount drops the entry\n // only while this hook still owns it; a second useFieldArray at the\n // same path competes for the slot last-wins, same as the field-mode\n // registration in useField.\n registerArrayIds(form, path.key, idsRef.current);\n useEffect(() => {\n registerArrayIds(form, path.key, idsRef.current);\n return () => {\n const registry = arrayIdsRegistry.get(form);\n if (registry?.get(path.key) === idsRef.current) registry.delete(path.key);\n };\n }, [form, path.key]);\n\n // Unmount behavior mirrors a bound field's: the effective\n // shouldUnregister (this hook's option, falling back to the form-level\n // default — tombstone unless the form opts into RHF's keep-the-value\n // semantics) decides whether the branch drops out of reads and\n // getValues(). Removing the branch also clears its\n // errors/touched/dirty entries. The snapshot/restore pair rides\n // useUnmountRestore so StrictMode's dev setup→cleanup→setup cycle does\n // not wipe the branch on mount while real unmounts stay synchronous.\n const removalSnapshotRef = useRef<RemovedFieldSnapshot | null>(null);\n const teardownOnUnmount = useStageFn(() => {\n if ((shouldUnregister ?? form.shouldUnregister) === false) return;\n removalSnapshotRef.current = removeFieldForUnmount(form, path);\n });\n const restoreAfterStrictMode = useStageFn(() => {\n const snapshot = removalSnapshotRef.current;\n removalSnapshotRef.current = null;\n if (snapshot) restoreRemovedField(form, path, snapshot);\n });\n useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);\n\n // Declarative array rules: `required` splits into the synchronous gate\n // (runs immediately on every kick, never debounced) exactly like\n // useField's rules; the remaining rules land as the debounced validator.\n useValidate(\n rules ? rulesToValidator({...rules, required: undefined}) : undefined,\n path,\n form,\n {\n sync:\n rules && rules.required !== undefined\n ? rulesToValidator({required: rules.required})\n : undefined\n }\n );\n\n const append = useStageFn((value: any) => {\n const arr = getArray();\n idsRef.current.push(generateId(form));\n setArray([...arr, value]);\n });\n\n const prepend = useStageFn((value: any) => {\n const arr = getArray();\n idsRef.current.unshift(generateId(form));\n setArray([value, ...arr]);\n });\n\n const insert = useStageFn((index: number, value: any) => {\n const arr = getArray();\n idsRef.current.splice(index, 0, generateId(form));\n const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];\n setArray(newArr);\n });\n\n const remove = useStageFn((index: number) => {\n const arr = getArray();\n idsRef.current.splice(index, 1);\n const newArr = arr.filter((_: any, i: number) => i !== index);\n setArray(newArr);\n });\n\n const swap = useStageFn((from: number, to: number) => {\n const arr = getArray();\n [idsRef.current[from], idsRef.current[to]] = [\n idsRef.current[to],\n idsRef.current[from]\n ];\n const newArr = [...arr];\n [newArr[from], newArr[to]] = [newArr[to], newArr[from]];\n setArray(newArr);\n });\n\n const move = useStageFn((from: number, to: number) => {\n const arr = getArray();\n const [id] = idsRef.current.splice(from, 1);\n idsRef.current.splice(to, 0, id);\n const newArr = [...arr];\n const [item] = newArr.splice(from, 1);\n newArr.splice(to, 0, item);\n setArray(newArr);\n });\n\n // replace is a full swap (length may change), so every row is conceptually\n // a new row: regenerate all ids to remount them, mirroring how reset works.\n const replace = useStageFn((values: any[]) => {\n idsRef.current = values.map(() => generateId(form));\n setArray([...values]);\n });\n\n // update only overwrites one value, so the id at that index is kept and the\n // row does not remount. Out-of-bounds indices are a silent no-op — plain\n // assignment would instead punch sparse-array holes into the form state.\n const update = useStageFn((index: number, value: any) => {\n const arr = getArray();\n if (index < 0 || index >= arr.length) return;\n const newArr = [...arr];\n newArr[index] = value;\n setArray(newArr);\n });\n\n return {fields, append, prepend, insert, remove, swap, move, replace, update};\n}\n\nexport default function useFieldArray<K extends string = 'id'>(\n options: UseFieldArrayOptions<K>\n): UseFieldArrayResult<K> {\n return useFieldArrayCore(options, FormContext);\n}\n\n/**\n * The result of {@link useFieldArrayItem}. Mirrors the {@link useField}\n * return shape (`value`/`errors`/`error`) plus the row's `index` and\n * `name` (path key) so nested fields can build on it —\n * `useField({name: ['tags', item.index, 'label']})`.\n */\nexport type UseFieldArrayItemResult<TValue = any> = {\n value: TValue;\n /** Overwrite this row's value in place (same array-layer write as\n * `update(index, value)`: the row's id and position are kept). */\n setValue: (value: TValue) => void;\n /** Every error registered for the row's path, insertion order; the\n * shared empty constant while clean, so consumers can memo on it. */\n errors: FieldError[];\n /** First error's message — the display text — or undefined. */\n error: string | undefined;\n /** The row's current path key (JSON-stringified segments, e.g.\n * `[\"tags\",0]`); moves with the row across reorder/remove. */\n name: string;\n /** The row's current position in the array. `-1` while the row is being\n * removed (or when no useFieldArray is mounted at `name`): reads return\n * undefined and nothing writes the dangling path. */\n index: number;\n form: Form;\n};\n\n/**\n * Shared core of {@link useFieldArrayItem} and the per-instance hook\n * returned by `createFormContext()`: identical behavior, but the form is\n * resolved from whichever Context instance is passed in instead of the\n * module-level one.\n */\nexport function useFieldArrayItemCore<TValue = any>(\n options: {name: Name; id: string; form?: Form},\n Context: Context<Form<any> | null>\n): UseFieldArrayItemResult<TValue> {\n // Read the context unconditionally (hook call order must be stable), then\n // let an explicitly passed form win — works without a <FormProvider>.\n const contextForm = useContext(Context);\n const form = options.form || contextForm;\n if (!form) throw new Error('no form provided');\n const {id} = options;\n const arrayPath = usePath(options.name);\n\n // --- snapshots: locate the row by its stable id through the array's\n // published ids table, then read its value from the array layer — the\n // same layer every useFieldArray operation and `setValue` below write,\n // so `value` and update/append/swap/… always agree with each other.\n const computeIndex = useCallback(\n () => getArrayIds(form, arrayPath.key)?.indexOf(id) ?? -1,\n [form, arrayPath.key, id]\n );\n const computeValue = useCallback(\n (index: number) => {\n const arr = getValueByPath(form, arrayPath);\n return Array.isArray(arr) ? arr[index] : undefined;\n },\n [form, arrayPath]\n );\n\n // Both are read synchronously during render (SSR included: no effect is\n // involved), and the last-rendered pair is mirrored into refs for the\n // subscription below. Writing own refs during render follows the same\n // pattern as `useStage`.\n const index = computeIndex();\n const value = computeValue(index) as TValue;\n const lastRef = useRef({index, value});\n lastRef.current = {index, value};\n\n // A render is scheduled only when the row's own view would change. The\n // subscription is 'leaf'-scoped on the array key: every useFieldArray\n // operation rewrites that key (payload-less broadcasts — reset,\n // setInitialValues — always fire), so this fires exactly when the row\n // order or the array can have moved, while a write to one item's leaf\n // path (`['tags', 1]`) never fires it. The comparison happens in the\n // listener — not through React's equal-state bailout, which act/test\n // environments do not honor — so an unchanged row never dispatches at\n // all and its component function never runs: append, update and\n // single-row edits leave untouched rows completely quiet, and a\n // whole-array rewrite re-renders only rows whose value reference (or\n // index) actually changed — the shallow copies keep untouched items'\n // references stable. Rows whose index migrates (remove/move/swap/\n // insert) re-render by design; computing `next` with the fresh index\n // means a row that moved but kept its value still bumps.\n const computeRef = useStage({computeIndex, computeValue});\n const [, bump] = useReducer(bumpReducer, 0);\n useEffect(\n () =>\n onPathEvent(form.emitter, 'change', arrayPath, 'leaf', () => {\n const {computeIndex: idx, computeValue: val} = computeRef.current;\n const nextIndex = idx();\n if (\n nextIndex !== lastRef.current.index ||\n !Object.is(val(nextIndex), lastRef.current.value)\n )\n bump();\n }),\n [form.emitter, arrayPath, computeRef]\n );\n\n // --- errors: stored per exact key, so this is the one place the row's\n // indexed path is needed. A removed row resolves to index -1: the\n // parent is about to unmount this component (its key left `fields`),\n // and until that commit lands the dangling key is inert — reads return\n // undefined/no errors and the `setValue` guard refuses to write. -1\n // also surfaces when no useFieldArray is mounted at `name`; pairing\n // the two hooks is the documented contract.\n const itemPath = usePath([...arrayPath.value, index]);\n const errors = useFieldErrorsByPath(form, itemPath);\n\n const setValue = useStageFn((v: TValue) => {\n if (index < 0) return;\n const arr = [...(getValueByPath(form, arrayPath) ?? [])];\n if (index >= arr.length) return;\n arr[index] = v;\n setValueByPath(form, arrayPath, arr);\n });\n\n return {\n value,\n setValue,\n errors,\n error: errors[0]?.message,\n name: itemPath.key,\n index,\n form\n };\n}\n\n/**\n * Subscribe to a single row of a {@link useFieldArray} field — the\n * per-item counterpart `useFieldArray` alone cannot offer. `useFieldArray`\n * subscribes to the whole branch, so any row's edit re-renders the\n * component holding the array (and, without memoization, every row);\n * `useFieldArrayItem` scopes what re-renders to one row identified by its\n * stable id: editing row K re-renders only row K's component, and a\n * whole-array rewrite re-renders only rows whose value reference actually\n * changed. Pair it with a `React.memo` row component that takes stable\n * props (`form`, `id`) so the array component's own re-render cannot drag\n * the rows along.\n *\n * Rows whose index migrates — remove/move/swap/insert reshuffles —\n * re-render by design: the row's path contains the index, exactly like\n * TanStack Form's per-field api. The win is single-row edits staying\n * single-row.\n *\n * Value reads and writes live on the array layer — the same layer every\n * `useFieldArray` operation touches — so `value`, `setValue` and\n * `update`/`append`/… always agree with each other.\n *\n * @param options `name` of the array (a useFieldArray must be mounted at\n * the same path — it publishes the id table), the row's `id` from\n * `fields[i].id`, and optionally an explicit `form`\n */\nexport function useFieldArrayItem<TValue = any>(options: {\n name: Name;\n id: string;\n form?: Form;\n}): UseFieldArrayItemResult<TValue> {\n return useFieldArrayItemCore(options, FormContext);\n}\n","import {createContext, createElement, useContext, type ReactNode} from 'react';\nimport {\n useFieldCore,\n type UseFieldOptions,\n type UseFieldResult\n} from './hooks/field';\nimport {\n useFieldArrayCore,\n useFieldArrayItemCore,\n type UseFieldArrayOptions,\n type UseFieldArrayResult,\n type UseFieldArrayItemResult\n} from './hooks/fieldArray';\nimport type {FieldRules} from './rules';\nimport type {Form} from './form';\nimport type {Name, PathSegments} from './path';\nimport type {FieldPath} from './types';\n\nexport const FormContext = createContext<Form<any> | null>(null);\n\nexport const FormProvider = FormContext.Provider;\n\n/**\n * Read the form from the module-level {@link FormContext}. Pass the values\n * shape — `useFormContext<Values>()` — to get a fully typed `Form<Values>`\n * headless API; the `any` default keeps untyped call sites compiling.\n *\n * For multiple forms in one subtree use {@link createFormContext} instead.\n *\n * @throws when no `<FormProvider>` is mounted above the call site.\n */\nexport function useFormContext<T extends Record<string, any> = any>(): Form<T> {\n const form = useContext(FormContext);\n if (!form) throw new Error('no form provided');\n return form;\n}\n\n/**\n * Create an isolated bundle of form-context bindings: its own React context\n * plus `useField` / `useFieldArray` / `useFieldArrayItem` /\n * `useFormContext` hooks that resolve their form from it.\n *\n * Why: the module-level {@link FormContext} works fine for a single form per\n * subtree, but nesting two forms (or reusing a component inside a different\n * form) makes them fight over one context. Calling this factory once per app\n * area — `const Ctx = createFormContext<Values>()` — fixes the value shape\n * (`Ctx.useField({name: 'user.name'})` gets its `name` constrained by\n * `FieldPath<Values>` and its `value` typed accordingly), so call sites stop\n * hand-writing generics, and each instance's Provider scopes a strictly\n * separate form. The bundle also carries its raw React context\n * (`Ctx.context`) so `<Form context={Ctx.context}>` can provide into it.\n */\nexport function createFormContext<TValues extends Record<string, any> = any>() {\n const Context = createContext<Form<TValues> | null>(null);\n\n // A `form`-prop wrapper instead of exposing Context.Provider directly:\n // callers shouldn't have to know about the raw `value` prop shape.\n function FormProvider({\n form,\n children\n }: {\n form: Form<TValues>;\n children: ReactNode;\n }): ReactNode {\n return createElement(Context.Provider, {value: form}, children);\n }\n\n function useFormContext(): Form<TValues> {\n const form = useContext(Context);\n if (!form) throw new Error('no form provided');\n return form;\n }\n\n function useField<\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n // The bare `{name: TPath}` member keeps `name` a direct inference site\n // for TPath instead of routing it through the mapped Omit type.\n // `form` is omitted on purpose — the form always comes from this\n // factory's own Context.\n options: {name: TPath} & Omit<UseFieldOptions<TValues, TPath>, 'form'>\n ): UseFieldResult<TValues, TPath> {\n return useFieldCore(options as UseFieldOptions<TValues, TPath>, Context);\n }\n\n function useFieldArray<K extends string = 'id'>(options: {\n name: FieldPath<TValues> | Name;\n keyName?: K;\n rules?: FieldRules;\n shouldUnregister?: boolean;\n }): UseFieldArrayResult<K> {\n return useFieldArrayCore(options as UseFieldArrayOptions<K>, Context);\n }\n\n function useFieldArrayItem<TValue = any>(options: {\n name: FieldPath<TValues> | Name;\n id: string;\n }): UseFieldArrayItemResult<TValue> {\n return useFieldArrayItemCore(options as {name: Name; id: string}, Context);\n }\n\n // The raw React context, for `<Form context={...}>`: the component keeps\n // its submit machinery while providing into this instance's private\n // context, so the bound hooks above resolve the form it manages.\n return {\n context: Context,\n FormProvider,\n useFormContext,\n useField,\n useFieldArray,\n useFieldArrayItem\n };\n}\n\nexport const CheckboxGroupContext = createContext<any>(null);\n\nexport const CheckboxGroupProvider = CheckboxGroupContext.Provider;\n\nexport function useCheckboxGroupContext(): any {\n const group = useContext(CheckboxGroupContext);\n if (!group) throw new Error('no group provided');\n return group;\n}\n","import {useCallback} from 'react';\nimport {getValueByPath, userChangeByPath} from '../form';\nimport type {Form} from '../form';\nimport type {PathSegments} from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\nimport {onPathEvent} from '../subscribe';\nimport {useWatchCore} from './form';\nimport usePath from './path';\n\n/**\n * Options accepted by {@link useTransform}.\n */\nexport type UseTransformOptions<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments,\n TDisplay = PathValueOf<TValues, TPath>\n> = {\n /**\n * Map the form's stored (raw) value to the display value the control\n * renders — the read direction. Omitted: the raw value is displayed\n * as-is (identity).\n */\n toDisplay?: (raw: PathValueOf<TValues, TPath>) => TDisplay;\n /**\n * Map a display value back to the raw value written into the form —\n * the write direction. Omitted: the display value is written as-is\n * (identity). The round trip should be an identity\n * (`toDisplay(fromDisplay(x)) === x`); a store value the transform\n * cannot invert (e.g. `undefined` for a not-yet-edited field) must be\n * handled by `toDisplay`, since it runs first.\n */\n fromDisplay?: (display: TDisplay) => PathValueOf<TValues, TPath>;\n};\n\n/**\n * Bind a control to a field whose stored value and display value differ\n * — TanStack Form's `useTransform` counterpart, with the round trip made\n * explicit: `toDisplay` maps the store value to what the control shows,\n * `fromDisplay` maps the control's display value back to what the store\n * holds. The store always carries the raw typed value, so\n * `getValues`/submit/validation never see display representations.\n *\n * ```jsx\n * const age = useTransform(form, 'age', {\n * toDisplay: (raw: number) => String(raw),\n * fromDisplay: (display: string) => Number(display)\n * });\n * <input value={age.value} onChange={e => age.onChange(e.target.value)} />\n * ```\n *\n * `value` subscribes to 'change' at leaf scope exactly like a controlled\n * `useField` value — typing, programmatic `setValue` and ancestor writes\n * all re-derive it, writes elsewhere never re-render it. `onChange`\n * writes through `userChangeByPath` (the user-change channel): with a\n * field mounted at the same path the mode/reValidateMode-gated\n * validation fires exactly as if the user typed into a bound field; with\n * no mounted field it degrades to a plain value write. Touched marking\n * stays a blur concern — pair this with `useField` at the same path, or\n * call `setTouched`, when blur semantics matter.\n *\n * The transform functions are read fresh on every render (inline\n * closures work), and `value` is recomputed per render — keep display\n * values primitive (string/number) so React's equal-state bailout holds.\n *\n * @param form the form instance (explicit; the hook is headless — no\n * context read, no provider required)\n * @param name the field's path (dotted string or segments)\n * @param options the two mapping directions; both optional (identity)\n */\nexport default function useTransform<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments,\n TDisplay = PathValueOf<TValues, TPath>\n>(\n form: Form<TValues>,\n name: TPath,\n options: UseTransformOptions<TValues, TPath, TDisplay> = {}\n): {value: TDisplay; onChange: (display: TDisplay) => void} {\n const path = usePath(name);\n const {toDisplay, fromDisplay} = options;\n\n const subscribeFactory = useCallback(\n (invalidate: () => void) =>\n onPathEvent(form.emitter, 'change', path, 'leaf', invalidate),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- usePath memoizes the Path per key, so key pins the subscription like every path-scoped hook\n [form.emitter, path.key]\n );\n const raw = useWatchCore(subscribeFactory, () => getValueByPath(form, path));\n const value = toDisplay ? toDisplay(raw) : (raw as TDisplay);\n\n const onChange = useCallback(\n (display: TDisplay) => {\n userChangeByPath(\n form,\n path,\n fromDisplay ? fromDisplay(display) : display\n );\n },\n [form, path, fromDisplay]\n );\n\n return {value, onChange};\n}\n","/**\n * Server-side validation entry — `react-f0rm/server`.\n *\n * The core (`./form`) is pure TypeScript with zero React imports, so it\n * already runs anywhere Node does; what the server lacked is an entry\n * that never pulls React into the module graph at all — the main entry\n * re-exports the hooks/components, and a Server Action or RSC that only\n * wants to check a payload should not have to depend on them. This module\n * is that entry: values in, one whole-form validation round, structured\n * result out.\n *\n * It plays the role TanStack Form gives `createServerValidate`, minus the\n * action prop: their API wraps validation inside a generated server\n * action, while react-f0rm keeps the values store the single source of\n * truth — {@link validateValues} is a plain function over values (the\n * same contract the client-side `trigger` has over a form instance), so\n * it composes into any server framework's handler instead of owning it.\n *\n * Like the resolvers and devtools it is intentionally NOT re-exported\n * from the main entry: importing `react-f0rm/server` is the only way this\n * code reaches a bundle, so client builds that never validate on the\n * server stay at baseline size.\n */\nimport createForm, {getErrors, getValues, trigger} from './form';\nimport type {FieldErrorEntry, Options, ValidationOutcome} from './form';\n\n// Building a branded ValidationOutcome server-side (schema adapters, or a\n// hand-written validate that returns parsed values) needs the brand symbol\n// itself; importing it from the package root would drag the React graph\n// back in, so it is re-exported here together with its result type.\nexport {VALIDATION_OUTCOME} from './form';\nexport type {ValidationOutcome};\n\n/** The outcome of {@link validateValues}: the error-free flag, the values\n * once the round has landed (schema-coerced where the validator produced\n * parsed values), and every error the round wrote as flat entries. */\nexport type ValidateValuesResult<T extends Record<string, any> = any> = {\n /** Whether the round landed no errors — `trigger`'s boolean. An invalid\n * payload is a normal outcome, never a rejection: unlike\n * `ensureValidate`, server callers learn validity from data instead of\n * catching, because both branches are interesting on the server\n * (persist vs. bounce back to the client). */\n valid: boolean;\n /** The values after the round. When the validator returned a branded\n * {@link ValidationOutcome} with `values`, those parsed values are the\n * baseline `getValues` layers over the input — schema coerce/transform\n * output included — so this is the tree to persist or feed onward, not\n * necessarily the object passed in. Deep-equals the input otherwise. */\n values: T;\n /** Every error the round landed, flattened to `{path, type, message}`\n * entries — the same list {@link getErrors} hands out on the client.\n * Feed it to `setServerErrors` to land a failed round back on the\n * client form (the Server Actions bridge; see the docs' Server Actions\n * guide). */\n errors: FieldErrorEntry[];\n};\n\n/** Append one value under `key` into `fd`. Arrays and FileLists flatten\n * to one entry per item (FormData's multi-entry convention); Files keep\n * their name; Dates become ISO strings; other objects JSON.stringify;\n * booleans/numbers/strings String() as a native form submit would. */\nfunction appendFormDataValue(fd: FormData, key: string, value: any): void {\n if (value == null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendFormDataValue(fd, key, item);\n return;\n }\n if (typeof FileList !== 'undefined' && value instanceof FileList) {\n for (let i = 0; i < value.length; i++) fd.append(key, value.item(i)!);\n return;\n }\n if (typeof File !== 'undefined' && value instanceof File) {\n fd.append(key, value, value.name);\n return;\n }\n if (typeof Blob !== 'undefined' && value instanceof Blob) {\n fd.append(key, value);\n return;\n }\n if (value instanceof Date) {\n fd.append(key, value.toISOString());\n return;\n }\n fd.append(\n key,\n typeof value === 'object' ? JSON.stringify(value) : String(value)\n );\n}\n\n/**\n * Convert a values object into FormData — the transport shape React 19\n * Server Actions and multipart handlers expect. Built to pair with the\n * `<Form action>` prop and `validateValues`: the validated (schema-coerced)\n * values tree lands in the server action as FormData, files included.\n *\n * Array values become multiple entries under the same key (FormData's\n * native multi-value convention); File values keep their name; Dates\n * become ISO strings; plain objects JSON.stringify; null/undefined are\n * skipped.\n */\nexport function formDataFromValues(values: Record<string, any>): FormData {\n const fd = new FormData();\n for (const key of Object.keys(values)) {\n appendFormDataValue(fd, key, values[key]);\n }\n return fd;\n}\n\n/**\n * Validate a payload of values on the server — no form instance, no\n * React.\n *\n * Spins up a throwaway form from `options` (with `initialValues` forced\n * to `values`), runs one whole-form `trigger`, and reads the outcome\n * back. `trigger` never rejects and waits out async validators and any\n * `validateDebounce` window, so a single `await` drains the whole round —\n * the returned `valid`/`errors` are final, not a snapshot mid-flight.\n *\n * Validation comes from `options.validate` — the form-level validator.\n * Field validators register through mounted fields (`useField`), and\n * nothing is mounted on the server, so they cannot participate by\n * construction; pass a schema-backed form validator\n * (`standardSchemaFormValidator(schema)` from\n * `react-f0rm/resolvers/standard-schema`) or a hand-written `validate`\n * instead. `mode`/`reValidateMode` are equally inert here — there are no\n * field events to gate — and may be omitted.\n *\n * When the validator returns a branded {@link ValidationOutcome} whose\n * `values` carry the schema's output, those parsed values become the\n * form's parsedValues baseline, so `result.values` flows coercion and\n * transforms forward (`z.coerce.number()` turning `'42'` into `42`, and\n * friends). Persist that tree; on the client the same schema round runs\n * again on submit, keeping one validation source across the boundary.\n *\n * Safe to call from Node, Server Actions and RSC — the module graph is\n * this file plus the pure core, zero React.\n *\n * @param values the payload to validate; becomes the form's initialValues\n * @param options form options; `validate` is where the rules come from\n * @return the settled round: `valid`, the (possibly parsed) values, and\n * the flat error entries\n */\nexport async function validateValues<T extends Record<string, any> = any>(\n values: T,\n options?: Options<T>\n): Promise<ValidateValuesResult<T>> {\n const form = createForm({...options, initialValues: values});\n const valid = await trigger(form);\n return {valid, values: getValues(form), errors: getErrors(form)};\n}\n","import * as React from 'react';\nimport {handleSubmit, setDisabled} from '../form';\n// 别名规避 rollup-plugin-dts 对「type import 与本地 default export 同名」\n// 的 Identifier already declared 误报(类型引用语义不变)。\nimport type {Form as FormApi} from '../form';\nimport {formDataFromValues} from '../server';\nimport {FormContext} from '../context';\nimport useForm from '../hooks/form';\n\n/**\n * Props for <Form>.\n *\n * Native validation behavior: the rendered <form> always sets noValidate,\n * which suppresses the browser's built-in blocked-submit UI. However, native\n * constraint validation still gates submission — the form element's\n * checkValidity() runs before custom validators, and when it fails,\n * reportValidity() surfaces the offending constraints as native bubbles and\n * submission stops (onInvalidSubmit fires). onSubmit/onValidSubmit only run\n * once every native constraint (required, type=email, minLength, ...) passes.\n *\n * The submit flow itself lives in the headless `handleSubmit` (see form.ts);\n * this component is a thin wrapper that binds it to the rendered <form>.\n */\ntype FormProps<T extends Record<string, any> = any> = Omit<\n React.FormHTMLAttributes<HTMLFormElement>,\n 'onSubmit'\n> & {\n form?: FormApi<T>;\n /**\n * Provide into an isolated context from `createFormContext()` instead of\n * the module-level one — `<Form context={ProfileForm.context}>` keeps the\n * component's full submit machinery while the factory's bound hooks\n * (`ProfileForm.useField`, `ProfileForm.useFormContext`, ...) resolve this\n * form from their private context. The module-level `useFormContext()` /\n * `useField` do not see it; that is the point of the isolation. Omitted,\n * the form lands in the module-level FormContext as before.\n */\n context?: React.Context<FormApi<any> | null>;\n /**\n * The values baseline — a sync object, a Promise, or a thunk returning\n * either ({@link Options.initialValues}). Async sources render the form\n * empty and gate on `form.isLoading` until they resolve.\n */\n initialValues?: T | Promise<T> | (() => T | Promise<T>);\n /**\n * Form-level default for a bound field's unmount behavior\n * ({@link Options.shouldUnregister}): `true` (the default) tombstones\n * unmounted fields, `false` keeps their values.\n */\n shouldUnregister?: boolean;\n /**\n * Validate on mount (see {@link Options.validateOnMount}): every\n * mounted field with a validator kicks once after mount and the\n * form-level `validate` (if any) runs once. A field's own\n * `validateOnMount` prop overrides this flag.\n */\n validateOnMount?: boolean;\n /**\n * Disable every bound field: the form-level flag fields OR with their\n * own `disabled` option (a field cannot opt out). Seeded at create and\n * kept in sync while this prop changes (undefined leaves the current\n * flag untouched — toggle at runtime with `setDisabled`).\n */\n disabled?: boolean;\n /**\n * Form-level default for field validation's `asyncAlways`: a field\n * whose `required` gate failed still runs its debounced validator, its\n * result landing per-source alongside the gate's errors. A field's own\n * `asyncAlways` prop overrides this flag.\n */\n asyncAlways?: boolean;\n /**\n * Controlled external values. When the `values` reference changes, the\n * new object is synced into the form (via setInitialValues semantics):\n * uncommitted user edits are discarded -- master-detail semantics, where\n * selecting another record replaces the draft -- while touched flags and\n * errors are kept. Sync is reference-based: re-renders that pass the same\n * `values` reference never clobber what the user is typing.\n */\n values?: T;\n /** May be async — the submit flow awaits it, so form.isSubmitting\n * covers the entire flight. */\n onSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;\n /** May be async, same as onSubmit. */\n onValidSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;\n /**\n * React 19 Server Action target: after validation passes (and after\n * onSubmit/onValidSubmit), the validated, schema-coerced values are\n * converted to FormData ({@link formDataFromValues} — files, arrays and\n * nested objects included) and dispatched to this callback, e.g.\n * `action={createUser}` for a server action or\n * `action={formData => startTransition(() => dispatch(formData))}` in a\n * useActionState bridge. `isSubmitting` covers the whole flight.\n */\n action?: (formData: FormData) => void | Promise<void>;\n /**\n * Called when validation fails.\n * @param errors array of {path, type, message} entries in insertion\n * order; path is the dotted field path ('a.b', 'list.0'), type is\n * the error kind ('custom' for plain string errors, 'native' for\n * failed DOM constraint validation), message is the display text\n * @param values current form values\n */\n onInvalidSubmit?: (\n errors: {path: string; type: string; message: string}[],\n values: T\n ) => void;\n /**\n * Focus the first field with an error after a failed submit: custom\n * validation failures focus the first errored field, native constraint\n * failures focus the first ':invalid' control. Defaults to true; pass\n * false to disable.\n */\n shouldFocusError?: boolean;\n};\n\nexport default function Form<T extends Record<string, any> = any>({\n form: f1,\n context,\n initialValues,\n values,\n shouldUnregister,\n validateOnMount,\n disabled,\n asyncAlways,\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n action,\n shouldFocusError,\n ...props\n}: FormProps<T>) {\n const f2 = useForm<T>({\n initialValues,\n values,\n shouldUnregister,\n validateOnMount,\n disabled,\n asyncAlways\n });\n const form = f1 || f2;\n\n // The form instance outlives prop changes (useForm creates it once), so\n // a changing `disabled` prop re-applies through the runtime channel —\n // the same `setDisabled` consumers toggle imperatively. undefined means\n // \"not controlled here\": leave the flag as-is.\n React.useEffect(() => {\n if (disabled !== undefined) setDisabled(form, disabled);\n }, [form, disabled]);\n\n const submit = handleSubmit(form, {\n onSubmit,\n onValidSubmit,\n onInvalidSubmit,\n shouldFocusError,\n onAction: action ? values => action(formDataFromValues(values)) : undefined\n });\n\n // Route the form into the caller's isolated context (createFormContext)\n // or the module-level default, whichever Provider we ended up with.\n const {Provider} = context ?? FormContext;\n\n return (\n <Provider value={form}>\n <form {...props} noValidate onSubmit={submit} />\n </Provider>\n );\n}\n","import * as React from 'react';\nimport useField from '../hooks/field';\nimport type {UseFieldOptions, UseFieldResult} from '../hooks/field';\nimport type {FieldPath} from '../types';\nimport type {PathSegments} from '../path';\n\n/**\n * Props for {@link FormField}: every {@link UseFieldOptions} option plus a\n * render-prop `children` receiving the bound field result.\n */\nexport type FormFieldProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n children: (field: UseFieldResult<TValues, TPath>) => React.ReactNode;\n};\n\n/**\n * Headless field bound through a render prop — the non-hook counterpart of\n * {@link useField} for class components, callback-style consumers and\n * library bridges where a hook cannot be called (Formik `<Field>` /\n * TanStack `form.Field` shape).\n *\n * The child function receives the full {@link UseFieldResult} — value,\n * error(s), onChange/onBlur, `disabled`, `focusRef`, the bound `form` —\n * and renders whatever UI it wants; nothing is rendered when it returns\n * null/undefined, so it can also gate conditional layout. Resolves its\n * form from the module-level `FormContext` or the explicit `form` option\n * (per-instance contexts from `createFormContext()` keep using their own\n * `useField` hook).\n */\nexport default function FormField<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n>({children, ...options}: FormFieldProps<TValues, TPath>): React.ReactNode {\n const field = useField<TValues, TPath>(options);\n return children(field);\n}\n","import * as React from 'react';\nimport useField from '../hooks/field';\nimport type {Validator} from '../hooks/validate';\nimport type {Form, ValidationMode} from '../form';\nimport {rulesToConstraintAttrs} from '../rules';\nimport type {FieldRules} from '../rules';\nimport type {Name, Path, PathSegments} from '../path';\nimport createPath from '../path';\nimport type {FieldPath, PathValueOf} from '../types';\n\n/** Dev-only flag, replaced at build time (rollup.config.js `replace`);\n * defined for the test environment in vitest.config.ts. */\ndeclare const __DEV__: boolean;\n\n/**\n * Props shared by Field/Checkbox/Select. Generic so a typed form flows into\n * the `validate` callback: with `form` (a `Form<Values>`) and `name`\n * (a `FieldPath<Values>`) provided, `validate` receives the value at that\n * path — `PathValueOf<Values, P>` — instead of `any`. The defaults keep the\n * bare `<Field name=\"x\" />` (context-resolved, untyped) call sites exactly\n * as permissive as before.\n */\ntype UseFieldOptions<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = {\n form?: Form<TValues>;\n name?: TPath;\n initialValue?: any;\n shouldUnregister?: boolean;\n /**\n * Field-level validator. The value argument is typed when the field is\n * tied to a typed form (via the `form` prop); the return shape mirrors\n * {@link Validator} — an error (string / FieldError / mixed array) or\n * undefined when valid, possibly a Promise for async validation. The\n * second argument carries the validation context (`meta.signal` aborts\n * when the round is superseded).\n */\n validate?: (\n value: PathValueOf<TValues, TPath>,\n meta: {form: Form; path: Path; signal: AbortSignal}\n ) => ReturnType<Validator>;\n /**\n * Declarative rules (required/min/max/minLength/maxLength/pattern,\n * plus custom `validate` callbacks), compiled into a validator that\n * runs before `validate`; failures land in the form's error state.\n * The declarative subset is also rendered as native constraint\n * attributes (`required`, `minLength`, `pattern`, …) onto the element\n * for browser/AT hints — `:invalid` styling, screen-reader\n * announcements — while the store pipeline stays the source of truth\n * for messages (`renderError`/`aria-invalid` keep working; a user-passed\n * `required`/`pattern`/… prop overrides the derived attribute). Passed\n * through to useField — like validateDebounce it is never spread onto\n * the DOM element.\n */\n rules?: FieldRules;\n /**\n * Milliseconds to debounce this field's validation kicks. Defaults to 0\n * (validate immediately); only the last kick inside the window runs the\n * validator, and `trigger` waits the window out. Passed through to\n * useField/useValidate.\n */\n validateDebounce?: number;\n /**\n * Run this field's debounced validator even when its `required` gate\n * failed (TanStack Form's `asyncAlways`): the gate's errors land\n * immediately, the validator's own result lands alongside them\n * per-source. Falls back to the form-level `createForm({asyncAlways})`.\n * Passed through to useField.\n */\n asyncAlways?: boolean;\n /**\n * Validate this field once on mount (see {@link\n * UseFieldOptions}' `validateOnMount`): overrides the form-level\n * `createForm({validateOnMount})` / `<Form validateOnMount>` flag in\n * either direction. Passed through to useField.\n */\n validateOnMount?: boolean;\n /**\n * Disable this field's control: OR-ed with the form-level flag\n * (`createForm({disabled})` / `setDisabled`) — a field cannot opt out\n * of a disabled form. Passed through to useField, like every option,\n * never spread onto the DOM element from props.\n */\n disabled?: boolean;\n /**\n * Milliseconds to delay showing a newly appearing error (render layer\n * only — `aria-invalid`/`renderError` wait out the window while the\n * form's error state stays immediate for trigger/submit). An error\n * that clears inside the window never shows; once visible, error\n * changes apply immediately. Passed through to useField.\n */\n delayError?: number;\n /**\n * Field-level validation mode override: this field validates on its own\n * schedule instead of the form's `mode` (other fields are unaffected);\n * the form's `reValidateMode` still governs re-validation once the\n * field has an error. Passed through to useField, never spread onto\n * the DOM element.\n */\n mode?: ValidationMode;\n /**\n * Uncontrolled mode: render the element with `defaultValue` instead of\n * `value` — typing re-renders nothing (the store still carries every\n * write; errors/touched/disabled still re-render the field). The\n * snapshot is pinned at mount; bulk operations (reset/setInitialValues)\n * sync the DOM element directly without a render — RHF-register\n * behavior (read live values with useValue/getValues). Passed through\n * to useField, never spread onto the DOM element.\n */\n uncontrolled?: boolean;\n [key: string]: any;\n};\n\ntype FieldProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n as?: React.ComponentType<any>;\n asProps?: Record<string, any>;\n eventToValue?: (e: any) => any;\n valueToProps?: (value: any) => Record<string, any>;\n /**\n * Optional error renderer. When provided and the field has an error,\n * Field renders `<span id={id} role=\"alert\">{renderError(error, id)}</span>`\n * next to the input. The input's aria-describedby points at that span's\n * id (the same `fieldErrorId(name)` derivation) whenever the field has\n * an error — with or without renderError — so custom error components\n * that render the element themselves (using `fieldErrorId`) get the\n * wiring for free.\n */\n renderError?: (error: string, id: string) => React.ReactNode;\n /**\n * Store `e.target.valueAsNumber` instead of the string value —\n * react-hook-form's `register({valueAsNumber})` counterpart for number\n * inputs (`<input type=\"number\">`). `NaN` passes through as-is when the\n * input cannot be parsed, matching RHF. An explicit `eventToValue`\n * takes precedence.\n */\n valueAsNumber?: boolean;\n /**\n * Store `e.target.valueAsDate` instead of the string value — RHF's\n * `register({valueAsDate})` counterpart for date/time inputs. `null`\n * passes through when the input cannot be parsed. An explicit\n * `eventToValue` takes precedence; combining with `valueAsNumber` is a\n * TypeError.\n */\n valueAsDate?: boolean;\n};\n\nfunction setRef<T>(ref: React.Ref<T> | undefined, value: T | null) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref) {\n (ref as React.MutableRefObject<T | null>).current = value;\n }\n}\n\n/**\n * Converts a path key (the JSON.stringify'd path segments, e.g. '[\"a\",\"0\"]')\n * into a valid HTML id ('a-0'): quotes, brackets, commas and whitespace\n * become hyphens; leading/trailing hyphens are trimmed. Falls back to\n * 'field' if nothing remains.\n */\nfunction errorIdFromKey(key: string): string {\n const id = key.replace(/[\"'[\\],\\s]+/g, '-').replace(/^-+|-+$/g, '');\n return id || 'field';\n}\n\n/**\n * The aria wiring every bound field shares: `aria-invalid` when the field\n * has an error, and `aria-describedby` pointing at the error-message\n * element id derived from the field key — the same id `fieldErrorId(name)`\n * derives (the key is what useField returns as `name`). User-provided ids\n * survive, joined ahead of the error id.\n */\nfunction ariaProps(\n error: string | undefined,\n fieldKey: string,\n props: Record<string, any>\n) {\n return {\n 'aria-invalid': error ? true : props['aria-invalid'],\n 'aria-describedby': error\n ? [props['aria-describedby'], errorIdFromKey(fieldKey)]\n .filter(Boolean)\n .join(' ')\n : props['aria-describedby']\n };\n}\n\n/**\n * The error-message element id a field's `aria-describedby` points at —\n * `fieldErrorId('a[0].b')` is `'a-0-b'`, the same id `Field`'s built-in\n * `renderError` span carries. This is the library-level wiring convention:\n * whenever a bound field (Field/Checkbox/Select) has an error it sets\n * `aria-invalid` and describes the element with this id, so a custom error\n * component only needs `<span id={fieldErrorId(name)} role=\"alert\">` to\n * complete the accessible-name chain for screen readers.\n * @param name the same field name passed to the bound component\n */\nexport function fieldErrorId(name: Name): string {\n return errorIdFromKey(createPath(name).key);\n}\n\n/**\n * The callable shape of {@link Field}: `form` + `name` flow their generics\n * into `validate`'s value argument (`PathValueOf<TValues, TPath>`). A named\n * interface rather than an inline `as <TValues, ...>() => ...` signature —\n * same types, and the inline form trips no-use-before-define on the type\n * parameters.\n */\ntype FieldComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: FieldProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>\n ): React.ReactElement | null;\n};\n\nexport const Field = React.forwardRef<HTMLInputElement, FieldProps>(\n (\n {\n validate,\n eventToValue,\n initialValue,\n name,\n asProps,\n renderError,\n as,\n valueToProps,\n form: formProp,\n shouldUnregister,\n rules,\n validateDebounce,\n validateOnMount,\n valueAsNumber,\n valueAsDate,\n asyncAlways,\n disabled,\n delayError,\n mode,\n uncontrolled,\n ...props\n },\n ref\n ) => {\n const innerRef = React.useRef<HTMLInputElement | null>(null);\n const [nativeInvalidCount, setNativeInvalidCount] = React.useState(0);\n // Only declared options go into the hook; DOM props stay in `props` and\n // are spread onto the element below — useField no longer echoes unknown\n // options back, so `as`/`valueToProps`/DOM props are destructured here\n // instead of being fished out of its result.\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled,\n focusRef\n } = useField({\n name: name!,\n form: formProp,\n initialValue,\n shouldUnregister,\n rules,\n validateDebounce,\n validateOnMount,\n delayError,\n disabled,\n asyncAlways,\n mode,\n // File inputs cannot be value-controlled at all — force the\n // uncontrolled path so no `value` prop ever reaches the element.\n uncontrolled: uncontrolled || props.type === 'file',\n validate: (...params: [any, any]) => {\n const el = innerRef.current;\n if (el && typeof el.checkValidity === 'function') {\n el.setCustomValidity('');\n if (el.checkValidity() === false) {\n setNativeInvalidCount(count => count + 1);\n return undefined;\n }\n }\n if (validate) return validate(...params);\n }\n });\n // One merged ref, three duties: the private innerRef (validate's\n // setCustomValidity above), the focus channel (useField's focusRef —\n // setFocus and a failed submit's shouldFocusError focus through it),\n // and the user's forwarded ref. focusRef is identity-stable, so the\n // deps behave exactly as the previous [ref] did.\n const mergedRef = React.useCallback(\n (node: HTMLInputElement | null) => {\n innerRef.current = node;\n focusRef(node);\n setRef(ref, node);\n },\n [ref, focusRef]\n );\n const Component = as || 'input';\n\n React.useEffect(() => {\n const el = innerRef.current;\n if (!el || typeof el.setCustomValidity !== 'function') return;\n if (typeof error === 'string') {\n el.setCustomValidity(error);\n el.reportValidity();\n } else {\n el.setCustomValidity('');\n }\n }, [error]);\n\n React.useEffect(() => {\n if (nativeInvalidCount > 0) innerRef.current?.reportValidity();\n }, [nativeInvalidCount]);\n\n const isFile = props.type === 'file';\n if (__DEV__ && valueAsNumber && valueAsDate) {\n // eslint-disable-next-line no-console -- dev-only diagnostics\n console.warn(\n 'react-f0rm: valueAsNumber and valueAsDate are mutually exclusive — ' +\n 'valueAsNumber wins. Use eventToValue for anything else.'\n );\n }\n const toValue =\n eventToValue ??\n (isFile\n ? (e: any) => e.target.files\n : valueAsNumber\n ? (e: any) => e.target.valueAsNumber\n : valueAsDate\n ? (e: any) => e.target.valueAsDate\n : (e: any) => e.target.value);\n\n // file inputs never receive a value/defaultValue prop (they cannot be\n // value-controlled); uncontrolled renders defaultValue, controlled\n // renders value.\n const valueProps = valueToProps\n ? valueToProps(value)\n : isFile\n ? {}\n : uncontrolled\n ? {defaultValue: value}\n : {value};\n\n // fieldKey is the field's path key (set by useField), e.g. '[\"a\",\"0\"]'.\n const errorId = errorIdFromKey(fieldKey);\n // Declarative rules → native constraint attributes for browser/AT\n // hints (:invalid styling, screen-reader announcements). Spread\n // before `props` so a user-passed required/minLength/pattern always\n // wins over the derived one. The store pipeline keeps owning\n // messages: rules run ahead of the wrapper below, so their errors\n // land in the form state (renderError/aria-invalid) even when the\n // native checkValidity gate now also sees the derived attrs and\n // skips the user's `validate` for that kick (RHF first-error\n // semantics).\n const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : undefined;\n\n return (\n <>\n <Component\n {...constraintAttrs}\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n {...asProps}\n {...valueProps}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: any) => onChange(toValue(e))}\n ref={mergedRef}\n />\n {error && renderError ? (\n <span id={errorId} role=\"alert\">\n {renderError(error, errorId)}\n </span>\n ) : null}\n </>\n );\n }\n) as FieldComponent;\n\ntype CheckboxProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath>;\n\n/**\n * Callable shape of {@link Checkbox}: the same form-typed `validate`\n * inference contract as {@link FieldComponent}.\n */\ntype CheckboxComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: CheckboxProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>\n ): React.ReactElement | null;\n};\n\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n name,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateOnMount,\n asyncAlways,\n disabled,\n delayError,\n mode,\n ...props\n },\n ref\n ) => {\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled\n } = useField({\n name: name!,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateOnMount,\n asyncAlways,\n delayError,\n disabled,\n mode\n });\n // Same error-id convention as Field: the checkbox describes the\n // fieldErrorId(name) element whenever it has an error.\n const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : undefined;\n return (\n <input\n {...constraintAttrs}\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n type=\"checkbox\"\n checked={!!value}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n onChange(e.target.checked)\n }\n ref={ref}\n />\n );\n }\n) as CheckboxComponent;\n\ntype SelectProps<\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n> = UseFieldOptions<TValues, TPath> & {\n multiple?: boolean;\n children?: React.ReactNode;\n};\n\n/**\n * Controlled <select>. Options are passed as children (<option> elements).\n * Single-select stores the selected option's value as a string, matching\n * Field's default event-to-value behavior; a multiple select stores the\n * values of all selected options as a string array.\n */\n/** Normalize a field value for a <select>: multiple wants a string array,\n * single-select wants a string. */\nfunction toSelectValue(\n multiple: boolean | undefined,\n value: any\n): string | string[] {\n if (multiple) return Array.isArray(value) ? value : [];\n return value ?? '';\n}\n\n/**\n * Callable shape of {@link Select}: the same form-typed `validate`\n * inference contract as {@link FieldComponent}.\n */\ntype SelectComponent = {\n <\n TValues extends Record<string, any> = any,\n TPath extends FieldPath<TValues> | PathSegments =\n FieldPath<TValues> | PathSegments\n >(\n props: SelectProps<TValues, TPath> & React.RefAttributes<HTMLSelectElement>\n ): React.ReactElement | null;\n};\n\nexport const Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n (\n {\n name,\n multiple,\n children,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateOnMount,\n asyncAlways,\n disabled,\n delayError,\n mode,\n ...props\n },\n ref\n ) => {\n const {\n value,\n onChange,\n onBlur,\n error,\n name: fieldKey,\n disabled: isDisabled\n } = useField({\n name: name!,\n form,\n initialValue,\n shouldUnregister,\n validate,\n rules,\n validateDebounce,\n validateOnMount,\n asyncAlways,\n delayError,\n disabled,\n mode\n });\n // Same error-id convention as Field: the select describes the\n // fieldErrorId(name) element whenever it has an error.\n const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : undefined;\n return (\n <select\n {...constraintAttrs}\n {...props}\n name={fieldKey}\n onBlur={onBlur}\n multiple={multiple}\n value={toSelectValue(multiple, value)}\n {...ariaProps(error, fieldKey, props)}\n disabled={isDisabled}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>\n onChange(\n multiple\n ? Array.from(e.target.selectedOptions, option => option.value)\n : e.target.value\n )\n }\n ref={ref}\n >\n {children}\n </select>\n );\n }\n) as SelectComponent;\n"],"names":["pathCache","Map","normalizePath","path","Array","isArray","cached","get","value","result","identifier","flushIdentifier","isIndex","dotted","map","String","join","bracket","reduce","acc","seg","TypeError","push","i","length","char","quote","close","indexOf","slice","content","Number","parsePath","size","oldest","keys","next","done","delete","set","segment","test","values","current","p","unset","prop","props","arr","copy","index","setOwned","root","owned","container","parent","parentProp","has","add","isPromise","then","isEqual","a","b","Object","is","Date","getTime","proto","getPrototypeOf","prototype","keysA","keysB","key","waitUntil","emitter","event","isResolve","isReject","Promise","resolve","reject","off","on","create","name","JSON","stringify","valuesCaches","WeakMap","bumpValuesVersion","form","cache","version","dirtyBaselines","getDirtyBaseline","segments","baselines","initialValues","setDirtyBaseline","pruneDirtyBaselines","stem","baselineKey","startsWith","clearDirtyBaselines","clear","dirtyFieldsCaches","bumpDirtyVersion","isSegmentsPath","some","part","isFieldError","type","message","FORM_ERROR","VALIDATION_OUTCOME","getError","getErrorByPath","createPath","errors","NO_ERRORS","getFieldErrors","getFieldErrorsByPath","getErrors","entries","list","parse","getFirstError","setError","error","options","setErrorByPath","forEach","item","normalizeErrors","emit","shouldFocus","clearErrors","paths","one","setServerErrors","keepExisting","hasErrors","isFieldDirtyByPath","live","isDirty","dirty","forEachDirtyField","fn","computeDirtyFields","dirtyFields","getDirtyFields","aKeys","every","sameDirtyKeys","setTouched","setTouchedByPath","touched","hasTouched","hasTouchedByPath","getTouchedFields","from","isTouched","getValues","computeValues","parsedValues","deleted","Set","merged","getValue","getValueByPath","ancestorKey","setValue","setValueByPath","pruneDescendantKeys","reviveBranch","shouldDirty","shouldTouch","shouldValidate","validators","seedValueByPath","emitChangeByPath","getFieldState","validating","isValidating","removeField","removeFieldByPath","keepValue","keepDirty","hasLiveBranch","keepTouched","keepError","k","tombstone","setInitialValues","collectValueLeaves","node","out","reset","keptValues","keepValues","keepDirtyValues","keepDefaultValues","keepErrors","keepIsSubmitting","isSubmitting","keepSubmitCount","submitCount","keepIsSubmitted","isSubmitted","keepIsSubmitSuccessful","isSubmitSuccessful","resetField","initial","unsetValidatingByPath","setValidatingByPath","registerValidatorByPath","registration","timer","controller","marked","lock","errorSource","mark","unmark","runSync","sync","validate","land","asyncAlways","gate","collectSyncErrors","own","supersede","clearTimeout","abort","runValidator","AbortController","round","signal","e","catch","finally","run","debounce","setTimeout","async","trigger","settle","fieldsSettled","validator","runFormValidate","touchKeys","firstKey","find","setFormErrors","footprint","recordFootprint","stored","applyValidateResult","validateDeps","formErrorFootprints","getFormErrorFootprint","written","clearFormValidateErrors","outcome","setParsedValues","FORM_VALIDATING_KEY","SETTLED","formValidateStates","validateDebounce","state","waiters","getFormValidateState","runFormValidateRound","settleFormValidate","waiter","revalidateFormOnChange","mode","reValidateMode","hasFormValidateErrors","fieldValidateDeps","registerFieldValidateDeps","depKeys","deps","depKey","dependents","unregisterFieldValidateDeps","revalidateDependentsOnChange","dependent","validationError","Error","ensureValidate","fieldModes","changeValue","changeValueByPath","userChangeByPath","registerFieldMode","modes","displaced","token","unregisterFieldMode","entry","runUserChangeGate","userBlur","setIsSubmitting","incrementSubmitCount","setSubmitSuccessful","setDisabled","disabled","setStatus","status","nameToPath","handleSubmit","onSubmit","onValidSubmit","onInvalidSubmit","onAction","shouldFocusError","preventDefault","formEl","currentTarget","checkValidity","reportValidity","querySelector","invalid","focus","elements","el","validationMessage","getNativeErrors","submitted","setFocus","createEmitter","setMaxListeners","source","validateOnMount","dep","isLoading","resolved","defaultMessage","bound","rulesToValidator","rules","meta","required","messages","min","n","isNaN","max","isSized","minLength","maxLength","pattern","fns","rulesToConstraintAttrs","attrs","isDescendant","onPathEvent","scope","cb","changed","onKeyEvent","subscribe","callback","names","isNameList","unsubscribes","unsubscribe","useForm","useState","created","createForm","seededRef","useRef","useEffect","seeded","controlledRef","useWatchCore","subscribeFactory","getter","cacheRef","hasValue","getterRef","isEqualRef","getSnapshot","useCallback","notify","compare","useSyncExternalStore","useWatch","formOrEmitter","invalidate","useValue","useValueByPath","exact","defaultValue","useTouched","useTouchedByPath","bind","useError","useErrorByPath","useFieldErrors","useFieldErrorsByPath","useIsDirty","useIsFieldDirty","useIsFieldDirtyByPath","useDirtyFields","useTouchedFields","FORM_STATE_EVENTS","isSameFormState","sameTouched","touchedFields","isValid","useFormState","getFormState","offs","useHasErrors","useIsValid","useIsSubmitting","useIsLoading","useStatus","useCanSubmit","offErrors","offSubmitting","useSubmitCount","useIsValidating","useIsSubmitSuccessful","useFormError","useFormErrors","usePath","useMemo","useStage","ref","useStageFn","params","useUnmountRestore","teardown","restore","removedRef","useValidate","formProp","contextForm","useContext","FormContext","validateRef","debounceRef","syncRef","asyncAlwaysRef","dispose","disposed","kick","removeFieldForUnmount","snapshot","present","restoreRemovedField","uncontrolledSyncRegistry","useFieldCore","f1","initialValue","shouldUnregister","delayError","uncontrolled","modeOption","Context","hasRuleConstraints","ruleValidator","ruleErrors","merge","other","combineRulesAndValidate","delay","shown","setShown","useDelayedErrors","errorObject","snapshotRef","useFieldValue","formDisabled","onChange","v","onBlur","depsKey","elementRef","focusRef","shouldSelect","select","cells","read","asString","removalSnapshotRef","useField","idCounters","generateId","arrayIdsRegistry","registerArrayIds","ids","registry","bumpReducer","count","useFieldArrayCore","keyName","idsRef","getArray","setArray","computeFields","pop","id","fields","syncFields","useReducer","append","prepend","unshift","insert","splice","newArr","remove","filter","_","swap","to","move","replace","update","useFieldArray","useFieldArrayItemCore","arrayPath","computeIndex","getArrayIds","computeValue","lastRef","computeRef","bump","idx","val","nextIndex","itemPath","useFieldArrayItem","createContext","FormProvider","Provider","useFormContext","createFormContext","context","children","createElement","CheckboxGroupContext","CheckboxGroupProvider","useCheckboxGroupContext","group","useTransform","toDisplay","fromDisplay","raw","display","appendFormDataValue","fd","FileList","File","Blob","toISOString","Form","action","f2","React","submit","FormData","formDataFromValues","noValidate","FormField","errorIdFromKey","ariaProps","fieldKey","Boolean","fieldErrorId","Field","forwardRef","eventToValue","asProps","renderError","as","valueToProps","valueAsNumber","valueAsDate","innerRef","nativeInvalidCount","setNativeInvalidCount","isDisabled","setCustomValidity","mergedRef","setRef","Component","isFile","toValue","target","files","valueProps","errorId","constraintAttrs","Fragment","role","Checkbox","checked","toSelectValue","multiple","Select","selectedOptions","option"],"mappings":"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"}
|