react-f0rm 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +107 -24
  2. package/dist/devtools/index.cjs.js +1 -1
  3. package/dist/devtools/index.cjs.js.map +1 -1
  4. package/dist/devtools/index.mjs +1 -1
  5. package/dist/devtools/index.mjs.map +1 -1
  6. package/dist/errors-BKrUdpfI.cjs.js +2 -0
  7. package/dist/errors-BKrUdpfI.cjs.js.map +1 -0
  8. package/dist/errors-CrQBddrJ.mjs +2 -0
  9. package/dist/errors-CrQBddrJ.mjs.map +1 -0
  10. package/dist/{form-CvmWHUrd.d.ts → form-CeKSBs31.d.ts} +68 -5
  11. package/dist/index.cjs.js +1 -1
  12. package/dist/index.cjs.js.map +1 -1
  13. package/dist/index.d.ts +344 -49
  14. package/dist/index.mjs +1 -1
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/index.umd.js +379 -283
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/index.umd.min.js +2 -2
  19. package/dist/index.umd.min.js.map +1 -1
  20. package/dist/persist.cjs.js +1 -1
  21. package/dist/persist.cjs.js.map +1 -1
  22. package/dist/persist.mjs +1 -1
  23. package/dist/persist.mjs.map +1 -1
  24. package/dist/resolvers/standard-schema.cjs.js +1 -1
  25. package/dist/resolvers/standard-schema.mjs +1 -1
  26. package/dist/resolvers/yup.cjs.js +1 -1
  27. package/dist/resolvers/yup.d.ts +1 -1
  28. package/dist/resolvers/yup.mjs +1 -1
  29. package/dist/resolvers/zod.cjs.js +1 -1
  30. package/dist/resolvers/zod.d.ts +1 -1
  31. package/dist/resolvers/zod.mjs +1 -1
  32. package/dist/server/index.cjs.js +1 -1
  33. package/dist/server/index.cjs.js.map +1 -1
  34. package/dist/server/index.d.ts +1 -1
  35. package/dist/server/index.mjs +1 -1
  36. package/dist/server/index.mjs.map +1 -1
  37. package/dist/{validate-B1Gdjeaq.mjs → validate-CNtuUhmk.mjs} +2 -2
  38. package/dist/validate-CNtuUhmk.mjs.map +1 -0
  39. package/dist/{validate-DAfz8Nbb.cjs.js → validate-Cl4ksNFu.cjs.js} +2 -2
  40. package/dist/validate-Cl4ksNFu.cjs.js.map +1 -0
  41. package/dist/{validate-CUmNZqg6.d.ts → validate-nksgv1pR.d.ts} +37 -3
  42. package/dist/values-Cu6awQOJ.cjs.js +2 -0
  43. package/dist/values-Cu6awQOJ.cjs.js.map +1 -0
  44. package/dist/values-DRY-a32G.mjs +2 -0
  45. package/dist/values-DRY-a32G.mjs.map +1 -0
  46. package/package.json +20 -9
  47. package/dist/errors-CxSjrWJO.cjs.js +0 -2
  48. package/dist/errors-CxSjrWJO.cjs.js.map +0 -1
  49. package/dist/errors-CzWtwjO0.mjs +0 -2
  50. package/dist/errors-CzWtwjO0.mjs.map +0 -1
  51. package/dist/validate-B1Gdjeaq.mjs.map +0 -1
  52. package/dist/validate-DAfz8Nbb.cjs.js.map +0 -1
  53. package/dist/values-B1IV-6V4.mjs +0 -2
  54. package/dist/values-B1IV-6V4.mjs.map +0 -1
  55. package/dist/values-CDNAYEOB.cjs.js +0 -2
  56. package/dist/values-CDNAYEOB.cjs.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { a as FieldError, F as Form$1, P as Path, b as FieldPath, c as PathSegments, d as PathValueOf, N as Name, V as ValidationMode, e as FieldErrorEntry, O as Options, f as FormEvents } from './form-CvmWHUrd.js';
2
- export { g as FORM_ERROR, h as FormValidateFn, i as FormValidateMeta, j as PathValue, R as ReValidateMode, S as SetFocusOptions, k as SetServerErrorsOptions, l as VALIDATION_OUTCOME, m as ValidateResult, n as ValidationOutcome, o as clearErrors, p as createForm, q as getError, r as getErrorByPath, s as getErrors, t as getFieldErrors, u as getFieldErrorsByPath, v as getFirstError, w as hasErrors, x as setError, y as setErrorByPath, z as setFocus, A as setServerErrors } from './form-CvmWHUrd.js';
1
+ import { a as FieldError, F as Form$1, P as Path, b as FieldPath, c as PathSegments, d as PathValueOf, N as Name, V as ValidationMode, e as FieldErrorEntry, O as Options, f as FormEvents } from './form-CeKSBs31.js';
2
+ export { g as FORM_ERROR, h as FormValidateFn, i as FormValidateMeta, j as PathValue, R as ReValidateMode, S as SetErrorOptions, k as SetFocusOptions, l as SetServerErrorsOptions, m as VALIDATION_OUTCOME, n as ValidateResult, o as ValidationOutcome, p as clearErrors, q as createForm, r as getError, s as getErrorByPath, t as getErrors, u as getFieldErrors, v as getFieldErrorsByPath, w as getFirstError, x as hasErrors, y as setError, z as setErrorByPath, A as setFocus, B as setServerErrors } from './form-CeKSBs31.js';
3
+ import { EventEmitter } from '@for-fun/event-emitter';
4
+ export { EventEmitter } from '@for-fun/event-emitter';
3
5
  import * as React from 'react';
