react-f0rm 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +527 -33
- package/dist/devtools/index.cjs.js +737 -0
- package/dist/devtools/index.cjs.js.map +1 -0
- package/dist/devtools/index.d.ts +33 -0
- package/dist/devtools/index.mjs +717 -0
- package/dist/devtools/index.mjs.map +1 -0
- package/dist/form-61297bc0.d.ts +578 -0
- package/dist/form-94c70b4b.mjs +378 -0
- package/dist/form-94c70b4b.mjs.map +1 -0
- package/dist/form-b9441d8c.cjs.js +387 -0
- package/dist/form-b9441d8c.cjs.js.map +1 -0
- package/dist/index.cjs.js +1257 -157
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +416 -0
- package/dist/index.mjs +1676 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1257 -157
- 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/resolvers/standard-schema.cjs.js +90 -0
- package/dist/resolvers/standard-schema.cjs.js.map +1 -0
- package/dist/resolvers/standard-schema.d.ts +66 -0
- package/dist/resolvers/standard-schema.mjs +86 -0
- package/dist/resolvers/standard-schema.mjs.map +1 -0
- package/dist/resolvers/yup.cjs.js +12 -2
- package/dist/resolvers/yup.cjs.js.map +1 -1
- package/dist/resolvers/yup.d.ts +7 -0
- package/dist/resolvers/yup.mjs +23 -0
- package/dist/resolvers/yup.mjs.map +1 -0
- package/dist/resolvers/zod.cjs.js +14 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.ts +7 -0
- package/dist/resolvers/zod.mjs +23 -0
- package/dist/resolvers/zod.mjs.map +1 -0
- package/dist/validate-148fe167.d.ts +22 -0
- package/package.json +44 -8
- package/dist/index.esm.js +0 -593
- package/dist/index.esm.js.map +0 -1
- package/dist/resolvers/yup.esm.js +0 -13
- package/dist/resolvers/yup.esm.js.map +0 -1
- package/dist/resolvers/zod.esm.js +0 -10
- package/dist/resolvers/zod.esm.js.map +0 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { F as FieldPath, N as Name, a as Form$1, P as PathValueOf, b as FieldError, O as Options, c as Path } from './form-61297bc0.js';
|
|
2
|
+
export { f as FieldErrorEntry, u as FieldState, a3 as HandleSubmitOptions, e as PathValue, R as ReValidateMode, U as ResetFieldOptions, Q as ResetOptions, S as SetFieldOptions, a5 as SetFocusOptions, g as VALIDATION_OUTCOME, i as ValidateResult, V as ValidationMode, h as ValidationOutcome, A as clearErrors, d as createForm, Z as ensureValidate, H as getDirtyFields, n as getError, o as getErrorByPath, r as getErrors, p as getFieldErrors, q as getFieldErrorsByPath, v as getFieldState, t as getFirstError, I as getTouchedFields, k as getValue, l as getValueByPath, j as getValues, a4 as handleSubmit, X as hasErrors, D as hasTouched, E as hasTouchedByPath, a0 as incrementSubmitCount, G as isDirty, J as isTouched, K as removeField, L as removeFieldByPath, T as reset, W as resetField, a2 as setDisabled, y as setError, z as setErrorByPath, a6 as setFocus, M as setInitialValues, $ as setIsSubmitting, a1 as setSubmitSuccessful, B as setTouched, C as setTouchedByPath, x as setValidatingByPath, s as setValue, m as setValueByPath, Y as trigger, w as unsetValidatingByPath, _ as validate } from './form-61297bc0.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { V as Validator } from './validate-148fe167.js';
|
|
6
|
+
import { EventEmitter } from '@for-fun/event-emitter';
|
|
7
|
+
|
|
8
|
+
/** Type tag of a failed rule, as stored on the resulting FieldError. */
|
|
9
|
+
type RuleType = 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern';
|
|
10
|
+
/**
|
|
11
|
+
* Declarative field rules — a subset of react-hook-form's `register` rules.
|
|
12
|
+
*
|
|
13
|
+
* Failed rules land in the form's error state as FieldErrors (`type` is the
|
|
14
|
+
* rule name) instead of only surfacing through the browser's validity
|
|
15
|
+
* bubble, so any design system can render the messages uniformly.
|
|
16
|
+
*/
|
|
17
|
+
interface FieldRules {
|
|
18
|
+
/**
|
|
19
|
+
* Fails on empty values: `''`, `undefined` or `null` (`0` and `false`
|
|
20
|
+
* count as filled). A string is the error message; `true` uses the
|
|
21
|
+
* default. When it fails, the remaining rules are skipped — an empty
|
|
22
|
+
* value reports only its required error.
|
|
23
|
+
*/
|
|
24
|
+
required?: string | true;
|
|
25
|
+
/** Fails when `Number(value)` is below this bound; `NaN` values skip. */
|
|
26
|
+
min?: number;
|
|
27
|
+
/** Fails when `Number(value)` is above this bound; `NaN` values skip. */
|
|
28
|
+
max?: number;
|
|
29
|
+
/** Fails when a string value is shorter than this; non-strings skip. */
|
|
30
|
+
minLength?: number;
|
|
31
|
+
/** Fails when a string value is longer than this; non-strings skip. */
|
|
32
|
+
maxLength?: number;
|
|
33
|
+
/** Fails when the value does not match `pattern.value`. */
|
|
34
|
+
pattern?: {
|
|
35
|
+
value: RegExp;
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Overrides the message per rule type — `min`, `max`, `minLength`,
|
|
40
|
+
* `maxLength` defaults and pattern's inline `message` alike — e.g. for
|
|
41
|
+
* centralizing or localizing messages.
|
|
42
|
+
*/
|
|
43
|
+
messages?: Partial<Record<Exclude<RuleType, 'required'>, string>>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> {
|
|
47
|
+
form?: Form$1<TValues>;
|
|
48
|
+
name: TPath;
|
|
49
|
+
initialValue?: any;
|
|
50
|
+
shouldUnregister?: boolean;
|
|
51
|
+
validate?: Validator;
|
|
52
|
+
/**
|
|
53
|
+
* Declarative rules (required/min/max/minLength/maxLength/pattern),
|
|
54
|
+
* compiled into a validator that runs before `validate` — both sources'
|
|
55
|
+
* errors merge into one FieldError[], rules errors ahead. Failures land
|
|
56
|
+
* in the form's error state with the given or default messages.
|
|
57
|
+
*/
|
|
58
|
+
rules?: FieldRules;
|
|
59
|
+
/**
|
|
60
|
+
* Milliseconds to debounce this field's validation kicks. Defaults to 0
|
|
61
|
+
* (validate immediately); while the timer is pending the field counts as
|
|
62
|
+
* validating, so `trigger`/`ensureValidate` wait out the window. Only the
|
|
63
|
+
* last kick inside the window runs the validator.
|
|
64
|
+
*/
|
|
65
|
+
validateDebounce?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Milliseconds to delay showing a newly appearing error in the render
|
|
68
|
+
* layer (`error`/`errorObject`/`errors` stay undefined/empty until the
|
|
69
|
+
* window passes). The form's error state is never delayed — trigger,
|
|
70
|
+
* submit and `getError` read it immediately. An error that clears inside
|
|
71
|
+
* the window never shows; once an error is visible, later changes apply
|
|
72
|
+
* immediately. Only the none → some transition waits.
|
|
73
|
+
*/
|
|
74
|
+
delayError?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Disable this field: OR-ed with the form-level flag
|
|
77
|
+
* (`createForm({disabled})` / `setDisabled`) into the result's
|
|
78
|
+
* `disabled`. A field cannot opt out of a disabled form.
|
|
79
|
+
*/
|
|
80
|
+
disabled?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The result of {@link useField}. Deliberately a closed shape: no index
|
|
84
|
+
* signature, so a typo'd property access (`field.vlaue`) is a type error
|
|
85
|
+
* instead of silently reading `undefined`.
|
|
86
|
+
*/
|
|
87
|
+
interface UseFieldResult<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> {
|
|
88
|
+
/** The form instance this field is bound to (explicit prop or context) —
|
|
89
|
+
* handy for consumers that need direct access to the headless API. */
|
|
90
|
+
form: Form$1<TValues>;
|
|
91
|
+
value: PathValueOf<TValues, TPath>;
|
|
92
|
+
/** Error message string (FieldError#message) for display, or undefined */
|
|
93
|
+
error: string | undefined;
|
|
94
|
+
/** Full FieldError object ({type, message}), or undefined */
|
|
95
|
+
errorObject: FieldError | undefined;
|
|
96
|
+
/** Every error registered for the field, in insertion order — `error`
|
|
97
|
+
* and `errorObject` are its first entry. Empty (and reference-stable)
|
|
98
|
+
* when the field has no errors. */
|
|
99
|
+
errors: FieldError[];
|
|
100
|
+
onChange: (v: any) => void;
|
|
101
|
+
onBlur: () => void;
|
|
102
|
+
name: string;
|
|
103
|
+
/** Merged disabled flag: the form-level flag (`createForm({disabled})`
|
|
104
|
+
* toggled by `setDisabled`) OR-ed with this field's own `disabled`
|
|
105
|
+
* option, updated live through the form's event core. */
|
|
106
|
+
disabled: boolean;
|
|
107
|
+
}
|
|
108
|
+
declare function useField<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name>(options: UseFieldOptions$1<TValues, TPath>): UseFieldResult<TValues, TPath>;
|
|
109
|
+
|
|
110
|
+
interface FieldArrayItem {
|
|
111
|
+
id: string;
|
|
112
|
+
index: number;
|
|
113
|
+
}
|
|
114
|
+
interface UseFieldArrayResult {
|
|
115
|
+
fields: FieldArrayItem[];
|
|
116
|
+
append: (value: any) => void;
|
|
117
|
+
prepend: (value: any) => void;
|
|
118
|
+
insert: (index: number, value: any) => void;
|
|
119
|
+
remove: (index: number) => void;
|
|
120
|
+
swap: (from: number, to: number) => void;
|
|
121
|
+
move: (from: number, to: number) => void;
|
|
122
|
+
replace: (values: any[]) => void;
|
|
123
|
+
update: (index: number, value: any) => void;
|
|
124
|
+
}
|
|
125
|
+
declare function useFieldArray(options: {
|
|
126
|
+
name: Name;
|
|
127
|
+
form?: Form$1;
|
|
128
|
+
}): UseFieldArrayResult;
|
|
129
|
+
|
|
130
|
+
declare const FormContext: React.Context<any>;
|
|
131
|
+
declare const FormProvider: React.Provider<any>;
|
|
132
|
+
/**
|
|
133
|
+
* Read the form from the module-level {@link FormContext}. Pass the values
|
|
134
|
+
* shape — `useFormContext<Values>()` — to get a fully typed `Form<Values>`
|
|
135
|
+
* headless API; the `any` default keeps untyped call sites compiling.
|
|
136
|
+
*
|
|
137
|
+
* For multiple forms in one subtree use {@link createFormContext} instead.
|
|
138
|
+
*
|
|
139
|
+
* @throws when no `<FormProvider>` is mounted above the call site.
|
|
140
|
+
*/
|
|
141
|
+
declare function useFormContext<T extends Record<string, any> = any>(): Form$1<T>;
|
|
142
|
+
/**
|
|
143
|
+
* Create an isolated bundle of form-context bindings: its own React context
|
|
144
|
+
* plus `useField` / `useFieldArray` / `useFormContext` hooks that resolve
|
|
145
|
+
* their form from it.
|
|
146
|
+
*
|
|
147
|
+
* Why: the module-level {@link FormContext} works fine for a single form per
|
|
148
|
+
* subtree, but nesting two forms (or reusing a component inside a different
|
|
149
|
+
* form) makes them fight over one context. Calling this factory once per app
|
|
150
|
+
* area — `const Ctx = createFormContext<Values>()` — fixes the value shape
|
|
151
|
+
* (`Ctx.useField({name: 'user.name'})` gets its `name` constrained by
|
|
152
|
+
* `FieldPath<Values>` and its `value` typed accordingly), so call sites stop
|
|
153
|
+
* hand-writing generics, and each instance's Provider scopes a strictly
|
|
154
|
+
* separate form.
|
|
155
|
+
*/
|
|
156
|
+
declare function createFormContext<TValues extends Record<string, any> = any>(): {
|
|
157
|
+
FormProvider: ({ form, children }: {
|
|
158
|
+
form: Form$1<TValues>;
|
|
159
|
+
children: ReactNode;
|
|
160
|
+
}) => ReactNode;
|
|
161
|
+
useFormContext: () => Form$1<TValues>;
|
|
162
|
+
useField: <TPath extends FieldPath<TValues> | Name = Name>(options: {
|
|
163
|
+
name: TPath;
|
|
164
|
+
} & Omit<UseFieldOptions$1<TValues, TPath>, "form">) => UseFieldResult<TValues, TPath>;
|
|
165
|
+
useFieldArray: (options: {
|
|
166
|
+
name: FieldPath<TValues> | Name;
|
|
167
|
+
}) => UseFieldArrayResult;
|
|
168
|
+
};
|
|
169
|
+
declare const CheckboxGroupContext: React.Context<any>;
|
|
170
|
+
declare const CheckboxGroupProvider: React.Provider<any>;
|
|
171
|
+
declare function useCheckboxGroupContext(): any;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Create a form instance bound to this component.
|
|
175
|
+
*
|
|
176
|
+
* Beyond {@link Options}, the optional `values` object enables controlled
|
|
177
|
+
* usage: when it genuinely changes it is re-synced into the form with
|
|
178
|
+
* setInitialValues semantics -- uncommitted user edits are discarded
|
|
179
|
+
* (master-detail semantics: selecting another record replaces the draft),
|
|
180
|
+
* while touched flags and errors survive. Change detection is
|
|
181
|
+
* reference-first with a structural fallback, so re-renders that pass an
|
|
182
|
+
* inline literal with equal content never re-sync -- the user's
|
|
183
|
+
* in-progress typing is never clobbered.
|
|
184
|
+
*/
|
|
185
|
+
declare function useForm<T extends Record<string, any> = any>(options?: Options<T> & {
|
|
186
|
+
values?: T;
|
|
187
|
+
}): Form$1<T>;
|
|
188
|
+
/**
|
|
189
|
+
* Subscribe to a form event and keep the component's snapshot of `getter()`
|
|
190
|
+
* in sync with the form state.
|
|
191
|
+
*
|
|
192
|
+
* Built on useSyncExternalStore, so snapshots taken while React renders are
|
|
193
|
+
* guaranteed consistent (no tearing under concurrent rendering) and changes
|
|
194
|
+
* emitted before the subscription effect runs are still picked up.
|
|
195
|
+
*/
|
|
196
|
+
declare function useWatch<T>(emitter: EventEmitter, event: string, getter: () => T): T;
|
|
197
|
+
/**
|
|
198
|
+
* Get field value state
|
|
199
|
+
*/
|
|
200
|
+
declare function useValue<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): PathValueOf<T, P>;
|
|
201
|
+
/**
|
|
202
|
+
* Get field value state by path
|
|
203
|
+
*/
|
|
204
|
+
declare function useValueByPath(form: Form$1, path: Path): any;
|
|
205
|
+
/**
|
|
206
|
+
* Get field touched state
|
|
207
|
+
*/
|
|
208
|
+
declare function useTouched<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): boolean;
|
|
209
|
+
/**
|
|
210
|
+
* Get field touched state by path
|
|
211
|
+
*/
|
|
212
|
+
declare function useTouchedByPath(form: Form$1, path: Path): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Get field error message state
|
|
215
|
+
* @return current error's message string (display text), or undefined
|
|
216
|
+
*/
|
|
217
|
+
declare function useError<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): string | undefined;
|
|
218
|
+
/**
|
|
219
|
+
* Get field error state by path
|
|
220
|
+
* @return current FieldError object ({type, message}), or undefined
|
|
221
|
+
*/
|
|
222
|
+
declare function useErrorByPath(form: Form$1, path: Path): FieldError | undefined;
|
|
223
|
+
/**
|
|
224
|
+
* Get all field errors
|
|
225
|
+
* @return every error registered for the field (insertion order); an empty
|
|
226
|
+
* array when the field has none
|
|
227
|
+
*/
|
|
228
|
+
declare function useFieldErrors<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): FieldError[];
|
|
229
|
+
/**
|
|
230
|
+
* Get all field errors by path
|
|
231
|
+
* @return every error registered for the field (insertion order); an empty
|
|
232
|
+
* array when the field has none
|
|
233
|
+
*/
|
|
234
|
+
declare function useFieldErrorsByPath(form: Form$1, path: Path): FieldError[];
|
|
235
|
+
declare function useIsDirty(form: Form$1): boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Get dirty fields state -- object mapping each dirty field's user-facing
|
|
238
|
+
* dotted path ('a.b', 'a.0.c') to true; recalculated after 'change' events
|
|
239
|
+
*/
|
|
240
|
+
declare function useDirtyFields(form: Form$1): Record<string, boolean>;
|
|
241
|
+
/**
|
|
242
|
+
* Get touched fields state -- array of touched fields' user-facing dotted
|
|
243
|
+
* paths ('a.b', 'a.0.c'); recalculated after 'touched' events
|
|
244
|
+
*/
|
|
245
|
+
declare function useTouchedFields(form: Form$1): string[];
|
|
246
|
+
declare function useHasErrors(form: Form$1): boolean;
|
|
247
|
+
declare function useIsSubmitting(form: Form$1): boolean;
|
|
248
|
+
declare function useSubmitCount(form: Form$1): number;
|
|
249
|
+
|
|
250
|
+
/** Subscription granularity for {@link onPathEvent}.
|
|
251
|
+
* - `'leaf'`: the subscriber reads exactly one key ({@link
|
|
252
|
+
* useValueByPath}); only writes at that key or above it can change what
|
|
253
|
+
* it reads.
|
|
254
|
+
* - `'branch'`: the subscriber aggregates a whole subtree below a key
|
|
255
|
+
* ({@link useFieldArray}); descendant writes matter too. */
|
|
256
|
+
type WatchScope = 'leaf' | 'branch';
|
|
257
|
+
/** Events {@link subscribe} can watch. `'errors'` and `'touched'` are
|
|
258
|
+
* stored per exact key, so they match exact keys ({@link onKeyEvent});
|
|
259
|
+
* `'change'`, `'submitting'` and `'submitCount'` carry paths and go
|
|
260
|
+
* through {@link onPathEvent}. */
|
|
261
|
+
type SubscribeEvent = 'change' | 'errors' | 'touched' | 'submitting' | 'submitCount';
|
|
262
|
+
/** Options accepted by {@link subscribe}. */
|
|
263
|
+
type SubscribeOptions = {
|
|
264
|
+
/** Path (or list of paths) to watch. Omit to receive every emission of
|
|
265
|
+
* `event`, payload-less broadcasts included. A single segments path
|
|
266
|
+
* (`['tags', 0]`) and a list of names (`['tags', 'user.name']`) are told
|
|
267
|
+
* apart by the same rule `trigger` uses: only a segments path can hold
|
|
268
|
+
* a number. */
|
|
269
|
+
name?: Name | Name[];
|
|
270
|
+
/** Event to watch. Defaults to `'change'`. */
|
|
271
|
+
event?: SubscribeEvent;
|
|
272
|
+
/** Which writes around `name` are relevant — `'leaf'` or `'branch'`.
|
|
273
|
+
* Only meaningful for `'change'`: `'errors'`/`'touched'` match exact
|
|
274
|
+
* keys and `'submitting'`/`'submitCount'` are payload-less. Defaults to
|
|
275
|
+
* `'branch'` — the intuitive linkage semantics, where subscribing to
|
|
276
|
+
* `'tags'` means the whole branch. */
|
|
277
|
+
scope?: WatchScope;
|
|
278
|
+
/** Invoked with no arguments after each matching emission. Read fresh
|
|
279
|
+
* state through the `get*` readers inside it. */
|
|
280
|
+
callback: () => void;
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* Subscribe to form events imperatively — the non-render counterpart of
|
|
284
|
+
* the `use*` hooks: linkages and side effects (province changed → clear
|
|
285
|
+
* city, autosave, analytics) run without mounting a watching component.
|
|
286
|
+
*
|
|
287
|
+
* Without `name`, `callback` fires on every `event` emission, payload-less
|
|
288
|
+
* broadcasts (reset, setInitialValues) included. With `name`, matching
|
|
289
|
+
* follows the event's shape: `'errors'`/`'touched'` match the exact key
|
|
290
|
+
* ({@link onKeyEvent}) — another field's error never wakes this
|
|
291
|
+
* subscriber — while `'change'`/`'submitting'`/`'submitCount'` go through
|
|
292
|
+
* {@link onPathEvent}, so the default `'branch'` scope wakes a `'tags'`
|
|
293
|
+
* subscriber when any `tags.*` descendant is written. A `name` array
|
|
294
|
+
* builds one subscription per path and the returned function unsubscribes
|
|
295
|
+
* them all.
|
|
296
|
+
*
|
|
297
|
+
* @param form the form to watch
|
|
298
|
+
* @param options event, name(s), scope and callback
|
|
299
|
+
* @return unsubscribe function
|
|
300
|
+
*/
|
|
301
|
+
declare function subscribe(form: Form$1, options: SubscribeOptions): () => void;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Props for <Form>.
|
|
305
|
+
*
|
|
306
|
+
* Native validation behavior: the rendered <form> always sets noValidate,
|
|
307
|
+
* which suppresses the browser's built-in blocked-submit UI. However, native
|
|
308
|
+
* constraint validation still gates submission — the form element's
|
|
309
|
+
* checkValidity() runs before custom validators, and when it fails,
|
|
310
|
+
* reportValidity() surfaces the offending constraints as native bubbles and
|
|
311
|
+
* submission stops (onInvalidSubmit fires). onSubmit/onValidSubmit only run
|
|
312
|
+
* once every native constraint (required, type=email, minLength, ...) passes.
|
|
313
|
+
*
|
|
314
|
+
* The submit flow itself lives in the headless `handleSubmit` (see form.ts);
|
|
315
|
+
* this component is a thin wrapper that binds it to the rendered <form>.
|
|
316
|
+
*/
|
|
317
|
+
interface FormProps<T extends Record<string, any> = any> extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {
|
|
318
|
+
form?: Form<T>;
|
|
319
|
+
initialValues?: T;
|
|
320
|
+
/**
|
|
321
|
+
* Controlled external values. When the `values` reference changes, the
|
|
322
|
+
* new object is synced into the form (via setInitialValues semantics):
|
|
323
|
+
* uncommitted user edits are discarded -- master-detail semantics, where
|
|
324
|
+
* selecting another record replaces the draft -- while touched flags and
|
|
325
|
+
* errors are kept. Sync is reference-based: re-renders that pass the same
|
|
326
|
+
* `values` reference never clobber what the user is typing.
|
|
327
|
+
*/
|
|
328
|
+
values?: T;
|
|
329
|
+
onSubmit?: (values: T, e: React.FormEvent) => void;
|
|
330
|
+
onValidSubmit?: (values: T, e: React.FormEvent) => void;
|
|
331
|
+
/**
|
|
332
|
+
* Called when validation fails.
|
|
333
|
+
* @param errors array of {path, type, message} entries in insertion
|
|
334
|
+
* order; path is the dotted field path ('a.b', 'list.0'), type is
|
|
335
|
+
* the error kind ('custom' for plain string errors, 'native' for
|
|
336
|
+
* failed DOM constraint validation), message is the display text
|
|
337
|
+
* @param values current form values
|
|
338
|
+
*/
|
|
339
|
+
onInvalidSubmit?: (errors: {
|
|
340
|
+
path: string;
|
|
341
|
+
type: string;
|
|
342
|
+
message: string;
|
|
343
|
+
}[], values: T) => void;
|
|
344
|
+
/**
|
|
345
|
+
* Focus the first field with an error after a failed submit: custom
|
|
346
|
+
* validation failures focus the first errored field, native constraint
|
|
347
|
+
* failures focus the first ':invalid' control. Defaults to true; pass
|
|
348
|
+
* false to disable.
|
|
349
|
+
*/
|
|
350
|
+
shouldFocusError?: boolean;
|
|
351
|
+
}
|
|
352
|
+
declare function Form<T extends Record<string, any> = any>({ form: f1, initialValues, values, onSubmit, onValidSubmit, onInvalidSubmit, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
|
|
353
|
+
|
|
354
|
+
interface UseFieldOptions {
|
|
355
|
+
form?: any;
|
|
356
|
+
name?: Name;
|
|
357
|
+
initialValue?: any;
|
|
358
|
+
shouldUnregister?: boolean;
|
|
359
|
+
validate?: Validator;
|
|
360
|
+
/**
|
|
361
|
+
* Declarative rules (required/min/max/minLength/maxLength/pattern),
|
|
362
|
+
* compiled into a validator that runs before `validate`; failures land
|
|
363
|
+
* in the form's error state. Passed through to useField — like
|
|
364
|
+
* validateDebounce it is never spread onto the DOM element.
|
|
365
|
+
*/
|
|
366
|
+
rules?: FieldRules;
|
|
367
|
+
/**
|
|
368
|
+
* Milliseconds to debounce this field's validation kicks. Defaults to 0
|
|
369
|
+
* (validate immediately); only the last kick inside the window runs the
|
|
370
|
+
* validator, and `trigger` waits the window out. Passed through to
|
|
371
|
+
* useField/useValidate.
|
|
372
|
+
*/
|
|
373
|
+
validateDebounce?: number;
|
|
374
|
+
/**
|
|
375
|
+
* Disable this field's control: OR-ed with the form-level flag
|
|
376
|
+
* (`createForm({disabled})` / `setDisabled`) — a field cannot opt out
|
|
377
|
+
* of a disabled form. Passed through to useField, like every option,
|
|
378
|
+
* never spread onto the DOM element from props.
|
|
379
|
+
*/
|
|
380
|
+
disabled?: boolean;
|
|
381
|
+
/**
|
|
382
|
+
* Milliseconds to delay showing a newly appearing error (render layer
|
|
383
|
+
* only — `aria-invalid`/`renderError` wait out the window while the
|
|
384
|
+
* form's error state stays immediate for trigger/submit). An error
|
|
385
|
+
* that clears inside the window never shows; once visible, error
|
|
386
|
+
* changes apply immediately. Passed through to useField.
|
|
387
|
+
*/
|
|
388
|
+
delayError?: number;
|
|
389
|
+
[key: string]: any;
|
|
390
|
+
}
|
|
391
|
+
interface FieldProps extends UseFieldOptions {
|
|
392
|
+
as?: React.ComponentType<any>;
|
|
393
|
+
asProps?: Record<string, any>;
|
|
394
|
+
eventToValue?: (e: any) => any;
|
|
395
|
+
valueToProps?: (value: any) => Record<string, any>;
|
|
396
|
+
/**
|
|
397
|
+
* Optional error renderer. When provided and the field has an error,
|
|
398
|
+
* Field renders `<span id={id} role="alert">{renderError(error, id)}</span>`
|
|
399
|
+
* next to the input and points the input's aria-describedby at that span.
|
|
400
|
+
* When omitted, no extra element is rendered (headless) and no
|
|
401
|
+
* aria-describedby is attached, avoiding dangling id references.
|
|
402
|
+
*/
|
|
403
|
+
renderError?: (error: string, id: string) => React.ReactNode;
|
|
404
|
+
}
|
|
405
|
+
declare const Field: React.ForwardRefExoticComponent<Omit<FieldProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
406
|
+
interface CheckboxProps extends UseFieldOptions {
|
|
407
|
+
}
|
|
408
|
+
declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
409
|
+
interface SelectProps extends UseFieldOptions {
|
|
410
|
+
multiple?: boolean;
|
|
411
|
+
children?: React.ReactNode;
|
|
412
|
+
}
|
|
413
|
+
declare const Select: React.ForwardRefExoticComponent<Omit<SelectProps, "ref"> & React.RefAttributes<HTMLSelectElement>>;
|
|
414
|
+
|
|
415
|
+
export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, FieldError, FieldPath, Form, FormContext, Form$1 as FormInstance, FormProvider, Name, Options, PathValueOf, Select, createFormContext, subscribe, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useField, useFieldArray, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useHasErrors, useIsDirty, useIsSubmitting, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useValue, useValueByPath, useWatch };
|
|
416
|
+
export type { FieldRules, SubscribeEvent, SubscribeOptions, WatchScope };
|