react-f0rm 1.3.0 → 1.5.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.
Files changed (99) hide show
  1. package/README.md +98 -1140
  2. package/devtools.d.ts +1 -0
  3. package/devtools.js +1 -0
  4. package/dist/array-Bu7W8BSz.d.ts +54 -0
  5. package/dist/devtools/index.cjs.js +1 -1
  6. package/dist/devtools/index.cjs.js.map +1 -1
  7. package/dist/devtools/index.d.cts +24 -0
  8. package/dist/devtools/index.d.mts +24 -0
  9. package/dist/devtools/index.d.ts +8 -17
  10. package/dist/devtools/index.mjs +1 -1
  11. package/dist/devtools/index.mjs.map +1 -1
  12. package/dist/errors-DA4ReEd9.mjs +2 -0
  13. package/dist/errors-DA4ReEd9.mjs.map +1 -0
  14. package/dist/errors-TzyWwBfw.cjs.js +2 -0
  15. package/dist/errors-TzyWwBfw.cjs.js.map +1 -0
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.cts +1253 -0
  19. package/dist/index.d.mts +1253 -0
  20. package/dist/index.d.ts +570 -895
  21. package/dist/index.mjs +1 -1
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.umd.js +1256 -535
  24. package/dist/index.umd.js.map +1 -1
  25. package/dist/index.umd.min.js +2 -2
  26. package/dist/index.umd.min.js.map +1 -1
  27. package/dist/persist.cjs.js +1 -1
  28. package/dist/persist.cjs.js.map +1 -1
  29. package/dist/persist.d.cts +28 -0
  30. package/dist/persist.d.mts +28 -0
  31. package/dist/persist.d.ts +9 -30
  32. package/dist/persist.mjs +1 -1
  33. package/dist/persist.mjs.map +1 -1
  34. package/dist/resolvers/standard-schema.cjs.js +1 -1
  35. package/dist/resolvers/standard-schema.cjs.js.map +1 -1
  36. package/dist/resolvers/standard-schema.d.cts +2 -0
  37. package/dist/resolvers/standard-schema.d.mts +2 -0
  38. package/dist/resolvers/standard-schema.d.ts +1 -67
  39. package/dist/resolvers/standard-schema.mjs +1 -1
  40. package/dist/resolvers/standard-schema.mjs.map +1 -1
  41. package/dist/resolvers/yup.cjs.js +1 -1
  42. package/dist/resolvers/yup.cjs.js.map +1 -1
  43. package/dist/resolvers/yup.d.cts +6 -0
  44. package/dist/resolvers/yup.d.mts +6 -0
  45. package/dist/resolvers/yup.d.ts +0 -1
  46. package/dist/resolvers/yup.mjs +1 -1
  47. package/dist/resolvers/yup.mjs.map +1 -1
  48. package/dist/resolvers/zod.cjs.js +1 -1
  49. package/dist/resolvers/zod.cjs.js.map +1 -1
  50. package/dist/resolvers/zod.d.cts +34 -0
  51. package/dist/resolvers/zod.d.mts +34 -0
  52. package/dist/resolvers/zod.d.ts +30 -3
  53. package/dist/resolvers/zod.mjs +1 -1
  54. package/dist/resolvers/zod.mjs.map +1 -1
  55. package/dist/server/index.cjs.js +1 -1
  56. package/dist/server/index.cjs.js.map +1 -1
  57. package/dist/server/index.d.cts +38 -0
  58. package/dist/server/index.d.mts +38 -0
  59. package/dist/server/index.d.ts +26 -65
  60. package/dist/server/index.mjs +1 -1
  61. package/dist/server/index.mjs.map +1 -1
  62. package/dist/standard-schema-BAaTmAHh.d.ts +682 -0
  63. package/dist/standardSchema-5WezjHlp.mjs +2 -0
  64. package/dist/standardSchema-5WezjHlp.mjs.map +1 -0
  65. package/dist/standardSchema-DINHlsYR.cjs.js +2 -0
  66. package/dist/standardSchema-DINHlsYR.cjs.js.map +1 -0
  67. package/dist/validate-2pX-N1O6.cjs.js +2 -0
  68. package/dist/validate-2pX-N1O6.cjs.js.map +1 -0
  69. package/dist/validate-C0HOsP9v.mjs +2 -0
  70. package/dist/validate-C0HOsP9v.mjs.map +1 -0
  71. package/dist/values-BbPnLByD.cjs.js +2 -0
  72. package/dist/values-BbPnLByD.cjs.js.map +1 -0
  73. package/dist/values-CHsmcZk4.mjs +2 -0
  74. package/dist/values-CHsmcZk4.mjs.map +1 -0
  75. package/package.json +75 -28
  76. package/persist.d.ts +1 -0
  77. package/persist.js +1 -0
  78. package/resolvers/standard-schema.d.ts +1 -0
  79. package/resolvers/standard-schema.js +1 -0
  80. package/resolvers/yup.d.ts +1 -0
  81. package/resolvers/yup.js +1 -0
  82. package/resolvers/zod.d.ts +1 -0
  83. package/resolvers/zod.js +1 -0
  84. package/server.d.ts +1 -0
  85. package/server.js +1 -0
  86. package/dist/errors-BKrUdpfI.cjs.js +0 -2
  87. package/dist/errors-BKrUdpfI.cjs.js.map +0 -1
  88. package/dist/errors-CrQBddrJ.mjs +0 -2
  89. package/dist/errors-CrQBddrJ.mjs.map +0 -1
  90. package/dist/form-CeKSBs31.d.ts +0 -486
  91. package/dist/validate-CNtuUhmk.mjs +0 -2
  92. package/dist/validate-CNtuUhmk.mjs.map +0 -1
  93. package/dist/validate-Cl4ksNFu.cjs.js +0 -2
  94. package/dist/validate-Cl4ksNFu.cjs.js.map +0 -1
  95. package/dist/validate-nksgv1pR.d.ts +0 -272
  96. package/dist/values-Cu6awQOJ.cjs.js +0 -2
  97. package/dist/values-Cu6awQOJ.cjs.js.map +0 -1
  98. package/dist/values-DRY-a32G.mjs +0 -2
  99. package/dist/values-DRY-a32G.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,127 +1,74 @@
1
- import { a as FieldError, F as Form$1, P as Path, b as FieldPath, c as PathSegments, d as PathValueOf, N as Name, V as ValidationMode, e as FieldErrorEntry, O as Options, f as FormEvents } from './form-CeKSBs31.js';
2
- export { g as FORM_ERROR, h as FormValidateFn, i as FormValidateMeta, j as PathValue, R as ReValidateMode, S as SetErrorOptions, k as SetFocusOptions, l as SetServerErrorsOptions, m as VALIDATION_OUTCOME, n as ValidateResult, o as ValidationOutcome, p as clearErrors, q as createForm, r as getError, s as getErrorByPath, t as getErrors, u as getFieldErrors, v as getFieldErrorsByPath, w as getFirstError, x as hasErrors, y as setError, z as setErrorByPath, A as setFocus, B as setServerErrors } from './form-CeKSBs31.js';
1
+ import { a as FieldRules, f as FieldError, F as Form$1, P as Path, A as AnyPath, g as PathValueOf, N as Name, h as ValidationMode, R as RegisterOptions, i as RegisterProps, b as FieldErrorEntry, V as Validator, S as StandardSchemaV1, j as FieldPath, k as FieldErrors, l as FieldErrorsTree, O as Options, m as FormEvents } from './standard-schema-BAaTmAHh.js';
2
+ export { e as ArrayItemOf, D as DottedPath, n as FORM_ERROR, o as FormMessages, p as FormValidateFn, q as FormValidateMeta, r as FormValidateMode, s as FormValidationError, I as InferSchemaValues, t as OpaqueTypes, u as PathSegments, v as PathValue, w as ReValidateMode, x as SetErrorOptions, y as SetFocusOptions, z as SetServerErrorsOptions, B as SyncValidator, T as TriggerOptions, c as VALIDATION_OUTCOME, C as ValidateResult, d as ValidationOutcome, E as ValidatorOutput, G as ValidatorRegistration, H as clearErrors, J as clearServerErrors, K as createForm, L as dottedKeyToFieldPath, M as ensureValidate, Q as fieldPathToDottedKey, U as getError, W as getErrorByPath, X as getErrors, Y as getErrorsRecord, Z as getErrorsTree, _ as getFieldErrors, $ as getFieldErrorsByPath, a0 as getFirstError, a1 as hasErrors, a2 as registerFieldValidateDeps, a3 as registerValidatorByPath, a4 as revalidateDependentsOnChange, a5 as revalidateFormOnChange, a6 as runFormValidate, a7 as setError, a8 as setErrorByPath, a9 as setFocus, aa as setServerErrors, ab as setValidatingByPath, ac as shouldKick, ad as trigger, ae as unregisterFieldValidateDeps, af as unsetValidatingByPath, ag as validate } from './standard-schema-BAaTmAHh.js';
3
3
  import { EventEmitter } from '@for-fun/event-emitter';
4
4
  export { EventEmitter } from '@for-fun/event-emitter';
5
5
  import * as React from 'react';
6
- import { ReactNode } from 'react';
7
- import { S as SyncValidator, V as Validator } from './validate-nksgv1pR.js';
8
- export { F as FormValidationError, T as TriggerOptions, a as ValidatorRegistration, e as ensureValidate, r as registerFieldValidateDeps, b as registerValidatorByPath, c as revalidateDependentsOnChange, d as revalidateFormOnChange, f as runFormValidate, s as setValidatingByPath, t as trigger, u as unregisterFieldValidateDeps, g as unsetValidatingByPath, v as validate } from './validate-nksgv1pR.js';
6
+ import { Context, Provider, ReactNode } from 'react';
7
+ export { a as appendValue, c as appendValueByPath, i as insertValue, d as insertValueByPath, m as moveValue, e as moveValueByPath, p as prependValue, f as prependValueByPath, r as removeValue, g as removeValueByPath, b as replaceValues, h as replaceValuesByPath, s as swapValues, j as swapValuesByPath, u as updateValue, k as updateValueByPath } from './array-Bu7W8BSz.js';
9
8
 
10
- /**
11
- * Get form values: the values Map layered over parsedValues (when a schema
12
- * validation produced them) layered over initialValues.
13
- *
14
- * Merged with copy-on-write ownership tracking ({@link setOwned}): every
15
- * distinct container on a written path is allocated once and shared by all
16
- * paths through it, instead of re-copying the whole branch for every key.
17
- * One owned set spans the whole merge, so containers borrowed from the
18
- * parsedValues tree are copied before mutation exactly like initialValues
19
- * ones. The result is a freshly merged tree per mutation, with untouched
20
- * branches sharing references with the baseline exactly like chained
21
- * `set` did.
22
- *
23
- * Memoized per form like {@link getDirtyFields}: every value write bumps a
24
- * `version` counter ({@link bumpValuesVersion}) while reads reset it, so
25
- * consecutive reads hand back the same reference (submit, changeValue and
26
- * form-level validate all read the whole tree, often several times per
27
- * interaction). Treat the result as read-only the next read after a
28
- * write returns a fresh tree, but between writes the cached one is shared
29
- * with every other reader.
30
- *
31
- * parsedValues is the schema's complete output tree: once validation
32
- * succeeds it replaces the initialValues baseline (fields the schema
33
- * dropped disappear), while live edits in the values Map still win over
34
- * both. It never affects dirty state — {@link isDirty} and
35
- * {@link getDirtyFields} compare live edits against initialValues only,
36
- * because parsing is not a user edit.
37
- *
38
- * @param form
39
- */
9
+ /** Option spellings shared across the field, field-array and validator
10
+ * hooks private to the hooks slice, never part of the public facade. */
11
+ type FieldOptionBase = {
12
+ /** Declarative rules compiled into a sync validator. */
13
+ rules?: FieldRules;
14
+ /** Whether unmounting removes the branch; defaults to the form-level
15
+ * `shouldUnregister` (tombstone). `false` keeps the values. */
16
+ shouldUnregister?: boolean;
17
+ /** Keep the debounced validator running when the sync gate failed
18
+ * (TanStack `asyncAlways`): gate errors land immediately, the
19
+ * validator's result lands alongside them per-source. */
20
+ asyncAlways?: boolean;
21
+ /** Validate once on mount (overrides the form-level flag in either
22
+ * direction). Deferred while async `initialValues` is pending. */
23
+ validateOnMount?: boolean;
24
+ };
25
+
26
+ /** Get form values: the values Map layered over parsedValues (when a
27
+ * schema validation produced them) over initialValues. Merged with
28
+ * copy-on-write ownership tracking ({@link setOwned}), so untouched
29
+ * branches share references with the baseline. Memoized per form via a
30
+ * version-bump/read counter ({@link bumpValuesVersion}): consecutive reads
31
+ * hand back the same reference; treat it as read-only. parsedValues never
32
+ * affects dirty state dirty compares live edits against initialValues. */
40
33
  declare function getValues<T extends Record<string, any> = any>(form: Form$1<T>): T;
41
- /**
42
- * Get field value
43
- * @param form
44
- * @param name
45
- */
46
- declare function getValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): PathValueOf<T, P>;
47
- /**
48
- * Get field value by path
49
- * @param form
50
- * @param path
51
- */
34
+ /** Get a field's value. */
35
+ declare function getValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): PathValueOf<T, P>;
36
+ /** Get a field's value by path. */
52
37
  declare function getValueByPath({ initialValues, parsedValues, values, deleted }: Form$1, path: Path): any;