4
6
  import { ReactNode } from 'react';
5
- import { V as Validator } from './validate-CUmNZqg6.js';
6
- export { F as FormValidationError, S as SyncValidator, T as TriggerOptions, a as ValidatorRegistration, e as ensureValidate, r as registerFieldValidateDeps, b as registerValidatorByPath, c as revalidateDependentsOnChange, d as revalidateFormOnChange, s as setValidatingByPath, t as trigger, u as unregisterFieldValidateDeps, f as unsetValidatingByPath, v as validate } from './validate-CUmNZqg6.js';
7
- import { EventEmitter } from '@for-fun/event-emitter';
7
+ import { S as SyncValidator, V as Validator } from './validate-nksgv1pR.js';
8
+ export { F as FormValidationError, T as TriggerOptions, a as ValidatorRegistration, e as ensureValidate, r as registerFieldValidateDeps, b as registerValidatorByPath, c as revalidateDependentsOnChange, d as revalidateFormOnChange, f as runFormValidate, s as setValidatingByPath, t as trigger, u as unregisterFieldValidateDeps, g as unsetValidatingByPath, v as validate } from './validate-nksgv1pR.js';
8
9
 
9
10
  /**
10
11
  * Get form values: the values Map layered over parsedValues (when a schema
@@ -69,21 +70,28 @@ type SetFieldOptions = {
69
70
  shouldDirty?: boolean;
70
71
  };
71
72
  /**
72
- * Set field value
73
+ * Set field value. The value may also be an updater function receiving
74
+ * the field's current value and returning the next one (TanStack Form's
75
+ * `setFieldValue` contract) — handy for increments and array transforms:
76
+ * `setValue(form, 'count', c => c + 1)`. The tradeoff: a function can
77
+ * never itself be stored as a field value through this function.
73
78
  * @param form
74
79
  * @param name
75
80
  * @param value
76
81
  * @param options
77
82
  */
78
- declare function setValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, value: PathValueOf<T, P>, options?: SetFieldOptions): void;
83
+ declare function setValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, value: PathValueOf<T, P> | ((prev: PathValueOf<T, P>) => PathValueOf<T, P>), options?: SetFieldOptions): void;
79
84
  /**
80
- * Set field value
85
+ * Set field value. The value may also be an updater function receiving
86
+ * the field's current value and returning the next one (TanStack Form's
87
+ * `setFieldValue` contract) — note that a function can therefore never
88
+ * itself be stored as a field value through this function.
81
89
  * @param form
82
90
  * @param path
83
91
  * @param value
84
92
  * @param options
85
93
  */
86
- declare function setValueByPath(form: Form$1, path: Path, value: any, options?: SetFieldOptions): void;
94
+ declare function setValueByPath(form: Form$1, path: Path, value: any | ((prev: any) => any), options?: SetFieldOptions): void;
87
95
  /**
88
96
  * The write of {@link setValueByPath} minus the `'change'` emit: the
89
97
  * render-time {@link useField} `initialValue` seed. The field's first
@@ -205,9 +213,12 @@ type ResetOptions = {
205
213
  keepTouched?: boolean;
206
214
  /** Keep field errors instead of clearing them. */
207
215
  keepErrors?: boolean;
208
- /** Keep the submitted flag (`isSubmitSuccessful`) instead of clearing
209
- * it. */
216
+ /** Keep the submitted flag (`isSubmitted`) instead of clearing it —
217
+ * react-hook-form's `keepIsSubmitted`. */
210
218
  keepIsSubmitted?: boolean;
219
+ /** Keep the last submit's success flag (`isSubmitSuccessful`) instead of
220
+ * clearing it. */
221
+ keepIsSubmitSuccessful?: boolean;
211
222
  /** Keep `submitCount` instead of resetting it to 0. */
212
223
  keepSubmitCount?: boolean;
213
224
  /** Keep `isSubmitting` instead of resetting it to false. */
@@ -293,6 +304,15 @@ declare function getTouchedFields({ touched }: Form$1): string[];
293
304
  */
294
305
  declare function isTouched({ touched }: Form$1): boolean;
295
306
 
307
+ /**
308
+ * Is one field dirty — the per-field rule behind `getFieldState`'s
309
+ * `isDirty` and {@link useIsFieldDirty}: a live value exists at the path
310
+ * and differs from the field's effective baseline (committed
311
+ * `shouldDirty: false` baselines included). A leaf under a wholesale
312
+ * ancestor write reports clean — dirtiness belongs to the branch that
313
+ * actually diverged, the same attribution {@link getDirtyFields} applies.
314
+ */
315
+ declare function isFieldDirtyByPath(form: Form$1, path: Path): boolean;
296
316
  /**
297
317
  * Is dirty -- any value differs from initialValues
298
318
  * @param form
@@ -411,6 +431,16 @@ declare function setSubmitSuccessful(form: Form$1, value: boolean): void;
411
431
  * @param value
412
432
  */
413
433
  declare function setDisabled(form: Form$1, value: boolean): void;
434
+ /**
435
+ * Set the form's user-owned metadata slot (Formik's `status` role): the
436
+ * payload-less 'status' event wakes {@link useStatus} and any imperative
437
+ * `subscribe(form, {event: 'status'})` listeners. Nothing else reads or
438
+ * interprets the value — server session flags, step state, non-field
439
+ * errors of any shape are all fair game. Starts `undefined`.
440
+ * @param form
441
+ * @param value
442
+ */
443
+ declare function setStatus(form: Form$1, value: any): void;
414
444
  /** Submit callbacks for {@link handleSubmit}. All optional — a missing
415
445
  * callback is simply skipped, matching the <Form> component semantics. */
