react-f0rm 0.2.2 → 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.
Files changed (45) hide show
  1. package/README.md +527 -33
  2. package/dist/devtools/index.cjs.js +737 -0
  3. package/dist/devtools/index.cjs.js.map +1 -0
  4. package/dist/devtools/index.d.ts +33 -0
  5. package/dist/devtools/index.mjs +717 -0
  6. package/dist/devtools/index.mjs.map +1 -0
  7. package/dist/form-61297bc0.d.ts +578 -0
  8. package/dist/form-94c70b4b.mjs +378 -0
  9. package/dist/form-94c70b4b.mjs.map +1 -0
  10. package/dist/form-b9441d8c.cjs.js +387 -0
  11. package/dist/form-b9441d8c.cjs.js.map +1 -0
  12. package/dist/index.cjs.js +1257 -157
  13. package/dist/index.cjs.js.map +1 -1
  14. package/dist/index.d.ts +357 -53
  15. package/dist/index.mjs +1676 -0
  16. package/dist/index.mjs.map +1 -0
  17. package/dist/index.umd.js +1257 -157
  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/resolvers/standard-schema.cjs.js +90 -0
  22. package/dist/resolvers/standard-schema.cjs.js.map +1 -0
  23. package/dist/resolvers/standard-schema.d.ts +66 -0
  24. package/dist/resolvers/standard-schema.mjs +86 -0
  25. package/dist/resolvers/standard-schema.mjs.map +1 -0
  26. package/dist/resolvers/yup.cjs.js +12 -2
  27. package/dist/resolvers/yup.cjs.js.map +1 -1
  28. package/dist/resolvers/yup.d.ts +2 -2
  29. package/dist/resolvers/yup.mjs +23 -0
  30. package/dist/resolvers/yup.mjs.map +1 -0
  31. package/dist/resolvers/zod.cjs.js +14 -1
  32. package/dist/resolvers/zod.cjs.js.map +1 -1
  33. package/dist/resolvers/zod.d.ts +2 -2
  34. package/dist/resolvers/zod.mjs +23 -0
  35. package/dist/resolvers/zod.mjs.map +1 -0
  36. package/dist/validate-148fe167.d.ts +22 -0
  37. package/package.json +34 -8
  38. package/dist/form-d06e6444.d.ts +0 -201
  39. package/dist/index.esm.js +0 -593
  40. package/dist/index.esm.js.map +0 -1
  41. package/dist/resolvers/yup.esm.js +0 -13
  42. package/dist/resolvers/yup.esm.js.map +0 -1
  43. package/dist/resolvers/zod.esm.js +0 -10
  44. package/dist/resolvers/zod.esm.js.map +0 -1
  45. package/dist/validate-0f17f86a.d.ts +0 -8
package/dist/index.d.ts CHANGED
@@ -1,21 +1,203 @@
1
- import { O as Options, F as Form$1, N as Name, P as Path, a as Name$1 } from './form-d06e6444.js';
2
- export { b as PathValue, o as clearErrors, c as createForm, D as ensureValidate, h as getError, i as getErrorByPath, j as getErrors, k as getFirstError, d as getValue, e as getValueByPath, g as getValues, B as hasErrors, r as hasTouched, t as hasTouchedByPath, H as incrementSubmitCount, v as isDirty, w as isTouched, x as removeField, y as removeFieldByPath, A as reset, m as setError, n as setErrorByPath, z as setInitialValues, G as setIsSubmitting, I as setSubmitSuccessful, p as setTouched, q as setTouchedByPath, l as setValidatingByPath, s as setValue, f as setValueByPath, C as trigger, u as unsetValidatingByPath, E as validate } from './form-d06e6444.js';
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
3
  import * as React from 'react';
4
+ import { ReactNode } from 'react';
5
+ import { V as Validator } from './validate-148fe167.js';
4
6
  import { EventEmitter } from '@for-fun/event-emitter';
5
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
+
6
130
  declare const FormContext: React.Context<any>;
7
131
  declare const FormProvider: React.Provider<any>;
8
- declare function useFormContext(): 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
+ };
9
169
  declare const CheckboxGroupContext: React.Context<any>;
10
170
  declare const CheckboxGroupProvider: React.Provider<any>;
11
171
  declare function useCheckboxGroupContext(): any;
12
172
 
13
- declare function useForm<T extends Record<string, any> = any>(options?: Options<T>): Form$1<T>;
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
+ */
14
196
  declare function useWatch<T>(emitter: EventEmitter, event: string, getter: () => T): T;
15
197
  /**
16
198
  * Get field value state
17
199
  */