53
38
  /** Options accepted by {@link setValue} / {@link setValueByPath} / {@link
54
39
  * changeValue} / {@link changeValueByPath}. `shouldValidate`/`shouldTouch`
55
- * default to `false`; omitting the options object entirely keeps the plain
56
- * set-value behavior (no validation, no touched marking, dirty stays
57
- * derived). */
40
+ * default to `false`. */
58
41
  type SetFieldOptions = {
59
- /** Run the field's registered validator (if any) after the value lands,
60
- * same as triggering that single field. Defaults to `false`. */
42
+ /** Run the field's registered validator (if any) after the value lands.
43
+ * Defaults to `false`. */
61
44
  shouldValidate?: boolean;
62
45
  /** Mark the field as touched. Defaults to `false`. */
63
46
  shouldTouch?: boolean;
64
- /** Land the value as a commit instead of an edit: the value becomes the
65
- * field's dirty-comparison baseline, so `getDirtyFields`/`isDirty`/
66
- * `getFieldState().isDirty` read the field as clean, and a later write
67
- * dirties it only by differing from the new baseline. `true` (or
68
- * omitting the flag) keeps the default derived behavior — dirty while
69
- * the live value differs from initialValues. */
47
+ /** Land the value as a commit instead of an edit: it becomes the field's
48
+ * dirty-comparison baseline. `true` (or omitting) keeps the default
49
+ * derived behavior dirty while the live value differs from
50
+ * initialValues. */
70
51
  shouldDirty?: boolean;
71
52
  };
72
- /**
73
- * Set field value. The value may also be an updater function receiving
74
- * the field's current value and returning the next one (TanStack Form's
75
- * `setFieldValue` contract) handy for increments and array transforms:
76
- * `setValue(form, 'count', c => c + 1)`. The tradeoff: a function can
77
- * never itself be stored as a field value through this function.
78
- * @param form
79
- * @param name
80
- * @param value
81
- * @param options
82
- */
83
- declare function setValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, value: PathValueOf<T, P> | ((prev: PathValueOf<T, P>) => PathValueOf<T, P>), options?: SetFieldOptions): void;
84
- /**
85
- * Set field value. The value may also be an updater function receiving
86
- * the field's current value and returning the next one (TanStack Form's
87
- * `setFieldValue` contract) — note that a function can therefore never
88
- * itself be stored as a field value through this function.
89
- * @param form
90
- * @param path
91
- * @param value
92
- * @param options
93
- */
53
+ /** Set a field's value. `value` may be an updater function receiving the
54
+ * current value and returning the next (TanStack Form's `setFieldValue`
55
+ * contract) so a function can never itself be stored as a value. */
56
+ declare function setValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P, value: PathValueOf<T, P> | ((prev: PathValueOf<T, P>) => PathValueOf<T, P>), options?: SetFieldOptions): void;
57
+ /** Set a field's value by path. `value` may be an updater function (see
58
+ * {@link setValue}). */
94
59
  declare function setValueByPath(form: Form$1, path: Path, value: any | ((prev: any) => any), options?: SetFieldOptions): void;
95
- /**
96
- * The write of {@link setValueByPath} minus the `'change'` emit: the
97
- * render-time {@link useField} `initialValue` seed. The field's first
98
- * paint (SSR included effects never run on the server) must already
99
- * carry the value, so the write happens during render where emitting is
100
- * illegal; the seeding field announces it from its post-commit effect
101
- * through {@link emitChangeByPath} instead.
102
- *
103
- * Everything else matches a plain write: descendant keys of the seeded
104
- * path are pruned, the branch's tombstones and committed baselines are
105
- * revived/dropped, and both memo caches are invalidated. Like the effect
106
- * seed it replaces, the caller guards it to paths with no value yet.
107
- */
60
+ /** The write of {@link setValueByPath} minus the `'change'` emit: the
61
+ * render-time `useField` `initialValue` seed. The field's first paint
62
+ * (SSR included) must already carry the value, so the write happens during
63
+ * render where emitting is illegal; the field announces it post-commit via
64
+ * {@link emitChangeByPath}. */
108
65
  declare function seedValueByPath(form: Form$1, path: Path, value: any): void;
109
66
  /** Announce a {@link seedValueByPath} that happened during render: the
110
67
  * payload-carrying `'change'` emit {@link setValueByPath} would have
111
- * fired, split out so it can run post-commit where emitting is safe.
112
- * Subscribers that rendered after the seed re-read an unchanged snapshot
113
- * and bail; subscribers from earlier commits resync. */
68
+ * fired, split out so it runs post-commit where emitting is safe. */
114
69
  declare function emitChangeByPath({ emitter }: Form$1, path: Path): void;
115
- /** Per-form registry of mounted fields' validation-mode overrides: path
116
- * key -> the field's `mode` option (undefined = follow {@link Form.mode})
117
- * plus an owner token so competing mounts at one path clean up safely.
118
- * Presence of an entry is the "a field is mounted at this path" signal
119
- * that routes {@link changeValueByPath} into the gated user-change
120
- * pipeline ({@link userChangeByPath}). Held in a WeakMap so the Form
121
- * shape carries only plain state fields. */
122
- /** Snapshot of one field's aggregated state, as {@link getFieldState}
123
- * returns it. `errors` is the stored array shared with the form — treat it
124
- * as read-only, like every {@link getFieldErrors} result. */
70
+ /** One field's aggregated state, as {@link getFieldState} returns it.
71
+ * `errors` is the stored array shared with the form treat it read-only. */
125
72
  type FieldState<T = any> = {
126
73
  value: T;
127
74
  error: FieldError | undefined;
@@ -130,42 +77,18 @@ type FieldState<T = any> = {
130
77
  isTouched: boolean;
131
78
  isValidating: boolean;
132
79
  };
133
- /**
134
- * Get one field's aggregated state: the layered value ({@link getValue}),
135
- * the first error ({@link getError}) and every error ({@link
136
- * getFieldErrors}), dirtiness, the touched flag, and whether a validator
137
- * is in flight. `isDirty` applies the same per-field rule as {@link
138
- * getDirtyFields}: a live value exists and differs from initialValues at
139
- * that path (parsedValues never counts — parsing is not an edit).
140
- *
141
- * @param form
142
- * @param name
143
- */
144
- declare function getFieldState<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): FieldState<PathValueOf<T, P>>;
145
- /**
146
- * Remove a field: by default its live value drops out of reads and
147
- * `getValues()` (the path is tombstoned, so it never falls back to
148
- * initialValues), its dirty baseline, touched flag and errors are cleared.
149
- * The keep-flags preserve slices of that state instead.
150
- *
151
- * @param form
152
- * @param name
153
- */
154
- /**
155
- * Options accepted by {@link removeField}. All flags default to `false` —
80
+ /** Get one field's aggregated state: layered value, first/every error,
81
+ * dirtiness, touched flag, and validating flag. `isDirty` applies the same
82
+ * per-field rule as {@link getDirtyFields}. */
83
+ declare function getFieldState<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): FieldState<PathValueOf<T, P>>;
84
+ /** Options accepted by {@link removeField}. All flags default to `false`
156
85
  * the historical remove semantics (value dropped, path tombstoned, dirty
157
- * baseline/touched/errors cleared). Names mirror react-hook-form's
158
- * `unregister` options to ease migration; RHF's `shouldValidate` and
159
- * `keepDefaultValue` have no counterparts (removal never validates, and
160
- * the tombstone is exactly the "do not revive from initialValues" choice).
161
- */
86
+ * baseline/touched/errors cleared). */
162
87
  type RemoveFieldOptions = {
163
88
  /** Keep the field's live value and dirty baseline instead of
164
- * tombstoning: reads and `getValues()` keep returning the value, submit
165
- * includes it, and dirtiness against initialValues is preserved. */
89
+ * tombstoning: reads, `getValues()`, and submit keep the value. */
166
90
  keepValue?: boolean;
167
- /** Keep the field's dirty baseline. Implies `keepValue` — a removed
168
- * value has nothing to be dirty about. */
91
+ /** Keep the field's dirty baseline. Implies `keepValue`. */
169
92
  keepDirty?: boolean;
170
93
  /** Keep the field's touched flag instead of clearing it. */
171
94
  keepTouched?: boolean;
@@ -173,384 +96,213 @@ type RemoveFieldOptions = {
173
96
  keepError?: boolean;
174
97
  };
175
98
  declare function removeField(form: Form$1, name: Name, options?: RemoveFieldOptions): void;
176
- /**
177
- * Remove field
178
- * @param form
179
- * @param path
180
- * @param options keep-flags to preserve slices of state through the removal
181
- */
99
+ /** Remove a field by path; the keep-flags preserve slices of state. */
182
100
  declare function removeFieldByPath(form: Form$1, path: Path, options?: RemoveFieldOptions): void;
183
- /**
184
- * Set form initialValues
185
- *
186
- * Content-based early return: a new reference with equal content (the
187
- * re-rendered inline literal) is a no-op, so committed edits survive, while
188
- * genuinely changed content swaps the baseline and re-seeds — live values
189
- * and tombstones are cleared, touched flags and errors survive.
190
- * @param form
191
- * @param initialValues
192
- */
101
+ /** Set form initialValues. Content-based early return: a new reference with
102
+ * equal content is a no-op (committed edits survive); genuinely changed
103
+ * content swaps the baseline and re-seeds — live values and tombstones are
104
+ * cleared, touched flags and errors survive. */
193
105
  declare function setInitialValues(form: Form$1, initialValues: any): void;
194
- /** Options accepted by {@link reset}. Every flag defaults to `false`
195
- * omitting the object (or any flag) keeps the plain full-reset behavior.
196
- * Names mirror react-hook-form's reset options to ease migration. */
106
+ /** Options accepted by {@link reset}. Every flag defaults to `false`. */
197
107
  type ResetOptions = {
198
108
  /** Keep the current values of fields that are dirty — differ from the
199
- * pre-reset initialValues (the same rule {@link getDirtyFields} applies).
200
- * Clean fields fall back to the new initialValues as usual. */
109
+ * pre-reset initialValues (the same rule {@link getDirtyFields} applies). */
201
110
  keepDirtyValues?: boolean;
202
111
  /** Keep every field's current live value instead of returning to the
203
- * baseline (react-hook-form's `keepValues` a strict superset of
204
- * `keepDirtyValues`, which only preserves dirty fields' values).
205
- * Dirtiness is recomputed against the post-reset baseline, so kept
206
- * values that differ from a newly provided baseline count as dirty. */
112
+ * baseline (a superset of `keepDirtyValues`). Dirtiness is recomputed
113
+ * against the post-reset baseline. */
207
114
  keepValues?: boolean;
208
- /** Ignore a newly provided `initialValues` argument and keep the current
209
- * baseline — fields still return to it (react-hook-form's
210
- * `keepDefaultValues`). */
115
+ /** Ignore a newly provided `initialValues` and keep the current baseline. */
211
116
  keepDefaultValues?: boolean;
212
117
  /** Keep the touched set instead of clearing it. */
213
118
  keepTouched?: boolean;
214
119
  /** Keep field errors instead of clearing them. */
215
120
  keepErrors?: boolean;
216
- /** Keep the submitted flag (`isSubmitted`) instead of clearing it
217
- * react-hook-form's `keepIsSubmitted`. */
121
+ /** Keep the submitted flag (`isSubmitted`) instead of clearing it. */
218
122
  keepIsSubmitted?: boolean;
219
- /** Keep the last submit's success flag (`isSubmitSuccessful`) instead of
220
- * clearing it. */
123
+ /** Keep the last submit's success flag (`isSubmitSuccessful`). */
221
124
  keepIsSubmitSuccessful?: boolean;
222
125
  /** Keep `submitCount` instead of resetting it to 0. */
223
126
  keepSubmitCount?: boolean;
224
127
  /** Keep `isSubmitting` instead of resetting it to false. */
225
128
  keepIsSubmitting?: boolean;
226
129
  };
227
- /**
228
- * Reset form
229
- * @param form
230
- * @param initialValues new baseline — omitted (or undefined), the form
231
- * keeps its current initialValues and fields simply return to them
232
- * (react-hook-form's reset-without-values semantics)
233
- * @param options keep-flags to preserve slices of state through the reset
234
- */
130
+ /** Reset the form. Omitted (or undefined) `initialValues` keeps the current
131
+ * baseline — fields simply return to it (react-hook-form's
132
+ * reset-without-values semantics). */
235
133
  declare function reset(form: Form$1, initialValues?: any, options?: ResetOptions): void;
236
- /** Options accepted by {@link resetField}. The flags default to `false`;
237
- * `value` has no default — omitted, the field falls back to initialValues;
238
- * provided, the explicit value becomes the live value with no fallback at
239
- * all. Mirrors react-hook-form's resetField options (`value` plays their
240
- * `defaultValue`'s role) to ease migration. */
134
+ /** Options accepted by {@link resetField}. Flags default to `false`;
135
+ * `value` has no default — omitted, the field falls back to initialValues. */
241
136
  type ResetFieldOptions = {
242
137
  /** Keep the field's touched flag instead of clearing it. */
243
138
  keepTouched?: boolean;
244
139
  /** Keep the field's errors instead of clearing them. */
245
140
  keepErrors?: boolean;
246
- /** Explicit post-reset value for the field — never falls back to
247
- * initialValues. */
141
+ /** Explicit post-reset value — never falls back to initialValues. */
248
142
  value?: any;
249
143
  };
250
- /**
251
- * Reset a single field: drop its live value (reads fall back to the
252
- * baseline initialValues, or the schema's parsed output when one
253
- * exists, in which case the path is removed from parsedValues and the
254
- * initial value pinned back so the field reads initialValues again),
255
- * clear its touched flag and errors, and revive the path's removal
256
- * tombstones — the inverse of {@link removeFieldByPath}. Other fields
257
- * and the submission flags are untouched; see {@link reset} for the
258
- * form-wide counterpart.
259
- *
260
- * @param form
261
- * @param name
262
- * @param options
263
- */
264
- declare function resetField<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, options?: ResetFieldOptions): void;
144
+ /** Reset a single field: drop its live value (reads fall back to the
145
+ * baseline), clear touched/errors, and revive the path's tombstones the
146
+ * inverse of {@link removeFieldByPath}. Other fields are untouched. */
147
+ declare function resetField<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P, options?: ResetFieldOptions): void;
265
148
 
266
- /**
267
- * Set field touched state
268
- * @param form
269
- * @param name
270
- */
149
+ /** Set a field's touched state. */
271
150
  declare function setTouched(form: Form$1, name: Name): void;
272
- /**
273
- * Set field touched state
274
- * @param form
275
- * @param path
276
- */
151
+ /** Set a field's touched state by path. */
277
152
  declare function setTouchedByPath({ emitter, touched }: Form$1, path: Path): void;