416
446
  type HandleSubmitOptions<T extends Record<string, any> = any> = {
@@ -479,25 +509,39 @@ type RuleType = 'required' | 'min' | 'max' | 'minLength' | 'maxLength' | 'patter
479
509
  */
480
510
  type FieldRules = {
481
511
  /**
482
- * Fails on empty values: `''`, `undefined` or `null` (`0` and `false`
483
- * count as filled). A string is the error message; `true` uses the
484
- * default. When it fails, the remaining rules are skipped an empty
485
- * value reports only its required error.
512
+ * Fails on empty values: `''`, `undefined`, `null` or an empty array
513
+ * (`0` and `false` count as filled) react-hook-form's `required`
514
+ * semantics. A string is the error message; `true` uses the default.
515
+ * When it fails, the remaining rules are skipped — an empty value
516
+ * reports only its required error.
486
517
  */
487
518
  required?: string | true;
488
519
  /** Fails when `Number(value)` is below this bound; `NaN` values skip. */
489
520
  min?: number;
490
521
  /** Fails when `Number(value)` is above this bound; `NaN` values skip. */
491
522
  max?: number;
492
- /** Fails when a string value is shorter than this; non-strings skip. */
523
+ /** Fails when a string value is shorter than this, or an array has
524
+ * fewer entries; other values skip. */
493
525
  minLength?: number;
494
- /** Fails when a string value is longer than this; non-strings skip. */
526
+ /** Fails when a string value is longer than this, or an array has more
527
+ * entries; other values skip. */
495
528
  maxLength?: number;
496
529
  /** Fails when the value does not match `pattern.value`. */
497
530
  pattern?: {
498
531
  value: RegExp;
499
532
  message: string;
500
533
  };
534
+ /**
535
+ * Custom rule callbacks — react-hook-form's `register({validate})`
536
+ * shape: one function, or a record of named functions. Each runs after
537
+ * the declarative checks, and only when they passed (`required` failing
538
+ * short-circuits the rest, RHF's first-error semantics). A returned
539
+ * error keeps its message; its `type` becomes the record key
540
+ * (`'validate'` for the single-function form) so consumers can switch
541
+ * on `error.type`. Sync-only — async checks belong in the field's
542
+ * `validate` option.
543
+ */
544
+ validate?: SyncValidator | Record<string, SyncValidator>;
501
545
  /**
502
546
  * Overrides the message per rule type — `min`, `max`, `minLength`,
503
547
  * `maxLength` defaults and pattern's inline `message` alike — e.g. for
@@ -511,7 +555,22 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
511
555
  name: TPath;
512
556
  initialValue?: any;
513
557
  shouldUnregister?: boolean;
514
- validate?: Validator;
558
+ /**
559
+ * Field-level validator. The value argument follows the path: with a
560
+ * typed form the callback receives `PathValueOf<TValues, TPath>` (the
561
+ * TanStack-parity inference — `name: 'age'` on a `{age: number}` shape
562
+ * types `value` as `number`), and falls back to `any` for untyped call
563
+ * sites (segment arrays, dynamic names). The return shape mirrors
564
+ * {@link Validator} — an error (string / FieldError / mixed array) or
565
+ * undefined when valid, possibly a Promise for async validation. The
566
+ * second argument carries the validation context (`meta.signal` aborts
567
+ * when the round is superseded).
568
+ */
569
+ validate?: (value: PathValueOf<TValues, TPath>, meta: {
570
+ form: Form$1<TValues>;
571
+ path: Path;
572
+ signal: AbortSignal;
573
+ }) => ReturnType<Validator>;
515
574
  /**
516
575
  * Declarative rules (required/min/max/minLength/maxLength/pattern),
517
576
  * compiled into a synchronous validator. `required` is special: it runs
@@ -532,6 +591,18 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
532
591
  * shows immediately instead of waiting out the window.
533
592
  */
534
593
  validateDebounce?: number;
594
+ /**
595
+ * Run this field's debounced validator even when its `required` gate
596
+ * failed — TanStack Form's `asyncAlways`. The gate's errors land
597
+ * immediately (never debounced) and the validator's own result lands
598
+ * alongside them, per-source: a passing async round clears only its
599
+ * own errors while the gate's verdict stays. Falls back to the
600
+ * form-level `createForm({asyncAlways})` flag when omitted, so a field
601
+ * opts out with `asyncAlways: false`. The use case: the cheap format
602
+ * check fails (gate) but the expensive backend check should still run
603
+ * ("not in the right shape — and the backend says taken, too").
604
+ */
605
+ asyncAlways?: boolean;
535
606
  /**
536
607
  * Milliseconds to delay showing a newly appearing error in the render
537
608
  * layer (`error`/`errorObject`/`errors` stay undefined/empty until the
@@ -553,10 +624,14 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
553
624
  * (getValues/submit/validation read it), and errors/touched/disabled/
554
625
  * validating still re-render the field like react-hook-form's
555
626
  * `register`. The result's `value` is the mount-time snapshot (initial
556
- * value seed or baseline); reset/setInitialValues do not push into it
557
- * or into the DOM read live values with useValue/getValues instead.
558
- * Attach the result with `<input defaultValue={field.value}>`-style
559
- * binding (no `value` prop), exactly like <Field uncontrolled /> does.
627
+ * value seed or baseline); it never refreshes, and bulk operations
628
+ * (reset/setInitialValues) sync the DOM element directly through the
629
+ * `focusRef`-held element instead of a render — the register-style
630
+ * contract, RHF's reset clears the input the same way. Attach the
631
+ * result with `<input defaultValue={field.value} ref={field.focusRef}>`
632
+ * -style binding (no `value` prop), exactly like <Field uncontrolled />
633
+ * does. The DOM sync writes the raw stored value (file inputs are
634
+ * skipped); read live values with useValue/getValues.
560
635
  */
561
636
  uncontrolled?: boolean;
562
637
  /**
@@ -592,6 +667,15 @@ type UseFieldOptions$1<TValues extends Record<string, any> = any, TPath extends
592
667
  * the field's own path is a no-op (its own change already validates it).
593
668
  */
594
669
  validateDeps?: FieldPath<TValues>[];
670
+ /**
671
+ * Validate this field once on mount instead of waiting for the first
672
+ * submit/change — errors show immediately for an untouched field.
673
+ * Overrides the form-level `createForm({validateOnMount})` flag in
674
+ * either direction (`false` opts a field out of a validating form).
675
+ * While an async `initialValues` source is still pending the kick waits
676
+ * for the resolved baseline; a field unmounted in between never kicks.
677
+ */
678
+ validateOnMount?: boolean;
595
679
  };
596
680
  /**
597
681
  * The result of {@link useField}. Deliberately a closed shape: no index
@@ -611,6 +695,22 @@ type UseFieldResult<TValues extends Record<string, any> = any, TPath extends Fie
611
695
  * and `errorObject` are its first entry. Empty (and reference-stable)
612
696
  * when the field has no errors. */
613
697
  errors: FieldError[];
698
+ /**
699
+ * Whether the field is dirty: its live value exists and differs from
700
+ * the field's effective baseline (the same per-field rule
701
+ * `getFieldState(form, name).isDirty` applies — committed
702
+ * `shouldDirty: false` baselines included). Live in controlled mode;
703
+ * pinned at mount in uncontrolled mode (like `value`) so typing never
704
+ * re-renders the field — {@link useIsFieldDirty} is the live scoped
705
+ * channel for either mode.
706
+ */
707
+ isDirty: boolean;
708
+ /**
709
+ * Whether a validator round for this field is currently in flight —
710
+ * a pending debounce window or an unresolved async validator (the
711
+ * `getFieldState(form, name).isValidating` reading, made reactive).
712
+ */
713
+ validating: boolean;
614
714
  onChange: (v: any) => void;
615
715
  onBlur: () => void;
616
716
  name: string;
@@ -631,12 +731,38 @@ type UseFieldResult<TValues extends Record<string, any> = any, TPath extends Fie
631
731
  };