18
- declare function useValue(form: Form$1, name: Name): any;
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>;
19
201
  /**
20
202
  * Get field value state by path
21
203
  */
@@ -23,79 +205,187 @@ declare function useValueByPath(form: Form$1, path: Path): any;
23
205
  /**
24
206
  * Get field touched state
25
207
  */
26
- declare function useTouched(form: Form$1, name: Name): boolean;
208
+ declare function useTouched<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): boolean;
27
209
  /**
28
210
  * Get field touched state by path
29
211
  */
30
212
  declare function useTouchedByPath(form: Form$1, path: Path): boolean;
31
213
  /**
32
- * Get field error state
214
+ * Get field error message state
215
+ * @return current error's message string (display text), or undefined
33
216
  */
34
- declare function useError(form: Form$1, name: Name): string | undefined;
217
+ declare function useError<T extends Record<string, any> = any, P extends FieldPath<T> | Name = Name>(form: Form$1<T>, name: P): string | undefined;
35
218
  /**
36
219
  * Get field error state by path
220
+ * @return current FieldError object ({type, message}), or undefined
37
221
  */
38
- declare function useErrorByPath(form: Form$1, path: Path): string | undefined;
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[];
39
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[];
40
246
  declare function useHasErrors(form: Form$1): boolean;
41
247
  declare function useIsSubmitting(form: Form$1): boolean;
42
248
  declare function useSubmitCount(form: Form$1): number;
43
249
 
44
- interface UseFieldOptions$1 {
45
- form?: Form$1;
46
- name: Name$1;
47
- initialValue?: any;
48
- shouldUnregister?: boolean;
49
- validate?: (value: any, meta: {
50
- form: Form$1;
51
- path: Path;
52
- }) => string | undefined | Promise<string | undefined>;
53
- [key: string]: any;
54
- }
55
- interface UseFieldResult {
56
- value: any;
57
- error: string | undefined;
58
- onChange: (v: any) => void;
59
- onBlur: () => void;
60
- name: string;
61
- [key: string]: any;
62
- }
63
- declare function useField({ form: f1, name, initialValue, shouldUnregister, validate, ...rest }: UseFieldOptions$1): UseFieldResult;
64
-
65
- interface FieldArrayItem {
66
- id: string;
67
- index: number;
68
- }
69
- declare function useFieldArray(options: {
70
- name: Name;
71
- form?: Form$1;
72
- }): {
73
- fields: FieldArrayItem[];
74
- append: (value: any) => void;
75
- prepend: (value: any) => void;
76
- insert: (index: number, value: any) => void;
77
- remove: (index: number) => void;
78
- swap: (from: number, to: number) => void;
79
- move: (from: number, to: number) => void;
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;
80
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;
81
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
+ */
82
317
  interface FormProps<T extends Record<string, any> = any> extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {
83
318
  form?: Form<T>;
84
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;
85
329
  onSubmit?: (values: T, e: React.FormEvent) => void;
86
330
  onValidSubmit?: (values: T, e: React.FormEvent) => void;
87
- onInvalidSubmit?: (errors: string[], values: T) => 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;
88
351
  }
89
- declare function Form<T extends Record<string, any> = any>({ form: f1, initialValues, onSubmit, onValidSubmit, onInvalidSubmit, ...props }: FormProps<T>): React.JSX.Element;
352
+ declare function Form<T extends Record<string, any> = any>({ form: f1, initialValues, values, onSubmit, onValidSubmit, onInvalidSubmit, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
90
353
 
91
354
  interface UseFieldOptions {
92
355
  form?: any;
93
- name?: Name$1;
356
+ name?: Name;
94
357
  initialValue?: any;
95
- validate?: (value: any, meta: {
96
- form: any;
97
- path: any;
98
- }) => string | undefined | Promise<string | undefined>;
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;
99
389
  [key: string]: any;
100
390
  }
101
391
  interface FieldProps extends UseFieldOptions {
@@ -103,10 +393,24 @@ interface FieldProps extends UseFieldOptions {
103
393
  asProps?: Record<string, any>;
104
394
  eventToValue?: (e: any) => any;
105
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;
106
404
  }
107
405
  declare const Field: React.ForwardRefExoticComponent<Omit<FieldProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
108
406
  interface CheckboxProps extends UseFieldOptions {
109
407
  }
110
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>>;
111
414
 
112
- export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, Form, FormContext, FormProvider, Name, Options, useCheckboxGroupContext, useError, useErrorByPath, useField, useFieldArray, useForm, useFormContext, useHasErrors, useIsDirty, useIsSubmitting, useSubmitCount, useTouched, useTouchedByPath, useValue, useValueByPath, useWatch };
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 };