278
- /**
279
- * Check if field has been touched
280
- * @param form
281
- * @param name
282
- */
283
- declare function hasTouched<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): boolean;
284
- /**
285
- * Check if field has been touched
286
- * @param form
287
- * @param path
288
- */
153
+ /** Check if a field has been touched. */
154
+ declare function hasTouched<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): boolean;
155
+ /** Check if a field has been touched by path. */
289
156
  declare function hasTouchedByPath({ touched }: Form$1, path: Path): boolean;
290
- /**
291
- * Is dirty -- any value differs from initialValues
292
- * @param form
293
- */
294
- /**
295
- * Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'), unlike
296
- * the JSON array keys stored in the touched Set.
297
- * @param form
298
- * @return array of touched fields' dotted paths
299
- */
157
+ /** Get touched fields as user-facing dotted paths ('a.b', 'a.0.c'). */
300
158
  declare function getTouchedFields({ touched }: Form$1): string[];
301
- /**
302
- * Is touched -- any field has been touched
303
- * @param form
304
- */
159
+ /** Is touched — any field has been touched. */
305
160
  declare function isTouched({ touched }: Form$1): boolean;
306
161
 
307
- /**
308
- * Is one field dirty the per-field rule behind `getFieldState`'s
309
- * `isDirty` and {@link useIsFieldDirty}: a live value exists at the path
310
- * and differs from the field's effective baseline (committed
311
- * `shouldDirty: false` baselines included). A leaf under a wholesale
312
- * ancestor write reports clean — dirtiness belongs to the branch that
313
- * actually diverged, the same attribution {@link getDirtyFields} applies.
314
- */
162
+ /** Is one field dirty — the per-field rule behind `getFieldState`'s
163
+ * `isDirty`: a live value exists at the path and differs from the field's
164
+ * effective baseline (committed `shouldDirty: false` baselines included).
165
+ * A leaf under a wholesale ancestor write reports clean — dirtiness
166
+ * belongs to the branch that actually diverged. */
315
167
  declare function isFieldDirtyByPath(form: Form$1, path: Path): boolean;
316
- /**
317
- * Is dirty -- any value differs from initialValues
318
- * @param form
319
- */
168
+ /** Is dirty — any value differs from initialValues. */
320
169
  declare function isDirty(form: Form$1): boolean;
321
- /**
322
- * Get dirty fields -- fields whose current value differs from initialValues.
323
- * Keys are user-facing dotted paths ('a.b', 'a.0.c'), unlike the JSON array
324
- * keys stored in the values Map.
325
- * @param form
326
- * @return object mapping each dirty field's dotted path to true; the same
327
- * reference is returned until the dirty set actually changes
328
- */
170
+ /** Get dirty fields — fields whose current value differs from
171
+ * initialValues. Keys are user-facing dotted paths ('a.b', 'a.0.c'); the
172
+ * same reference is returned until the dirty set actually changes. */
329
173
  declare function getDirtyFields(form: Form$1): Record<string, boolean>;
330
174
 
331
- /**
332
- * Set a field value as a user change.
333
- *
334
- * The write rides the same gated user-change pipeline a user typing into
335
- * the field would fire when a field is mounted on the path (registered
336
- * through {@link registerFieldMode} `useField` registers on mount): the
337
- * field's effective `mode` (per-field override included) and the form's
338
- * `reValidateMode` drive validation exactly as in {@link
339
- * userChangeByPath}. With no mounted field on the path it degrades to a
340
- * plain value set ({@link setValue}).
341
- *
342
- * This is the channel for component-library bridges that hand a control a
343
- * plain setter bound to a field — they cannot rebuild the gating from
344
- * public form state, because the per-field mode override and the
345
- * live-error view that gates `reValidateMode` live in the field
346
- * registration, not in public state.
347
- *
348
- * Contrast {@link setValue}: that is the imperative channel — its
349
- * `shouldValidate` option kicks the field's validator unconditionally,
350
- * ignoring any mode. Functional updaters are the caller's to evaluate
351
- * ({@link getValue}).
352
- *
353
- * `options` carries the same {@link SetFieldOptions}: on the fallback path
354
- * (no mounted field) they forward to {@link setValueByPath} wholesale,
355
- * while on the mounted-field path only `shouldDirty: false` applies — the
356
- * write lands as a commit while the field's own mode gating keeps driving
357
- * validation, which is the point of this channel.
358
- *
359
- * @param form
360
- * @param name
361
- * @param value
362
- * @param options
363
- */
364
- declare function changeValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, value: PathValueOf<T, P>, options?: SetFieldOptions): void;
365
- /**
366
- * Set a field value as a user change, by parsed path
367
- * @param form
368
- * @param path
369
- * @param value
370
- * @param options
371
- */
175
+ /** Set a field's value as a user change. When a field is mounted on the
176
+ * path it rides the gated user-change pipeline (the field's effective
177
+ * `mode` and the form's `reValidateMode` drive validation, as in
178
+ * {@link userChangeByPath}); with no mounted field it degrades to a plain
179
+ * {@link setValue}. Contrast {@link setValue}, whose `shouldValidate`
180
+ * kicks the validator unconditionally. */
181
+ declare function changeValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P, value: PathValueOf<T, P>, options?: SetFieldOptions): void;
182
+ /** Set a field's value as a user change, by parsed path. */
372
183
  declare function changeValueByPath(form: Form$1, path: Path, value: any, options?: SetFieldOptions): void;
373
- /**
374
- * Register a mounted field's `mode` override at `path` for user-change
375
- * gating ({@link userChangeByPath} / {@link userBlur}). Returns the
376
- * registration token for {@link unregisterFieldMode} plus whether the
377
- * slot was already occupied — two fields mounted at one path is almost
378
- * always a bug: the latest mount's mode governs every user-change write
379
- * there, which the React layer warns about in DEV.
380
- *
381
- * @param form
382
- * @param path
383
- * @param mode the field's `mode` option, or undefined to follow
384
- * {@link Form.mode}
385
- * @return `token` to hand to {@link unregisterFieldMode}; `displaced`
386
- * true when a previous registration at the same path still owned
387
- * the slot
388
- */
184
+ /** Register a mounted field's `mode` override at `path` for user-change
185
+ * gating. Returns the registration token for {@link unregisterFieldMode}
186
+ * plus whether the slot was already occupied — two fields at one path is
187
+ * almost always a bug (the latest mount's mode governs). */
389
188
  declare function registerFieldMode(form: Form$1, path: Path, mode: ValidationMode | undefined): {
390
189
  token: object;
391
190
  displaced: boolean;
392
191
  };
393
- /** Drop a {@link registerFieldMode} registration. A later mount at the
394
- * same path keeps its slot: only the entry owned by `token` is removed. */
192
+ /** Drop a {@link registerFieldMode} registration; only the entry owned by
193
+ * `token` is removed, so a later mount keeps its slot. */
395
194
  declare function unregisterFieldMode(form: Form$1, path: Path, token: object): void;
396
- /**
397
- * Write a bound field's user change by path: the write plus the
398
- * mode/reValidateMode-gated validation pipeline what a bound field's
399
- * onChange does when the user types. Reads the effective mode from the
400
- * field-mode registry (the latest mount's override governs), so a plain
401
- * write happens when no field is registered at `path`. Framework
402
- * adapters (React's `useField`, a Solid binding) forward their field
403
- * change events here.
404
- *
405
- * @param form
406
- * @param path
407
- * @param value
408
- */
195
+ /** First key in the mounted-field registry that is a strict descendant of
196
+ * `ancestor`, in registration order undefined when none is mounted.
197
+ * Same descendant rule as `onPathEvent` ('['+','+segment keeps sibling
198
+ * lookalike keys from matching). */
199
+ declare function firstMountedDescendantKey(form: Form$1, ancestor: Path): string | undefined;
200
+ /** Write a bound field's user change by path: the write plus the
201
+ * mode/reValidateMode-gated validation pipeline. Reads the effective mode
202
+ * from the field-mode registry, so a plain write happens when no field is
203
+ * registered at `path`. Framework adapters forward their change events
204
+ * here. */
409
205
  declare function userChangeByPath(form: Form$1, path: Path, value: any): void;
206
+ /** A bound field's blur: mark the path touched (unconditional), then kick
207
+ * its validator under the blur-side gate. Framework adapters forward blur
208
+ * events here. */
209
+ declare function userBlur(form: Form$1, path: Path): void;
210
+
410
211
  /**
411
- * A bound field's blur: mark the path touched, then kick its validator
412
- * under the blur-side gate (`mode` `'onBlur'`/`'onTouched'`/`'all'`, or
413
- * `reValidateMode: 'onBlur'` while the field carries a live error). The
414
- * touched marking is unconditional a field counts as touched on blur
415
- * regardless of mode. Framework adapters forward field blur events here.
212
+ * Create a non-hook field binding react-hook-form's `register`
213
+ * contract, wired onto this library's store: the bound element never
214
+ * re-renders, every change still lands in the store through the gated
215
+ * user-change pipeline, and `trigger`/submit/`getValues` read it like
216
+ * any other field. `useField({uncontrolled: true})` already covers the
217
+ * hook case; `register` exists for the call sites a hook cannot serve —
218
+ * dynamic lists, conditional fields, non-React adapters — and for RHF
219
+ * migration (`{...register('name')}` spreads unchanged).
220
+ *
221
+ * Lifecycle rides the returned `ref` callback, exactly like React's own
222
+ * ref semantics guarantee attach/detach:
223
+ * - **attach** (element handed over): restore a StrictMode-detached
224
+ * snapshot (React 19 detaches refs on the dev remount), seed the
225
+ * element's initial DOM content into the store when the path has no
226
+ * live value yet (an uncontrolled element's `defaultValue`/`checked`
227
+ * is invisible to React state, so the DOM is the source), register the
228
+ * field-mode entry (the "mounted field" signal routing `changeValue`
229
+ * into the gated pipeline), wire declarative `rules` through
230
+ * `registerValidatorByPath`, and subscribe the `'focusError'` channel
231
+ * (`setFocus`, failed-submit auto-focus) plus the bulk-reset DOM sync
232
+ * (payload-less `'change'` rewrites the element, register-style);
233
+ * - **detach** (`null`): unregister mode entry and validator, drop the
234
+ * subscriptions, and tombstone the path unless
235
+ * `shouldUnregister: false` — the library's historical unmount
236
+ * default, snapshot/restore-safe under StrictMode.
237
+ *
238
+ * Event extraction defaults to the element's own protocol (files →
239
+ * `target.files`, checkbox → `target.checked`, `valueAsNumber`/
240
+ * `valueAsDate` under their flags, else `target.value`), overridable
241
+ * with `eventToValue` — the same extraction `<Field>` performs.
416
242
  *
417
243
  * @param form
418
- * @param path
244
+ * @param name path or segment array
245
+ * @param options {@link RegisterOptions}
246
+ * @return spreadable props {@link RegisterProps}
419
247
  */
420
- declare function userBlur(form: Form$1, path: Path): void;
248
+ declare function registerField(form: Form$1, name: Name, options?: RegisterOptions): RegisterProps;
421
249
 
422
250
  declare function setIsSubmitting(form: Form$1, value: boolean): void;
423
251
  declare function incrementSubmitCount(form: Form$1): void;
424
252
  declare function setSubmitSuccessful(form: Form$1, value: boolean): void;
425
- /**
426
- * Set the form-level disabled flag and emit a payload-less 'disabled'
427
- * event subscribed fields (useField and the components built on it)
428
- * re-render with the merged disabled state: form flag || their own
429
- * `disabled` option.
430
- * @param form
431
- * @param value
432
- */
253
+ /** Set the form-level disabled flag and emit a payload-less 'disabled'
254
+ * event subscribed fields re-render with the merged state (form flag ||
255
+ * their own `disabled` option). */
433
256
  declare function setDisabled(form: Form$1, value: boolean): void;
434
- /**
435
- * Set the form's user-owned metadata slot (Formik's `status` role): the
436
- * payload-less 'status' event wakes {@link useStatus} and any imperative
437
- * `subscribe(form, {event: 'status'})` listeners. Nothing else reads or
438
- * interprets the value — server session flags, step state, non-field
439
- * errors of any shape are all fair game. Starts `undefined`.
440
- * @param form
441
- * @param value
442
- */
257
+ /** Set the form's user-owned metadata slot (Formik's `status` role): the
258
+ * payload-less 'status' event wakes {@link useStatus} and imperative
259
+ * `subscribe` listeners. Nothing else interprets the value. */
443
260
  declare function setStatus(form: Form$1, value: any): void;
261
+ /** A submit callback: the submitted values plus the triggering event. */
262
+ type SubmitCallback<T> = (values: T, e?: any) => void | Promise<void>;
444
263
  /** Submit callbacks for {@link handleSubmit}. All optional — a missing
445
264
  * callback is simply skipped, matching the <Form> component semantics. */
