attaform 0.17.0 → 0.17.2

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 (59) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.d.cts +4 -4
  3. package/dist/index.d.mts +4 -4
  4. package/dist/index.d.ts +4 -4
  5. package/dist/index.mjs +2 -2
  6. package/dist/nuxt.d.cts +1 -1
  7. package/dist/nuxt.d.mts +1 -1
  8. package/dist/nuxt.d.ts +1 -1
  9. package/dist/shared/{attaform.ClfCi1i2.d.mts → attaform.B1jvxsOF.d.mts} +1 -1
  10. package/dist/shared/{attaform.BT55rDNN.mjs → attaform.B3ZaPIzS.mjs} +15 -2
  11. package/dist/shared/attaform.B3ZaPIzS.mjs.map +1 -0
  12. package/dist/shared/{attaform.0Wg7UEeX.cjs → attaform.BPRHR3Zs.cjs} +20 -8
  13. package/dist/shared/attaform.BPRHR3Zs.cjs.map +1 -0
  14. package/dist/shared/{attaform.C6_zOf8x.cjs → attaform.BV40t5y2.cjs} +16 -6
  15. package/dist/shared/attaform.BV40t5y2.cjs.map +1 -0
  16. package/dist/shared/attaform.C0iFnTN0.d.ts +165 -0
  17. package/dist/shared/attaform.C5MH4lNh.d.mts +53 -0
  18. package/dist/shared/attaform.C6lbmMUe.d.ts +53 -0
  19. package/dist/shared/{attaform.D7lomopc.d.cts → attaform.C6qzEdIM.d.cts} +1 -1
  20. package/dist/shared/attaform.CHorcsIU.d.cts +165 -0
  21. package/dist/shared/{attaform.B0zue7zt.d.ts → attaform.CTwNcpLE.d.ts} +1 -1
  22. package/dist/shared/{attaform.BYbsV2Wv.d.mts → attaform.C_5aB6EQ.d.cts} +95 -15
  23. package/dist/shared/{attaform.BYbsV2Wv.d.ts → attaform.C_5aB6EQ.d.mts} +95 -15
  24. package/dist/shared/{attaform.BYbsV2Wv.d.cts → attaform.C_5aB6EQ.d.ts} +95 -15
  25. package/dist/shared/{attaform.BFumZXY2.cjs → attaform.Cer8JO_P.cjs} +15 -2
  26. package/dist/shared/attaform.Cer8JO_P.cjs.map +1 -0
  27. package/dist/shared/{attaform.Cj0pCNVn.mjs → attaform.CpERWz3u.mjs} +16 -6
  28. package/dist/shared/attaform.CpERWz3u.mjs.map +1 -0
  29. package/dist/shared/attaform.CuE-bS1C.d.mts +165 -0
  30. package/dist/shared/{attaform.D6Q5ZP8L.mjs → attaform.Drt6fivF.mjs} +20 -8
  31. package/dist/shared/attaform.Drt6fivF.mjs.map +1 -0
  32. package/dist/shared/attaform.DtMN-MAm.d.cts +53 -0
  33. package/dist/zod-v3.cjs +2 -2
  34. package/dist/zod-v3.d.cts +35 -61
  35. package/dist/zod-v3.d.mts +35 -61
  36. package/dist/zod-v3.d.ts +35 -61
  37. package/dist/zod-v3.mjs +2 -2
  38. package/dist/zod-v4.cjs +2 -2
  39. package/dist/zod-v4.d.cts +4 -4
  40. package/dist/zod-v4.d.mts +4 -4
  41. package/dist/zod-v4.d.ts +4 -4
  42. package/dist/zod-v4.mjs +2 -2
  43. package/dist/zod.cjs +9 -5
  44. package/dist/zod.cjs.map +1 -1
  45. package/dist/zod.d.cts +37 -11
  46. package/dist/zod.d.mts +37 -11
  47. package/dist/zod.d.ts +37 -11
  48. package/dist/zod.mjs +9 -5
  49. package/dist/zod.mjs.map +1 -1
  50. package/package.json +4 -4
  51. package/dist/shared/attaform.0Wg7UEeX.cjs.map +0 -1
  52. package/dist/shared/attaform.AOgGyRoI.d.cts +0 -65
  53. package/dist/shared/attaform.BFumZXY2.cjs.map +0 -1
  54. package/dist/shared/attaform.BQ-iGGWd.d.mts +0 -65
  55. package/dist/shared/attaform.BT55rDNN.mjs.map +0 -1
  56. package/dist/shared/attaform.C6_zOf8x.cjs.map +0 -1
  57. package/dist/shared/attaform.CX9v2M8k.d.ts +0 -65
  58. package/dist/shared/attaform.Cj0pCNVn.mjs.map +0 -1
  59. package/dist/shared/attaform.D6Q5ZP8L.mjs.map +0 -1