632
732
  declare function useField<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(options: UseFieldOptions$1<TValues, TPath>): UseFieldResult<TValues, TPath>;
633
733
 
634
- type FieldArrayItem = {
734
+ type FieldArrayItem<K extends string> = {
635
735
  id: string;
636
736
  index: number;
737
+ } & Record<K, string>;
738
+ /** Options accepted by {@link useFieldArray} and the per-instance hook
739
+ * returned by `createFormContext()`. */
740
+ type UseFieldArrayOptions<K extends string = 'id'> = {
741
+ name: Name;
742
+ form?: Form$1;
743
+ /**
744
+ * Property name the stable row key is exposed under on each `fields`
745
+ * entry (react-hook-form's `keyName`): defaults to `'id'`, a custom
746
+ * name (e.g. `'key'`) avoids clashing with a row data field of the
747
+ * same name. The underlying id is unchanged.
748
+ */
749
+ keyName?: K;
750
+ /**
751
+ * Declarative rules validated against the whole array value
752
+ * (react-hook-form's `useFieldArray` `rules`): `required` fails on an
753
+ * empty array, `minLength`/`maxLength` read the array's length. Checked
754
+ * on submit and `trigger`, like every registered validator.
755
+ */
756
+ rules?: FieldRules;
757
+ /**
758
+ * Whether unmounting this array removes its branch. Defaults to the
759
+ * form-level `shouldUnregister` — tombstone (drop values) like a bound
760
+ * field's unmount; pass `false` to keep the values.
761
+ */
762
+ shouldUnregister?: boolean;
637
763
  };
638
- type UseFieldArrayResult = {
639
- fields: FieldArrayItem[];
764
+ type UseFieldArrayResult<K extends string = 'id'> = {
765
+ fields: FieldArrayItem<K>[];
640
766
  append: (value: any) => void;
641
767
  prepend: (value: any) => void;
642
768
  insert: (index: number, value: any) => void;
@@ -646,10 +772,7 @@ type UseFieldArrayResult = {
646
772
  replace: (values: any[]) => void;
647
773
  update: (index: number, value: any) => void;
648
774
  };
649
- declare function useFieldArray(options: {
650
- name: Name;
651
- form?: Form$1;
652
- }): UseFieldArrayResult;
775
+ declare function useFieldArray<K extends string = 'id'>(options: UseFieldArrayOptions<K>): UseFieldArrayResult<K>;
653
776
  /**
654
777
  * The result of {@link useFieldArrayItem}. Mirrors the {@link useField}
655
778
  * return shape (`value`/`errors`/`error`) plus the row's `index` and
@@ -743,9 +866,12 @@ declare function createFormContext<TValues extends Record<string, any> = any>():
743
866
  useField: <TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments>(options: {
744
867
  name: TPath;
745
868
  } & Omit<UseFieldOptions$1<TValues, TPath>, "form">) => UseFieldResult<TValues, TPath>;
746
- useFieldArray: (options: {
869
+ useFieldArray: <K extends string = "id">(options: {
747
870
  name: FieldPath<TValues> | Name;
748
- }) => UseFieldArrayResult;
871
+ keyName?: K;
872
+ rules?: FieldRules;
873
+ shouldUnregister?: boolean;
874
+ }) => UseFieldArrayResult<K>;
749
875
  useFieldArrayItem: <TValue = any>(options: {
750
876
  name: FieldPath<TValues> | Name;
751
877
  id: string;
@@ -765,13 +891,13 @@ type WatchScope = 'leaf' | 'branch';
765
891
  /** Events {@link subscribe} can watch. `'errors'` and `'touched'` are
766
892
  * stored per exact key, so they match exact keys ({@link onKeyEvent});
767
893
  * `'change'`, `'validating'`, `'submitting'`, `'submitCount'`,
768
- * `'disabled'` and `'submitSuccessful'` go through
894
+ * `'disabled'`, `'status'` and `'submitSuccessful'` go through
769
895
  * {@link onPathEvent}. `'validating'` carries paths (one per async
770
896
  * validator round) and matches by path exactly like `'change'`;
771
- * `'submitting'`, `'submitCount'`, `'disabled'` and
897
+ * `'submitting'`, `'submitCount'`, `'disabled'`, `'status'` and
772
898
  * `'submitSuccessful'` are payload-less broadcasts, so `name` never
773
899
  * narrows them — every subscriber hears every emission. */
774
- type SubscribeEvent = 'change' | 'errors' | 'touched' | 'validating' | 'submitting' | 'submitCount' | 'submitSuccessful' | 'disabled' | 'loading';
900
+ type SubscribeEvent = 'change' | 'errors' | 'touched' | 'validating' | 'submitting' | 'submitCount' | 'submitSuccessful' | 'disabled' | 'status' | 'loading';
775
901
  /** Options accepted by {@link subscribe}. */
776
902
  type SubscribeOptions = {
777
903
  /** Path (or list of paths) to watch. Omit to receive every emission of
@@ -785,9 +911,10 @@ type SubscribeOptions = {
785
911
  /** Which writes around `name` are relevant — `'leaf'` or `'branch'`.
786
912
  * Only meaningful for the path-carrying events `'change'` and
787
913
  * `'validating'`: `'errors'`/`'touched'` match exact keys and
788
- * `'submitting'`/`'submitCount'`/`'disabled'`/`'submitSuccessful'`
789
- * are payload-less. Defaults to `'branch'` — the intuitive linkage
790
- * semantics, where subscribing to `'tags'` means the whole branch. */
914
+ * `'submitting'`/`'submitCount'`/`'disabled'`/`'status'`/
915
+ * `'submitSuccessful'` are payload-less. Defaults to `'branch'` — the
916
+ * intuitive linkage semantics, where subscribing to `'tags'` means the
917
+ * whole branch. */
791
918
  scope?: WatchScope;
792
919
  /** Invoked with no arguments after each matching emission. Read fresh
793
920
  * state through the `get*` readers inside it. */
@@ -875,14 +1002,31 @@ declare function useWatchCore<T>(subscribeFactory: (invalidate: () => void) => (
875
1002
  * `useSelector` compare. Omitted, behavior is unchanged.
876
1003
  */
877
1004
  declare function useWatch<T>(formOrEmitter: Form$1 | EventEmitter<FormEvents>, event: SubscribeEvent, getter: () => T, isEqual?: (prev: T, next: T) => boolean): T;
1005
+ /** Options for {@link useValue} and {@link useValueByPath}. */
1006
+ type UseValueOptions<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments> = {
1007
+ /** Value to return while the field reads undefined — react-hook-form's
1008
+ * `useWatch` `defaultValue`: an untouched, never-seeded field reads
1009
+ * this instead of `undefined`. */
1010
+ defaultValue?: PathValueOf<T, P>;
1011
+ /** Watch descendants too (react-hook-form's `exact: false`): a write
1012
+ * to `a.b` invalidates a `useValue(form, 'a')` read, and the read
1013
+ * resolves the merged subtree (the copy-on-write `getValues` tree) so
1014
+ * descendant edits show up in the result. Defaults to true — the leaf
1015
+ * scope, where only the exact key and its ancestors invalidate (the
1016
+ * long-standing behavior). */
1017
+ exact?: boolean;
1018
+ };
878
1019
  /**
879
1020
  * Get field value state
880
1021
  */
881
- declare function useValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): PathValueOf<T, P>;
1022
+ declare function useValue<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P, options?: UseValueOptions<T, P>): PathValueOf<T, P>;
882
1023
  /**
883
1024
  * Get field value state by path
884
1025
  */
885
- declare function useValueByPath(form: Form$1, path: Path): any;
1026
+ declare function useValueByPath(form: Form$1, path: Path, options?: {
1027
+ defaultValue?: any;
1028
+ exact?: boolean;
1029
+ }): any;
886
1030
  /**
887
1031
  * Get field touched state
888
1032
  */
@@ -914,6 +1058,21 @@ declare function useFieldErrors<T extends Record<string, any> = any, P extends F
914
1058
  */
915
1059
  declare function useFieldErrorsByPath(form: Form$1, path: Path): FieldError[];
916
1060
  declare function useIsDirty(form: Form$1): boolean;
1061
+ /**
1062
+ * Get whether one field is dirty: its live value exists and differs from
1063
+ * the field's effective baseline — the same per-field rule
1064
+ * `getFieldState(form, name).isDirty` applies (committed
1065
+ * `shouldDirty: false` baselines included). Subscribes to 'change' at
1066
+ * leaf scope like {@link useValue}: own-key and ancestor writes re-check
1067
+ * the flag, payload-less broadcasts (reset, setInitialValues) always
1068
+ * sync, and writes elsewhere never re-render it.
1069
+ */
1070
+ declare function useIsFieldDirty<T extends Record<string, any> = any, P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments>(form: Form$1<T>, name: P): boolean;
1071
+ /**
1072
+ * Get whether one field is dirty, by parsed path. See {@link
1073
+ * useIsFieldDirty}.
1074
+ */
1075
+ declare function useIsFieldDirtyByPath(form: Form$1, path: Path): boolean;
917
1076
  /**
918
1077
  * Get dirty fields state -- object mapping each dirty field's user-facing
919
1078
  * dotted path ('a.b', 'a.0.c') to true; recalculated after 'change' events
@@ -952,6 +1111,13 @@ type FormState = {
952
1111
  * separate signal; async rounds temporarily pass this flag like RHF's). */
953
1112
  isValid: boolean;
954
1113
  isSubmitting: boolean;
1114
+ /**
1115
+ * Whether a submit has been attempted on this form — set on the first
1116
+ * `handleSubmit` call (validation outcome aside) and cleared by
1117
+ * `reset`, react-hook-form's `formState.isSubmitted` semantics. Read
1118
+ * after a failed submit to render a "fix the errors below" panel.
1119
+ */
1120
+ isSubmitted: boolean;
955
1121
  /** Any validation round is running (field, form-level, or a pending
956
1122
  * debounce window). */
957
1123
  isValidating: boolean;
@@ -978,6 +1144,15 @@ declare function useIsSubmitting(form: Form$1): boolean;
978
1144
  * the core emits around the resolution cycle.
979
1145
  */
980
1146
  declare function useIsLoading(form: Form$1): boolean;
1147
+ /**
1148
+ * Get the form's user-owned metadata slot reactively (Formik's `status`
1149
+ * counterpart): any value the app stores through {@link setStatus} —
1150
+ * server session flags, wizard step state, non-field errors. Subscribes
1151
+ * to the payload-less 'status' event, so unrelated events never re-render
1152
+ * the caller, and the returned reference is stable between writes that
1153
+ * store an equal value (useSyncExternalStore's Object.is bailout).
1154
+ */
1155
+ declare function useStatus<T = any>(form: Form$1): T;
981
1156
  /**
982
1157
  * Get whether the form accepts a submit right now:
983
1158
  * `!isSubmitting && !hasErrors`. This is the single flag a submit
@@ -1037,6 +1212,66 @@ declare function useFormError(form: Form$1): string | undefined;
1037
1212
  */
1038
1213
  declare function useFormErrors(form: Form$1): FieldError[];
1039
1214
 
1215
+ /**
1216
+ * Options accepted by {@link useTransform}.
1217
+ */
1218
+ type UseTransformOptions<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments, TDisplay = PathValueOf<TValues, TPath>> = {
1219
+ /**
1220
+ * Map the form's stored (raw) value to the display value the control
1221
+ * renders — the read direction. Omitted: the raw value is displayed
1222
+ * as-is (identity).
1223
+ */
1224
+ toDisplay?: (raw: PathValueOf<TValues, TPath>) => TDisplay;
1225
+ /**
1226
+ * Map a display value back to the raw value written into the form —
1227
+ * the write direction. Omitted: the display value is written as-is
1228
+ * (identity). The round trip should be an identity
1229
+ * (`toDisplay(fromDisplay(x)) === x`); a store value the transform
1230
+ * cannot invert (e.g. `undefined` for a not-yet-edited field) must be
1231
+ * handled by `toDisplay`, since it runs first.
1232
+ */
1233
+ fromDisplay?: (display: TDisplay) => PathValueOf<TValues, TPath>;
1234
+ };
1235
+ /**
1236
+ * Bind a control to a field whose stored value and display value differ
1237
+ * — TanStack Form's `useTransform` counterpart, with the round trip made
1238
+ * explicit: `toDisplay` maps the store value to what the control shows,
1239
+ * `fromDisplay` maps the control's display value back to what the store
1240
+ * holds. The store always carries the raw typed value, so
1241
+ * `getValues`/submit/validation never see display representations.
1242
+ *
1243
+ * ```jsx
1244
+ * const age = useTransform(form, 'age', {
1245
+ * toDisplay: (raw: number) => String(raw),
1246
+ * fromDisplay: (display: string) => Number(display)
1247
+ * });
1248
+ * <input value={age.value} onChange={e => age.onChange(e.target.value)} />
1249
+ * ```
1250
+ *
1251
+ * `value` subscribes to 'change' at leaf scope exactly like a controlled
1252
+ * `useField` value — typing, programmatic `setValue` and ancestor writes
1253
+ * all re-derive it, writes elsewhere never re-render it. `onChange`
1254
+ * writes through `userChangeByPath` (the user-change channel): with a
1255
+ * field mounted at the same path the mode/reValidateMode-gated
1256
+ * validation fires exactly as if the user typed into a bound field; with
1257
+ * no mounted field it degrades to a plain value write. Touched marking
1258
+ * stays a blur concern — pair this with `useField` at the same path, or
1259
+ * call `setTouched`, when blur semantics matter.
1260
+ *
1261
+ * The transform functions are read fresh on every render (inline
1262
+ * closures work), and `value` is recomputed per render — keep display
1263
+ * values primitive (string/number) so React's equal-state bailout holds.
1264
+ *
1265
+ * @param form the form instance (explicit; the hook is headless — no
1266
+ * context read, no provider required)
1267
+ * @param name the field's path (dotted string or segments)
1268
+ * @param options the two mapping directions; both optional (identity)
1269
+ */
1270
+ declare function useTransform<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | PathSegments = FieldPath<TValues> | PathSegments, TDisplay = PathValueOf<TValues, TPath>>(form: Form$1<TValues>, name: TPath, options?: UseTransformOptions<TValues, TPath, TDisplay>): {
1271
+ value: TDisplay;
1272
+ onChange: (display: TDisplay) => void;
1273
+ };
1274
+
1040
1275
  /**
1041
1276
  * Props for <Form>.
1042
1277
  *
@@ -1075,6 +1310,27 @@ type FormProps<T extends Record<string, any> = any> = Omit<React.FormHTMLAttribu
1075
1310
  * unmounted fields, `false` keeps their values.
1076
1311
  */
1077
1312
  shouldUnregister?: boolean;
1313
+ /**
1314
+ * Validate on mount (see {@link Options.validateOnMount}): every
1315
+ * mounted field with a validator kicks once after mount and the
1316
+ * form-level `validate` (if any) runs once. A field's own
1317
+ * `validateOnMount` prop overrides this flag.
1318
+ */
1319
+ validateOnMount?: boolean;
1320
+ /**
1321
+ * Disable every bound field: the form-level flag fields OR with their
1322
+ * own `disabled` option (a field cannot opt out). Seeded at create and
1323
+ * kept in sync while this prop changes (undefined leaves the current
1324
+ * flag untouched — toggle at runtime with `setDisabled`).
1325
+ */
1326
+ disabled?: boolean;
1327
+ /**
1328
+ * Form-level default for field validation's `asyncAlways`: a field
1329
+ * whose `required` gate failed still runs its debounced validator, its
1330
+ * result landing per-source alongside the gate's errors. A field's own
1331
+ * `asyncAlways` prop overrides this flag.
1332
+ */
1333
+ asyncAlways?: boolean;
1078
1334
  /**
1079
1335
  * Controlled external values. When the `values` reference changes, the
1080
1336
  * new object is synced into the form (via setInitialValues semantics):
@@ -1120,7 +1376,7 @@ type FormProps<T extends Record<string, any> = any> = Omit<React.FormHTMLAttribu
1120
1376
  */
1121
1377
  shouldFocusError?: boolean;
1122
1378
  };
1123
- declare function Form<T extends Record<string, any> = any>({ form: f1, context, initialValues, values, shouldUnregister, onSubmit, onValidSubmit, onInvalidSubmit, action, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
1379
+ declare function Form<T extends Record<string, any> = any>({ form: f1, context, initialValues, values, shouldUnregister, validateOnMount, disabled, asyncAlways, onSubmit, onValidSubmit, onInvalidSubmit, action, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
1124
1380
 
1125
1381
  /**
1126
1382
  * Props for {@link FormField}: every {@link UseFieldOptions} option plus a
@@ -1172,10 +1428,17 @@ type UseFieldOptions<TValues extends Record<string, any> = any, TPath extends Fi
1172
1428
  signal: AbortSignal;
1173
1429
  }) => ReturnType<Validator>;
1174
1430
  /**
1175
- * Declarative rules (required/min/max/minLength/maxLength/pattern),
1176
- * compiled into a validator that runs before `validate`; failures land
1177
- * in the form's error state. Passed through to useField — like
1178
- * validateDebounce it is never spread onto the DOM element.
1431
+ * Declarative rules (required/min/max/minLength/maxLength/pattern,
1432
+ * plus custom `validate` callbacks), compiled into a validator that
1433
+ * runs before `validate`; failures land in the form's error state.
1434
+ * The declarative subset is also rendered as native constraint
1435
+ * attributes (`required`, `minLength`, `pattern`, …) onto the element
1436
+ * for browser/AT hints — `:invalid` styling, screen-reader
1437
+ * announcements — while the store pipeline stays the source of truth
1438
+ * for messages (`renderError`/`aria-invalid` keep working; a user-passed
1439
+ * `required`/`pattern`/… prop overrides the derived attribute). Passed
1440
+ * through to useField — like validateDebounce it is never spread onto
1441
+ * the DOM element.
1179
1442
  */
1180
1443
  rules?: FieldRules;
1181
1444
  /**
@@ -1185,6 +1448,21 @@ type UseFieldOptions<TValues extends Record<string, any> = any, TPath extends Fi
1185
1448
  * useField/useValidate.
1186
1449
  */
1187
1450
  validateDebounce?: number;
1451
+ /**
1452
+ * Run this field's debounced validator even when its `required` gate
1453
+ * failed (TanStack Form's `asyncAlways`): the gate's errors land
1454
+ * immediately, the validator's own result lands alongside them
1455
+ * per-source. Falls back to the form-level `createForm({asyncAlways})`.
1456
+ * Passed through to useField.
1457
+ */
1458
+ asyncAlways?: boolean;
1459
+ /**
1460
+ * Validate this field once on mount (see {@link
1461
+ * UseFieldOptions}' `validateOnMount`): overrides the form-level
1462
+ * `createForm({validateOnMount})` / `<Form validateOnMount>` flag in
1463
+ * either direction. Passed through to useField.
1464
+ */
1465
+ validateOnMount?: boolean;
1188
1466
  /**
1189
1467
  * Disable this field's control: OR-ed with the form-level flag
1190
1468
  * (`createForm({disabled})` / `setDisabled`) — a field cannot opt out
@@ -1212,9 +1490,10 @@ type UseFieldOptions<TValues extends Record<string, any> = any, TPath extends Fi
1212
1490
  * Uncontrolled mode: render the element with `defaultValue` instead of
1213
1491
  * `value` — typing re-renders nothing (the store still carries every
1214
1492
  * write; errors/touched/disabled still re-render the field). The
1215
- * snapshot is pinned at mount; reset does not clear the DOM element
1216
- * (read live values with useValue/getValues). Passed through to
1217
- * useField, never spread onto the DOM element.
1493
+ * snapshot is pinned at mount; bulk operations (reset/setInitialValues)
1494
+ * sync the DOM element directly without a render — RHF-register
1495
+ * behavior (read live values with useValue/getValues). Passed through
1496
+ * to useField, never spread onto the DOM element.
1218
1497
  */
1219
1498
  uncontrolled?: boolean;
1220
1499
  [key: string]: any;
@@ -1234,6 +1513,22 @@ type FieldProps<TValues extends Record<string, any> = any, TPath extends FieldPa
1234
1513
  * wiring for free.
1235
1514
  */
1236
1515
  renderError?: (error: string, id: string) => React.ReactNode;
1516
+ /**
1517
+ * Store `e.target.valueAsNumber` instead of the string value —
1518
+ * react-hook-form's `register({valueAsNumber})` counterpart for number
1519
+ * inputs (`<input type="number">`). `NaN` passes through as-is when the
1520
+ * input cannot be parsed, matching RHF. An explicit `eventToValue`
1521
+ * takes precedence.
1522
+ */
1523
+ valueAsNumber?: boolean;
1524
+ /**
1525
+ * Store `e.target.valueAsDate` instead of the string value — RHF's
1526
+ * `register({valueAsDate})` counterpart for date/time inputs. `null`
1527
+ * passes through when the input cannot be parsed. An explicit
1528
+ * `eventToValue` takes precedence; combining with `valueAsNumber` is a
1529
+ * TypeError.
1530
+ */
1531
+ valueAsDate?: boolean;
1237
1532
  };
1238
1533
  /**
1239
1534
  * The error-message element id a field's `aria-describedby` points at —
@@ -1279,5 +1574,5 @@ type SelectComponent = {
1279
1574
  };
1280
1575
  declare const Select: SelectComponent;
1281
1576
 
1282
- export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, FieldError, FieldErrorEntry, FieldPath, Form, FormContext, FormEvents, FormField, Form$1 as FormInstance, FormProvider, Name, Options, Path, PathSegments, PathValueOf, Select, ValidationMode, Validator, changeValue, changeValueByPath, createFormContext, emitChangeByPath, fieldErrorId, getDirtyFields, getFieldState, getTouchedFields, getValue, getValueByPath, getValues, handleSubmit, hasTouched, hasTouchedByPath, incrementSubmitCount, isDirty, isTouched, registerFieldMode, removeField, removeFieldByPath, reset, resetField, seedValueByPath, setDisabled, setInitialValues, setIsSubmitting, setSubmitSuccessful, setTouched, setTouchedByPath, setValue, setValueByPath, subscribe, unregisterFieldMode, useCanSubmit, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useField, useFieldArray, useFieldArrayItem, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useFormError, useFormErrors, useFormState, useHasErrors, useIsDirty, useIsLoading, useIsSubmitSuccessful, useIsSubmitting, useIsValid, useIsValidating, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useValue, useValueByPath, useWatch, useWatchCore, userBlur, userChangeByPath };
1283
- export type { FieldRules, FieldState, FormState, HandleSubmitOptions, RemoveFieldOptions, ResetFieldOptions, ResetOptions, SetFieldOptions, SubscribeEvent, SubscribeOptions, WatchScope };
1577
+ export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, FieldError, FieldErrorEntry, FieldPath, Form, FormContext, FormEvents, FormField, Form$1 as FormInstance, FormProvider, Name, Options, Path, PathSegments, PathValueOf, Select, SyncValidator, ValidationMode, Validator, changeValue, changeValueByPath, createFormContext, emitChangeByPath, fieldErrorId, getDirtyFields, getFieldState, getTouchedFields, getValue, getValueByPath, getValues, handleSubmit, hasTouched, hasTouchedByPath, incrementSubmitCount, isDirty, isFieldDirtyByPath, isTouched, registerFieldMode, removeField, removeFieldByPath, reset, resetField, seedValueByPath, setDisabled, setInitialValues, setIsSubmitting, setStatus, setSubmitSuccessful, setTouched, setTouchedByPath, setValue, setValueByPath, subscribe, unregisterFieldMode, useCanSubmit, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useField, useFieldArray, useFieldArrayItem, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useFormError, useFormErrors, useFormState, useHasErrors, useIsDirty, useIsFieldDirty, useIsFieldDirtyByPath, useIsLoading, useIsSubmitSuccessful, useIsSubmitting, useIsValid, useIsValidating, useStatus, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useTransform, useValue, useValueByPath, useWatch, useWatchCore, userBlur, userChangeByPath };
1578
+ export type { FieldRules, FieldState, FormState, HandleSubmitOptions, RemoveFieldOptions, ResetFieldOptions, ResetOptions, SetFieldOptions, SubscribeEvent, SubscribeOptions, UseTransformOptions, UseValueOptions, WatchScope };