446
265
  type HandleSubmitOptions<T extends Record<string, any> = any> = {
447
266
  /** Called after validation passes, before onValidSubmit. */
448
- onSubmit?: (values: T, e?: any) => void | Promise<void>;
267
+ onSubmit?: SubmitCallback<T>;
449
268
  /** Called after validation passes, following a successful onSubmit. */
450
- onValidSubmit?: (values: T, e?: any) => void | Promise<void>;
451
- /**
452
- * Called when validation fails.
453
- * @param errors array of {path, type, message} entries in insertion
454
- * order; path is the dotted field path ('a.b', 'list.0'), type is
455
- * the error kind ('custom' for plain string errors, 'native' for
456
- * failed DOM constraint validation), message is the display text
457
- * @param values current form values
458
- */
269
+ onValidSubmit?: SubmitCallback<T>;
270
+ /** Called when validation fails, with the flattened error entries and
271
+ * current values. */
459
272
  onInvalidSubmit?: (errors: FieldErrorEntry[], values: T) => void;
460
- /**
461
- * Called after validation passes and the submit callbacks ran, with the
462
- * final (schema-coerced) values the slot <Form>'s `action` prop uses
463
- * to dispatch React 19 server actions with FormData. Runs inside the
464
- * same isSubmitting window and is awaited like onSubmit/onValidSubmit.
465
- */
466
- onAction?: (values: T, e?: any) => void | Promise<void>;
467
- /**
468
- * Focus the first error field after a failed submit. Defaults to true —
469
- * only an explicit `false` disables it. When custom validation fails,
470
- * a 'focusError' event carrying the first error's path key is emitted
471
- * on the form (bound fields such as <Field> subscribe and focus their
472
- * input); when native constraint validation fails, the submitted
473
- * form's first ':invalid' control is focused directly.
474
- */
273
+ /** Called after validation passes with the final (schema-coerced)
274
+ * values the slot <Form>'s `action` prop uses to dispatch React 19
275
+ * server actions. May return an {@link ActionErrorResult}: its `errors`
276
+ * record lands as `type: 'server'` errors and the submit counts
277
+ * unsuccessful; any other return means success. */
278
+ onAction?: (values: T, e?: any) => void | Promise<void | ActionErrorResult>;
279
+ /** Focus the first error field after a failed submit. Defaults to true. */
475
280
  shouldFocusError?: boolean;
281
+ /** Whether native constraint validation gates this attempt. Defaults to
282
+ * the form's {@link Form.shouldUseNativeValidation} flag. Targets
283
+ * without checkValidity never gate. */
284
+ shouldUseNativeValidation?: boolean;
476
285
  };
477
- /**
478
- * Create an async submit handler for `form` the headless counterpart of
479
- * the <Form> component's onSubmit wiring.
480
- *
481
- * Behavior mirrors <Form> exactly: preventDefault when present, then the
482
- * submit state machine (isSubmitting/submitCount/isSubmitSuccessful) runs
483
- * around native constraint validation (via `e.currentTarget.checkValidity`,
484
- * skipped when the target has no checkValidity e.g. React Native or
485
- * toolbar-button submits) and custom validators. Failed validation fires
486
- * onInvalidSubmit with the flattened error entries; a passing submit runs
487
- * onSubmit then onValidSubmit. Errors thrown by either are swallowed into
488
- * isSubmitSuccessful=false rather than rejecting the returned promise.
489
- * Failed validation also focuses the offending field (see
490
- * {@link HandleSubmitOptions.shouldFocusError}).
491
- *
492
- * @param form form instance
493
- * @param options submit callbacks
494
- * @return async event handler, callable without an event object
495
- */
286
+ /** What a server action / onAction callback returns when the server
287
+ * rejected the payload: a field-path message(s) record, landed as
288
+ * `type: 'server'` errors. Undefined (or anything else) means success. */
289
+ type ActionErrorResult = {
290
+ errors?: Record<string, string | string[]>;
291
+ };
292
+ /** Create an async submit handler for `form` — the headless counterpart of
293
+ * the <Form> component's onSubmit wiring. Runs the submit state machine
294
+ * around native constraint validation (skipped for targets without
295
+ * checkValidity) and custom validators; failed validation fires
296
+ * onInvalidSubmit, a passing submit runs onSubmit then onValidSubmit.
297
+ * Errors thrown by either are swallowed into isSubmitSuccessful=false.
298
+ * A new attempt while one is in flight is ignored outright (no state
299
+ * changes at all) — including handleSubmit calls nested inside onSubmit. */
496
300
  declare function handleSubmit<T extends Record<string, any> = any>(form: Form$1<T>, options?: HandleSubmitOptions<T>): (e?: {
497
301
  preventDefault?: () => void;
498
302
  currentTarget?: any;
499
303
  }) => Promise<void>;
500
304
 
