react-f0rm 1.4.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.
- package/README.md +17 -4
- package/dist/array-Bu7W8BSz.d.ts +54 -0
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.d.cts +8 -18
- package/dist/devtools/index.d.mts +8 -18
- package/dist/devtools/index.d.ts +8 -18
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/errors-DA4ReEd9.mjs +2 -0
- package/dist/errors-DA4ReEd9.mjs.map +1 -0
- package/dist/errors-TzyWwBfw.cjs.js +2 -0
- package/dist/errors-TzyWwBfw.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.cts +347 -927
- package/dist/index.d.mts +347 -927
- package/dist/index.d.ts +347 -927
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +538 -451
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/persist.cjs.js +1 -1
- package/dist/persist.cjs.js.map +1 -1
- package/dist/persist.d.cts +9 -30
- package/dist/persist.d.mts +9 -30
- package/dist/persist.d.ts +9 -30
- package/dist/persist.mjs +1 -1
- package/dist/persist.mjs.map +1 -1
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.d.cts +1 -1
- package/dist/resolvers/standard-schema.d.mts +1 -1
- package/dist/resolvers/standard-schema.d.ts +1 -1
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.cts +30 -2
- package/dist/resolvers/zod.d.mts +30 -2
- package/dist/resolvers/zod.d.ts +30 -2
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/resolvers/zod.mjs.map +1 -1
- package/dist/server/index.cjs.js +1 -1
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.d.cts +24 -92
- package/dist/server/index.d.mts +24 -92
- package/dist/server/index.d.ts +24 -92
- package/dist/server/index.mjs +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/standard-schema-BAaTmAHh.d.ts +682 -0
- package/dist/standardSchema-5WezjHlp.mjs +2 -0
- package/dist/standardSchema-5WezjHlp.mjs.map +1 -0
- package/dist/standardSchema-DINHlsYR.cjs.js +2 -0
- package/dist/standardSchema-DINHlsYR.cjs.js.map +1 -0
- package/dist/validate-2pX-N1O6.cjs.js +2 -0
- package/dist/validate-2pX-N1O6.cjs.js.map +1 -0
- package/dist/validate-C0HOsP9v.mjs +2 -0
- package/dist/validate-C0HOsP9v.mjs.map +1 -0
- package/dist/values-BbPnLByD.cjs.js +2 -0
- package/dist/values-BbPnLByD.cjs.js.map +1 -0
- package/dist/values-CHsmcZk4.mjs +2 -0
- package/dist/values-CHsmcZk4.mjs.map +1 -0
- package/package.json +6 -4
- package/dist/array-3hAjl6Bz.d.ts +0 -160
- package/dist/errors-8oPux7GR.cjs.js +0 -2
- package/dist/errors-8oPux7GR.cjs.js.map +0 -1
- package/dist/errors-ClH3eV1R.mjs +0 -2
- package/dist/errors-ClH3eV1R.mjs.map +0 -1
- package/dist/standard-schema-CYbnugL7.d.ts +0 -1184
- package/dist/standardSchema-BpZvg0tZ.mjs +0 -2
- package/dist/standardSchema-BpZvg0tZ.mjs.map +0 -1
- package/dist/standardSchema-CxV_DhBO.cjs.js +0 -2
- package/dist/standardSchema-CxV_DhBO.cjs.js.map +0 -1
- package/dist/validate-BEjNsNvd.mjs +0 -2
- package/dist/validate-BEjNsNvd.mjs.map +0 -1
- package/dist/validate-BvN6hiEG.cjs.js +0 -2
- package/dist/validate-BvN6hiEG.cjs.js.map +0 -1
- package/dist/values-Bod74Kzu.mjs +0 -2
- package/dist/values-Bod74Kzu.mjs.map +0 -1
- package/dist/values-DKpOCD5J.cjs.js +0 -2
- package/dist/values-DKpOCD5J.cjs.js.map +0 -1
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
import { EventEmitter } from '@for-fun/event-emitter';
|
|
2
|
+
|
|
3
|
+
/** A single Standard Schema issue. */
|
|
4
|
+
type StandardSchemaIssue = {
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly path?: ReadonlyArray<PropertyKey | {
|
|
7
|
+
readonly key: PropertyKey;
|
|
8
|
+
}> | undefined;
|
|
9
|
+
};
|
|
10
|
+
/** The union Standard Schema's `validate` resolves to. */
|
|
11
|
+
type StandardSchemaResult<Output = unknown> = {
|
|
12
|
+
readonly value: Output;
|
|
13
|
+
readonly issues?: undefined;
|
|
14
|
+
} | {
|
|
15
|
+
readonly issues: ReadonlyArray<StandardSchemaIssue>;
|
|
16
|
+
};
|
|
17
|
+
/** Structural Standard Schema v1. `types` (optional in the spec) is what
|
|
18
|
+
* {@link InferSchemaValues} and `createForm`'s inference read. */
|
|
19
|
+
type StandardSchemaV1<Input = unknown, Output = Input> = {
|
|
20
|
+
readonly '~standard': {
|
|
21
|
+
readonly version: 1;
|
|
22
|
+
readonly vendor: string;
|
|
23
|
+
readonly validate: (value: Input) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;
|
|
24
|
+
readonly types?: {
|
|
25
|
+
readonly input: Input;
|
|
26
|
+
readonly output: Output;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/** The values type a Standard Schema produces: the `Output` of its
|
|
31
|
+
* `~standard.types` (coercions/transforms included). `never` when the
|
|
32
|
+
* schema lacks `types` — pass an explicit `TValues`. */
|
|
33
|
+
type InferSchemaValues<S> = S extends {
|
|
34
|
+
readonly '~standard': {
|
|
35
|
+
readonly types: {
|
|
36
|
+
readonly output: infer Out;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
} ? Out : never;
|
|
40
|
+
/** Implements Standard Schema v1 props? A boolean predicate, not a type
|
|
41
|
+
* guard — narrowing the union through a guard fails either way, so call
|
|
42
|
+
* sites cast after the check. */
|
|
43
|
+
declare function hasStandardProps(schema: any): boolean;
|
|
44
|
+
/** Field-level adapter: validate one value with a schema and map every
|
|
45
|
+
* issue to a FieldError (all issues surface; readers see the first). The
|
|
46
|
+
* parsed output is validation-only — field validators never rewrite. */
|
|
47
|
+
declare function schemaToFieldValidator(schema: StandardSchemaV1<any, any>): Validator;
|
|
48
|
+
/** Form-level adapter: validate the whole values object and return a
|
|
49
|
+
* ValidationOutcome. Failure nests errors ({a: {b: FieldError[]}});
|
|
50
|
+
* pathless issues land on FORM_ERROR. Success exposes the schema's parsed
|
|
51
|
+
* output as the parsedValues baseline. `createForm({validate: schema})`
|
|
52
|
+
* wraps through this automatically. */
|
|
53
|
+
declare function schemaToFormValidator<T extends Record<string, any>>(schema: StandardSchemaV1<any, T>): (values: T) => Promise<ValidationOutcome<T>>;
|
|
54
|
+
|
|
55
|
+
type PathSegments = (string | number)[];
|
|
56
|
+
type Name = string | PathSegments;
|
|
57
|
+
type Path = {
|
|
58
|
+
value: PathSegments;
|
|
59
|
+
key: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** Compile-time field path utilities: `FieldPath<T>` enumerates valid
|
|
63
|
+
* path strings, `PathValue<T, P>` resolves the leaf type. Grammar mirrors
|
|
64
|
+
* `normalizePath`: numeric segments are bracket-only ('a[0]', never
|
|
65
|
+
* 'a.0' — dotted numerics throw at runtime). */
|
|
66
|
+
|
|
67
|
+
/** `true` only for the `any` type (`0 extends 1 & any`). */
|
|
68
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
69
|
+
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
|
|
70
|
+
/** Opt-in registry of value types the path types treat as opaque leaves:
|
|
71
|
+
* `FieldPath<T>` stops descending into them, `PathValue` resolves the
|
|
72
|
+
* field itself to that type. Merge via declaration merging
|
|
73
|
+
* (`interface OpaqueTypes { date: Date }`). Empty by default, so every
|
|
74
|
+
* object leaf stays navigable. */
|
|
75
|
+
interface OpaqueTypes {
|
|
76
|
+
}
|
|
77
|
+
/** Union of every registered leaf type — `never` until an app merges entries. */
|
|
78
|
+
type OpaqueLeaf = OpaqueTypes[keyof OpaqueTypes];
|
|
79
|
+
/** Depth countdown: Prev[9] = 8 ... Prev[1] = 0, Prev[0] = never stops recursion. */
|
|
80
|
+
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
81
|
+
/** Paths are capped at 10 segments to keep instantiation depth bounded. */
|
|
82
|
+
type MaxDepth = 9;
|
|
83
|
+
/** Valid path continuations after a segment: `.k` / `[k]` / `[0]`, then
|
|
84
|
+
* deeper continuations. Numeric segments are bracket-only; numeric-string
|
|
85
|
+
* keys likewise enumerate just the bracket subscript. */
|
|
86
|
+
type Continue<T, D extends number> = [D] extends [never] ? never : IsAny<T> extends true ? string : T extends OpaqueLeaf | Primitive | Function ? never : T extends readonly (infer U)[] ? `[${number}]` | `[${number}]${Continue<U, Prev[D]>}` : {
|
|
87
|
+
[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]>}`;
|
|
88
|
+
}[Extract<keyof T, string>];
|
|
89
|
+
/** Every valid field path string for a values shape `T`. Capped at 10
|
|
90
|
+
* segments ({@link MaxDepth}); beyond the cap call sites fall back to
|
|
91
|
+
* `any`. {@link OpaqueTypes} entries stop recursion entirely.
|
|
92
|
+
* @example FieldPath<{a: {b: string}}> // 'a' | 'a.b' | 'a[b]' */
|
|
93
|
+
type FieldPath<T> = IsAny<T> extends true ? string : T extends OpaqueLeaf | Primitive | Function ? never : T extends readonly (infer U)[] ? `[${number}]` | `[${number}]${Continue<U, MaxDepth>}` : {
|
|
94
|
+
[K in Extract<keyof T, string>]: K extends `${number}` ? never : K | `${K}${Continue<T[K], MaxDepth>}`;
|
|
95
|
+
}[Extract<keyof T, string>];
|
|
96
|
+
/** Field address as the hooks and components accept it: a typed path
|
|
97
|
+
* string or a raw segments array ({@link PathSegments}). */
|
|
98
|
+
type AnyPath<T> = FieldPath<T> | PathSegments;
|
|
99
|
+
/** Resolve `T[K]` for one bare segment: array index -> element, object key -> value. */
|
|
100
|
+
type Lookup<T, K extends string> = K extends `${number}` ? T extends readonly (infer U)[] ? U : never : K extends keyof T ? T[K] : never;
|
|
101
|
+
/** One dot-separated chunk: a bare segment plus any `[k]` / `[0]` suffixes. */
|
|
102
|
+
type ChunkValue<T, C extends string> = C extends `${infer Key}[${infer Tail}` ? ChunkSuffix<Lookup<T, Key>, `[${Tail}`> : Lookup<T, C>;
|
|
103
|
+
type ChunkSuffix<T, S extends string> = S extends `[${infer Key}]${infer Rest}` ? Rest extends '' ? Lookup<T, Key> : PathOf<Lookup<T, Key>, Rest> : never;
|
|
104
|
+
/** Resolve the value type the path string `P` points at inside `T`. */
|
|
105
|
+
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>;
|
|
106
|
+
/** The value type at path `P` of a values shape `T`.
|
|
107
|
+
* @example PathValue<{a: {b: string}}, 'a.b'> // string */
|
|
108
|
+
type PathValue<T, P extends FieldPath<T>> = PathOf<T, P & string>;
|
|
109
|
+
type ResolvedPathValue<T, P> = PathValue<T, Extract<P, FieldPath<T>>>;
|
|
110
|
+
/** The value type at `P`, or `any` when `P` is not a known field path
|
|
111
|
+
* (plain `string` / segment-array calls keep their old behavior). */
|
|
112
|
+
type PathValueOf<T, P> = P extends FieldPath<T> ? ResolvedPathValue<T, P> : any;
|
|
113
|
+
/** Element type of the array a path points at; non-array leaves resolve
|
|
114
|
+
* to themselves, unknown paths fall back to `any`. */
|
|
115
|
+
type ArrayItemOf<T, P> = P extends FieldPath<T> ? ResolvedPathValue<T, P> extends readonly (infer U)[] ? U : ResolvedPathValue<T, P> : any;
|
|
116
|
+
|
|
117
|
+
/** Type tag of a failed rule, as stored on the resulting FieldError. */
|
|
118
|
+
type RuleType = 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern';
|
|
119
|
+
/** Form-level default rule messages — the `createForm({messages})` table
|
|
120
|
+
* overriding the built-in English defaults for every field (i18n in one
|
|
121
|
+
* place). A string may carry a `{bound}` placeholder (replaced with the
|
|
122
|
+
* rule's bound); a function receives the bound. A field's own message
|
|
123
|
+
* (the `required` string, `rules.messages`, `pattern.message`) still
|
|
124
|
+
* wins. */
|
|
125
|
+
type FormMessages = Partial<Record<RuleType, string | ((bound?: number) => string)>>;
|
|
126
|
+
/** Declarative field rules — a subset of react-hook-form's `register`
|
|
127
|
+
* rules. Failures land in the error state as FieldErrors (`type` = rule
|
|
128
|
+
* name), so any design system can render them. */
|
|
129
|
+
type FieldRules = {
|
|
130
|
+
/** Fails on `''`, `undefined`, `null` or an empty array (`0`/`false`
|
|
131
|
+
* count as filled). A string is the message, `true` the default; failing
|
|
132
|
+
* skips the remaining rules. */
|
|
133
|
+
required?: string | true;
|
|
134
|
+
/** Fails when `Number(value)` is below this bound; `NaN` values skip. */
|
|
135
|
+
min?: number;
|
|
136
|
+
/** Fails when `Number(value)` is above this bound; `NaN` values skip. */
|
|
137
|
+
max?: number;
|
|
138
|
+
/** Fails when a string/array is shorter than this; other values skip. */
|
|
139
|
+
minLength?: number;
|
|
140
|
+
/** Fails when a string/array is longer than this; other values skip. */
|
|
141
|
+
maxLength?: number;
|
|
142
|
+
/** Fails when the value does not match `pattern.value`. */
|
|
143
|
+
pattern?: {
|
|
144
|
+
value: RegExp;
|
|
145
|
+
message: string;
|
|
146
|
+
};
|
|
147
|
+
/** Custom rule callbacks (one function or a named record), run after the
|
|
148
|
+
* declarative checks pass. A returned error keeps its message; `type`
|
|
149
|
+
* becomes the record key (`'validate'` for the single-function form).
|
|
150
|
+
* Sync-only. */
|
|
151
|
+
validate?: SyncValidator | Record<string, SyncValidator>;
|
|
152
|
+
/** Per-rule-type message override (defaults and pattern's inline message). */
|
|
153
|
+
messages?: Partial<Record<Exclude<RuleType, 'required'>, string>>;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** Options accepted by {@link setFocus}. All flags default to `false`. */
|
|
157
|
+
type SetFocusOptions = {
|
|
158
|
+
/** Select the field's text after focusing it. */
|
|
159
|
+
shouldSelect?: boolean;
|
|
160
|
+
};
|
|
161
|
+
/** Programmatically focus a bound field's element. Rides the same
|
|
162
|
+
* 'focusError' event channel a failed handleSubmit uses; being
|
|
163
|
+
* event-driven, it is a silent no-op when the field is unmounted or
|
|
164
|
+
* nothing subscribes. */
|
|
165
|
+
declare function setFocus(form: Form, name: Name, options?: SetFocusOptions): void;
|
|
166
|
+
|
|
167
|
+
/** An error value as validators yield it and the error setters
|
|
168
|
+
* accept it: one error, or a mixed list of them. */
|
|
169
|
+
type ValidatorOutput = string | FieldError | (string | FieldError)[];
|
|
170
|
+
/** Reserved top-level path segment for form-level errors: the Standard
|
|
171
|
+
* Schema adapter lands path-less issues under this key, read via
|
|
172
|
+
* getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */
|
|
173
|
+
declare const FORM_ERROR = "_form";
|
|
174
|
+
/** Brand marking a form-level validate result as a structured
|
|
175
|
+
* {@link ValidationOutcome} rather than a plain nested error record.
|
|
176
|
+
* Symbols can't collide with user records, so detection is
|
|
177
|
+
* `VALIDATION_OUTCOME in result`. */
|
|
178
|
+
declare const VALIDATION_OUTCOME: unique symbol;
|
|
179
|
+
/** Get a field's first error, or undefined. */
|
|
180
|
+
declare function getError<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P): FieldError | undefined;
|
|
181
|
+
/** Get a field's first error by path, or undefined. */
|
|
182
|
+
declare function getErrorByPath({ errors }: Form, path: Path): FieldError | undefined;
|
|
183
|
+
/** Get all errors of a field (insertion order; empty array when none). */
|
|
184
|
+
declare function getFieldErrors<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P): FieldError[];
|
|
185
|
+
/** Get all errors of a field by path (insertion order; empty when none). */
|
|
186
|
+
declare function getFieldErrorsByPath({ errors }: Form, path: Path): FieldError[];
|
|
187
|
+
/** Get all errors as {path, type, message} entries in insertion order;
|
|
188
|
+
* `path` is the dotted field path ('a.b', 'list.0'), one entry per error. */
|
|
189
|
+
declare function getErrors({ errors }: Form): FieldErrorEntry[];
|
|
190
|
+
/** A {@link FieldPath} string converted to the dotted key error records use
|
|
191
|
+
* at runtime ('items[0].name' → 'items.0.name'); quoted segments drop
|
|
192
|
+
* their quotes. Public so consumers can name the key style in their types. */
|
|
193
|
+
type DottedPath<P extends string> = P extends `${infer H}[${infer N}]${infer R}` ? `${H extends '' ? '' : `${H}.`}${N extends `"${infer K}"` | `'${infer K}'` ? K : N}${DottedPath<R>}` : P;
|
|
194
|
+
/** Every error as one record keyed by dotted path — react-hook-form's
|
|
195
|
+
* `FieldErrors<T>` shape — plus the {@link FORM_ERROR} slot. Values are
|
|
196
|
+
* the stored FieldError[] arrays shared with the form (read-only). */
|
|
197
|
+
type FieldErrors<T extends Record<string, any> = any> = Partial<Record<DottedPath<Extract<FieldPath<T>, string>>, FieldError[]>> & {
|
|
198
|
+
[FORM_ERROR]?: FieldError[];
|
|
199
|
+
};
|
|
200
|
+
/** `true` only for the `any` type (the same probe {@link FieldPath}
|
|
201
|
+
* uses), so the tree of an untyped form degrades to `any` instead of an
|
|
202
|
+
* infinite mapped-type expansion. */
|
|
203
|
+
type IsAnyTree<T> = 0 extends 1 & T ? true : false;
|
|
204
|
+
type TreePrimitive = null | undefined | string | number | boolean | symbol | bigint;
|
|
205
|
+
/** One level of the nested error tree: arrays become arrays of the item's
|
|
206
|
+
* tree, objects recurse per key, everything else is a leaf holding the
|
|
207
|
+
* stored FieldError[] (shared with the form — read-only). */
|
|
208
|
+
type FieldErrorsTreeNode<T> = IsAnyTree<T> extends true ? any : T extends OpaqueTypes[keyof OpaqueTypes] ? FieldError[] : T extends TreePrimitive | Function | Date | File | FileList | Map<any, any> | Set<any> ? FieldError[] : T extends ReadonlyArray<infer E> ? FieldErrorsTreeNode<E>[] : {
|
|
209
|
+
[K in keyof T]?: FieldErrorsTreeNode<T[K]>;
|
|
210
|
+
};
|
|
211
|
+
/** Every error as one nested object following the values tree — the typed
|
|
212
|
+
* optional-chain counterpart of {@link FieldErrors}' flat dotted keys.
|
|
213
|
+
* Leaves hold the stored FieldError[] arrays (read-only); {@link
|
|
214
|
+
* FORM_ERROR} sits at the top level. A row-level error at `items[0]` and a
|
|
215
|
+
* field error at `items[0].name` cannot both occupy the `items[0]` slot:
|
|
216
|
+
* whichever landed later owns it (insertion order). The flat record never
|
|
217
|
+
* conflicts — read it when both coexist. */
|
|
218
|
+
type FieldErrorsTree<T = any> = FieldErrorsTreeNode<T> & {
|
|
219
|
+
[FORM_ERROR]?: FieldError[];
|
|
220
|
+
};
|
|
221
|
+
/** Get every error as one record keyed by dotted path ('a.b', 'list.0') —
|
|
222
|
+
* react-hook-form's `formState.errors` shape. Values are the stored
|
|
223
|
+
* FieldError[] arrays (read-only). Memoized per form with the same
|
|
224
|
+
* version-bump/read pattern {@link getValues} uses, so consecutive reads
|
|
225
|
+
* hand back one stable reference until an error actually changes. */
|
|
226
|
+
declare function getErrorsRecord<T extends Record<string, any> = any>(form: Form<T>): FieldErrors<T>;
|
|
227
|
+
/** Get every error as one nested object following the values tree
|
|
228
|
+
* (`errors.items[0].name`), the optional-chaining counterpart of
|
|
229
|
+
* {@link getErrorsRecord}. Leaves hold the stored FieldError[] arrays
|
|
230
|
+
* (read-only); memoized via the same version-bump/read pattern. */
|
|
231
|
+
declare function getErrorsTree<T extends Record<string, any> = any>(form: Form<T>): FieldErrorsTree<T>;
|
|
232
|
+
/** Convert a field path (bracket spelling, the `name` every API takes)
|
|
233
|
+
* into the dotted key error records use: `'items[0].name'` →
|
|
234
|
+
* `'items.0.name'`. */
|
|
235
|
+
declare function fieldPathToDottedKey(name: Name): string;
|
|
236
|
+
/** Convert a dotted errors-record key back into bracket path spelling
|
|
237
|
+
* (`'items.0.name'` → `'items[0].name'`). Inherently lossy: the dotted key
|
|
238
|
+
* cannot distinguish a segment containing a literal dot, so for such paths
|
|
239
|
+
* keep the bracket spelling and read the record via
|
|
240
|
+
* {@link fieldPathToDottedKey}. */
|
|
241
|
+
declare function dottedKeyToFieldPath(key: string): string;
|
|
242
|
+
/** Get the first error's message, or undefined when there are no errors. */
|
|
243
|
+
declare function getFirstError({ errors }: Form): string | undefined;
|
|
244
|
+
/** Options accepted by {@link setError}. */
|
|
245
|
+
type SetErrorOptions = {
|
|
246
|
+
/** Focus the field's element after the error lands (react-hook-form's
|
|
247
|
+
* `setError` `shouldFocus`); unmounted fields are silent no-ops. */
|
|
248
|
+
shouldFocus?: boolean;
|
|
249
|
+
};
|
|
250
|
+
/** Set a field's error. A string is normalized to {type: 'custom',
|
|
251
|
+
* message}; a FieldError is stored as-is; an array holds several (falsy
|
|
252
|
+
* items dropped); undefined clears. */
|
|
253
|
+
declare function setError<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, error: ValidatorOutput | undefined, options?: SetErrorOptions): void;
|
|
254
|
+
/** Set a field's error by path. See {@link setError} for the input shapes. */
|
|
255
|
+
declare function setErrorByPath(form: Form, path: Path, error: ValidatorOutput | undefined, options?: SetErrorOptions): void;
|
|
256
|
+
/** Clear errors: a single path, a list of paths, or (omitted) every error. */
|
|
257
|
+
declare function clearErrors(form: Form, name?: Name | Name[]): void;
|
|
258
|
+
/** Options accepted by {@link setServerErrors}. */
|
|
259
|
+
type SetServerErrorsOptions = {
|
|
260
|
+
/** Keep existing field errors instead of clearing them first. Defaults
|
|
261
|
+
* to `false`: a fresh response replaces the prior error state. */
|
|
262
|
+
keepExisting?: boolean;
|
|
263
|
+
};
|
|
264
|
+
/** Land a server-side error response: each entry becomes the named field's
|
|
265
|
+
* error(s) with `type: 'server'`. A string lands as one error, an array as
|
|
266
|
+
* several, an empty array clears the field. By default existing errors are
|
|
267
|
+
* cleared first; pass `keepExisting: true` to layer instead. */
|
|
268
|
+
declare function setServerErrors(form: Form, errors: Record<string, string | string[]>, options?: SetServerErrorsOptions): void;
|
|
269
|
+
/** Drop every `type: 'server'` error — the round-trip state a previous
|
|
270
|
+
* submit landed. {@link handleSubmit} runs this before its validation
|
|
271
|
+
* round so a retry is judged fresh; client errors are untouched. Emits
|
|
272
|
+
* payload-less 'errors' when anything changed. */
|
|
273
|
+
declare function clearServerErrors(form: Form): void;
|
|
274
|
+
declare function hasErrors({ errors }: Form): boolean;
|
|
275
|
+
|
|
276
|
+
/** The meta bag passed to a validator's second argument. */
|
|
277
|
+
type ValidatorMeta = {
|
|
278
|
+
form: Form;
|
|
279
|
+
path: Path;
|
|
280
|
+
};
|
|
281
|
+
declare function unsetValidatingByPath({ emitter, validating }: Form, path: Path): void;
|
|
282
|
+
declare function setValidatingByPath({ emitter, validating }: Form, path: Path): void;
|
|
283
|
+
/** Field validator: an error (string, FieldError, or an array mixing
|
|
284
|
+
* both) or undefined — synchronously or as a Promise. `meta.signal`
|
|
285
|
+
* aborts when the round is superseded, so async work can be cancelled;
|
|
286
|
+
* stale results are dropped by the round lock either way. Older
|
|
287
|
+
* two-argument signatures keep working. */
|
|
288
|
+
type Validator = (value: any, meta: ValidatorMeta & {
|
|
289
|
+
signal: AbortSignal;
|
|
290
|
+
}) => ValidatorOutput | undefined | Promise<ValidatorOutput | undefined>;
|
|
291
|
+
/** Synchronous pre-validator (declarative `required` gates in practice):
|
|
292
|
+
* runs on every kick, never debounced; its errors land immediately and
|
|
293
|
+
* short-circuit the debounced validator while present. No Promise, no
|
|
294
|
+
* `signal` — nothing to abort. */
|
|
295
|
+
type SyncValidator = (value: any, meta: ValidatorMeta) => ValidatorOutput | undefined;
|
|
296
|
+
/** Live options for {@link registerValidatorByPath}: accessors, read at
|
|
297
|
+
* every kick, so `useValidate` can swap them per render without
|
|
298
|
+
* re-subscribing mid-flight. */
|
|
299
|
+
type ValidatorRegistration = {
|
|
300
|
+
validate: () => Validator | undefined;
|
|
301
|
+
/** Debounce delay in milliseconds; 0 (default) runs immediately. */
|
|
302
|
+
debounce: () => number;
|
|
303
|
+
/** Runs on every kick, never debounced. */
|
|
304
|
+
sync: () => SyncValidator | undefined;
|
|
305
|
+
/** Keep the debounced validator running when the sync gate failed
|
|
306
|
+
* (TanStack `asyncAlways`): gate errors land immediately, the
|
|
307
|
+
* validator's result lands alongside them per-source. Absent = false
|
|
308
|
+
* (gate owns the outcome). */
|
|
309
|
+
asyncAlways?: () => boolean;
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Register a field validator's kick at `path` ({@link Form.validators})
|
|
313
|
+
* — the framework-free machinery behind `useValidate`. Returns a
|
|
314
|
+
* disposer that drops the registration and cancels pending work.
|
|
315
|
+
*
|
|
316
|
+
* Contract (what `trigger`/`ensureValidate`/the user-change gate rely
|
|
317
|
+
* on): the `sync` gate runs on every kick, never debounced, and
|
|
318
|
+
* short-circuits the debounced validator while failing — unless
|
|
319
|
+
* `asyncAlways`, which lands the validator's result alongside the
|
|
320
|
+
* gate's (per-source); a positive `debounce` merges kicks, and the
|
|
321
|
+
* field counts as validating while the window is pending; async results
|
|
322
|
+
* land under a round lock — superseded outcomes drop, only the owning
|
|
323
|
+
* round releases the mark; a synchronous throw propagates. Registering
|
|
324
|
+
* at an occupied path replaces the entry (last-wins).
|
|
325
|
+
*/
|
|
326
|
+
declare function registerValidatorByPath(form: Form, path: Path, registration: ValidatorRegistration): () => void;
|
|
327
|
+
/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;
|
|
328
|
+
* omitting the options object entirely keeps the plain validate-only
|
|
329
|
+
* behavior, so the historical two-argument calls are untouched. */
|
|
330
|
+
type TriggerOptions = {
|
|
331
|
+
/** Mark the triggered scope touched once the round settles, pass or
|
|
332
|
+
* fail (RHF trigger `shouldTouch`). Defaults to `false`. */
|
|
333
|
+
shouldTouch?: boolean;
|
|
334
|
+
/** Focus the first errored field in the triggered scope once the round
|
|
335
|
+
* settles (RHF trigger `shouldFocus`). Rides the 'focusError' channel
|
|
336
|
+
* like failed-submit auto-focus; unmounted paths are silent no-ops.
|
|
337
|
+
* Defaults to `false`. */
|
|
338
|
+
shouldFocus?: boolean;
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Trigger validation. Without `name`: every registered field validator,
|
|
342
|
+
* then the form-level `validate` (after fields settle, same pipeline as
|
|
343
|
+
* {@link ensureValidate}). One name runs that field only; a name array
|
|
344
|
+
* runs each in order; `[]` is a no-op. A segments array mixes in numbers
|
|
345
|
+
* (`['items', 0]`); pure string arrays are name lists (`['a', 'b']`
|
|
346
|
+
* triggers fields `a` and `b`, not the nested path).
|
|
347
|
+
*
|
|
348
|
+
* The promise waits for the round to settle (async validators included)
|
|
349
|
+
* and never rejects — it resolves whether the triggered scope is
|
|
350
|
+
* error-free. With `name`, only those fields' errors count and
|
|
351
|
+
* form-level `validate` is skipped (RHF semantics). Fire-and-forget
|
|
352
|
+
* callers may ignore it: the kicks still run synchronously.
|
|
353
|
+
*/
|
|
354
|
+
declare function trigger(form: Form, name?: Name | Name[], options?: TriggerOptions): Promise<boolean>;
|
|
355
|
+
/**
|
|
356
|
+
* Run the form-level `validate` and land its result, honoring
|
|
357
|
+
* `validateDebounce`. Undebounced: the caller's await is the call — no
|
|
358
|
+
* mark, no gating, rejection propagates. Debounced: kicks merge into a
|
|
359
|
+
* window (the form counts as validating), the round reads then-current
|
|
360
|
+
* values and supersedes in-flight rounds, and every merged caller's
|
|
361
|
+
* promise settles with the final round's outcome. Form-level-only round:
|
|
362
|
+
* `useForm`'s validateOnMount and cross-cutting re-checks; `trigger` /
|
|
363
|
+
* `ensureValidate` compose it after fields settle.
|
|
364
|
+
*/
|
|
365
|
+
declare function runFormValidate(form: Form): Promise<void>;
|
|
366
|
+
/** The mode/reValidateMode gate shared by change/blur kicks and both
|
|
367
|
+
* validateDeps re-runs: fires for `cadence` and `'all'`, for
|
|
368
|
+
* `'onTouched'` once touched, else when `reValidateMode` matches
|
|
369
|
+
* `cadence` and an error is still live. `hasError` reads lazily. */
|
|
370
|
+
declare function shouldKick(mode: ValidationMode, cadence: 'onChange' | 'onBlur', touched: boolean, hasError: () => boolean, reValidateMode: ReValidateMode): boolean;
|
|
371
|
+
/**
|
|
372
|
+
* Form-level twin of the gated change kick: re-run `validate` after a
|
|
373
|
+
* user change to a field in `validateDeps`. Rides the changed field's
|
|
374
|
+
* onChange pipeline, so programmatic setValue writes never fire it. The
|
|
375
|
+
* gate uses the changed field's effective `mode` and the form-level
|
|
376
|
+
* `reValidateMode` against the last round's error footprint:
|
|
377
|
+
* onChange/all — every dep change; onTouched — once touched; otherwise
|
|
378
|
+
* while the round's error is still live under reValidateMode onChange
|
|
379
|
+
* (the submit-then-fix flow). Fire-and-forget: async rejections are
|
|
380
|
+
* swallowed, sync throws propagate. A no-op (one property check) unless
|
|
381
|
+
* `validateDeps` lists `path`.
|
|
382
|
+
*/
|
|
383
|
+
declare function revalidateFormOnChange(form: Form, path: Path, mode: ValidationMode): void;
|
|
384
|
+
/** Register one field's deps: `key` re-validates when any path in
|
|
385
|
+
* `depKeys` changes. Idempotent per pair — StrictMode's double effect is
|
|
386
|
+
* harmless. */
|
|
387
|
+
declare function registerFieldValidateDeps(form: Form, key: string, depKeys: string[]): void;
|
|
388
|
+
/** Drop one field's deps registration; empty entries are removed so the
|
|
389
|
+
* registry never outlives its fields. */
|
|
390
|
+
declare function unregisterFieldValidateDeps(form: Form, key: string, depKeys: string[]): void;
|
|
391
|
+
/**
|
|
392
|
+
* Field-level twin: after a user change to `path`, re-run every field
|
|
393
|
+
* validator that declared it as a dep. Same channel and gate as
|
|
394
|
+
* {@link revalidateFormOnChange} — the dependent's own error arms
|
|
395
|
+
* reValidateMode, and a passing re-run replaces it (a field validator
|
|
396
|
+
* owns its whole key). Ordinary validator kicks: the dependent's
|
|
397
|
+
* debounce applies, sync throws propagate. A no-op unless some field
|
|
398
|
+
* declared `path` as a dep.
|
|
399
|
+
*/
|
|
400
|
+
declare function revalidateDependentsOnChange(form: Form, path: Path, mode: ValidationMode): void;
|
|
401
|
+
/** {@link ensureValidate}'s rejection: `message` is the first error's
|
|
402
|
+
* display text; `.errors` carries the full flattened list ({@link
|
|
403
|
+
* getErrors}) for branching without re-reading the form. */
|
|
404
|
+
type FormValidationError = Error & {
|
|
405
|
+
errors: FieldErrorEntry[];
|
|
406
|
+
};
|
|
407
|
+
/**
|
|
408
|
+
* Validate and throw if any field error.
|
|
409
|
+
* @param form
|
|
410
|
+
* @return resolve if no error; reject and stop validate if has an error
|
|
411
|
+
*/
|
|
412
|
+
declare function ensureValidate(form: Form): Promise<void>;
|
|
413
|
+
/**
|
|
414
|
+
* Validate and return if any field error.
|
|
415
|
+
* @param form
|
|
416
|
+
* @return error message string or void
|
|
417
|
+
*/
|
|
418
|
+
declare function validate(form: Form): Promise<void | string>;
|
|
419
|
+
|
|
420
|
+
/** A field error: `type` is the error kind, `message` the display text. */
|
|
421
|
+
type FieldError = {
|
|
422
|
+
type: string;
|
|
423
|
+
message: string;
|
|
424
|
+
};
|
|
425
|
+
/** A flattened entry from {@link getErrors}. */
|
|
426
|
+
type FieldErrorEntry = {
|
|
427
|
+
path: string;
|
|
428
|
+
type: string;
|
|
429
|
+
message: string;
|
|
430
|
+
};
|
|
431
|
+
/** When a field is validated:
|
|
432
|
+
* - `'onSubmit'` (default): only on submit
|
|
433
|
+
* - `'onBlur'`: when the field loses focus
|
|
434
|
+
* - `'onChange'`: on every change
|
|
435
|
+
* - `'onTouched'`: on first blur, then on every change
|
|
436
|
+
* - `'all'`: on both change and blur
|
|
437
|
+
*/
|
|
438
|
+
type ValidationMode = 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';
|
|
439
|
+
/** When a field is re-validated after it already has an error:
|
|
440
|
+
* - `'onChange'` (default): on every change
|
|
441
|
+
* - `'onBlur'`: when the field loses focus
|
|
442
|
+
* - `'onSubmit'`: only on submit (no live re-validation)
|
|
443
|
+
*/
|
|
444
|
+
type ReValidateMode = 'onChange' | 'onBlur' | 'onSubmit';
|
|
445
|
+
/** When the form-level {@link Options.validate} re-runs outside
|
|
446
|
+
* submit/`trigger`/`validateOnMount`:
|
|
447
|
+
* - `'onSubmit'` (default): submit/trigger only — cross-field linkage via
|
|
448
|
+
* {@link Options.validateDeps}
|
|
449
|
+
* - `'onChange'`: every user change to a bound field
|
|
450
|
+
* - `'onBlur'`: every user blur of a bound field
|
|
451
|
+
*/
|
|
452
|
+
type FormValidateMode = 'onSubmit' | 'onChange' | 'onBlur';
|
|
453
|
+
/**
|
|
454
|
+
* Options accepted by {@link Form.register} — the non-hook binding for
|
|
455
|
+
* uncontrolled fields (react-hook-form's `register` contract: the bound
|
|
456
|
+
* element never re-renders; the store carries every write).
|
|
457
|
+
*/
|
|
458
|
+
type RegisterOptions = {
|
|
459
|
+
/** Field-level validation mode for this binding; defaults to the form's
|
|
460
|
+
* `mode`. */
|
|
461
|
+
mode?: ValidationMode;
|
|
462
|
+
/** Unmount behavior: `true` (the library's historical default) tombstones
|
|
463
|
+
* the path, `false` keeps the value. Falls back to the form-level
|
|
464
|
+
* `createForm({shouldUnregister})` when omitted. */
|
|
465
|
+
shouldUnregister?: boolean;
|
|
466
|
+
/** DOM event → value extractor for the returned `onChange`. Defaults to
|
|
467
|
+
* the element's protocol (`target.files`/`target.checked`/
|
|
468
|
+
* `target.valueAsNumber`/`target.valueAsDate`, else `target.value`) —
|
|
469
|
+
* the same extraction `<Field>` performs. */
|
|
470
|
+
eventToValue?: (e: any) => any;
|
|
471
|
+
/** Store `e.target.valueAsNumber` instead of the string value. An
|
|
472
|
+
* explicit `eventToValue` takes precedence. */
|
|
473
|
+
valueAsNumber?: boolean;
|
|
474
|
+
/** Store `e.target.valueAsDate` instead of the string value. An explicit
|
|
475
|
+
* `eventToValue` takes precedence; combining with `valueAsNumber` is a
|
|
476
|
+
* TypeError. */
|
|
477
|
+
valueAsDate?: boolean;
|
|
478
|
+
/** Declarative rules for this binding — the same {@link FieldRules}
|
|
479
|
+
* `useField`/`<Field>` take (`required` runs as the synchronous gate).
|
|
480
|
+
* Wired through `registerValidatorByPath`, so `trigger`/submit/`mode`
|
|
481
|
+
* gating see it like a hook-registered validator; `validateDebounce` is
|
|
482
|
+
* fixed at 0. */
|
|
483
|
+
rules?: FieldRules;
|
|
484
|
+
};
|
|
485
|
+
/** What {@link Form.register} returns: spread these onto an uncontrolled
|
|
486
|
+
* DOM element (`<input {...form.register('name')} />`). `name` is the
|
|
487
|
+
* store's path key; `onChange` writes through the gated user-change
|
|
488
|
+
* pipeline; `ref` attach seeds the element's DOM content and detach
|
|
489
|
+
* tombstones unless `shouldUnregister: false`. */
|
|
490
|
+
type RegisterProps = {
|
|
491
|
+
name: string;
|
|
492
|
+
onChange: (e: any) => void;
|
|
493
|
+
onBlur: () => void;
|
|
494
|
+
ref: (el: any) => void;
|
|
495
|
+
};
|
|
496
|
+
/** Structured form-level validate result: `errors` uses the same nested
|
|
497
|
+
* shape a plain error record uses, `values` is the schema's parsed output
|
|
498
|
+
* (coerce/transform included). Either side may be omitted. The brand
|
|
499
|
+
* constant lives in the errors module and is re-exported below. */
|
|
500
|
+
type ValidationOutcome<T> = {
|
|
501
|
+
[VALIDATION_OUTCOME]: true;
|
|
502
|
+
errors?: Record<string, any>;
|
|
503
|
+
values?: T;
|
|
504
|
+
};
|
|
505
|
+
/** What a form-level validate function may return: a plain nested error
|
|
506
|
+
* record (flattened into field errors — the long-standing shape), or a
|
|
507
|
+
* branded {@link ValidationOutcome} whose `values` become the form's
|
|
508
|
+
* parsedValues baseline. */
|
|
509
|
+
type ValidateResult<T> = Record<string, any> | ValidationOutcome<T> | Promise<Record<string, any> | ValidationOutcome<T>>;
|
|
510
|
+
/** Context passed to a form-level `validate`'s second argument. `signal`
|
|
511
|
+
* aborts when the round is superseded (only under a positive
|
|
512
|
+
* `validateDebounce`, where kicks merge), so async work can be cancelled;
|
|
513
|
+
* stale results are dropped by the round gate either way. */
|
|
514
|
+
type FormValidateMeta<T extends Record<string, any> = any> = {
|
|
515
|
+
form: Form<T>;
|
|
516
|
+
signal: AbortSignal;
|
|
517
|
+
};
|
|
518
|
+
/** Form-level validator: receives all values (plus an optional {@link
|
|
519
|
+
* FormValidateMeta}) and returns a {@link ValidateResult} — sync or async
|
|
520
|
+
* — or `undefined` when valid (falsy results are skipped). */
|
|
521
|
+
type FormValidateFn<T extends Record<string, any> = any> = (values: T, meta: FormValidateMeta<T>) => ValidateResult<T> | undefined;
|
|
522
|
+
/** The emitter event table for {@link Form.emitter}: path-carrying events
|
|
523
|
+
* declare an optional single `Path` payload (sent for single-field
|
|
524
|
+
* mutations, omitted for bulk payload-less broadcasts); `focusError`
|
|
525
|
+
* carries the path key plus optional {@link SetFocusOptions}. */
|
|
526
|
+
type FormEvents = ['change', [path?: Path]] | ['errors', [path?: Path]] | ['touched', [path?: Path]] | ['validating', [path?: Path]] | ['submitting', []] | ['submitCount', []] | ['submitSuccessful', []] | ['reset', []] | ['disabled', [path?: Path]] | ['status', []] | ['loading', []] | ['focusError', [key: string, options?: SetFocusOptions]];
|
|
527
|
+
type Form<T extends Record<string, any> = any> = {
|
|
528
|
+
emitter: EventEmitter<FormEvents>;
|
|
529
|
+
mode: ValidationMode;
|
|
530
|
+
reValidateMode: ReValidateMode;
|
|
531
|
+
initialValues: T;
|
|
532
|
+
values: Map<string, any>;
|
|
533
|
+
/** Tombstones of unregistered field paths (JSON path keys): reading or
|
|
534
|
+
* merging values must not fall back to initialValues for these paths. */
|
|
535
|
+
deleted: Set<string>;
|
|
536
|
+
/** Every error registered for a field, as a non-empty array (the
|
|
537
|
+
* write-side {@link setErrorByPath} normalizes to this invariant).
|
|
538
|
+
* First entry via {@link getError}, all of them via
|
|
539
|
+
* {@link getFieldErrors}. */
|
|
540
|
+
errors: Map<string, FieldError[]>;
|
|
541
|
+
touched: Set<string>;
|
|
542
|
+
/** Per-field validation kicks registered by {@link
|
|
543
|
+
* registerValidatorByPath}: invoking one validates the field's current
|
|
544
|
+
* value. `trigger`/`ensureValidate` run every entry; the user-change
|
|
545
|
+
* gate runs the entry at the changed path. */
|
|
546
|
+
validators: Map<string, () => void>;
|
|
547
|
+
validating: Set<string>;
|
|
548
|
+
/** Parsed values from the last successful schema validation: layered
|
|
549
|
+
* between initialValues and the values Map in {@link getValues}, cleared
|
|
550
|
+
* by `reset`/`setInitialValues`. Never affects dirty state. */
|
|
551
|
+
parsedValues: T | undefined;
|
|
552
|
+
/** Form-level validator, seeded from {@link Options.validate}. */
|
|
553
|
+
validate?: FormValidateFn<T>;
|
|
554
|
+
/** Delay in ms before the form-level `validate` runs; seeded from
|
|
555
|
+
* {@link Options.validateDebounce} and fixed at create time. */
|
|
556
|
+
validateDebounce?: number;
|
|
557
|
+
/** Path keys whose user changes re-run the form-level `validate`;
|
|
558
|
+
* normalized from {@link Options.validateDeps} at create time. */
|
|
559
|
+
validateDeps?: ReadonlySet<string>;
|
|
560
|
+
/** When the form-level `validate` re-runs outside submit/trigger — the
|
|
561
|
+
* cadence from {@link Options.validateMode}, seeded at create time. */
|
|
562
|
+
validateMode: FormValidateMode;
|
|
563
|
+
/** Form-level default messages for declarative rules, seeded from
|
|
564
|
+
* {@link Options.messages}: one table overriding every field's built-in
|
|
565
|
+
* English rule message (i18n in one place). Per-field messages still
|
|
566
|
+
* win. */
|
|
567
|
+
messages?: FormMessages;
|
|
568
|
+
isSubmitting: boolean;
|
|
569
|
+
/** Whether a submit has been attempted — set by `handleSubmit` on every
|
|
570
|
+
* attempt, cleared by `reset` (react-hook-form's `isSubmitted`). */
|
|
571
|
+
isSubmitted: boolean;
|
|
572
|
+
submitCount: number;
|
|
573
|
+
isSubmitSuccessful: boolean | undefined;
|
|
574
|
+
/** True while an async {@link Options.initialValues} source is pending —
|
|
575
|
+
* the form starts empty and the resolved values land as the baseline.
|
|
576
|
+
* Flips through the payload-less 'loading' event. */
|
|
577
|
+
isLoading: boolean;
|
|
578
|
+
/** Form-level default for a bound field's unmount behavior: `true` (the
|
|
579
|
+
* default) tombstones an unmounted field, `false` keeps its value. A
|
|
580
|
+
* field's own `shouldUnregister` option overrides this. */
|
|
581
|
+
shouldUnregister?: boolean;
|
|
582
|
+
/** Form-level disabled flag, OR-ed into every bound field's `disabled`
|
|
583
|
+
* (form flag || the field's own option). Toggled at runtime with
|
|
584
|
+
* {@link setDisabled}, which emits a payload-less 'disabled' event. */
|
|
585
|
+
disabled: boolean;
|
|
586
|
+
/** Form-level default for mount validation: `true` kicks every mounted
|
|
587
|
+
* field's validator once after mount (deferred until an async
|
|
588
|
+
* {@link Options.initialValues} source lands) and runs the form-level
|
|
589
|
+
* `validate` once. A field's own option overrides this. */
|
|
590
|
+
validateOnMount: boolean;
|
|
591
|
+
/** Form-level default for `asyncAlways`: whether a field's debounced
|
|
592
|
+
* validator still runs when its `required` gate failed. A field's own
|
|
593
|
+
* option overrides this flag. */
|
|
594
|
+
asyncAlways: boolean;
|
|
595
|
+
/** Whether native constraint validation gates submission and skips a
|
|
596
|
+
* bound `<Field>`'s custom validators on a native-failing kick. Seeded
|
|
597
|
+
* from {@link Options.shouldUseNativeValidation} (default `true`); a
|
|
598
|
+
* submit may override per attempt. */
|
|
599
|
+
shouldUseNativeValidation: boolean;
|
|
600
|
+
/** User-owned metadata slot for non-field state (Formik's `status`
|
|
601
|
+
* role). Written with {@link setStatus}, which emits the payload-less
|
|
602
|
+
* 'status' event; read via {@link useStatus}. Starts `undefined`. */
|
|
603
|
+
status: any;
|
|
604
|
+
/** Non-hook field binding — react-hook-form's `register` contract:
|
|
605
|
+
* spread the returned props onto an uncontrolled DOM element and the
|
|
606
|
+
* element never re-renders while the store carries every write. No
|
|
607
|
+
* React state involved, so it works anywhere. See {@link
|
|
608
|
+
* RegisterOptions} / {@link RegisterProps}. */
|
|
609
|
+
register: (name: Name, options?: RegisterOptions) => RegisterProps;
|
|
610
|
+
};
|
|
611
|
+
type Options<T extends Record<string, any> = any> = {
|
|
612
|
+
/** The values baseline. Sync objects seed immediately; async sources (a
|
|
613
|
+
* Promise, or a thunk returning a value/Promise) start the form empty
|
|
614
|
+
* with `isLoading: true` and land the resolved values as the baseline
|
|
615
|
+
* via setInitialValues. A rejected source keeps the form empty and logs
|
|
616
|
+
* in DEV. The thunk runs at create time. */
|
|
617
|
+
initialValues?: T | Promise<T> | (() => T | Promise<T>);
|
|
618
|
+
/** When fields are validated. Defaults to `'onSubmit'`. See
|
|
619
|
+
* {@link ValidationMode}. */
|
|
620
|
+
mode?: ValidationMode;
|
|
621
|
+
/** When a field is re-validated after it already has an error. Defaults
|
|
622
|
+
* to `'onChange'`. See {@link ReValidateMode}. */
|
|
623
|
+
reValidateMode?: ReValidateMode;
|
|
624
|
+
/** Form-level validator: returns a record of errors keyed by field path
|
|
625
|
+
* (nested objects flattened 'a.b' style, array values contribute each
|
|
626
|
+
* non-empty string). A branded {@link ValidationOutcome} adds parsed
|
|
627
|
+
* `values` as the parsedValues baseline. Alternatively pass a Standard
|
|
628
|
+
* Schema v1 object directly — it is wrapped into a validator
|
|
629
|
+
* automatically. */
|
|
630
|
+
validate?: FormValidateFn<T> | StandardSchemaV1<unknown, T>;
|
|
631
|
+
/** Milliseconds to debounce the form-level `validate`: kicks inside the
|
|
632
|
+
* window merge into one run, and while the timer is pending the form
|
|
633
|
+
* counts as validating. Defaults to `0` (runs immediately). */
|
|
634
|
+
validateDebounce?: number;
|
|
635
|
+
/** Fields whose user changes re-run the form-level `validate` — the
|
|
636
|
+
* cross-field dependency list. A re-run only clears errors the previous
|
|
637
|
+
* round wrote; errors the round never wrote are untouched. Omit it and
|
|
638
|
+
* the form-level `validate` only runs on `trigger`/submit. */
|
|
639
|
+
validateDeps?: FieldPath<T>[];
|
|
640
|
+
/** When the form-level `validate` re-runs outside submit/`trigger`/
|
|
641
|
+
* `validateOnMount` — a cadence declaration instead of enumerating
|
|
642
|
+
* {@link Options.validateDeps}. See {@link FormValidateMode}. */
|
|
643
|
+
validateMode?: FormValidateMode;
|
|
644
|
+
/** Form-level default messages for declarative rules, keyed by rule
|
|
645
|
+
* type — one table overriding the built-in English defaults for every
|
|
646
|
+
* field (i18n in one place). A string may carry a `{bound}`
|
|
647
|
+
* placeholder; a function receives the bound. A field's own message
|
|
648
|
+
* (the `required` string, `rules.messages`, `pattern.message`) still
|
|
649
|
+
* wins. See {@link FormMessages}. */
|
|
650
|
+
messages?: FormMessages;
|
|
651
|
+
/** Form-level default for a bound field's unmount behavior. `true` (the
|
|
652
|
+
* default) tombstones an unmounted field; `false` keeps the value
|
|
653
|
+
* (react-hook-form's `shouldUnregister`). A field's own option
|
|
654
|
+
* overrides this. */
|
|
655
|
+
shouldUnregister?: boolean;
|
|
656
|
+
/** Start the form with every bound field disabled — bound fields OR this
|
|
657
|
+
* flag with their own `disabled` option (a field cannot opt out).
|
|
658
|
+
* Toggle later with {@link setDisabled}. Defaults to `false`. */
|
|
659
|
+
disabled?: boolean;
|
|
660
|
+
/** Form-level default for `asyncAlways`: when true, a field whose
|
|
661
|
+
* `required` gate failed still runs its debounced validator (the gate's
|
|
662
|
+
* errors land immediately, the validator's result lands alongside
|
|
663
|
+
* them per-source). A field's own option overrides this. Defaults to
|
|
664
|
+
* `false`. */
|
|
665
|
+
asyncAlways?: boolean;
|
|
666
|
+
/** Whether native constraint validation gates submission and skips a
|
|
667
|
+
* bound `<Field>`'s custom validators on a native-failing kick
|
|
668
|
+
* (react-hook-form's `shouldUseNativeValidation`). Defaults to `true`.
|
|
669
|
+
* Fixed at create time; a single submit may override it. */
|
|
670
|
+
shouldUseNativeValidation?: boolean;
|
|
671
|
+
/** Validate on mount: `true` makes every mounted field's validator run
|
|
672
|
+
* once after mount (errors show for an untouched form) and runs the
|
|
673
|
+
* form-level `validate` once. Mount kicks are deferred while an async
|
|
674
|
+
* `initialValues` source is pending. A field's own option overrides
|
|
675
|
+
* this. Defaults to `false`. */
|
|
676
|
+
validateOnMount?: boolean;
|
|
677
|
+
};
|
|
678
|
+
/** Create a form instance. */
|
|
679
|
+
declare function create<T extends Record<string, any> = any>(options?: Options<T>): Form<T>;
|
|
680
|
+
|
|
681
|
+
export { getFieldErrorsByPath as $, clearErrors as H, clearServerErrors as J, create as K, dottedKeyToFieldPath as L, ensureValidate as M, fieldPathToDottedKey as Q, getError as U, getErrorByPath as W, getErrors as X, getErrorsRecord as Y, getErrorsTree as Z, getFieldErrors as _, getFirstError as a0, hasErrors as a1, registerFieldValidateDeps as a2, registerValidatorByPath as a3, revalidateDependentsOnChange as a4, revalidateFormOnChange as a5, runFormValidate as a6, setError as a7, setErrorByPath as a8, setFocus as a9, setServerErrors as aa, setValidatingByPath as ab, shouldKick as ac, trigger as ad, unregisterFieldValidateDeps as ae, unsetValidatingByPath as af, validate as ag, hasStandardProps as ai, schemaToFormValidator as aj, schemaToFieldValidator as ak, VALIDATION_OUTCOME as c, FORM_ERROR as n };
|
|
682
|
+
export type { AnyPath as A, SyncValidator as B, ValidateResult as C, DottedPath as D, ValidatorOutput as E, Form as F, ValidatorRegistration as G, InferSchemaValues as I, Name as N, Options as O, Path as P, RegisterOptions as R, StandardSchemaV1 as S, TriggerOptions as T, Validator as V, FieldRules as a, StandardSchemaIssue as ah, FieldErrorEntry as b, ValidationOutcome as d, ArrayItemOf as e, FieldError as f, PathValueOf as g, ValidationMode as h, RegisterProps as i, FieldPath as j, FieldErrors as k, FieldErrorsTree as l, FormEvents as m, FormMessages as o, FormValidateFn as p, FormValidateMeta as q, FormValidateMode as r, FormValidationError as s, OpaqueTypes as t, PathSegments as u, PathValue as v, ReValidateMode as w, SetErrorOptions as x, SetFocusOptions as y, SetServerErrorsOptions as z };
|