@@ -670,6 +670,34 @@ type AbstractSchema<Form, GetValueFormType> = {
670
670
  * callers treat that as "don't fill" and fall back to existing data.
671
671
  */
672
672
  getDefaultAtPath(path: Path): unknown;
673
+ /**
674
+ * Return the schema's "appropriate nullish value" at the given path
675
+ * — the underlying type's empty/falsy concrete, with `.default(x)`
676
+ * wrappers explicitly NOT honoured. Powers `form.clear(path)`:
677
+ * `clear` differs from `reset` precisely in that it ignores
678
+ * declared defaults and produces `false` / `0` / `''` / `[]` / a
679
+ * recursively-empty object instead.
680
+ *
681
+ * Semantics (mirrors `getDefaultAtPath`'s sub-path resolution,
682
+ * differs at leaves):
683
+ * - **Primitive leaf:** the primitive's falsy concrete
684
+ * (`''` / `0` / `false` / `0n` / `new Date(0)`, etc.).
685
+ * - **Array / Set / Record:** empty.
686
+ * - **Optional<T>:** `undefined` (the wrapper's "absent" marker).
687
+ * - **Nullable<T>:** `null` (the wrapper's "explicit empty").
688
+ * - **Default<T> / Prefault<T> / Catch<T>:** inner-schema empty
689
+ * — the declared default value is INTENTIONALLY skipped.
690
+ * - **Readonly<T> / preprocess(fn, T):** inner-schema empty.
691
+ * - **Object:** recursive — every property gets its own empty.
692
+ * - **Discriminated union:** first variant's recursive empty
693
+ * (parallels `getDefaultAtPath`'s first-success precedent).
694
+ * - **Path doesn't exist in schema:** `undefined`.
695
+ *
696
+ * Adapters may return `undefined` when the path can't be resolved;
697
+ * callers treat that as "don't write" and leave existing storage
698
+ * unchanged.
699
+ */
700
+ getEmptyValueAtPath(path: Path): unknown;
673
701
  /**
674
702
  * Give the schema a chance to normalize the consumer's write value
675
703
  * before it lands in storage / hits the slim-primitive gate. Each
@@ -3016,23 +3044,30 @@ type FormMeta<F = unknown> = FieldState<F> & {
3016
3044
  * form.meta.submitting // form-level reactive flag
3017
3045
  * ```
3018
3046
  *
3019
- * Two generic slots split the input view from the output view:
3047
+ * Three generic slots split the write view, parse view, and read view:
3020
3048
  *
3021
- * - `Form` — the **input / storage shape** (`z.input<Schema>`). Used
3022
- * by `setValue`, `defaultValues`, `values`, `fields`, `register`,
3023
- * `toRef`, and every path-addressed API. Storage holds values as
3024
- * the consumer wrote them; preprocess normalization runs at the
3025
- * write boundary, but `.transform()`s are deferred to parse-time.
3049
+ * - `Form` — the **input / write shape** (`z.input<Schema>`). Used
3050
+ * by `setValue`, `defaultValues`, and `register`'s write side.
3051
+ * Loose: preprocess paths accept `unknown` at the write boundary,
3052
+ * defaulted fields accept their inner type optionally.
3026
3053
  *
3027
3054
  * - `GetValueFormType` — the **output / parsed shape**
3028
3055
  * (`z.output<Schema>`). Used by `handleSubmit`'s `onSubmit`
3029
3056
  * callback and by `form.process()`'s success payload. This is the
3030
3057
  * shape after refinements have fired and transforms have run.
3031
3058
  *
3032
- * For schemas without transforms the two are identical, and the
3033
- * default `GetValueFormType = Form` keeps the surface ergonomic.
3059
+ * - `ReadForm` the **read / storage shape**. Used by `values`,
3060
+ * `fields`, `register`'s read side, `toRef`. Per-key precise: at
3061
+ * the write-boundary wrappers (`default` / `prefault` / `catch` /
3062
+ * `readonly` / `preprocess`) the value is `z.output<Inner>`
3063
+ * (default has fired, preprocess has normalized); at transforms /
3064
+ * pipes the value stays `z.input<Inner>` (transforms are deferred
3065
+ * until parse). For schema-agnostic call sites defaults to `Form`.
3066
+ *
3067
+ * For schemas without write-boundary wrappers or transforms the three
3068
+ * shapes coincide.
3034
3069
  */
3035
- type UseFormReturnType<Form extends GenericForm, GetValueFormType extends GenericForm = Form> = {
3070
+ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form> = {
3036
3071
  /**
3037
3072
  * Wraps your submit logic with validation and error routing.
3038
3073
  *
@@ -3079,7 +3114,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3079
3114
  * value reads as `string`, not `boolean`. Use `handleSubmit` or
3080
3115
  * `form.process()` when you need the post-transform output shape.
3081
3116
  */
3082
- values: ValuesSurface<WriteShape<Form>>;
3117
+ values: ValuesSurface<WriteShape<ReadForm>>;
3083
3118
  /**
3084
3119
  * Reactive per-field state proxy. Pinia-style nested object — read
3085
3120
  * leaf properties (`value`, `dirty`, `touched`, `errors`, `blurred`,
@@ -3108,7 +3143,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3108
3143
  * Document edge case; rename the offending schema field if the
3109
3144
  * collision matters.
3110
3145
  */
3111
- fields: FieldStateMap<WriteShape<Form>>;
3146
+ fields: FieldStateMap<WriteShape<ReadForm>>;
3112
3147
  /**
3113
3148
  * Write to the form programmatically. Two forms:
3114
3149
  *
@@ -3259,8 +3294,8 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3259
3294
  * for storage activity to actually happen.
3260
3295
  */
3261
3296
  register: {
3262
- <Path extends RegisterFlatPath<Form, keyof Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<Form>, Path>>;
3263
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form, keyof Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<Form>, JoinSegments<S>>>;
3297
+ <Path extends RegisterFlatPath<Form, keyof Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, Path>>;
3298
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form, keyof Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>;
3264
3299
  };
3265
3300
  /**
3266
3301
  * The form's identifier — either the explicit `key` passed to
@@ -3315,8 +3350,8 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3315
3350
  * scripts; `toRef` is for ref-shaped interop only.
3316
3351
  */
3317
3352
  toRef: {
3318
- <Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<Form>, Path>>>;
3319
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<Form>, JoinSegments<S>>>>;
3353
+ <Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, Path>>>;
3354
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>>;
3320
3355
  };
3321
3356
  /**
3322
3357
  * Replace every field error for this form with the provided list.
@@ -3430,6 +3465,51 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3430
3465
  * from the persisted draft too.
3431
3466
  */
3432
3467
  resetField: (path: FlatPath<Form>) => void;
3468
+ /**
3469
+ * Wipe a field (or the whole form) to the "appropriate nullish
3470
+ * value" for its declared type — the underlying type's empty/falsy
3471
+ * concrete, with any `.default(x)` wrapper INTENTIONALLY skipped.
3472
+ * Orthogonal to `reset` / `resetField` by design.
3473
+ *
3474
+ * ```ts
3475
+ * const schema = z.object({
3476
+ * notify: z.boolean().default(true),
3477
+ * count: z.number().default(5),
3478
+ * })
3479
+ * const form = useForm({ schema })
3480
+ *
3481
+ * form.reset() // notify → true, count → 5 (defaults)
3482
+ * form.clear() // notify → false, count → 0 (falsy-for-type)
3483
+ * form.clear('notify') // → false (NOT the declared default true)
3484
+ * ```
3485
+ *
3486
+ * Per-wrapper semantics:
3487
+ *
3488
+ * - `.default(x)` / `.prefault(x)` / `.catch(x)` → inner-schema
3489
+ * empty (default is INTENTIONALLY skipped).
3490
+ * - `.optional()` → `undefined` (the wrapper's "absent" marker).
3491
+ * - `.nullable()` → `null` (the wrapper's "explicit empty").
3492
+ * - Object → recursive (every property gets its own empty).
3493
+ * - Array / Set / Record → empty.
3494
+ *
3495
+ * Returns `true` when the write was accepted, `false` when the
3496
+ * adapter couldn't resolve an empty value at the path (e.g. the
3497
+ * path doesn't exist in the schema). The form state is unchanged
3498
+ * on a `false` return.
3499
+ *
3500
+ * Sugar over `setValue(path, schema.getEmptyValueAtPath(path))` —
3501
+ * no separate bookkeeping. Variant memory, history, persistence,
3502
+ * and listeners all see this as a regular write at the path.
3503
+ *
3504
+ * `clear()` (no arg) targets the whole form. `clear('')` targets
3505
+ * the empty-string path slot SPECIFICALLY — the two are NOT
3506
+ * interchangeable, matching `touch()` / `touch('')` from #184.
3507
+ */
3508
+ clear: {
3509
+ (): boolean;
3510
+ <Path extends FlatPath<Form> | ''>(path: Path): boolean;
3511
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown : never)): boolean;
3512
+ };
3433
3513
  /**
3434
3514
  * Write the current value at `path` to storage immediately. Useful
3435
3515
  * for explicit "Save draft" buttons, `beforeunload` handlers, or
@@ -670,6 +670,34 @@ type AbstractSchema<Form, GetValueFormType> = {
670
670
  * callers treat that as "don't fill" and fall back to existing data.
671
671
  */
672
672
  getDefaultAtPath(path: Path): unknown;
673
+ /**
674
+ * Return the schema's "appropriate nullish value" at the given path
675
+ * — the underlying type's empty/falsy concrete, with `.default(x)`
676
+ * wrappers explicitly NOT honoured. Powers `form.clear(path)`:
677
+ * `clear` differs from `reset` precisely in that it ignores
678
+ * declared defaults and produces `false` / `0` / `''` / `[]` / a
679
+ * recursively-empty object instead.
680
+ *
681
+ * Semantics (mirrors `getDefaultAtPath`'s sub-path resolution,
682
+ * differs at leaves):
683
+ * - **Primitive leaf:** the primitive's falsy concrete
684
+ * (`''` / `0` / `false` / `0n` / `new Date(0)`, etc.).
685
+ * - **Array / Set / Record:** empty.
686
+ * - **Optional<T>:** `undefined` (the wrapper's "absent" marker).
687
+ * - **Nullable<T>:** `null` (the wrapper's "explicit empty").
688
+ * - **Default<T> / Prefault<T> / Catch<T>:** inner-schema empty
689
+ * — the declared default value is INTENTIONALLY skipped.
690
+ * - **Readonly<T> / preprocess(fn, T):** inner-schema empty.
691
+ * - **Object:** recursive — every property gets its own empty.
692
+ * - **Discriminated union:** first variant's recursive empty
693
+ * (parallels `getDefaultAtPath`'s first-success precedent).
694
+ * - **Path doesn't exist in schema:** `undefined`.
695
+ *
696
+ * Adapters may return `undefined` when the path can't be resolved;
697
+ * callers treat that as "don't write" and leave existing storage
698
+ * unchanged.
699
+ */
700
+ getEmptyValueAtPath(path: Path): unknown;
673
701
  /**
674
702
  * Give the schema a chance to normalize the consumer's write value
675
703
  * before it lands in storage / hits the slim-primitive gate. Each
@@ -3016,23 +3044,30 @@ type FormMeta<F = unknown> = FieldState<F> & {
3016
3044
  * form.meta.submitting // form-level reactive flag
3017
3045
  * ```
3018
3046
  *
3019
- * Two generic slots split the input view from the output view:
3047
+ * Three generic slots split the write view, parse view, and read view:
3020
3048
  *
3021
- * - `Form` — the **input / storage shape** (`z.input<Schema>`). Used
3022
- * by `setValue`, `defaultValues`, `values`, `fields`, `register`,
3023
- * `toRef`, and every path-addressed API. Storage holds values as
3024
- * the consumer wrote them; preprocess normalization runs at the
3025
- * write boundary, but `.transform()`s are deferred to parse-time.
3049
+ * - `Form` — the **input / write shape** (`z.input<Schema>`). Used
3050
+ * by `setValue`, `defaultValues`, and `register`'s write side.
3051
+ * Loose: preprocess paths accept `unknown` at the write boundary,
3052
+ * defaulted fields accept their inner type optionally.
3026
3053
  *
3027
3054
  * - `GetValueFormType` — the **output / parsed shape**
3028
3055
  * (`z.output<Schema>`). Used by `handleSubmit`'s `onSubmit`
3029
3056
  * callback and by `form.process()`'s success payload. This is the
3030
3057
  * shape after refinements have fired and transforms have run.
3031
3058
  *
3032
- * For schemas without transforms the two are identical, and the
3033
- * default `GetValueFormType = Form` keeps the surface ergonomic.
3059
+ * - `ReadForm` the **read / storage shape**. Used by `values`,
3060
+ * `fields`, `register`'s read side, `toRef`. Per-key precise: at
3061
+ * the write-boundary wrappers (`default` / `prefault` / `catch` /
3062
+ * `readonly` / `preprocess`) the value is `z.output<Inner>`
3063
+ * (default has fired, preprocess has normalized); at transforms /
3064
+ * pipes the value stays `z.input<Inner>` (transforms are deferred
3065
+ * until parse). For schema-agnostic call sites defaults to `Form`.
3066
+ *
3067
+ * For schemas without write-boundary wrappers or transforms the three
3068
+ * shapes coincide.
3034
3069
  */
3035
- type UseFormReturnType<Form extends GenericForm, GetValueFormType extends GenericForm = Form> = {
3070
+ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form> = {
3036
3071
  /**
3037
3072
  * Wraps your submit logic with validation and error routing.
3038
3073
  *
@@ -3079,7 +3114,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3079
3114
  * value reads as `string`, not `boolean`. Use `handleSubmit` or
3080
3115
  * `form.process()` when you need the post-transform output shape.
3081
3116
  */
3082
- values: ValuesSurface<WriteShape<Form>>;
3117
+ values: ValuesSurface<WriteShape<ReadForm>>;
3083
3118
  /**
3084
3119
  * Reactive per-field state proxy. Pinia-style nested object — read
3085
3120
  * leaf properties (`value`, `dirty`, `touched`, `errors`, `blurred`,
@@ -3108,7 +3143,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3108
3143
  * Document edge case; rename the offending schema field if the
3109
3144
  * collision matters.
3110
3145
  */
3111
- fields: FieldStateMap<WriteShape<Form>>;
3146
+ fields: FieldStateMap<WriteShape<ReadForm>>;
3112
3147
  /**
3113
3148
  * Write to the form programmatically. Two forms:
3114
3149
  *
@@ -3259,8 +3294,8 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3259
3294
  * for storage activity to actually happen.
3260
3295
  */
3261
3296
  register: {
3262
- <Path extends RegisterFlatPath<Form, keyof Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<Form>, Path>>;
3263
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form, keyof Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<Form>, JoinSegments<S>>>;
3297
+ <Path extends RegisterFlatPath<Form, keyof Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, Path>>;
3298
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form, keyof Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>;
3264
3299
  };
3265
3300
  /**
3266
3301
  * The form's identifier — either the explicit `key` passed to
@@ -3315,8 +3350,8 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3315
3350
  * scripts; `toRef` is for ref-shaped interop only.
3316
3351
  */
3317
3352
  toRef: {
3318
- <Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<Form>, Path>>>;
3319
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<Form>, JoinSegments<S>>>>;
3353
+ <Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, Path>>>;
3354
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>>;
3320
3355
  };
3321
3356
  /**
3322
3357
  * Replace every field error for this form with the provided list.
@@ -3430,6 +3465,51 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
3430
3465
  * from the persisted draft too.
3431
3466
  */
3432
3467
  resetField: (path: FlatPath<Form>) => void;
3468
+ /**
3469
+ * Wipe a field (or the whole form) to the "appropriate nullish
3470
+ * value" for its declared type — the underlying type's empty/falsy
3471
+ * concrete, with any `.default(x)` wrapper INTENTIONALLY skipped.
3472
+ * Orthogonal to `reset` / `resetField` by design.
3473
+ *
3474
+ * ```ts
3475
+ * const schema = z.object({
3476
+ * notify: z.boolean().default(true),
3477
+ * count: z.number().default(5),
3478
+ * })
3479
+ * const form = useForm({ schema })
3480
+ *
3481
+ * form.reset() // notify → true, count → 5 (defaults)
3482
+ * form.clear() // notify → false, count → 0 (falsy-for-type)
3483
+ * form.clear('notify') // → false (NOT the declared default true)
3484
+ * ```
3485
+ *
3486
+ * Per-wrapper semantics:
3487
+ *
3488
+ * - `.default(x)` / `.prefault(x)` / `.catch(x)` → inner-schema
3489
+ * empty (default is INTENTIONALLY skipped).
3490
+ * - `.optional()` → `undefined` (the wrapper's "absent" marker).
3491
+ * - `.nullable()` → `null` (the wrapper's "explicit empty").
3492
+ * - Object → recursive (every property gets its own empty).
3493
+ * - Array / Set / Record → empty.
3494
+ *
3495
+ * Returns `true` when the write was accepted, `false` when the
3496
+ * adapter couldn't resolve an empty value at the path (e.g. the
3497
+ * path doesn't exist in the schema). The form state is unchanged
3498
+ * on a `false` return.
3499
+ *
3500
+ * Sugar over `setValue(path, schema.getEmptyValueAtPath(path))` —
3501
+ * no separate bookkeeping. Variant memory, history, persistence,
3502
+ * and listeners all see this as a regular write at the path.
3503
+ *
3504
+ * `clear()` (no arg) targets the whole form. `clear('')` targets
3505
+ * the empty-string path slot SPECIFICALLY — the two are NOT
3506
+ * interchangeable, matching `touch()` / `touch('')` from #184.
3507
+ */
3508
+ clear: {
3509
+ (): boolean;
3510
+ <Path extends FlatPath<Form> | ''>(path: Path): boolean;
3511
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown : never)): boolean;
3512
+ };
3433
3513
  /**
3434
3514
  * Write the current value at `path` to storage immediately. Useful
3435
3515
  * for explicit "Save draft" buttons, `beforeunload` handlers, or
@@ -2458,6 +2458,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
2458
2458
  void persistence.clearPersistedDraft(segments).catch(() => void 0);
2459
2459
  }
2460
2460
  };
2461
+ function clear(pathInput) {
2462
+ const segments = pathInput === void 0 ? paths.ROOT_PATH : paths.canonicalizePath(pathInput).segments;
2463
+ return state.clear(segments);
2464
+ }
2461
2465
  const persist = async (pathInput, options2) => {
2462
2466
  const segments = paths.canonicalizePath(pathInput).segments;
2463
2467
  plugin.enforceSensitiveCheck(segments, options2?.acknowledgeSensitive === true, state.isSensitivePath);
@@ -2520,6 +2524,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2520
2524
  meta: formMeta,
2521
2525
  reset,
2522
2526
  resetField,
2527
+ clear,
2523
2528
  persist,
2524
2529
  clearPersistedDraft,
2525
2530
  focusFirstError,
@@ -3406,6 +3411,9 @@ function createFormStore(options) {
3406
3411
  );
3407
3412
  }
3408
3413
  }
3414
+ function clear(path) {
3415
+ return setValueAtPath(path, schema.getEmptyValueAtPath(path));
3416
+ }
3409
3417
  function reset(nextDefaultValues) {
3410
3418
  const resetSource = nextDefaultValues ?? defaultValues;
3411
3419
  const completedResetConstraints = resetSource === void 0 ? void 0 : mergeStructural(schema, [], resetSource);
@@ -3616,6 +3624,7 @@ function createFormStore(options) {
3616
3624
  getValueAtPath,
3617
3625
  reset,
3618
3626
  resetField,
3627
+ clear,
3619
3628
  setSchemaErrorsForPath,
3620
3629
  setAllSchemaErrors,
3621
3630
  clearSchemaErrors,
@@ -4328,7 +4337,11 @@ function useAbstractForm(configuration) {
4328
4337
  if (merged.rememberVariants !== void 0) {
4329
4338
  apiOptions.rememberVariants = merged.rememberVariants;
4330
4339
  }
4331
- return buildFormApi(state, formInstanceId, apiOptions);
4340
+ return buildFormApi(
4341
+ state,
4342
+ formInstanceId,
4343
+ apiOptions
4344
+ );
4332
4345
  }
4333
4346
  function mergeWithDefaults(defaults, configuration) {
4334
4347
  const strict = configuration.strict ?? defaults.strict;
@@ -4819,4 +4832,4 @@ exports.setAtPath = setAtPath;
4819
4832
  exports.slimKindOf = slimKindOf;
4820
4833
  exports.unset = unset;
4821
4834
  exports.useAbstractForm = useAbstractForm;
4822
- //# sourceMappingURL=attaform.BFumZXY2.cjs.map
4835
+ //# sourceMappingURL=attaform.Cer8JO_P.cjs.map