react-f0rm 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +242 -39
  2. package/dist/devtools/index.cjs.js +1 -1
  3. package/dist/devtools/index.cjs.js.map +1 -1
  4. package/dist/devtools/index.d.ts +2 -2
  5. package/dist/devtools/index.mjs +1 -1
  6. package/dist/devtools/index.mjs.map +1 -1
  7. package/dist/errors-BKrUdpfI.cjs.js +2 -0
  8. package/dist/errors-BKrUdpfI.cjs.js.map +1 -0
  9. package/dist/errors-CrQBddrJ.mjs +2 -0
  10. package/dist/errors-CrQBddrJ.mjs.map +1 -0
  11. package/dist/form-CeKSBs31.d.ts +486 -0
  12. package/dist/index.cjs.js +1 -1
  13. package/dist/index.cjs.js.map +1 -1
  14. package/dist/index.d.ts +1097 -118
  15. package/dist/index.mjs +1 -1
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/index.umd.js +1082 -544
  18. package/dist/index.umd.js.map +1 -1
  19. package/dist/index.umd.min.js +2 -2
  20. package/dist/index.umd.min.js.map +1 -1
  21. package/dist/persist.cjs.js +2 -0
  22. package/dist/persist.cjs.js.map +1 -0
  23. package/dist/persist.d.ts +49 -0
  24. package/dist/persist.mjs +2 -0
  25. package/dist/persist.mjs.map +1 -0
  26. package/dist/resolvers/standard-schema.cjs.js +1 -1
  27. package/dist/resolvers/standard-schema.cjs.js.map +1 -1
  28. package/dist/resolvers/standard-schema.d.ts +7 -5
  29. package/dist/resolvers/standard-schema.mjs +1 -1
  30. package/dist/resolvers/standard-schema.mjs.map +1 -1
  31. package/dist/resolvers/yup.cjs.js +1 -1
  32. package/dist/resolvers/yup.cjs.js.map +1 -1
  33. package/dist/resolvers/yup.d.ts +1 -1
  34. package/dist/resolvers/yup.mjs +1 -1
  35. package/dist/resolvers/yup.mjs.map +1 -1
  36. package/dist/resolvers/zod.cjs.js +1 -1
  37. package/dist/resolvers/zod.cjs.js.map +1 -1
  38. package/dist/resolvers/zod.d.ts +1 -1
  39. package/dist/resolvers/zod.mjs +1 -1
  40. package/dist/resolvers/zod.mjs.map +1 -1
  41. package/dist/server/index.cjs.js +2 -0
  42. package/dist/server/index.cjs.js.map +1 -0
  43. package/dist/server/index.d.ts +77 -0
  44. package/dist/server/index.mjs +2 -0
  45. package/dist/server/index.mjs.map +1 -0
  46. package/dist/validate-CNtuUhmk.mjs +2 -0
  47. package/dist/validate-CNtuUhmk.mjs.map +1 -0
  48. package/dist/validate-Cl4ksNFu.cjs.js +2 -0
  49. package/dist/validate-Cl4ksNFu.cjs.js.map +1 -0
  50. package/dist/validate-nksgv1pR.d.ts +272 -0
  51. package/dist/values-Cu6awQOJ.cjs.js +2 -0
  52. package/dist/values-Cu6awQOJ.cjs.js.map +1 -0
  53. package/dist/values-DRY-a32G.mjs +2 -0
  54. package/dist/values-DRY-a32G.mjs.map +1 -0
  55. package/package.json +87 -29
  56. package/dist/form-2_tBkEXU.mjs +0 -2
  57. package/dist/form-2_tBkEXU.mjs.map +0 -1
  58. package/dist/form-BiDaJLjD.d.ts +0 -826
  59. package/dist/form-BwLNQ6WB.cjs.js +0 -2
  60. package/dist/form-BwLNQ6WB.cjs.js.map +0 -1
  61. package/dist/validate-2XUilILy.d.ts +0 -22