501
- /** Type tag of a failed rule, as stored on the resulting FieldError. */
502
- type RuleType = 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern';
503
- /**
504
- * Declarative field rules — a subset of react-hook-form's `register` rules.
505
- *
506
- * Failed rules land in the form's error state as FieldErrors (`type` is the
507
- * rule name) instead of only surfacing through the browser's validity
508
- * bubble, so any design system can render the messages uniformly.
509
- */
510
- type FieldRules = {
511
- /**
512
- * Fails on empty values: `''`, `undefined`, `null` or an empty array
513
- * (`0` and `false` count as filled) — react-hook-form's `required`
514
- * semantics. A string is the error message; `true` uses the default.
515
- * When it fails, the remaining rules are skipped — an empty value
516
- * reports only its required error.
517
- */
518
- required?: string | true;
519
- /** Fails when `Number(value)` is below this bound; `NaN` values skip. */
520
- min?: number;
521
- /** Fails when `Number(value)` is above this bound; `NaN` values skip. */
522
- max?: number;
523
- /** Fails when a string value is shorter than this, or an array has
524
- * fewer entries; other values skip. */
525
- minLength?: number;
526
- /** Fails when a string value is longer than this, or an array has more
527
- * entries; other values skip. */
528
- maxLength?: number;
529
- /** Fails when the value does not match `pattern.value`. */
530
- pattern?: {
531
- value: RegExp;
532
- message: string;
533
- };
534
- /**
535
- * Custom rule callbacks — react-hook-form's `register({validate})`
536
- * shape: one function, or a record of named functions. Each runs after
537
- * the declarative checks, and only when they passed (`required` failing
538
- * short-circuits the rest, RHF's first-error semantics). A returned
539
- * error keeps its message; its `type` becomes the record key
540
- * (`'validate'` for the single-function form) so consumers can switch
541
- * on `error.type`. Sync-only — async checks belong in the field's
542
- * `validate` option.
543
- */
544
- validate?: SyncValidator | Record<string, SyncValidator>;
545
- /**
546
- * Overrides the message per rule type — `min`, `max`, `minLength`,
547
- * `maxLength` defaults and pattern's inline `message` alike — e.g. for
548
- * centralizing or localizing messages.
549
- */
550
- messages?: Partial<Record<Exclude<RuleType, 'required'>, string>>;
551
- };
552
-
553
- type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = {
305
+ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = {
554
306
  form?: Form$1<TValues>;
555
307
  name: TPath;
556
308
  initialValue?: any;
@@ -566,11 +318,11 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
566
318
  * second argument carries the validation context (`meta.signal` aborts
567
319
  * when the round is superseded).
568
320
  */
569
- validate?: (value: PathValueOf<TValues, TPath>, meta: {
321
+ validate?: ((value: PathValueOf<TValues, TPath>, meta: {
570
322
  form: Form$1<TValues>;
571
323
  path: Path;
572
324
  signal: AbortSignal;
573
- }) => ReturnType<Validator>;
325
+ }) => ReturnType<Validator>) | StandardSchemaV1<PathValueOf<TValues, TPath>>;
574
326
  /**
575
327
  * Declarative rules (required/min/max/minLength/maxLength/pattern),
576
328
  * compiled into a synchronous validator. `required` is special: it runs
@@ -613,9 +365,13 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
613
365
  */
614
366
  delayError?: number;
615
367
  /**
616
- * Disable this field: OR-ed with the form-level flag
617
- * (`createForm({disabled})` / `setDisabled`) into the result's
618
- * `disabled`. A field cannot opt out of a disabled form.
368
+ * Disable this field: merged into the result's `disabled` as
369
+ * `form.disabled || own === true || (own !== false && an ancestor
370
+ * declared disabled)`. `disabled: true` on a parent path disables every
371
+ * descendant field too (react-hook-form subtree semantics), and a
372
+ * descendant declares `disabled: false` to opt back out of that
373
+ * ancestor. The form-level flag (`createForm({disabled})` /
374
+ * `setDisabled`) cannot be opted out of.
619
375
  */
620
376
  disabled?: boolean;
621
377
  /**
@@ -676,13 +432,39 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
676
432
  * for the resolved baseline; a field unmounted in between never kicks.
677
433
  */
678
434
  validateOnMount?: boolean;
435
+ /**
436
+ * DOM event → value extractor for the result's {@link
437
+ * UseFieldResult.inputProps} binding. Defaults to the element's own
438
+ * protocol (files → `target.files`, checkbox → `target.checked`,
439
+ * `valueAsNumber`/`valueAsDate` under their flags, else
440
+ * `target.value`); a non-DOM event passes through unchanged, so custom
441
+ * controls can hand raw values. Only consumed by `inputProps` — the
442
+ * headless `onChange` keeps taking raw values.
443
+ */
444
+ eventToValue?: (e: any) => any;
445
+ /** `inputProps` stores `e.target.valueAsNumber` instead of the string
446
+ * value (number inputs, RHF's `register({valueAsNumber})`). An
447
+ * explicit `eventToValue` takes precedence. */
448
+ valueAsNumber?: boolean;
449
+ /** `inputProps` stores `e.target.valueAsDate` instead of the string
450
+ * value (date/time inputs, RHF's `register({valueAsDate})`). An
451
+ * explicit `eventToValue` takes precedence; combining with
452
+ * `valueAsNumber` is a TypeError (`valueAsNumber` wins). */
453
+ valueAsDate?: boolean;
454
+ /**
455
+ * Element type hint for {@link UseFieldResult.inputProps} only:
456
+ * `'checkbox'` renders `checked` instead of `value`, `'file'` renders
457
+ * neither (file inputs cannot be value-controlled). The extraction
458
+ * itself already auto-detects both types from the event's target.
459
+ */
460
+ type?: string;
679
461
  };
680
462
  /**
681
463
  * The result of {@link useField}. Deliberately a closed shape: no index
682
464
  * signature, so a typo'd property access (`field.vlaue`) is a type error
683
465
  * instead of silently reading `undefined`.
684
466
  */
685
- type UseFieldResult<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = {
467
+ type UseFieldResult<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = {
686
468
  /** The form instance this field is bound to (explicit prop or context) —
687
469
  * handy for consumers that need direct access to the headless API. */
688
470
  form: Form$1<TValues>;
@@ -728,8 +510,42 @@ type UseFieldResult<TValues extends Record<string, any> = any, TPath extends Fie
728
510
  * whose element is not bound neither throws nor focuses anything.
729
511
  */
730
512
  focusRef: (el: any) => void;
513
+ /**
514
+ * DOM-ready props for an `<input>`: `<input {...field.inputProps} />`
515
+ * binds the element to the field without hand-wiring value/onChange/
516
+ * onBlur/ref/a11y. `onChange` takes the DOM event (extraction per
517
+ * {@link UseFieldOptions}' `eventToValue`/`valueAsNumber`/`valueAsDate`
518
+ * /`type`), `ref` is the focus channel, `aria-invalid`/`aria-describedby`
519
+ * complete the {@link errorIdFromKey} chain — render the error element
520
+ * with `fieldErrorId(name)` to finish it. The headless `value`/
521
+ * `onChange`/`onBlur`/`focusRef` stay available for custom controls
522
+ * that hand raw values (design systems) — `inputProps` is the DOM
523
+ * boundary adapter, never a replacement.
524
+ */
525
+ inputProps: UseFieldInputProps;
731
526
  };
732
- declare function useField<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(options: UseFieldOptions$1<TValues, TPath>): UseFieldResult<TValues, TPath>;
527
+ /**
528
+ * The spreadable DOM props {@link UseFieldResult.inputProps} carries:
529
+ * `name`, `onChange` (event-based), `onBlur`, `ref`, `disabled`, the
530
+ * error a11y wiring, and exactly one of `value` (controlled),
531
+ * `defaultValue` (uncontrolled) or `checked` (`type: 'checkbox'`) —
532
+ * `type: 'file'` carries none. Always spread `inputProps` FIRST, so the
533
+ * caller's own props (placeholder, className, an explicit `ref` they
534
+ * merge themselves) win.
535
+ */
536
+ type UseFieldInputProps = {
537
+ name: string;
538
+ value?: any;
539
+ defaultValue?: any;
540
+ checked?: boolean;
541
+ onChange: (e: any) => void;
542
+ onBlur: () => void;
543
+ ref: (el: any) => void;
544
+ disabled: boolean;
545
+ 'aria-invalid'?: boolean;
546
+ 'aria-describedby'?: string;
547
+ };
548
+ declare function useField<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>>(options: UseFieldOptions$1<TValues, TPath>): UseFieldResult<TValues, TPath>;
733
549
 
734
550
  type FieldArrayItem<K extends string> = {
735
551
  id: string;
@@ -737,7 +553,7 @@ type FieldArrayItem<K extends string> = {
737
553
  } & Record<K, string>;
738
554
  /** Options accepted by {@link useFieldArray} and the per-instance hook
739
555
  * returned by `createFormContext()`. */
740
- type UseFieldArrayOptions<K extends string = 'id'> = {
556
+ type UseFieldArrayOptions<K extends string = 'id'> = Pick<FieldOptionBase, 'rules' | 'shouldUnregister'> & {
741
557
  name: Name;
742
558
  form?: Form$1;
743
559
  /**
@@ -747,32 +563,31 @@ type UseFieldArrayOptions<K extends string = 'id'> = {
747
563
  * same name. The underlying id is unchanged.
748
564
  */
749
565
  keyName?: K;
750
- /**
751
- * Declarative rules validated against the whole array value
752
- * (react-hook-form's `useFieldArray` `rules`): `required` fails on an
753
- * empty array, `minLength`/`maxLength` read the array's length. Checked
754
- * on submit and `trigger`, like every registered validator.
755
- */
756
- rules?: FieldRules;
757
- /**
758
- * Whether unmounting this array removes its branch. Defaults to the
759
- * form-level `shouldUnregister` — tombstone (drop values) like a bound
760
- * field's unmount; pass `false` to keep the values.
761
- */
762
- shouldUnregister?: boolean;
763
566
  };
764
- type UseFieldArrayResult<K extends string = 'id'> = {
567
+ /** Second argument of the row-adding movers: `focus` decides whether the
568
+ * new row takes focus once it commits — `true` targets its first mounted
569
+ * child field, a string names the child field. */
570
+ type FieldArrayFocusOptions = {
571
+ focus?: boolean | string;
572
+ };
573
+ type UseFieldArrayResult<TItem = any, K extends string = 'id'> = {
765
574
  fields: FieldArrayItem<K>[];
766
- append: (value: any) => void;
767
- prepend: (value: any) => void;
768
- insert: (index: number, value: any) => void;
769
- remove: (index: number) => void;
575
+ /** Append one row. With the item type declared —
576
+ * `useFieldArray<Item>({name: 'items'})` the value is checked
577
+ * against the array's element type. */
578
+ append: (value: TItem, options?: FieldArrayFocusOptions) => void;
579
+ prepend: (value: TItem, options?: FieldArrayFocusOptions) => void;
580
+ insert: (index: number, value: TItem, options?: FieldArrayFocusOptions) => void;
581
+ /** Remove one row, or several in a single write (`remove([0, 2])` —
582
+ * order-insensitive, duplicates ignored, out-of-range indices are
583
+ * silent no-ops). */
584
+ remove: (indices: number | number[]) => void;
770
585
  swap: (from: number, to: number) => void;
771
586
  move: (from: number, to: number) => void;
772
- replace: (values: any[]) => void;
773
- update: (index: number, value: any) => void;
587
+ replace: (values: TItem[]) => void;
588
+ update: (index: number, value: TItem) => void;
774
589
  };
775
- declare function useFieldArray<K extends string = 'id'>(options: UseFieldArrayOptions<K>): UseFieldArrayResult<K>;
590
+ declare function useFieldArray<TItem = any, K extends string = 'id'>(options: UseFieldArrayOptions<K>): UseFieldArrayResult<TItem, K>;
776
591
  /**
777
592
  * The result of {@link useFieldArrayItem}. Mirrors the {@link useField}
778
593
  * return shape (`value`/`errors`/`error`) plus the row's `index` and
@@ -798,6 +613,14 @@ type UseFieldArrayItemResult<TValue = any> = {
798
613
  index: number;
799
614
  form: Form$1;
800
615
  };
616
+ /** Options for {@link useFieldArrayItem} and its per-instance core: the
617
+ * array's `name`, the row's stable `id` (from `fields[i].id`), and an
618
+ * optional explicit `form`. */
619
+ type UseFieldArrayItemOptions = {
620
+ name: Name;
621
+ id: string;
622
+ form?: Form$1;
623
+ };
801
624
  /**
802
625
  * Subscribe to a single row of a {@link useFieldArray} field — the
803
626
  * per-item counterpart `useFieldArray` alone cannot offer. `useFieldArray`
@@ -823,127 +646,116 @@ type UseFieldArrayItemResult<TValue = any> = {
823
646
  * the same path — it publishes the id table), the row's `id` from
824
647
  * `fields[i].id`, and optionally an explicit `form`
825
648
  */
826
- declare function useFieldArrayItem<TValue = any>(options: {
827
- name: Name;
828
- id: string;
829
- form?: Form$1;
830
- }): UseFieldArrayItemResult<TValue>;
649
+ declare function useFieldArrayItem<TValue = any>(options: UseFieldArrayItemOptions): UseFieldArrayItemResult<TValue>;
831
650
 
832
- declare const FormContext: React.Context<Form$1<any> | null>;
833
- declare const FormProvider: React.Provider<Form$1<any> | null>;
651
+ declare const FormContext: Context<Form$1<any> | null>;
652
+ declare const FormProvider: Provider<Form$1<any> | null>;
834
653
  /**
835
- * Read the form from the module-level {@link FormContext}. Pass the values
836
- * shape `useFormContext<Values>()` to get a fully typed `Form<Values>`
837
- * headless API; the `any` default keeps untyped call sites compiling.
838
- *
839
- * For multiple forms in one subtree use {@link createFormContext} instead.
840
- *
654
+ * Read the form from the module-level {@link FormContext}; pass the values
655
+ * shape (`useFormContext<Values>()`) for a typed `Form<Values>`. Use
656
+ * {@link createFormContext} for multiple forms in one subtree.
841
657
  * @throws when no `<FormProvider>` is mounted above the call site.
842
658
  */
843
659
  declare function useFormContext<T extends Record<string, any> = any>(): Form$1<T>;
844
- /**
845
- * Create an isolated bundle of form-context bindings: its own React context
846
- * plus `useField` / `useFieldArray` / `useFieldArrayItem` /
847
- * `useFormContext` hooks that resolve their form from it.
848
- *
849
- * Why: the module-level {@link FormContext} works fine for a single form per
850
- * subtree, but nesting two forms (or reusing a component inside a different
851
- * form) makes them fight over one context. Calling this factory once per app
852
- * area — `const Ctx = createFormContext<Values>()` — fixes the value shape
853
- * (`Ctx.useField({name: 'user.name'})` gets its `name` constrained by
854
- * `FieldPath<Values>` and its `value` typed accordingly), so call sites stop
855
- * hand-writing generics, and each instance's Provider scopes a strictly
856
- * separate form. The bundle also carries its raw React context
857
- * (`Ctx.context`) so `<Form context={Ctx.context}>` can provide into it.
858
- */
859
- declare function createFormContext<TValues extends Record<string, any> = any>(): {
860
- context: React.Context<Form$1<TValues> | null>;
861
- FormProvider: ({ form, children }: {
660
+ /** Options the bundle's pre-bound hooks take: the underlying hook's
661
+ * options minus `form` this factory's own context supplies it. For
662
+ * `useField`, `{name: TPath}` keeps `name` a direct TPath inference site. */
663
+ type BoundFieldOptions<TValues extends Record<string, any>, TPath extends AnyPath<TValues>> = {
664
+ name: TPath;
665
+ } & Omit<UseFieldOptions$1<TValues, TPath>, 'form'>;
666
+ type BoundFieldArrayOptions<TValues extends Record<string, any>, K extends string = 'id'> = {
667
+ name: FieldPath<TValues> | Name;
668
+ keyName?: K;
669
+ rules?: FieldRules;
670
+ shouldUnregister?: boolean;
671
+ };
672
+ type BoundFieldArrayItemOptions<TValues extends Record<string, any>> = {
673
+ name: FieldPath<TValues> | Name;
674
+ id: string;
675
+ };
676
+ /** The bundle {@link createFormContext} returns: a private React context
677
+ * plus the hooks pre-bound to it, all typed against `TValues`. */
678
+ type FormContextBundle<TValues extends Record<string, any> = any> = {
679
+ /** The raw React context, for `<Form context={...}>`: the component
680
+ * keeps its submit machinery while providing into this instance's
681
+ * private context. */
682
+ context: Context<Form$1<TValues> | null>;
683
+ FormProvider: (props: {
862
684
  form: Form$1<TValues>;
863
685
  children: ReactNode;
864
686
  }) => ReactNode;
865
687
  useFormContext: () => Form$1<TValues>;
866
- useField: <TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(options: {
867
- name: TPath;
868
- } & Omit<UseFieldOptions$1<TValues, TPath>, "form">) => UseFieldResult<TValues, TPath>;
869
- useFieldArray: <K extends string = "id">(options: {
870
- name: FieldPath<TValues> | Name;
871
- keyName?: K;
872
- rules?: FieldRules;
873
- shouldUnregister?: boolean;
874
- }) => UseFieldArrayResult<K>;
875
- useFieldArrayItem: <TValue = any>(options: {
876
- name: FieldPath<TValues> | Name;
877
- id: string;
878
- }) => UseFieldArrayItemResult<TValue>;
688
+ useField: <TPath extends AnyPath<TValues> = AnyPath<TValues>>(options: BoundFieldOptions<TValues, TPath>) => UseFieldResult<TValues, TPath>;
689
+ useFieldArray: <TItem = any, K extends string = 'id'>(options: BoundFieldArrayOptions<TValues, K>) => UseFieldArrayResult<TItem, K>;
690
+ useFieldArrayItem: <TValue = any>(options: BoundFieldArrayItemOptions<TValues>) => UseFieldArrayItemResult<TValue>;
879
691
  };
880
- declare const CheckboxGroupContext: React.Context<any>;
881
- declare const CheckboxGroupProvider: React.Provider<any>;
692
+ /**
693
+ * Create an isolated bundle of form-context bindings: its own React context
694
+ * plus `useField`/`useFieldArray`/`useFieldArrayItem`/`useFormContext`
695
+ * hooks resolving from it. One factory per app area scopes a separate
696
+ * form and fixes the value shape (`Ctx.useField` gets typed `name`/`value`);
697
+ * `Ctx.context` lets `<Form context={Ctx.context}>` provide into it.
698
+ */
699
+ declare function createFormContext<TValues extends Record<string, any> = any>(): FormContextBundle<TValues>;
700
+ declare const CheckboxGroupContext: Context<any>;
701
+ declare const CheckboxGroupProvider: Provider<any>;
882
702
  declare function useCheckboxGroupContext(): any;
883
703
 
884
- /** Subscription granularity for {@link onPathEvent}.
885
- * - `'leaf'`: the subscriber reads exactly one key ({@link
886
- * useValueByPath}); only writes at that key or above it can change what
887
- * it reads.
888
- * - `'branch'`: the subscriber aggregates a whole subtree below a key
889
- * ({@link useFieldArray}); descendant writes matter too. */
704
+ /** Subscription granularity for {@link onPathEvent}: `'leaf'` reads one
705
+ * key (only writes at it or above matter); `'branch'` aggregates a whole
706
+ * subtree (descendant writes matter too). */
890
707
  type WatchScope = 'leaf' | 'branch';
891
- /** Events {@link subscribe} can watch. `'errors'` and `'touched'` are
892
- * stored per exact key, so they match exact keys ({@link onKeyEvent});
893
- * `'change'`, `'validating'`, `'submitting'`, `'submitCount'`,
894
- * `'disabled'`, `'status'` and `'submitSuccessful'` go through
895
- * {@link onPathEvent}. `'validating'` carries paths (one per async
896
- * validator round) and matches by path exactly like `'change'`;
897
- * `'submitting'`, `'submitCount'`, `'disabled'`, `'status'` and
898
- * `'submitSuccessful'` are payload-less broadcasts, so `name` never
899
- * narrows them — every subscriber hears every emission. */
708
+ /** Events {@link subscribe} can watch. `'errors'`/`'touched'` match exact
709
+ * keys ({@link onKeyEvent}); `'change'`/`'validating'` match by path
710
+ * ({@link onPathEvent}); the rest are payload-less broadcasts every
711
+ * subscriber hears. */
900
712
  type SubscribeEvent = 'change' | 'errors' | 'touched' | 'validating' | 'submitting' | 'submitCount' | 'submitSuccessful' | 'disabled' | 'status' | 'loading';
901
- /** Options accepted by {@link subscribe}. */
902
713
  type SubscribeOptions = {
903
- /** Path (or list of paths) to watch. Omit to receive every emission of
904
- * `event`, payload-less broadcasts included. A single segments path
905
- * (`['tags', 0]`) and a list of names (`['tags', 'user.name']`) are told
906
- * apart by the same rule `trigger` uses: only a segments path can hold
907
- * a number. */
714
+ /** Path or paths to watch; omit to receive every emission. A segments
715
+ * path vs a name list is told apart by `trigger`'s rule: only segments
716
+ * hold a number. */
908
717
  name?: Name | Name[];
909
718
  /** Event to watch. Defaults to `'change'`. */
910
719
  event?: SubscribeEvent;
911
- /** Which writes around `name` are relevant `'leaf'` or `'branch'`.
912
- * Only meaningful for the path-carrying events `'change'` and
913
- * `'validating'`: `'errors'`/`'touched'` match exact keys and
914
- * `'submitting'`/`'submitCount'`/`'disabled'`/`'status'`/
915
- * `'submitSuccessful'` are payload-less. Defaults to `'branch'` — the
916
- * intuitive linkage semantics, where subscribing to `'tags'` means the
917
- * whole branch. */
720
+ /** Which writes around `name` are relevant. Only meaningful for the
721
+ * path-carrying events; defaults to `'branch'` (subscribing to `'tags'`
722
+ * means the whole branch). */
918
723
  scope?: WatchScope;
919
- /** Invoked with no arguments after each matching emission. Read fresh
920
- * state through the `get*` readers inside it. */
724
+ /** Invoked after each matching emission; read fresh state through the
725
+ * `get*` readers inside it. */
921
726
  callback: () => void;
922
727
  };
923
728
  /**
924
729
  * Subscribe to form events imperatively — the non-render counterpart of
925
- * the `use*` hooks: linkages and side effects (province changed → clear
926
- * city, autosave, analytics) run without mounting a watching component.
927
- *
928
- * Without `name`, `callback` fires on every `event` emission, payload-less
929
- * broadcasts (reset, setInitialValues) included. With `name`, matching
930
- * follows the event's shape: `'errors'`/`'touched'` match the exact key
931
- * ({@link onKeyEvent}) — another field's error never wakes this
932
- * subscriber — while `'change'`/`'validating'`/`'submitting'`/
933
- * `'submitCount'`/`'disabled'`/`'submitSuccessful'` go through
934
- * {@link onPathEvent}, so the default `'branch'` scope wakes a `'tags'`
935
- * subscriber when any `tags.*` descendant is written. `'validating'`
936
- * carries a path per validator round and narrows by path like
937
- * `'change'`; `'disabled'`/`'submitSuccessful'` (like `'submitting'`)
938
- * are payload-less broadcasts that every named subscriber receives. A
939
- * `name` array builds one subscription per path and the returned
940
- * function unsubscribes them all.
941
- *
942
- * @param form the form to watch
943
- * @param options event, name(s), scope and callback
944
- * @return unsubscribe function
730
+ * the `use*` hooks. Without `name`, `callback` fires on every emission;
731
+ * with `name`, matching follows the event's shape (`'errors'`/`'touched'`
732
+ * match exact keys, the rest match by path or broadcast). A name array
733
+ * builds one subscription per path.
945
734
  */
946
735
  declare function subscribe(form: Form$1, options: SubscribeOptions): () => void;
736
+ /** The handle {@link watch} returns: a subscribe/getSnapshot pair any
737
+ * reactive runtime can bind to. One internal listener stays alive from
738
+ * creation, so `getSnapshot()` is always fresh; `dispose` ends it. */
739
+ type WatchHandle<T> = {
740
+ /** Read the current snapshot, cached between events; repeated reads
741
+ * share one reference until state changes. */
742
+ getSnapshot: () => T;
743
+ /** Register a change listener; fires only when the projection changed.
744
+ * With `isEqual`, an equal verdict skips the callback; without one,
745
+ * every event wakes it. */
746
+ subscribe: (invalidate: () => void) => () => void;
747
+ /** Remove the internal listener and every consumer callback; the handle
748
+ * is dead afterwards. */
749
+ dispose: () => void;
750
+ };
751
+ /**
752
+ * Watch a projection of form state without React — the framework-free
753
+ * {@link useWatch} (same `isEqual` bailout), tree-shaken when unused.
754
+ * Returns a {@link WatchHandle}: read `getSnapshot()`, re-read/re-render
755
+ * when `subscribe`'s listener fires. The handle subscribes eagerly, so
756
+ * reads are never stale; `getter`/`isEqual` are captured at creation.
757
+ */
758
+ declare function watch<T>(form: Form$1, event: SubscribeEvent, getter: () => T, isEqual?: (prev: T, next: T) => boolean): WatchHandle<T>;
947
759
 
948
760
  /**
949
761
  * Create a form instance bound to this component.
@@ -955,11 +767,19 @@ declare function subscribe(form: Form$1, options: SubscribeOptions): () => void;
955
767
  * while touched flags and errors survive. Change detection is
956
768
  * reference-first with a structural fallback, so re-renders that pass an
957
769
  * inline literal with equal content never re-sync -- the user's
958
- * in-progress typing is never clobbered.
770
+ * in-progress typing is never clobbered. Passing `resetOptions` reroutes
771
+ * those changed-content syncs through {@link reset} instead, so its keep*
772
+ * flags govern what survives (`keepDirtyValues: true` keeps the user's
773
+ * uncommitted edits on dirty fields); the reference/structural guard
774
+ * applies to both routes.
959
775
  */
960
776
  declare function useForm<T extends Record<string, any> = any>(options?: Options<T> & {
961
777
  values?: T;
778
+ resetOptions?: ResetOptions;
962
779
  }): Form$1<T>;
780
+ /** Snapshot equality comparator — the `isEqual` contract {@link
781
+ * useWatchCore} documents. */
782
+ type SnapshotComparator<T> = (prev: T, next: T) => boolean;
963
783
  /**
964
784
  * Shared core of {@link useWatch} and the path-scoped hooks: a
965
785
  * useSyncExternalStore binding over a custom event subscription.
@@ -976,7 +796,7 @@ declare function useForm<T extends Record<string, any> = any>(options?: Options<
976
796
  * snapshot and notifies. Omitted, the historical drop-and-notify pipeline
977
797
  * runs byte-for-byte unchanged.
978
798
  */
979
- declare function useWatchCore<T>(subscribeFactory: (invalidate: () => void) => () => void, getter: () => T, isEqual?: (prev: T, next: T) => boolean): T;
799
+ declare function useWatchCore<T>(subscribeFactory: (invalidate: () => void) => () => void, getter: () => T, isEqual?: SnapshotComparator<T>): T;
980
800
  /**
981
801
  * Subscribe to a form event and keep the component's snapshot of `getter()`
982
802
  * in sync with the form state.
@@ -989,6 +809,12 @@ declare function useWatchCore<T>(subscribeFactory: (invalidate: () => void) => (
989
809
  * shape every hook shares; the raw emitter form remains accepted for
990
810
  * back-compat and for subscription sources that are not a full form.
991
811
  *
812
+ * Framework-free counterpart: {@link watch} — the same event/getter/
813
+ * `isEqual` contract exposed as a named export returning a
814
+ * subscribe/getSnapshot handle any reactive runtime can bind to
815
+ * (useWatch is its React binding; the ref-based cache here keeps inline
816
+ * getters from re-subscribing per render).
817
+ *
992
818
  * By default the re-render surface is the event's own scope: every emit
993
819
  * the subscription hears drops the snapshot cache and wakes React, which
994
820
  * then bails out when the recomputed snapshot is reference-identical
@@ -1001,9 +827,9 @@ declare function useWatchCore<T>(subscribeFactory: (invalidate: () => void) => (
1001
827
  * stores the new snapshot and re-renders. Same contract as TanStack's
1002
828
  * `useSelector` compare. Omitted, behavior is unchanged.
1003
829
  */
1004
- declare function useWatch<T>(formOrEmitter: Form$1 | EventEmitter<FormEvents>, event: SubscribeEvent, getter: () => T, isEqual?: (prev: T, next: T) => boolean): T;
830
+ declare function useWatch<T>(formOrEmitter: Form$1 | EventEmitter<FormEvents>, event: SubscribeEvent, getter: () => T, isEqual?: SnapshotComparator<T>): T;
1005
831
  /** Options for {@link useValue} and {@link useValueByPath}. */
1006
- type UseValueOptions<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments> = {
832
+ type UseValueOptions<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>> = {
1007
833
  /** Value to return while the field reads undefined — react-hook-form's
1008
834
  * `useWatch` `defaultValue`: an untouched, never-seeded field reads
1009
835
  * this instead of `undefined`. */
@@ -1019,7 +845,7 @@ type UseValueOptions<T extends Record<string, any> = any, P extends FieldPath<T>
1019
845
  /**
1020
846
  * Get field value state
1021
847
  */
1022
- declare function useValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, options?: UseValueOptions<T, P>): PathValueOf<T, P>;
848
+ declare function useValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P, options?: UseValueOptions<T, P>): PathValueOf<T, P>;
1023
849
  /**
1024
850
  * Get field value state by path
1025
851
  */
@@ -1027,10 +853,22 @@ declare function useValueByPath(form: Form$1, path: Path, options?: {
1027
853
  defaultValue?: any;
1028
854
  exact?: boolean;
1029
855
  }): any;
856
+ /**
857
+ * Subscribe to the whole values tree: re-renders the calling component
858
+ * whenever any 'change' event lands — react-hook-form's `watch()` with no
859
+ * arguments. The snapshot is the memoized `getValues(form)` result, so
860
+ * repeated reads during one render share one reference and, under
861
+ * `__DEV__`, one frozen copy.
862
+ *
863
+ * Broad scope by design: read it in components that must stay cheap and
864
+ * need the full tree; per-field readers should reach for {@link useValue}
865
+ * instead so a keystroke re-renders exactly the affected field.
866
+ */
867
+ declare function useValues<T extends Record<string, any> = any>(form: Form$1<T>): T;
1030
868
  /**
1031
869
  * Get field touched state
1032
870
  */
1033
- declare function useTouched<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): boolean;
871
+ declare function useTouched<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): boolean;
1034
872
  /**
1035
873
  * Get field touched state by path
1036
874
  */
@@ -1039,7 +877,7 @@ declare function useTouchedByPath(form: Form$1, path: Path): boolean;
1039
877
  * Get field error message state
1040
878
  * @return current error's message string (display text), or undefined
1041
879
  */
1042
- declare function useError<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): string | undefined;
880
+ declare function useError<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): string | undefined;
1043
881
  /**
1044
882
  * Get field error state by path
1045
883
  * @return current FieldError object ({type, message}), or undefined
@@ -1050,7 +888,7 @@ declare function useErrorByPath(form: Form$1, path: Path): FieldError | undefine
1050
888
  * @return every error registered for the field (insertion order); an empty
1051
889
  * array when the field has none
1052
890
  */
1053
- declare function useFieldErrors<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): FieldError[];
891
+ declare function useFieldErrors<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): FieldError[];
1054
892
  /**
1055
893
  * Get all field errors by path
1056
894
  * @return every error registered for the field (insertion order); an empty
@@ -1067,7 +905,7 @@ declare function useIsDirty(form: Form$1): boolean;
1067
905
  * the flag, payload-less broadcasts (reset, setInitialValues) always
1068
906
  * sync, and writes elsewhere never re-render it.
1069
907
  */
1070
- declare function useIsFieldDirty<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): boolean;
908
+ declare function useIsFieldDirty<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form$1<T>, name: P): boolean;
1071
909
  /**
1072
910
  * Get whether one field is dirty, by parsed path. See {@link
1073
911
  * useIsFieldDirty}.
@@ -1095,7 +933,7 @@ declare function useTouchedFields(form: Form$1): string[];
1095
933
  * {@link useIsDirty}. Cheaper than calling the granular hooks one by one
1096
934
  * (one subscription and one snapshot instead of one per flag).
1097
935
  */