@@ -0,0 +1,486 @@
1
+ import { EventEmitter } from '@for-fun/event-emitter';
2
+
3
+ type PathSegments = (string | number)[];
4
+ type Name = string | PathSegments;
5
+ type Path = {
6
+ value: PathSegments;
7
+ key: string;
8
+ };
9
+
10
+ /**
11
+ * Compile-time field path utilities: `FieldPath<T>` enumerates the valid
12
+ * path strings for a values shape `T` ('a', 'a.b', 'a[0]', 'a[b]', ...),
13
+ * and `PathValue<T, P>` resolves the leaf type a path points at.
14
+ * The grammar mirrors the paths accepted at runtime by `normalizePath`:
15
+ * numeric segments are bracket-only ('a[0]', never 'a.0' — dotted
16
+ * numerics throw a TypeError at runtime).
17
+ */
18
+ /** `true` only for the `any` type (`0 extends 1 & any`). */
19
+ type IsAny<T> = 0 extends 1 & T ? true : false;
20
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;
21
+ /** Depth countdown: Prev[9] = 8 ... Prev[1] = 0, Prev[0] = never stops recursion. */
22
+ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
23
+ /** Paths are capped at 10 segments to keep instantiation depth bounded. */
24
+ type MaxDepth = 9;
25
+ /**
26
+ * Valid path continuations after a segment: `.k` / `[k]` / `[0]`,
27
+ * optionally followed by deeper continuations into the child node.
28
+ * Numeric segments are bracket-only (`.0` throws at runtime); object
29
+ * keys that are themselves numeric strings likewise enumerate just the
30
+ * bracket subscript.
31
+ */
32
+ type Continue<T, D extends number> = [D] extends [never] ? never : IsAny<T> extends true ? string : T extends Primitive | Function ? never : T extends readonly (infer U)[] ? `[${number}]` | `[${number}]${Continue<U, Prev[D]>}` : {
33
+ [K in Extract<keyof T, string>]: (K extends `${number}` ? never : `.${K}`) | `[${K}]` | (K extends `${number}` ? never : `.${K}${Continue<T[K], Prev[D]>}`) | `[${K}]${Continue<T[K], Prev[D]>}`;
34
+ }[Extract<keyof T, string>];
35
+ /**
36
+ * Every valid field path string for a values shape `T`.
37
+ * @example FieldPath<{a: {b: string}}> // 'a' | 'a.b' | 'a[b]'
38
+ */
39
+ type FieldPath<T> = IsAny<T> extends true ? string : T extends Primitive | Function ? never : T extends readonly (infer U)[] ? `[${number}]` | `[${number}]${Continue<U, MaxDepth>}` : {
40
+ [K in Extract<keyof T, string>]: K extends `${number}` ? never : K | `${K}${Continue<T[K], MaxDepth>}`;
41
+ }[Extract<keyof T, string>];
42
+ /** Resolve `T[K]` for one bare segment: array index -> element, object key -> value. */
43
+ type Lookup<T, K extends string> = K extends `${number}` ? T extends readonly (infer U)[] ? U : never : K extends keyof T ? T[K] : never;
44
+ /** One dot-separated chunk: a bare segment plus any `[k]` / `[0]` suffixes. */
45
+ type ChunkValue<T, C extends string> = C extends `${infer Key}[${infer Tail}` ? ChunkSuffix<Lookup<T, Key>, `[${Tail}`> : Lookup<T, C>;
46
+ type ChunkSuffix<T, S extends string> = S extends `[${infer Key}]${infer Rest}` ? Rest extends '' ? Lookup<T, Key> : PathOf<Lookup<T, Key>, Rest> : never;
47
+ /** Resolve the value type the path string `P` points at inside `T`. */
48
+ type PathOf<T, P extends string> = P extends '' ? never : P extends `[${infer Key}]${infer Rest}` ? Rest extends '' ? Lookup<T, Key> : PathOf<Lookup<T, Key>, Rest> : P extends `.${infer Rest}` ? PathOf<T, Rest> : P extends `${infer Chunk}.${infer Rest}` ? PathOf<ChunkValue<T, Chunk>, Rest> : ChunkValue<T, P>;
49
+ /**
50
+ * The value type at path `P` of a values shape `T`.
51
+ * @example PathValue<{a: {b: string}}, 'a.b'> // string
52
+ */
53
+ type PathValue<T, P extends FieldPath<T>> = PathOf<T, P & string>;
54
+ /**
55
+ * The value type at path `P` of `T`, or `any` when `P` is not a known
56
+ * field path (plain `string` / segment-array calls keep their old behavior).
57
+ */
58
+ type PathValueOf<T, P> = P extends FieldPath<T> ? PathValue<T, Extract<P, FieldPath<T>>> : any;
59
+
60
+ /** Options accepted by {@link setFocus}. All flags default to `false`. */
61
+ type SetFocusOptions = {
62
+ /** Select the field's text after focusing it. Bound fields call
63
+ * `select()` on their element; elements without one (custom `as`
64
+ * components) just focus. */
65
+ shouldSelect?: boolean;
66
+ };
67
+ /**
68
+ * Programmatically focus a bound field's element (e.g. the <Field>'s
69
+ * input).
70
+ *
71
+ * Rides the same 'focusError' event channel a failed handleSubmit uses to
72
+ * focus the first errored field: the payload is the target's path key,
73
+ * with the focus options as a second, backward-compatible argument (older
74
+ * subscribers declared with a single `key` parameter simply ignore it).
75
+ * Being event-driven, it is a silent no-op when the field is unmounted or
76
+ * nothing subscribes — unknown names never throw.
77
+ *
78
+ * @param form form instance
79
+ * @param name field name (dot path or segments path)
80
+ * @param options focus options
81
+ */
82
+ declare function setFocus(form: Form, name: Name, options?: SetFocusOptions): void;
83
+
84
+ /** Reserved top-level path segment for form-level errors. The Standard
85
+ * Schema form-level adapter lands path-less issues under this key; the
86
+ * exported constant replaces the magic string, and readers consume it via
87
+ * getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */
88
+ declare const FORM_ERROR = "_form";
89
+ /** When a field is validated:
90
+ * - `'onSubmit'` (default): only on submit
91
+ * - `'onBlur'`: when the field loses focus
92
+ * - `'onChange'`: on every change
93
+ * - `'onTouched'`: on first blur, then on every change
94
+ * - `'all'`: on both change and blur
95
+ */
96
+ /** Brand marking a form-level validate result as a structured
97
+ * {@link ValidationOutcome} (parsed values and/or errors) rather than a
98
+ * plain nested error record. Symbols cannot collide with user error
99
+ * records, so detection is an exact `VALIDATION_OUTCOME in result`. */
100
+ declare const VALIDATION_OUTCOME: unique symbol;
101
+ /** Structured form-level validate result: `errors` uses the same nested
102
+ * shape a plain error record uses, `values` is the schema's parsed output
103
+ * (coerce/transform results included). Either side may be omitted. */
104
+ /**
105
+ * Get field error
106
+ * @param form
107
+ * @param name
108
+ * @return FieldError object or undefined
109
+ */
110
+ declare function getError<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form<T>, name: P): FieldError | undefined;
111
+ /**
112
+ * Get field error by path
113
+ * @param form
114
+ * @param path
115
+ * @return first FieldError of the field, or undefined
116
+ */
117
+ declare function getErrorByPath({ errors }: Form, path: Path): FieldError | undefined;
118
+ /**
119
+ * Get all errors of a field
120
+ * @param form
121
+ * @param name
122
+ * @return every error registered for the field (insertion order); an empty
123
+ * array when the field has none
124
+ */
125
+ declare function getFieldErrors<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form<T>, name: P): FieldError[];
126
+ /**
127
+ * Get all errors of a field by path
128
+ * @param form
129
+ * @param path
130
+ * @return every error registered for the field (insertion order); an empty
131
+ * array when the field has none
132
+ */
133
+ declare function getFieldErrorsByPath({ errors }: Form, path: Path): FieldError[];
134
+ /**
135
+ * Get all errors
136
+ * @param form
137
+ * @return array of {path, type, message} entries, in insertion order; path
138
+ * is the user-facing dotted field path ('a.b', 'list.0'), and a
139
+ * field holding several errors contributes one entry per error
140
+ */
141
+ declare function getErrors({ errors }: Form): FieldErrorEntry[];
142
+ /**
143
+ * Get first error message
144
+ * @param form
145
+ * @return first error's message string, or undefined when there are no errors
146
+ */
147
+ declare function getFirstError({ errors }: Form): string | undefined;
148
+ /** Snapshot of one field's aggregated state, as {@link getFieldState}
149
+ * returns it. `errors` is the stored array shared with the form — treat it
150
+ * as read-only, like every {@link getFieldErrors} result. */
151
+ /** Options accepted by {@link setError}. */
152
+ type SetErrorOptions = {
153
+ /**
154
+ * Focus the named field's element after the error lands (react-hook-form's
155
+ * `setError` `shouldFocus`). Rides the same 'focusError' channel
156
+ * `setFocus` and a failed submit's auto-focus use: only mounted bound
157
+ * fields react, unmounted ones are silent no-ops.
158
+ */
159
+ shouldFocus?: boolean;
160
+ };
161
+ /**
162
+ * Set field error
163
+ * @param form
164
+ * @param name
165
+ * @param error string is normalized to {type: 'custom', message}; a
166
+ * FieldError object is stored as-is; an array holds several errors
167
+ * (falsy items dropped, strings normalized); undefined clears
168
+ * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field
169
+ * after the error lands
170
+ */
171
+ declare function setError<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form<T>, name: P, error: string | FieldError | (string | FieldError)[] | undefined, options?: SetErrorOptions): void;
172
+ /**
173
+ * Set field error
174
+ * @param form
175
+ * @param path
176
+ * @param error string is normalized to {type: 'custom', message}; a
177
+ * FieldError object is stored as-is; an array holds several errors
178
+ * (falsy items dropped, strings normalized); undefined clears
179
+ * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field
180
+ * after the error lands
181
+ */
182
+ declare function setErrorByPath(form: Form, path: Path, error: string | FieldError | (string | FieldError)[] | undefined, options?: SetErrorOptions): void;
183
+ /**
184
+ * Clear errors
185
+ * @param form
186
+ * @param name a single path or a list of paths; omit to clear every error
187
+ */
188
+ declare function clearErrors(form: Form, name?: Name | Name[]): void;
189
+ /** Options accepted by {@link setServerErrors}. */
190
+ type SetServerErrorsOptions = {
191
+ /** Keep existing field errors instead of clearing them first. Defaults
192
+ * to `false`: a fresh server response replaces the prior error state. */
193
+ keepExisting?: boolean;
194
+ };
195
+ /**
196
+ * Land a server-side error response on the form: each entry becomes the
197
+ * named field's error(s) with `type: 'server'`, ready for the same
198
+ * renderError/`useError` channel client-side validation uses. Takes the
199
+ * flat `Record<string, string | string[]>` shape REST APIs commonly
200
+ * return (RealWorld: `422 {errors: {email: ['has already been taken']}}`)
201
+ * without a hand-rolled `Object.entries` + `setError` loop.
202
+ *
203
+ * A string value lands as one error, a string array as several (first one
204
+ * is what `getError`/`error` expose); an empty array clears that field's
205
+ * errors. By default every existing error is cleared first — a fresh
206
+ * response describes the current state, not a patch onto stale client
207
+ * errors; pass `keepExisting: true` to layer instead.
208
+ * @param form
209
+ * @param errors field errors keyed by name
210
+ * @param options
211
+ */
212
+ declare function setServerErrors(form: Form, errors: Record<string, string | string[]>, options?: SetServerErrorsOptions): void;
213
+ /**
214
+ * Set field touched state
215
+ * @param form
216
+ * @param name
217
+ */
218
+ /**
219
+ * @param form
220
+ */
221
+ declare function hasErrors({ errors }: Form): boolean;
222
+
223
+ /** A field error: `type` identifies the error kind ('custom' for plain
224
+ * string errors), `message` is the display text. */
225
+ type FieldError = {
226
+ type: string;
227
+ message: string;
228
+ };
229
+ /** A flattened entry from {@link getErrors}. */
230
+ type FieldErrorEntry = {
231
+ path: string;
232
+ type: string;
233
+ message: string;
234
+ };
235
+ /** When a field is validated:
236
+ * - `'onSubmit'` (default): only on submit
237
+ * - `'onBlur'`: when the field loses focus
238
+ * - `'onChange'`: on every change
239
+ * - `'onTouched'`: on first blur, then on every change
240
+ * - `'all'`: on both change and blur
241
+ */
242
+ type ValidationMode = 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';
243
+ /** When a field is re-validated after it already has an error:
244
+ * - `'onChange'` (default): on every change
245
+ * - `'onBlur'`: when the field loses focus
246
+ * - `'onSubmit'`: only on submit (no live re-validation)
247
+ */
248
+ type ReValidateMode = 'onChange' | 'onBlur' | 'onSubmit';
249
+ /** Structured form-level validate result: `errors` uses the same nested
250
+ * shape a plain error record uses, `values` is the schema's parsed output
251
+ * (coerce/transform results included). Either side may be omitted.
252
+ *
253
+ * The brand constant itself lives in the errors module (the leaf module of
254
+ * the core dependency graph — every consumer imports it from there) and is
255
+ * re-exported below with `export *`. */
256
+ type ValidationOutcome<T> = {
257
+ [VALIDATION_OUTCOME]: true;
258
+ errors?: Record<string, any>;
259
+ values?: T;
260
+ };
261
+ /** What a form-level validate function may return: a plain nested error
262
+ * record (flattened into field errors — the long-standing shape), or a
263
+ * branded {@link ValidationOutcome} whose `values` become the form's
264
+ * parsedValues baseline. */
265
+ type ValidateResult<T> = Record<string, any> | ValidationOutcome<T> | Promise<Record<string, any> | ValidationOutcome<T>>;
266
+ /** Context passed to a form-level `validate` function's second argument.
267
+ * `signal` aborts as soon as the round is superseded — a newer round
268
+ * started (which only happens under a positive `validateDebounce`, where
269
+ * kicks merge into windows) — so async validators can cancel their
270
+ * underlying work instead of racing a stale result home. Stale results
271
+ * are dropped independently by the round gate, so validators that ignore
272
+ * the signal stay correct too; the same contract field-level validators
273
+ * get through their own `meta`. */
274
+ type FormValidateMeta<T extends Record<string, any> = any> = {
275
+ form: Form<T>;
276
+ signal: AbortSignal;
277
+ };
278
+ /** Form-level validator: receives all values (plus {@link
279
+ * FormValidateMeta} as an optional second argument) and returns a
280
+ * {@link ValidateResult} — sync or async — or `undefined`/nothing when
281
+ * valid (the runtime skips falsy results, so implicit-return callbacks
282
+ * type-check). */
283
+ type FormValidateFn<T extends Record<string, any> = any> = (values: T, meta: FormValidateMeta<T>) => ValidateResult<T> | undefined;
284
+ /**
285
+ * The emitter event table for {@link Form.emitter}: each event's payload
286
+ * tuple. Path-carrying events declare an optional single `Path` payload —
287
+ * emit sites send it for single-field mutations and omit it for bulk
288
+ * payload-less broadcasts (reset, setInitialValues, clear-all), both of
289
+ * which subscribers handle. `focusError` carries the target's path key
290
+ * plus optional {@link SetFocusOptions}.
291
+ */
292
+ type FormEvents = ['change', [path?: Path]] | ['errors', [path?: Path]] | ['touched', [path?: Path]] | ['validating', [path?: Path]] | ['submitting', []] | ['submitCount', []] | ['submitSuccessful', []] | ['reset', []] | ['disabled', []] | ['status', []] | ['loading', []] | ['focusError', [key: string, options?: SetFocusOptions]];
293
+ type Form<T extends Record<string, any> = any> = {
294
+ emitter: EventEmitter<FormEvents>;
295
+ mode: ValidationMode;
296
+ reValidateMode: ReValidateMode;
297
+ initialValues: T;
298
+ values: Map<string, any>;
299
+ /** Tombstones of unregistered field paths (JSON path keys): reading or
300
+ * merging values must not fall back to initialValues for these paths. */
301
+ deleted: Set<string>;
302
+ /** Every error registered for a field, as a non-empty array (the
303
+ * write-side {@link setErrorByPath} normalizes to this invariant, so
304
+ * readers never need to guard against an empty list). Readers wanting
305
+ * the display error take the first entry ({@link getError}); readers
306
+ * wanting all of them use {@link getFieldErrors}. */
307
+ errors: Map<string, FieldError[]>;
308
+ touched: Set<string>;
309
+ /** Per-field validation kicks, registered by {@link
310
+ * registerValidatorByPath} (`useValidate` is the React-side
311
+ * registration): each is the field's debounce/lock-aware kick —
312
+ * invoking it validates the field's current value. `trigger` /
313
+ * `ensureValidate` run every entry; the user-change gate ({@link
314
+ * userChangeByPath}) runs the entry at the changed path. */
315
+ validators: Map<string, () => void>;
316
+ validating: Set<string>;
317
+ /** Parsed values from the last successful schema validation: the
318
+ * schema's complete output tree (coerced/transformed values included).
319
+ * Sits between initialValues and the values Map in {@link getValues}
320
+ * until `reset`/`setInitialValues` clears it. Never affects dirty
321
+ * state — that compares live edits against initialValues only. */
322
+ parsedValues: T | undefined;
323
+ /** Form-level validator, seeded from {@link Options.validate}. May
324
+ * receive a second {@link FormValidateMeta} argument. */
325
+ validate?: FormValidateFn<T>;
326
+ /** Delay in milliseconds before the form-level `validate` runs; seeded
327
+ * from {@link Options.validateDebounce} and fixed at create time. */
328
+ validateDebounce?: number;
329
+ /** Path keys (JSON-stringified segments) of the fields whose user
330
+ * changes re-run the form-level `validate`; normalized from {@link
331
+ * Options.validateDeps} at create time and fixed thereafter. */
332
+ validateDeps?: ReadonlySet<string>;
333
+ isSubmitting: boolean;
334
+ /** Whether a submit has been attempted — set by `handleSubmit` on every
335
+ * attempt (validation outcome aside), cleared by `reset`.
336
+ * `useFormState().isSubmitted` reads it (react-hook-form's
337
+ * `formState.isSubmitted` semantics). */
338
+ isSubmitted: boolean;
339
+ submitCount: number;
340
+ isSubmitSuccessful: boolean | undefined;
341
+ /** True while an async {@link Options.initialValues} source (a Promise,
342
+ * or a thunk returning one) is still pending — the form starts empty
343
+ * and the resolved values become the baseline via setInitialValues when
344
+ * it lands. Flips through the payload-less 'loading' event
345
+ * (`useIsLoading` / `useFormState().isLoading`). */
346
+ isLoading: boolean;
347
+ /** Form-level default for a bound field's unmount behavior, seeded from
348
+ * {@link Options.shouldUnregister}: `true` (the default) tombstones an
349
+ * unmounted field, `false` keeps its value (react-hook-form's
350
+ * `shouldUnregister` semantics). A field's own `shouldUnregister` option
351
+ * overrides this. */
352
+ shouldUnregister?: boolean;
353
+ /** Form-level disabled flag, OR-ed into every bound field's `disabled`
354
+ * (form flag || the field's own option). Seeded from
355
+ * {@link Options}.disabled at create time and toggled at runtime with
356
+ * {@link setDisabled}, which emits a payload-less 'disabled' event so
357
+ * subscribed fields re-render. */
358
+ disabled: boolean;
359
+ /** Form-level default for mount validation, seeded from
360
+ * {@link Options.validateOnMount}: `true` makes every mounted field
361
+ * with a validator kick once after mount (deferred until an async
362
+ * {@link Options.initialValues} source lands), and makes `useForm` run
363
+ * the form-level `validate` once. A field's own `validateOnMount`
364
+ * option overrides this flag in either direction. */
365
+ validateOnMount: boolean;
366
+ /** Form-level default for {@link UseValidateOptions.asyncAlways}:
367
+ * whether a field's debounced validator still runs when its `required`
368
+ * gate failed. A field's own `asyncAlways` option overrides this flag
369
+ * in either direction. Seeded from {@link Options.asyncAlways}. */
370
+ asyncAlways: boolean;
371
+ /**
372
+ * User-owned metadata slot for non-field state — session flags, server
373
+ * backfill that belongs to no field, step indices (Formik's `status`
374
+ * role). Written with {@link setStatus}, which emits the payload-less
375
+ * 'status' event; read directly or reactively through {@link useStatus}.
376
+ * Starts `undefined`.
377
+ */
378
+ status: any;
379
+ };
380
+ type Options<T extends Record<string, any> = any> = {
381
+ /**
382
+ * The values baseline. Sync objects seed immediately (SSR renders
383
+ * them). Async sources — a Promise, or a thunk returning a value or
384
+ * Promise (react-hook-form's async `defaultValues` shape) — start the
385
+ * form empty with `isLoading: true` and land the resolved values as
386
+ * the baseline via setInitialValues once they resolve: value
387
+ * subscribers re-sync, dirty/touched state starts clean, and a later
388
+ * `reset()` returns to the resolved baseline. A rejected source flips
389
+ * isLoading back to false, keeps the form empty, and logs the error in
390
+ * DEV — attach a `.catch` on the source itself to handle it. The thunk
391
+ * runs at create time: keep its identity stable (module scope or
392
+ * useMemo) when passing it inline, and note StrictMode double-invokes
393
+ * it in development, like every render-phase call.
394
+ */
395
+ initialValues?: T | Promise<T> | (() => T | Promise<T>);
396
+ /** When fields are validated. Defaults to `'onSubmit'`. See
397
+ * {@link ValidationMode}. */
398
+ mode?: ValidationMode;
399
+ /** When a field is re-validated after it already has an error — it only
400
+ * takes effect once the field has an error. Defaults to `'onChange'`. See
401
+ * {@link ReValidateMode}. */
402
+ reValidateMode?: ReValidateMode;
403
+ /**
404
+ * Form-level validator. Returns a record of errors keyed by field path;
405
+ * nested objects are flattened ('a.b' style) and array values contribute
406
+ * every non-empty string they hold as separate errors (zod `flatten()`
407
+ * formErrors style). Schema adapters instead return a branded
408
+ * {@link ValidationOutcome}: `errors` flattens the same way, `values`
409
+ * (the schema's parsed output) becomes the form's parsedValues baseline
410
+ * that {@link getValues} layers over initialValues.
411
+ */
412
+ validate?: FormValidateFn<T>;
413
+ /**
414
+ * Milliseconds to debounce the form-level `validate`: kicks from
415
+ * `trigger`/`ensureValidate`/submit inside the window merge into one
416
+ * run, and while the timer is pending the form counts as validating,
417
+ * so `trigger` and submit wait the window out — the same contract the
418
+ * per-field `validateDebounce` gives field validators. The merged run
419
+ * reads the values current when its timer fires. Defaults to `0`
420
+ * (validate runs immediately, exactly as before this option existed).
421
+ */
422
+ validateDebounce?: number;
423
+ /** Fields whose user changes re-run the form-level `validate` — the
424
+ * cross-field dependency list (password-confirm mismatch and friends).
425
+ * Each entry is a field path ('password', 'user.email', 'items.0.qty');
426
+ * a user change to a listed field re-runs the form-level `validate`
427
+ * under the same mode/`reValidateMode` gating the field's own
428
+ * validator gets. Omit it and the form-level `validate` only runs on
429
+ * `trigger`/submit, exactly as before this option existed.
430
+ *
431
+ * Opting in also changes what a re-run may clear: each round first
432
+ * drops the errors the previous round wrote (paths it flattened onto),
433
+ * so a dep change that fixes the cross-field error makes it disappear.
434
+ * Errors the round never wrote — field validators', `setServerErrors`,
435
+ * manual `setError` — are never touched. TanStack Form's counterpart is
436
+ * `onChangeListenTo` (v1) / validator `triggers` (v2 alpha). */
437
+ validateDeps?: FieldPath<T>[];
438
+ /**
439
+ * Form-level default for a bound field's unmount behavior. `true` (the
440
+ * default) tombstones an unmounted field — it drops out of
441
+ * `getValues()` instead of reviving its initial value (this library's
442
+ * historical default); `false` keeps the value, matching
443
+ * react-hook-form's `shouldUnregister`. A field's own
444
+ * `useField({shouldUnregister})` option overrides the form-level flag
445
+ * in either direction.
446
+ */
447
+ shouldUnregister?: boolean;
448
+ /** Start the form with every bound field disabled — the flag bound
449
+ * fields OR with their own `disabled` option (a field cannot opt out
450
+ * of a disabled form). Toggle later with {@link setDisabled}.
451
+ * Defaults to `false`. */
452
+ disabled?: boolean;
453
+ /**
454
+ * Form-level default for field validation's `asyncAlways`: when true,
455
+ * a field whose `required` gate failed still runs its debounced
456
+ * validator (the gate's errors land immediately, the validator's own
457
+ * result lands alongside them per-source). TanStack Form's
458
+ * `asyncAlways` counterpart. A field's own
459
+ * `useField({asyncAlways})` option overrides the form-level flag in
460
+ * either direction. Defaults to `false`.
461
+ */
462
+ asyncAlways?: boolean;
463
+ /**
464
+ * Validate on mount: `true` makes every mounted field with a validator
465
+ * (declarative `rules` or a `validate` callback) run it once after
466
+ * mount, instead of waiting for the first submit/change — errors show
467
+ * immediately for an untouched form (Formik's `validateOnMount` /
468
+ * TanStack Form's per-field `validateOnMount`). The form-level
469
+ * `validate` also runs once after mount. Mount kicks are deferred
470
+ * while an async `initialValues` source is still pending: validating
471
+ * the empty shell would land spurious required errors, so the kicks
472
+ * fire after the resolved baseline lands instead. A field's own
473
+ * `useField({validateOnMount})` option overrides the form-level flag
474
+ * in either direction. Defaults to `false`.
475
+ */
476
+ validateOnMount?: boolean;
477
+ };
478
+ /**
479
+ * Create form instance
480
+ * @param options
481
+ * @return form instance
482
+ */
483
+ declare function create<T extends Record<string, any> = any>(options?: Options<T>): Form<T>;
484
+
485
+ export { setFocus as A, setServerErrors as B, FORM_ERROR as g, VALIDATION_OUTCOME as m, clearErrors as p, create as q, getError as r, getErrorByPath as s, getErrors as t, getFieldErrors as u, getFieldErrorsByPath as v, getFirstError as w, hasErrors as x, setError as y, setErrorByPath as z };
486
+ export type { Form as F, Name as N, Options as O, Path as P, ReValidateMode as R, SetErrorOptions as S, ValidationMode as V, FieldError as a, FieldPath as b, PathSegments as c, PathValueOf as d, FieldErrorEntry as e, FormEvents as f, FormValidateFn as h, FormValidateMeta as i, PathValue as j, SetFocusOptions as k, SetServerErrorsOptions as l, ValidateResult as n, ValidationOutcome as o };