1098
- type FormState = {
936
+ type FormState<T extends Record<string, any> = any> = {
1099
937
  /** Any live value differs from its baseline (see {@link isDirty}). */
1100
938
  isDirty: boolean;
1101
939
  /** Dirty fields keyed by user-facing dotted path ('a.b', 'a.0.c'). */
@@ -1110,6 +948,12 @@ type FormState = {
1110
948
  * In-flight validation is NOT factored in ({@link isValidating} is the
1111
949
  * separate signal; async rounds temporarily pass this flag like RHF's). */
1112
950
  isValid: boolean;
951
+ /** Every error as one record keyed by user-facing dotted path
952
+ * ('a.b', 'list.0') — react-hook-form's `formState.errors` shape,
953
+ * typed as {@link FieldErrors} (per-key values optional). Memoized
954
+ * (see {@link getErrorsRecord}): the reference is stable between error
955
+ * writes, so the snapshot comparator can bail on it. */
956
+ errors: FieldErrors<T>;
1113
957
  isSubmitting: boolean;
1114
958
  /**
1115
959
  * Whether a submit has been attempted on this form — set on the first
@@ -1128,8 +972,50 @@ type FormState = {
1128
972
  /** The form-level disabled flag (fields OR their own `disabled`). */
1129
973
  disabled: boolean;
1130
974
  };
1131
- declare function useFormState(form: Form$1): FormState;
975
+ declare function useFormState<T extends Record<string, any> = any>(form: Form$1<T>): FormState<T>;
976
+ /**
977
+ * The official selector primitive — TanStack Form's
978
+ * `useStore(store, selector)` counterpart. Subscribes to every
979
+ * state-bearing form event and keeps `selector()`'s result as the
980
+ * snapshot; the selector itself is a plain closure (read the form through
981
+ * any getter — `getValue`, `getValues`, `form.errors.size`, …).
982
+ *
983
+ * Without `isEqual` the subscription is object-identity based: each event
984
+ * recomputes the selector and React bails out when the result is
985
+ * reference-identical (the contract every `useWatch` reader relies on).
986
+ * The optional `isEqual(prev, next)` comparator is for wide-scope
987
+ * selectors that return a fresh reference per call (a whole-values
988
+ * projection, say): an equal verdict skips notifying React altogether —
989
+ * no render, not even a bailed-out one (TanStack `useSelector` compare
990
+ * contract).
991
+ *
992
+ * `useFormState` is the built-in aggregate selector; {@link useWatch} is
993
+ * the single-event version. Reach for `useStore` when the projection is
994
+ * yours and spans state events — e.g. `form.validating.size > 0 &&
995
+ * form.isSubmitting` as one flag.
996
+ */
997
+ declare function useStore<T>(form: Form$1, selector: () => T, isEqual?: SnapshotComparator<T>): T;
1132
998
  declare function useHasErrors(form: Form$1): boolean;
999
+ /**
1000
+ * Get every error as one record keyed by user-facing dotted path
1001
+ * ('a.b', 'list.0') — react-hook-form's `formState.errors` shape, for
1002
+ * error-summary panels and a11y announcements. Values are the stored
1003
+ * FieldError[] arrays shared with the form (treat as read-only). The
1004
+ * record is memoized per form (see {@link getErrorsRecord}): the hook
1005
+ * re-renders only when an error write actually changed the record's
1006
+ * content.
1007
+ */
1008
+ declare function useErrors<T extends Record<string, any> = any>(form: Form$1<T>): FieldErrors<T>;
1009
+ /**
1010
+ * Get every error as one nested object following the values tree
1011
+ * (`errors.items?.[0]?.name` reads) — the typed optional-chaining
1012
+ * counterpart of {@link useErrors}' flat dotted record. Leaves hold the
1013
+ * stored FieldError[] arrays shared with the form (treat as read-only).
1014
+ * Memoized alongside the record (see {@link getErrorsTree}): the hook
1015
+ * re-renders only when an error write actually changed the tree's
1016
+ * content.
1017
+ */
1018
+ declare function useErrorsTree<T extends Record<string, any> = any>(form: Form$1<T>): FieldErrorsTree<T>;
1133
1019
  /**
1134
1020
  * Get whether the form currently has no errors — react-hook-form's
1135
1021
  * `formState.isValid` counterpart. Subscribes to the `'errors'` event only;
@@ -1212,367 +1098,156 @@ declare function useFormError(form: Form$1): string | undefined;
1212
1098
  */
1213
1099
  declare function useFormErrors(form: Form$1): FieldError[];
1214
1100
 
1215
- /**
1216
- * Options accepted by {@link useTransform}.
1217
- */
1218
- type UseTransformOptions<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments, TDisplay = PathValueOf<TValues, TPath>> = {
1219
- /**
1220
- * Map the form's stored (raw) value to the display value the control
1221
- * renders — the read direction. Omitted: the raw value is displayed
1222
- * as-is (identity).
1223
- */
1101
+ type UseTransformOptions<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>, TDisplay = PathValueOf<TValues, TPath>> = {
1102
+ /** Map the stored (raw) value to the display value (read direction);
1103
+ * omitted = identity. */
1224
1104
  toDisplay?: (raw: PathValueOf<TValues, TPath>) => TDisplay;
1225
- /**
1226
- * Map a display value back to the raw value written into the form
1227
- * the write direction. Omitted: the display value is written as-is
1228
- * (identity). The round trip should be an identity
1229
- * (`toDisplay(fromDisplay(x)) === x`); a store value the transform
1230
- * cannot invert (e.g. `undefined` for a not-yet-edited field) must be
1231
- * handled by `toDisplay`, since it runs first.
1232
- */
1233
- fromDisplay?: (display: TDisplay) => PathValueOf<TValues, TPath>;
1105
+ /** Map a display value back to the raw value (write direction);
1106
+ * omitted = identity. May return a Promise only the latest write
1107
+ * commits (stale resolutions drop). The round trip should be an
1108
+ * identity; non-invertible store values must be handled by
1109
+ * `toDisplay`, which runs first. */
1110
+ fromDisplay?: (display: TDisplay) => PathValueOf<TValues, TPath> | Promise<PathValueOf<TValues, TPath>>;
1111
+ /** Debounce the display→raw commit; only the last write in the window
1112
+ * commits (TanStack `asyncDebounceMs`). `0`/omitted commits
1113
+ * immediately; validation fires at commit time through the
1114
+ * user-change pipeline. */
1115
+ asyncDebounceMs?: number;
1234
1116
  };
1235
1117
  /**
1236
- * Bind a control to a field whose stored value and display value differ
1237
- * TanStack Form's `useTransform` counterpart, with the round trip made
1238
- * explicit: `toDisplay` maps the store value to what the control shows,
1239
- * `fromDisplay` maps the control's display value back to what the store
1240
- * holds. The store always carries the raw typed value, so
1241
- * `getValues`/submit/validation never see display representations.
1242
- *
1243
- * ```jsx
1244
- * const age = useTransform(form, 'age', {
1245
- * toDisplay: (raw: number) => String(raw),
1246
- * fromDisplay: (display: string) => Number(display)
1247
- * });
1248
- * <input value={age.value} onChange={e => age.onChange(e.target.value)} />
1249
- * ```
1250
- *
1251
- * `value` subscribes to 'change' at leaf scope exactly like a controlled
1252
- * `useField` value — typing, programmatic `setValue` and ancestor writes
1253
- * all re-derive it, writes elsewhere never re-render it. `onChange`
1254
- * writes through `userChangeByPath` (the user-change channel): with a
1255
- * field mounted at the same path the mode/reValidateMode-gated
1256
- * validation fires exactly as if the user typed into a bound field; with
1257
- * no mounted field it degrades to a plain value write. Touched marking
1258
- * stays a blur concern — pair this with `useField` at the same path, or
1259
- * call `setTouched`, when blur semantics matter.
1260
- *
1261
- * The transform functions are read fresh on every render (inline
1262
- * closures work), and `value` is recomputed per render — keep display
1263
- * values primitive (string/number) so React's equal-state bailout holds.
1264
- *
1265
- * @param form the form instance (explicit; the hook is headless — no
1266
- * context read, no provider required)
1267
- * @param name the field's path (dotted string or segments)
1268
- * @param options the two mapping directions; both optional (identity)
1118
+ * Bind a control whose display value differs from the stored raw value
1119
+ * (TanStack `useTransform`): `toDisplay` maps store→display,
1120
+ * `fromDisplay` maps display→store. The store always carries the raw
1121
+ * value. `value` subscribes to 'change' at leaf scope; `onChange` writes
1122
+ * through the user-change channel, so mode-gated validation fires as if
1123
+ * the user typed. Transform functions are read fresh each render.
1269
1124
  */
1270
- declare function useTransform<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments, TDisplay = PathValueOf<TValues, TPath>>(form: Form$1<TValues>, name: TPath, options?: UseTransformOptions<TValues, TPath, TDisplay>): {
1125
+ declare function useTransform<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>, TDisplay = PathValueOf<TValues, TPath>>(form: Form$1<TValues>, name: TPath, options?: UseTransformOptions<TValues, TPath, TDisplay>): {
1271
1126
  value: TDisplay;
1272
1127
  onChange: (display: TDisplay) => void;
1273
1128
  };
1274
1129
 
1275
- /**
1276
- * Props for <Form>.
1277
- *
1278
- * Native validation behavior: the rendered <form> always sets noValidate,
1279
- * which suppresses the browser's built-in blocked-submit UI. However, native
1280
- * constraint validation still gates submission the form element's
1281
- * checkValidity() runs before custom validators, and when it fails,
1282
- * reportValidity() surfaces the offending constraints as native bubbles and
1283
- * submission stops (onInvalidSubmit fires). onSubmit/onValidSubmit only run
1284
- * once every native constraint (required, type=email, minLength, ...) passes.
1285
- *
1286
- * The submit flow itself lives in the headless `handleSubmit` (see form.ts);
1287
- * this component is a thin wrapper that binds it to the rendered <form>.
1288
- */
1130
+ /** Props for <Form>. Native constraint validation gates submission: the
1131
+ * form always sets noValidate, but checkValidity() runs before custom
1132
+ * validators and a failure stops submission (onInvalidSubmit fires).
1133
+ * `shouldUseNativeValidation={false}` skips the gate (targets without
1134
+ * checkValidity are always exempt). The flow itself lives in the headless
1135
+ * `handleSubmit`; this is a thin wrapper binding it to the <form>. */
1289
1136
  type FormProps<T extends Record<string, any> = any> = Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> & {
1290
1137
  form?: Form$1<T>;
1291
- /**
1292
- * Provide into an isolated context from `createFormContext()` instead of
1293
- * the module-level one — `<Form context={ProfileForm.context}>` keeps the
1294
- * component's full submit machinery while the factory's bound hooks
1295
- * (`ProfileForm.useField`, `ProfileForm.useFormContext`, ...) resolve this
1296
- * form from their private context. The module-level `useFormContext()` /
1297
- * `useField` do not see it; that is the point of the isolation. Omitted,
1298
- * the form lands in the module-level FormContext as before.
1299
- */
1138
+ /** Isolated context from `createFormContext()`: its bound hooks see this
1139
+ * form, the module-level ones do not. Defaults to FormContext. */
1300
1140
  context?: React.Context<Form$1<any> | null>;
1301
- /**
1302
- * The values baseline — a sync object, a Promise, or a thunk returning
1303
- * either ({@link Options.initialValues}). Async sources render the form
1304
- * empty and gate on `form.isLoading` until they resolve.
1305
- */
1141
+ /** Values baseline — sync object, Promise, or thunk; async sources gate on `isLoading`. */
1306
1142
  initialValues?: T | Promise<T> | (() => T | Promise<T>);
1307
- /**
1308
- * Form-level default for a bound field's unmount behavior
1309
- * ({@link Options.shouldUnregister}): `true` (the default) tombstones
1310
- * unmounted fields, `false` keeps their values.
1311
- */
1143
+ /** Default unmount behavior: `true` tombstones unmounted fields, `false` keeps values. */
1312
1144
  shouldUnregister?: boolean;
1313
- /**
1314
- * Validate on mount (see {@link Options.validateOnMount}): every
1315
- * mounted field with a validator kicks once after mount and the
1316
- * form-level `validate` (if any) runs once. A field's own
1317
- * `validateOnMount` prop overrides this flag.
1318
- */
1145
+ /** Validate on mount: each validator kicks once; a field's own prop overrides. */
1319
1146
  validateOnMount?: boolean;
1320
- /**
1321
- * Disable every bound field: the form-level flag fields OR with their
1322
- * own `disabled` option (a field cannot opt out). Seeded at create and
1323
- * kept in sync while this prop changes (undefined leaves the current
1324
- * flag untouched — toggle at runtime with `setDisabled`).
1325
- */
1147
+ /** Disable every bound field (fields OR with their own option); undefined leaves the flag untouched. */
1326
1148
  disabled?: boolean;
1327
- /**
1328
- * Form-level default for field validation's `asyncAlways`: a field
1329
- * whose `required` gate failed still runs its debounced validator, its
1330
- * result landing per-source alongside the gate's errors. A field's own
1331
- * `asyncAlways` prop overrides this flag.
1332
- */
1149
+ /** Form-level default for `asyncAlways`; a field's own prop overrides. */
1333
1150
  asyncAlways?: boolean;
1334
- /**
1335
- * Controlled external values. When the `values` reference changes, the
1336
- * new object is synced into the form (via setInitialValues semantics):
1337
- * uncommitted user edits are discarded -- master-detail semantics, where
1338
- * selecting another record replaces the draft -- while touched flags and
1339
- * errors are kept. Sync is reference-based: re-renders that pass the same
1340
- * `values` reference never clobber what the user is typing.
1341
- */
1151
+ /** Controlled external values: a new reference syncs via setInitialValues
1152
+ * (draft discarded, touched/errors kept); same reference never clobbers. */
1342
1153
  values?: T;
1343
- /** May be async the submit flow awaits it, so form.isSubmitting
1344
- * covers the entire flight. */
1154
+ /** May be async; `isSubmitting` covers the flight. */
1345
1155
  onSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;
1346
1156
  /** May be async, same as onSubmit. */
1347
1157
  onValidSubmit?: (values: T, e: React.FormEvent) => void | Promise<void>;
1348
- /**
1349
- * React 19 Server Action target: after validation passes (and after
1350
- * onSubmit/onValidSubmit), the validated, schema-coerced values are
1351
- * converted to FormData ({@link formDataFromValues} files, arrays and
1352
- * nested objects included) and dispatched to this callback, e.g.
1353
- * `action={createUser}` for a server action or
1354
- * `action={formData => startTransition(() => dispatch(formData))}` in a
1355
- * useActionState bridge. `isSubmitting` covers the whole flight.
1356
- */
1357
- action?: (formData: FormData) => void | Promise<void>;
1358
- /**
1359
- * Called when validation fails.
1360
- * @param errors array of {path, type, message} entries in insertion
1361
- * order; path is the dotted field path ('a.b', 'list.0'), type is
1362
- * the error kind ('custom' for plain string errors, 'native' for
1363
- * failed DOM constraint validation), message is the display text
1364
- * @param values current form values
1365
- */
1158
+ /** Server Action target: after validation, schema-coerced values become
1159
+ * FormData and dispatch here. Returning {@link ActionErrorResult} lands
1160
+ * `type: 'server'` per-field errors (unsuccessful submit); a URL string
1161
+ * renders the native `action` for no-JS progressive enhancement. */
1162
+ action?: string | ((formData: FormData) => void | Promise<void | ActionErrorResult>);
1163
+ /** Called when validation fails; errors are {path, type, message} entries
1164
+ * (type: 'custom' | 'native'). */
1366
1165
  onInvalidSubmit?: (errors: {
1367
1166
  path: string;
1368
1167
  type: string;
1369
1168
  message: string;
1370
1169
  }[], values: T) => void;
1371
- /**
1372
- * Focus the first field with an error after a failed submit: custom
1373
- * validation failures focus the first errored field, native constraint
1374
- * failures focus the first ':invalid' control. Defaults to true; pass
1375
- * false to disable.
1376
- */
1170
+ /** Focus the first errored field (or first ':invalid' control) after a failed submit. Default true. */
1377
1171
  shouldFocusError?: boolean;
1172
+ /** Whether native constraint validation gates submission (pass false for
1173
+ * custom-validator-only forms). Seeds the created form's flag and this
1174
+ * form's submit wiring. */
1175
+ shouldUseNativeValidation?: boolean;
1378
1176
  };
1379
- declare function Form<T extends Record<string, any> = any>({ form: f1, context, initialValues, values, shouldUnregister, validateOnMount, disabled, asyncAlways, onSubmit, onValidSubmit, onInvalidSubmit, action, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
1177
+ declare function Form<T extends Record<string, any> = any>({ form: f1, context, initialValues, values, shouldUnregister, validateOnMount, disabled, asyncAlways, onSubmit, onValidSubmit, onInvalidSubmit, action, shouldFocusError, shouldUseNativeValidation, ...props }: FormProps<T>): React.JSX.Element;
1380
1178
 
1381
- /**
1382
- * Props for {@link FormField}: every {@link UseFieldOptions} option plus a
1383
- * render-prop `children` receiving the bound field result.
1384
- */
1385
- type FormFieldProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = UseFieldOptions$1<TValues, TPath> & {
1179
+ /** Every {@link UseFieldOptions} option plus a render-prop `children`
1180
+ * receiving the bound field result. */
1181
+ type FormFieldProps<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = UseFieldOptions$1<TValues, TPath> & {
1386
1182
  children: (field: UseFieldResult<TValues, TPath>) => React.ReactNode;
1387
1183
  };
1388
- /**
1389
- * Headless field bound through a render prop — the non-hook counterpart of
1390
- * {@link useField} for class components, callback-style consumers and
1391
- * library bridges where a hook cannot be called (Formik `<Field>` /
1392
- * TanStack `form.Field` shape).
1393
- *
1394
- * The child function receives the full {@link UseFieldResult} — value,
1395
- * error(s), onChange/onBlur, `disabled`, `focusRef`, the bound `form` —
1396
- * and renders whatever UI it wants; nothing is rendered when it returns
1397
- * null/undefined, so it can also gate conditional layout. Resolves its
1398
- * form from the module-level `FormContext` or the explicit `form` option
1399
- * (per-instance contexts from `createFormContext()` keep using their own
1400
- * `useField` hook).
1401
- */
1402
- declare function FormField<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>({ children, ...options }: FormFieldProps<TValues, TPath>): React.ReactNode;
1184
+ /** Headless field via a render prop — the non-hook {@link useField} for
1185
+ * class components/callback consumers. The child receives the full
1186
+ * {@link UseFieldResult}; resolves its form from FormContext or the
1187
+ * `form` option. */
1188
+ declare function FormField<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>>({ children, ...options }: FormFieldProps<TValues, TPath>): React.ReactNode;
1403
1189
 
1404
- /**
1405
- * Props shared by Field/Checkbox/Select. Generic so a typed form flows into
1406
- * the `validate` callback: with `form` (a `Form<Values>`) and `name`
1407
- * (a `FieldPath<Values>`) provided, `validate` receives the value at that
1408
- * path `PathValueOf<Values, P>` — instead of `any`. The defaults keep the
1409
- * bare `<Field name="x" />` (context-resolved, untyped) call sites exactly
1410
- * as permissive as before.
1411
- */
1412
- type UseFieldOptions<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = {
1413
- form?: Form$1<TValues>;
1190
+ /** The error-message element id a field's `aria-describedby` points at
1191
+ * (same id `<Field>`'s renderError span carries). A custom error
1192
+ * component completes the accessible-name chain with
1193
+ * `<span id={fieldErrorId(name)} role="alert">`. */
1194
+ declare function fieldErrorId(name: Name): string;
1195
+
1196
+ /** Props shared by Field/Checkbox/Select: the hook options minus the
1197
+ * required `name` (the components type it optional) and `validateDeps`
1198
+ * (the components do not forward it), plus the index signature that lets
1199
+ * DOM props flow through. */
1200
+ type UseFieldOptions<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = Omit<UseFieldOptions$1<TValues, TPath>, 'name' | 'validateDeps'> & {
1414
1201
  name?: TPath;
1415
- initialValue?: any;
1416
- shouldUnregister?: boolean;
1417
- /**
1418
- * Field-level validator. The value argument is typed when the field is
1419
- * tied to a typed form (via the `form` prop); the return shape mirrors
1420
- * {@link Validator} — an error (string / FieldError / mixed array) or
1421
- * undefined when valid, possibly a Promise for async validation. The
1422
- * second argument carries the validation context (`meta.signal` aborts
1423
- * when the round is superseded).
1424
- */
1425
- validate?: (value: PathValueOf<TValues, TPath>, meta: {
1426
- form: Form$1;
1427
- path: Path;
1428
- signal: AbortSignal;
1429
- }) => ReturnType<Validator>;
1430
- /**
1431
- * Declarative rules (required/min/max/minLength/maxLength/pattern,
1432
- * plus custom `validate` callbacks), compiled into a validator that
1433
- * runs before `validate`; failures land in the form's error state.
1434
- * The declarative subset is also rendered as native constraint
1435
- * attributes (`required`, `minLength`, `pattern`, …) onto the element
1436
- * for browser/AT hints — `:invalid` styling, screen-reader
1437
- * announcements — while the store pipeline stays the source of truth
1438
- * for messages (`renderError`/`aria-invalid` keep working; a user-passed
1439
- * `required`/`pattern`/… prop overrides the derived attribute). Passed
1440
- * through to useField — like validateDebounce it is never spread onto
1441
- * the DOM element.
1442
- */
1443
- rules?: FieldRules;
1444
- /**
1445
- * Milliseconds to debounce this field's validation kicks. Defaults to 0
1446
- * (validate immediately); only the last kick inside the window runs the
1447
- * validator, and `trigger` waits the window out. Passed through to
1448
- * useField/useValidate.
1449
- */
1450
- validateDebounce?: number;
1451
- /**
1452
- * Run this field's debounced validator even when its `required` gate
1453
- * failed (TanStack Form's `asyncAlways`): the gate's errors land
1454
- * immediately, the validator's own result lands alongside them
1455
- * per-source. Falls back to the form-level `createForm({asyncAlways})`.
1456
- * Passed through to useField.
1457
- */
1458
- asyncAlways?: boolean;
1459
- /**
1460
- * Validate this field once on mount (see {@link
1461
- * UseFieldOptions}' `validateOnMount`): overrides the form-level
1462
- * `createForm({validateOnMount})` / `<Form validateOnMount>` flag in
1463
- * either direction. Passed through to useField.
1464
- */
1465
- validateOnMount?: boolean;
1466
- /**
1467
- * Disable this field's control: OR-ed with the form-level flag
1468
- * (`createForm({disabled})` / `setDisabled`) — a field cannot opt out
1469
- * of a disabled form. Passed through to useField, like every option,
1470
- * never spread onto the DOM element from props.
1471
- */
1472
- disabled?: boolean;
1473
- /**
1474
- * Milliseconds to delay showing a newly appearing error (render layer
1475
- * only — `aria-invalid`/`renderError` wait out the window while the
1476
- * form's error state stays immediate for trigger/submit). An error
1477
- * that clears inside the window never shows; once visible, error
1478
- * changes apply immediately. Passed through to useField.
1479
- */
1480
- delayError?: number;
1481
- /**
1482
- * Field-level validation mode override: this field validates on its own
1483
- * schedule instead of the form's `mode` (other fields are unaffected);
1484
- * the form's `reValidateMode` still governs re-validation once the
1485
- * field has an error. Passed through to useField, never spread onto
1486
- * the DOM element.
1487
- */
1488
- mode?: ValidationMode;
1489
- /**
1490
- * Uncontrolled mode: render the element with `defaultValue` instead of
1491
- * `value` — typing re-renders nothing (the store still carries every
1492
- * write; errors/touched/disabled still re-render the field). The
1493
- * snapshot is pinned at mount; bulk operations (reset/setInitialValues)
1494
- * sync the DOM element directly without a render — RHF-register
1495
- * behavior (read live values with useValue/getValues). Passed through
1496
- * to useField, never spread onto the DOM element.
1497
- */
1498
- uncontrolled?: boolean;
1499
1202
  [key: string]: any;
1500
1203
  };
1501
- type FieldProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = UseFieldOptions<TValues, TPath> & {
1204
+ type FieldProps<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = UseFieldOptions<TValues, TPath> & {
1502
1205
  as?: React.ComponentType<any>;
1503
1206
  asProps?: Record<string, any>;
1504
- eventToValue?: (e: any) => any;
1505
1207
  valueToProps?: (value: any) => Record<string, any>;
1506
- /**
1507
- * Optional error renderer. When provided and the field has an error,
1508
- * Field renders `<span id={id} role="alert">{renderError(error, id)}</span>`
1509
- * next to the input. The input's aria-describedby points at that span's
1510
- * id (the same `fieldErrorId(name)` derivation) whenever the field has
1511
- * an error — with or without renderError — so custom error components
1512
- * that render the element themselves (using `fieldErrorId`) get the
1513
- * wiring for free.
1514
- */
1208
+ /** Error renderer: renders `<span id role="alert">` beside the input;
1209
+ * `aria-describedby` always points at that id (`fieldErrorId`). */
1515
1210
  renderError?: (error: string, id: string) => React.ReactNode;
1516
- /**
1517
- * Store `e.target.valueAsNumber` instead of the string value —
1518
- * react-hook-form's `register({valueAsNumber})` counterpart for number
1519
- * inputs (`<input type="number">`). `NaN` passes through as-is when the
1520
- * input cannot be parsed, matching RHF. An explicit `eventToValue`
1521
- * takes precedence.
1522
- */
1523
- valueAsNumber?: boolean;
1524
- /**
1525
- * Store `e.target.valueAsDate` instead of the string value — RHF's
1526
- * `register({valueAsDate})` counterpart for date/time inputs. `null`
1527
- * passes through when the input cannot be parsed. An explicit
1528
- * `eventToValue` takes precedence; combining with `valueAsNumber` is a
1529
- * TypeError.
1530
- */
1531
- valueAsDate?: boolean;
1532
1211
  };
1533
- /**
1534
- * The error-message element id a field's `aria-describedby` points at —
1535
- * `fieldErrorId('a[0].b')` is `'a-0-b'`, the same id `Field`'s built-in
1536
- * `renderError` span carries. This is the library-level wiring convention:
1537
- * whenever a bound field (Field/Checkbox/Select) has an error it sets
1538
- * `aria-invalid` and describes the element with this id, so a custom error
1539
- * component only needs `<span id={fieldErrorId(name)} role="alert">` to
1540
- * complete the accessible-name chain for screen readers.
1541
- * @param name the same field name passed to the bound component
1542
- */
1543
- declare function fieldErrorId(name: Name): string;
1544
- /**
1545
- * The callable shape of {@link Field}: `form` + `name` flow their generics
1546
- * into `validate`'s value argument (`PathValueOf<TValues, TPath>`). A named
1547
- * interface rather than an inline `as <TValues, ...>() => ...` signature —
1548
- * same types, and the inline form trips no-use-before-define on the type
1549
- * parameters.
1550
- */
1212
+ /** Callable shape of {@link Field}; a named interface because the inline
1213
+ * `as <TValues,...>() => ...` form trips no-use-before-define. */
1551
1214
  type FieldComponent = {
1552
- <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(props: FieldProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
1215
+ <TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>>(props: FieldProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
1553
1216
  };
1554
1217
  declare const Field: FieldComponent;
1555
- type CheckboxProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = UseFieldOptions<TValues, TPath>;
1556
- /**
1557
- * Callable shape of {@link Checkbox}: the same form-typed `validate`
1558
- * inference contract as {@link FieldComponent}.
1559
- */
1218
+ /** Callable shape of {@link Checkbox}: same form-typed `validate` contract
1219
+ * as {@link FieldComponent}. */
1560
1220
  type CheckboxComponent = {
1561
- <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(props: CheckboxProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
1221
+ <TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>>(props: UseFieldOptions<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
1562
1222
  };
1563
1223
  declare const Checkbox: CheckboxComponent;
1564
- type SelectProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments> = UseFieldOptions<TValues, TPath> & {
1224
+ type SelectProps<TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>> = UseFieldOptions<TValues, TPath> & {
1565
1225
  multiple?: boolean;
1566
1226
  children?: React.ReactNode;
1567
1227
  };
1568
- /**
1569
- * Callable shape of {@link Select}: the same form-typed `validate`
1570
- * inference contract as {@link FieldComponent}.
1571
- */
1228
+ /** Callable shape of {@link Select}: same form-typed `validate` contract
1229
+ * as {@link FieldComponent}. */
1572
1230
  type SelectComponent = {
1573
- <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(props: SelectProps<TValues, TPath> & React.RefAttributes<HTMLSelectElement>): React.ReactElement | null;
1231
+ <TValues extends Record<string, any> = any, TPath extends AnyPath<TValues> = AnyPath<TValues>>(props: SelectProps<TValues, TPath> & React.RefAttributes<HTMLSelectElement>): React.ReactElement | null;
1574
1232
  };
1575
1233
  declare const Select: SelectComponent;
1576
1234
 
1577
- export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, FieldError, FieldErrorEntry, FieldPath, Form, FormContext, FormEvents, FormField, Form$1 as FormInstance, FormProvider, Name, Options, Path, PathSegments, PathValueOf, Select, SyncValidator, ValidationMode, Validator, changeValue, changeValueByPath, createFormContext, emitChangeByPath, fieldErrorId, getDirtyFields, getFieldState, getTouchedFields, getValue, getValueByPath, getValues, handleSubmit, hasTouched, hasTouchedByPath, incrementSubmitCount, isDirty, isFieldDirtyByPath, isTouched, registerFieldMode, removeField, removeFieldByPath, reset, resetField, seedValueByPath, setDisabled, setInitialValues, setIsSubmitting, setStatus, setSubmitSuccessful, setTouched, setTouchedByPath, setValue, setValueByPath, subscribe, unregisterFieldMode, useCanSubmit, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useField, useFieldArray, useFieldArrayItem, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useFormError, useFormErrors, useFormState, useHasErrors, useIsDirty, useIsFieldDirty, useIsFieldDirtyByPath, useIsLoading, useIsSubmitSuccessful, useIsSubmitting, useIsValid, useIsValidating, useStatus, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useTransform, useValue, useValueByPath, useWatch, useWatchCore, userBlur, userChangeByPath };
1578
- export type { FieldRules, FieldState, FormState, HandleSubmitOptions, RemoveFieldOptions, ResetFieldOptions, ResetOptions, SetFieldOptions, SubscribeEvent, SubscribeOptions, UseTransformOptions, UseValueOptions, WatchScope };
1235
+ /** Props for <ErrorSummary>: same form/context resolution <Form> itself
1236
+ * uses an explicit `form` wins, otherwise the (optionally isolated)
1237
+ * context form. */
1238
+ type ErrorSummaryProps<T extends Record<string, any> = any> = {
1239
+ form?: Form$1<T>;
1240
+ context?: React.Context<Form$1<any> | null>;
1241
+ heading?: string;
1242
+ };
1243
+ /** A GOV.UK-style error summary: one `role='alert'` box listing every
1244
+ * field error, each linking to the field's error element id. Clicking a
1245
+ * link focuses the field through the same `focusError` channel a failed
1246
+ * submit uses; after a failed submit the box itself takes focus (pair it
1247
+ * with `shouldFocusError={false}`, whose field focus lands later and
1248
+ * would otherwise win). {@link FORM_ERROR} entries have no field to focus
1249
+ * and render as plain list items. */
1250
+ declare function ErrorSummary<T extends Record<string, any> = any>({ form: formProp, context, heading }: ErrorSummaryProps<T>): React.ReactElement | null;
1251
+
1252
+ export { AnyPath, Checkbox, CheckboxGroupContext, CheckboxGroupProvider, ErrorSummary, Field, FieldError, FieldErrorEntry, FieldErrors, FieldErrorsTree, FieldPath, FieldRules, Form, FormContext, FormEvents, FormField, Form$1 as FormInstance, FormProvider, Name, Options, Path, PathValueOf, RegisterOptions, RegisterProps, Select, StandardSchemaV1, ValidationMode, Validator, changeValue, changeValueByPath, createFormContext, emitChangeByPath, fieldErrorId, firstMountedDescendantKey, getDirtyFields, getFieldState, getTouchedFields, getValue, getValueByPath, getValues, handleSubmit, hasTouched, hasTouchedByPath, incrementSubmitCount, isDirty, isFieldDirtyByPath, isTouched, registerField, registerFieldMode, removeField, removeFieldByPath, reset, resetField, seedValueByPath, setDisabled, setInitialValues, setIsSubmitting, setStatus, setSubmitSuccessful, setTouched, setTouchedByPath, setValue, setValueByPath, subscribe, unregisterFieldMode, useCanSubmit, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useErrors, useErrorsTree, useField, useFieldArray, useFieldArrayItem, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useFormError, useFormErrors, useFormState, useHasErrors, useIsDirty, useIsFieldDirty, useIsFieldDirtyByPath, useIsLoading, useIsSubmitSuccessful, useIsSubmitting, useIsValid, useIsValidating, useStatus, useStore, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useTransform, useValue, useValueByPath, useValues, useWatch, useWatchCore, userBlur, userChangeByPath, watch };
1253
+ export type { ActionErrorResult, FieldArrayFocusOptions, FieldState, FormContextBundle, FormState, HandleSubmitOptions, RemoveFieldOptions, ResetFieldOptions, ResetOptions, SetFieldOptions, SubscribeEvent, SubscribeOptions, UseTransformOptions, UseValueOptions, WatchHandle, WatchScope };