attaform 0.27.6 → 0.29.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 (192) hide show
  1. package/dist/abstract.d.mts +5 -4
  2. package/dist/abstract.mjs +4 -3
  3. package/dist/chunks/fingerprint.mjs +1 -2
  4. package/dist/chunks/fingerprint2.mjs +2 -3
  5. package/dist/dev/abstract.mjs +4 -0
  6. package/dist/{chunks → dev/chunks}/dev-key-collision-warnings.mjs +0 -1
  7. package/dist/{chunks → dev/chunks}/devtools.mjs +5 -6
  8. package/dist/{chunks/fingerprint.cjs → dev/chunks/fingerprint.mjs} +7 -10
  9. package/dist/{chunks/fingerprint2.cjs → dev/chunks/fingerprint2.mjs} +32 -35
  10. package/dist/dev/directive.mjs +1 -0
  11. package/dist/dev/history.mjs +89 -0
  12. package/dist/dev/index.mjs +5 -0
  13. package/dist/dev/runtime/plugins/attaform.mjs +40 -0
  14. package/dist/dev/shared/attaform-dev.A-TpJW0B.mjs +207 -0
  15. package/dist/dev/shared/attaform-dev.BO-71R54.mjs +820 -0
  16. package/dist/{shared/attaform.D6tk90Rc.cjs → dev/shared/attaform-dev.BgM6FdtA.mjs} +324 -73
  17. package/dist/dev/shared/attaform-dev.ButTkwHd.mjs +375 -0
  18. package/dist/{shared/attaform.BJGA_UOS.mjs → dev/shared/attaform-dev.BxfsuwBR.mjs} +8 -1
  19. package/dist/{shared/attaform.nMaz2C5P.mjs → dev/shared/attaform-dev.D8aoKb89.mjs} +190 -400
  20. package/dist/dev/shared/attaform-dev.DD5m2W51.mjs +220 -0
  21. package/dist/{shared/attaform.CKH2lGdL.mjs → dev/shared/attaform-dev.DHuydLAC.mjs} +3867 -4731
  22. package/dist/{shared/attaform.DYEr28Pt.mjs → dev/shared/attaform-dev.DrzObAZo.mjs} +6 -7
  23. package/dist/{shared/attaform.B1ZYt2Li.mjs → dev/shared/attaform-dev.q6UutkCx.mjs} +274 -672
  24. package/dist/dev/zod-v3.mjs +17 -0
  25. package/dist/dev/zod-v4.mjs +16 -0
  26. package/dist/dev/zod.mjs +5 -0
  27. package/dist/directive.d.mts +20 -0
  28. package/dist/directive.mjs +1 -0
  29. package/dist/esbuild.mjs +0 -1
  30. package/dist/history.d.mts +59 -0
  31. package/dist/history.mjs +89 -0
  32. package/dist/index.d.mts +14 -6
  33. package/dist/index.mjs +5 -4
  34. package/dist/nuxt.d.mts +10 -10
  35. package/dist/nuxt.mjs +5 -2
  36. package/dist/rollup.mjs +0 -1
  37. package/dist/rspack.d.mts +6 -1
  38. package/dist/rspack.mjs +0 -1
  39. package/dist/runtime/components/AttaformDevtoolsPanel.vue +9 -8
  40. package/dist/runtime/plugins/attaform.mjs +1 -2
  41. package/dist/shared/{attaform.CoR4mWfv.mjs → attaform.B0dKL8ST.mjs} +309 -46
  42. package/dist/shared/{attaform.Cs2Rbdlo.mjs → attaform.BK0cgu2K.mjs} +123 -140
  43. package/dist/shared/{attaform.B9Wyhfro.cjs → attaform.BndjUUYX.mjs} +11 -16
  44. package/dist/shared/{attaform.CQN9R62B.cjs → attaform.BxfsuwBR.mjs} +9 -4
  45. package/dist/shared/attaform.C2MVyuxC.mjs +811 -0
  46. package/dist/shared/{attaform.Fp3sCrVs.d.ts → attaform.CIWLMY-R.d.mts} +2 -2
  47. package/dist/shared/attaform.CZMAYwSK.mjs +6383 -0
  48. package/dist/shared/attaform.CZYt_5N_.mjs +207 -0
  49. package/dist/shared/{attaform.DniawQLP.d.cts → attaform.CsoeRi3P.d.mts} +490 -98
  50. package/dist/shared/attaform.Cvao8bW5.mjs +358 -0
  51. package/dist/shared/attaform.D0x-qSXm.mjs +197 -0
  52. package/dist/shared/{attaform.D8kliaKw.cjs → attaform.D1fnTifF.mjs} +279 -692
  53. package/dist/shared/{attaform.CHlJLAiv.d.mts → attaform.DDtqHYv1.d.mts} +155 -184
  54. package/dist/shared/{attaform.Biytrv0-.cjs → attaform.DffRL5pP.mjs} +215 -547
  55. package/dist/shared/attaform.DhnPb6nK.mjs +0 -1
  56. package/dist/shared/attaform.KvlEedlF.mjs +0 -1
  57. package/dist/shared/attaform.axHXVQO7.d.mts +44 -0
  58. package/dist/shared/attaform.v0fQtWyA.mjs +0 -1
  59. package/dist/transforms.d.mts +0 -22
  60. package/dist/transforms.mjs +1 -2
  61. package/dist/vite.d.mts +30 -9
  62. package/dist/vite.mjs +27 -4
  63. package/dist/webpack.d.mts +6 -1
  64. package/dist/webpack.mjs +0 -1
  65. package/dist/zod-v3.d.mts +13 -6
  66. package/dist/zod-v3.mjs +17 -4
  67. package/dist/zod-v4.d.mts +19 -26
  68. package/dist/zod-v4.mjs +16 -4
  69. package/dist/zod.d.mts +4 -3
  70. package/dist/zod.mjs +5 -4
  71. package/package.json +38 -20
  72. package/skills/attaform/SKILL.md +6 -2
  73. package/skills/attaform/references/custom-components.md +7 -2
  74. package/skills/attaform/references/errors.md +8 -3
  75. package/skills/attaform/references/saving.md +77 -0
  76. package/skills/attaform/references/wizards.md +10 -8
  77. package/dist/abstract.cjs +0 -48
  78. package/dist/abstract.cjs.map +0 -1
  79. package/dist/abstract.d.cts +0 -42
  80. package/dist/abstract.d.ts +0 -42
  81. package/dist/abstract.mjs.map +0 -1
  82. package/dist/chunks/dev-key-collision-warnings.cjs +0 -25
  83. package/dist/chunks/dev-key-collision-warnings.cjs.map +0 -1
  84. package/dist/chunks/dev-key-collision-warnings.mjs.map +0 -1
  85. package/dist/chunks/devtools.cjs +0 -157
  86. package/dist/chunks/devtools.cjs.map +0 -1
  87. package/dist/chunks/devtools.mjs.map +0 -1
  88. package/dist/chunks/fingerprint.cjs.map +0 -1
  89. package/dist/chunks/fingerprint.mjs.map +0 -1
  90. package/dist/chunks/fingerprint2.cjs.map +0 -1
  91. package/dist/chunks/fingerprint2.mjs.map +0 -1
  92. package/dist/esbuild.cjs +0 -28
  93. package/dist/esbuild.cjs.map +0 -1
  94. package/dist/esbuild.d.cts +0 -56
  95. package/dist/esbuild.d.ts +0 -56
  96. package/dist/esbuild.mjs.map +0 -1
  97. package/dist/index.cjs +0 -51
  98. package/dist/index.cjs.map +0 -1
  99. package/dist/index.d.cts +0 -249
  100. package/dist/index.d.ts +0 -249
  101. package/dist/index.mjs.map +0 -1
  102. package/dist/nuxt.cjs +0 -84
  103. package/dist/nuxt.cjs.map +0 -1
  104. package/dist/nuxt.d.cts +0 -66
  105. package/dist/nuxt.d.ts +0 -66
  106. package/dist/nuxt.mjs.map +0 -1
  107. package/dist/rollup.cjs +0 -24
  108. package/dist/rollup.cjs.map +0 -1
  109. package/dist/rollup.d.cts +0 -35
  110. package/dist/rollup.d.ts +0 -35
  111. package/dist/rollup.mjs.map +0 -1
  112. package/dist/rspack.cjs +0 -10
  113. package/dist/rspack.cjs.map +0 -1
  114. package/dist/rspack.d.cts +0 -40
  115. package/dist/rspack.d.ts +0 -40
  116. package/dist/rspack.mjs.map +0 -1
  117. package/dist/runtime/components/AttaformDevtoolsPanel.vue.d.ts +0 -7
  118. package/dist/runtime/components/DevtoolsValueTree.vue.d.ts +0 -35
  119. package/dist/runtime/plugins/attaform.cjs +0 -43
  120. package/dist/runtime/plugins/attaform.cjs.map +0 -1
  121. package/dist/runtime/plugins/attaform.d.cts +0 -5
  122. package/dist/runtime/plugins/attaform.d.ts +0 -5
  123. package/dist/runtime/plugins/attaform.mjs.map +0 -1
  124. package/dist/shared/attaform.B1ZYt2Li.mjs.map +0 -1
  125. package/dist/shared/attaform.B9Wyhfro.cjs.map +0 -1
  126. package/dist/shared/attaform.BGDV42hI.d.cts +0 -232
  127. package/dist/shared/attaform.BJGA_UOS.mjs.map +0 -1
  128. package/dist/shared/attaform.Biytrv0-.cjs.map +0 -1
  129. package/dist/shared/attaform.Bn0IzhD_.cjs +0 -800
  130. package/dist/shared/attaform.Bn0IzhD_.cjs.map +0 -1
  131. package/dist/shared/attaform.C9fPTxjB.d.cts +0 -41
  132. package/dist/shared/attaform.C9fPTxjB.d.ts +0 -41
  133. package/dist/shared/attaform.CKH2lGdL.mjs.map +0 -1
  134. package/dist/shared/attaform.CQN9R62B.cjs.map +0 -1
  135. package/dist/shared/attaform.CoR4mWfv.mjs.map +0 -1
  136. package/dist/shared/attaform.Cs2Rbdlo.mjs.map +0 -1
  137. package/dist/shared/attaform.D6tk90Rc.cjs.map +0 -1
  138. package/dist/shared/attaform.D8kliaKw.cjs.map +0 -1
  139. package/dist/shared/attaform.DLknk9nF.d.mts +0 -232
  140. package/dist/shared/attaform.DMxM2kol.mjs +0 -1275
  141. package/dist/shared/attaform.DMxM2kol.mjs.map +0 -1
  142. package/dist/shared/attaform.DRUT703x.d.cts +0 -56
  143. package/dist/shared/attaform.DRUT703x.d.ts +0 -56
  144. package/dist/shared/attaform.DYEr28Pt.mjs.map +0 -1
  145. package/dist/shared/attaform.DdQN7sgN.cjs +0 -1302
  146. package/dist/shared/attaform.DdQN7sgN.cjs.map +0 -1
  147. package/dist/shared/attaform.DhnPb6nK.mjs.map +0 -1
  148. package/dist/shared/attaform.DniawQLP.d.mts +0 -4763
  149. package/dist/shared/attaform.DniawQLP.d.ts +0 -4763
  150. package/dist/shared/attaform.DoQm_Vkd.cjs +0 -58
  151. package/dist/shared/attaform.DoQm_Vkd.cjs.map +0 -1
  152. package/dist/shared/attaform.DrvMscNX.cjs +0 -7697
  153. package/dist/shared/attaform.DrvMscNX.cjs.map +0 -1
  154. package/dist/shared/attaform.F2Q8iv38.d.ts +0 -2494
  155. package/dist/shared/attaform.FmqKO1Ex.d.cts +0 -2494
  156. package/dist/shared/attaform.KvlEedlF.mjs.map +0 -1
  157. package/dist/shared/attaform.RaTzp1WF.cjs +0 -26
  158. package/dist/shared/attaform.RaTzp1WF.cjs.map +0 -1
  159. package/dist/shared/attaform.nMaz2C5P.mjs.map +0 -1
  160. package/dist/shared/attaform.v0fQtWyA.mjs.map +0 -1
  161. package/dist/shared/attaform.yUrz7C2z.cjs +0 -29
  162. package/dist/shared/attaform.yUrz7C2z.cjs.map +0 -1
  163. package/dist/transforms.cjs +0 -12
  164. package/dist/transforms.cjs.map +0 -1
  165. package/dist/transforms.d.cts +0 -73
  166. package/dist/transforms.d.ts +0 -73
  167. package/dist/transforms.mjs.map +0 -1
  168. package/dist/vite.cjs +0 -363
  169. package/dist/vite.cjs.map +0 -1
  170. package/dist/vite.d.cts +0 -133
  171. package/dist/vite.d.ts +0 -133
  172. package/dist/vite.mjs.map +0 -1
  173. package/dist/webpack.cjs +0 -10
  174. package/dist/webpack.cjs.map +0 -1
  175. package/dist/webpack.d.cts +0 -37
  176. package/dist/webpack.d.ts +0 -37
  177. package/dist/webpack.mjs.map +0 -1
  178. package/dist/zod-v3.cjs +0 -53
  179. package/dist/zod-v3.cjs.map +0 -1
  180. package/dist/zod-v3.d.cts +0 -246
  181. package/dist/zod-v3.d.ts +0 -246
  182. package/dist/zod-v3.mjs.map +0 -1
  183. package/dist/zod-v4.cjs +0 -55
  184. package/dist/zod-v4.cjs.map +0 -1
  185. package/dist/zod-v4.d.cts +0 -172
  186. package/dist/zod-v4.d.ts +0 -172
  187. package/dist/zod-v4.mjs.map +0 -1
  188. package/dist/zod.cjs +0 -51
  189. package/dist/zod.cjs.map +0 -1
  190. package/dist/zod.d.cts +0 -7
  191. package/dist/zod.d.ts +0 -7
  192. package/dist/zod.mjs.map +0 -1
@@ -164,6 +164,65 @@ declare const ROOT_PATH_KEY: PathKey;
164
164
  */
165
165
  declare function isPathPrefix(prefix: readonly Segment[], path: readonly Segment[]): boolean;
166
166
 
167
+ /**
168
+ * Per-path field status. Replaced wholesale (not mutated in place) on
169
+ * every change. Five semantic groups:
170
+ *
171
+ * - `connected` — is a DOM element registered for this path?
172
+ * - `focused` / `blurred` — DOM-state flags. `null` while no element
173
+ * is connected (no DOM means the concepts don't apply); plain
174
+ * booleans once connected, with the invariant `blurred === !focused`
175
+ * enforced by `markFocused`.
176
+ * - `touched` — focus/blur history, not DOM state. Always a plain
177
+ * boolean: `false` at registration, sticky `true` after first blur,
178
+ * cleared only by `form.reset()` / `form.resetField(path)`. Persists
179
+ * across disconnects so v-if'd-away fields don't lose their touched
180
+ * state on rehide (wizard "show review of touched fields" patterns
181
+ * rely on this).
182
+ * - `interacted` — value-mutation history, not DOM state. Plain
183
+ * boolean: `false` at registration, sticky `true` once the user
184
+ * issues a value edit through the directive's input listeners
185
+ * (never on hydration, default seeding, or programmatic setValue);
186
+ * cleared with `touched` by `form.reset()` / `form.resetField(path)`.
187
+ * - `blurredAfterInteraction` — the first blur that follows a value
188
+ * edit (the field has been edited and then left). Plain boolean,
189
+ * sticky `true`. A tab-through blur with no prior edit does NOT set
190
+ * it (`interacted` is still false at that blur). Composes
191
+ * `interacted` with the departure; drives the default display gate.
192
+ */
193
+ type FieldRecord = {
194
+ readonly path: Path;
195
+ readonly updatedAt: string | null;
196
+ readonly connected: boolean;
197
+ readonly focused: boolean | null;
198
+ readonly blurred: boolean | null;
199
+ readonly touched: boolean;
200
+ readonly interacted: boolean;
201
+ readonly blurredAfterInteraction: boolean;
202
+ };
203
+ /** Per-path DOM element tracking. Client-only. */
204
+ type ElementRecord = {
205
+ /**
206
+ * Original Path captured at first registration. Stored alongside the
207
+ * elements Set so the DOM-order sort cache can recover the structured
208
+ * Path without round-tripping through `JSON.parse(pathKey)`.
209
+ */
210
+ readonly path: Path;
211
+ readonly elements: Set<HTMLElement>;
212
+ };
213
+ /**
214
+ * Per-path record stored in `originals`. Pairing `segments` with the tracked
215
+ * value means `dirty` and `resetField`'s container loop don't have to
216
+ * `JSON.parse(pathKey)` on every iteration — the canonical Path is already
217
+ * sitting next to the value it belongs to. PathKey still keys the Map (the
218
+ * stable string is the only collision-free identifier), but downstream
219
+ * iteration reads `segments` directly.
220
+ */
221
+ type OriginalsRecord = {
222
+ readonly segments: Path;
223
+ readonly value: unknown;
224
+ };
225
+
167
226
  /** Internal brand for the `Unset` type. Never exposed at runtime. */
168
227
  declare const _unsetBrand: unique symbol;
169
228
  /**
@@ -300,6 +359,48 @@ type JoinSegments<S extends ReadonlyArray<string | number>, Acc extends string =
300
359
  infer Head extends string | number,
301
360
  ...infer Rest extends ReadonlyArray<string | number>
302
361
  ] ? Acc extends '' ? JoinSegments<Rest, `${Head}`> : JoinSegments<Rest, `${Acc}.${Head}`> : Acc;
362
+ /**
363
+ * The advice half of a segment-array rejection, used when `S` never
364
+ * inferred a tuple at all.
365
+ *
366
+ * A caller who passes a plain `string` reaches this branch, because
367
+ * inference falls back to the constraint and `JoinSegments` of a
368
+ * non-tuple array is `''`. Naming a path would be a lie there, so the
369
+ * message names the remedies instead. This is the case behind #568: a
370
+ * row component received its path prefix as an untyped `string` prop,
371
+ * every concatenation widened to `string`, and the only signal was
372
+ * `segments: never`.
373
+ */
374
+ type PlainStringAdvice = 'attaform: a plain string cannot be checked against the schema. Pass a literal path, type the dynamic prefix, or use the segment-array form.';
375
+ /**
376
+ * Why a segment array was rejected, as a type the compiler prints.
377
+ *
378
+ * Every segment-array overload brands its parameter
379
+ * `S & (<joined path is valid> ? unknown : <this>)`. The brand used to
380
+ * be `never`, and `S & never` is `never`, so TypeScript reported the
381
+ * parameter as `never` and said nothing about what was wrong. A string
382
+ * literal intersects without collapsing, so the sentence survives into
383
+ * the diagnostic and the argument keeps its inferred tuple type:
384
+ *
385
+ * ```
386
+ * Argument of type '["boxes", 3, "nope"]' is not assignable to parameter
387
+ * of type 'readonly ["boxes", 3, "nope"] &
388
+ * "attaform: 'boxes.3.nope' is not a path in this form's schema"'.
389
+ * ```
390
+ *
391
+ * Nothing can satisfy the brand, so a wrong path is still a compile
392
+ * error; only the message changes.
393
+ */
394
+ type SegmentPathRejection<Joined extends string> = [Joined] extends [''] ? PlainStringAdvice : `attaform: '${Joined}' is not a path in this form's schema`;
395
+ /**
396
+ * `SegmentPathRejection` for `register`, whose accepted set is
397
+ * `RegisterFlatPath` rather than `FlatPath`.
398
+ *
399
+ * The distinction is worth its own sentence: a container path is in the
400
+ * schema and still not registrable, so "not a path in this form's
401
+ * schema" would be false where it is most likely to be read.
402
+ */
403
+ type SegmentRegisterRejection<Joined extends string> = [Joined] extends [''] ? PlainStringAdvice : `attaform: '${Joined}' is not a registrable path. v-register binds a leaf input, so container paths are excluded.`;
303
404
  /**
304
405
  * `true` when `T` is a union (multiple members), `false` when it's a
305
406
  * single type. Used to gate non-homomorphic mapped-type forms so
@@ -464,44 +565,89 @@ type IsTuple<T extends readonly unknown[]> = number extends T['length'] ? false
464
565
  * runtime possibility of a missing array position.
465
566
  */
466
567
  type NestedReadType<RootValue, FlattenedPath extends string> = NestedTypeBuilder<RootValue, FlattenedPath, true>;
568
+ /**
569
+ * The array a path actually addresses, nullish stripped, or `never`
570
+ * when the path does not address an array. Shared by `ArrayPath`
571
+ * (membership) and `ArrayItem` (element type) so the filter and the
572
+ * extractor cannot disagree about what counts as one.
573
+ *
574
+ * The strip is the load-bearing part. `Form` is the schema's INPUT
575
+ * shape, so `z.array(row).default([])` resolves to `row[] | undefined`,
576
+ * and `NestedType` tags a discriminated union's per-variant keys the
577
+ * same way on purpose: that tagging is what keeps `NestedType` in
578
+ * lockstep with `FlatPath`, so every path `FlatPath` offers resolves to
579
+ * a useful value type. A bare `extends readonly unknown[]` predicate
580
+ * read the tag as "not an array", which is how every optional,
581
+ * defaulted, nullable, and DU-variant array fell out of the field-array
582
+ * helpers while the runtime went on accepting all of them (#541).
583
+ *
584
+ * `extends infer Leaf` binds the stripped leaf once so the guards below
585
+ * do not re-instantiate `NestedType`, and the tuple wraps suppress
586
+ * distribution so a union leaf is judged whole: `A[] | B[]` is an
587
+ * array, `A[] | string` is not.
588
+ *
589
+ * Exported so `rollup-plugin-dts` keeps it as a named alias in the
590
+ * bundled `.d.ts` instead of inlining the body at every reference.
591
+ * Consumers reach for `ArrayPath` / `ArrayItem`; this alias is not part
592
+ * of the stable surface.
593
+ */
594
+ type ArrayLeafOf<Form, P extends string> = Exclude<NestedType<Form, P>, undefined | null> extends infer Leaf ? [Leaf] extends [never] ? never : [Leaf] extends [readonly unknown[]] ? Leaf : never : never;
467
595
  /**
468
596
  * Filter FlatPath<Form> down to the subset of paths whose resolved leaf
469
597
  * is an array. Used by the typed field-array helpers (append / remove /
470
598
  * swap / ...) so those helpers only accept paths that actually address
471
599
  * an array — calling `append('email', ...)` on a `{ email: string }`
472
- * is a compile error.
600
+ * is a compile error. Optionality is not a disqualifier; see
601
+ * `ArrayLeafOf` for what "is an array" means here.
473
602
  *
474
603
  * `P extends string` re-triggers distribution over the `FlatPath<Form>`
475
604
  * union so the conditional evaluates per member. Without it, the
476
605
  * branch would reduce against the union as a whole and collapse to
477
606
  * `never` whenever a single member failed the predicate.
478
607
  */
479
- type ArrayPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? NestedType<Form, P> extends readonly unknown[] ? P : never : never;
608
+ type ArrayPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? [ArrayLeafOf<Form, P>] extends [never] ? never : P : never;
480
609
  /**
481
610
  * Extract the element type of the array addressed by `Path`. Callers
482
611
  * constrain `Path extends ArrayPath<Form>` so this is always well-defined.
612
+ * Rides on `ArrayLeafOf`, the same alias `ArrayPath` admits the path
613
+ * with, so an accepted path never hands its helper a `never` value slot.
483
614
  */
484
- type ArrayItem<Form, Path extends ArrayPath<Form>> = NestedType<Form, Path> extends ReadonlyArray<infer Item> ? Item : never;
615
+ type ArrayItem<Form, Path extends ArrayPath<Form>> = ArrayLeafOf<Form, Path> extends ReadonlyArray<infer Item> ? Item : never;
616
+ /**
617
+ * The record a path actually addresses, nullish stripped, or `never`
618
+ * when the path does not address one. Shared by `RecordPath`
619
+ * (membership) and `RecordValue` (value type).
620
+ *
621
+ * `string extends keyof Leaf` is the index-signature probe: it holds for
622
+ * `Record<string, V>` (`keyof` is `string`) and fails for a fixed object
623
+ * (`keyof` is the literal key union). The leading array guard keeps
624
+ * arrays (which also satisfy the object check) out of the record set.
625
+ *
626
+ * Nullish is stripped first for the reason `ArrayLeafOf` gives, with an
627
+ * extra bite here: `keyof (Record<string, V> | undefined)` is `never`,
628
+ * so on a `.default({})` or `.optional()` record the probe could not
629
+ * fire at all and `form.record(path)` rejected the path (#541).
630
+ *
631
+ * Exported for the same `.d.ts` reason as `ArrayLeafOf`, and equally
632
+ * not part of the stable surface.
633
+ */
634
+ type RecordLeafOf<Form, P extends string> = Exclude<NestedType<Form, P>, undefined | null> extends infer Leaf ? [Leaf] extends [never] ? never : [Leaf] extends [readonly unknown[]] ? never : [Leaf] extends [Record<string, unknown>] ? string extends keyof Leaf ? Leaf : never : never : never;
485
635
  /**
486
636
  * Companion to `ArrayPath`: filter `FlatPath<Form>` down to the subset
487
637
  * of paths whose resolved leaf is a record (an object with an open
488
638
  * string-keyed index signature, e.g. `z.record(z.string(), V)`). A
489
639
  * fixed-shape object (`z.object({ ... })`) is excluded — its keys are
490
640
  * statically known, so it has no `string` index signature.
491
- *
492
- * `string extends keyof T` is the index-signature probe: it holds for
493
- * `Record<string, V>` (`keyof` is `string`) and fails for a fixed object
494
- * (`keyof` is the literal key union). The leading array guard keeps
495
- * arrays (which also satisfy the object check) out of the record set.
496
641
  */
497
- type RecordPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? NestedType<Form, P> extends readonly unknown[] ? never : NestedType<Form, P> extends Record<string, unknown> ? string extends keyof NestedType<Form, P> ? P : never : never : never;
642
+ type RecordPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? [RecordLeafOf<Form, P>] extends [never] ? never : P : never;
498
643
  /**
499
644
  * Value type of the record addressed by `Path` — the `V` in a
500
645
  * `Record<string, V>`. Callers constrain `Path extends RecordPath<Form>`,
501
646
  * so the leaf is always an open string-keyed record and this is
502
- * well-defined.
647
+ * well-defined. Rides on `RecordLeafOf`, the same alias `RecordPath`
648
+ * admits the path with, so the two cannot disagree.
503
649
  */
504
- type RecordValue<Form, Path extends RecordPath<Form>> = NestedType<Form, Path> extends Record<string, infer Value> ? Value : never;
650
+ type RecordValue<Form, Path extends RecordPath<Form>> = RecordLeafOf<Form, Path> extends Record<string, infer Value> ? Value : never;
505
651
  /**
506
652
  * Widens primitive-literal leaves to their primitive supertype to
507
653
  * match the runtime "slim-primitive write contract."
@@ -722,11 +868,13 @@ interface JsonObject {
722
868
  * structured array — `['user', 'address', 0, 'line1']` for a nested
723
869
  * field, `[]` (the root path) for a form-level error (root `.refine()`
724
870
  * messages, `setErrors` entries with no path, hydration failures,
725
- * server-emitted form banners). `formKey` identifies which form
726
- * produced the error so a single error list can be routed to multiple
727
- * forms. The optional `data` slot carries an arbitrary server payload.
871
+ * server-emitted form banners). Which form produced an error is
872
+ * envelope-level identity: the `ValidationResponse` / submit result
873
+ * that carries the list stamps `formKey` once, and aggregators that
874
+ * merge lists across forms (the wizard) stamp their own envelope. The
875
+ * optional `data` slot carries an arbitrary server payload.
728
876
  *
729
- * Returned by `validate()` / `validateAsync()` / `handleSubmit`'s
877
+ * Returned by `validate()` / `parse()` / `handleSubmit`'s
730
878
  * `onError` callback, and accepted (leniently, as `ErrorInput`) by
731
879
  * `form.setErrors`.
732
880
  */
@@ -741,8 +889,6 @@ type ValidationError = {
741
889
  * literal empty-key field.
742
890
  */
743
891
  path: (string | number)[];
744
- /** Identifies which form produced this error. */
745
- formKey: FormKey;
746
892
  /**
747
893
  * Stable machine identifier for the failure, scoped by prefix:
748
894
  *
@@ -764,6 +910,23 @@ type ValidationError = {
764
910
  */
765
911
  data?: Json | null;
766
912
  };
913
+ /**
914
+ * One path's slot in the form's tagged error store. The two sources
915
+ * that can put an error at a path stay segregated inside the cell:
916
+ * `schema` holds the validation pipeline's verdicts, `user` holds
917
+ * `setErrors` entries (and their history / SSR replays). Reads merge
918
+ * schema -> derived-blank -> user; each writer replaces exactly its
919
+ * own side. Cells are immutable — every write replaces the whole cell
920
+ * (or deletes the key when both sides empty), so Vue's per-key Map
921
+ * tracking fires for any side's change. An empty side is the shared
922
+ * frozen `NO_ERRORS` array, never a fresh allocation.
923
+ *
924
+ * @internal
925
+ */
926
+ type ErrorCell = {
927
+ readonly schema: readonly ValidationError[];
928
+ readonly user: readonly ValidationError[];
929
+ };
767
930
  /**
768
931
  * The lenient input shape `form.setErrors` accepts: a real `Error`, or
769
932
  * a partial `ValidationError` where every field is optional.
@@ -773,20 +936,17 @@ type ValidationError = {
773
936
  * the path-scoped `setErrors(path, …)` form, which stamps its own.
774
937
  * - `code`: defaults to `atta:user-error`.
775
938
  * - `data`: forwarded verbatim onto the produced `ValidationError`.
776
- * - `formKey`: accepted but ignored — the form always stamps its own.
777
939
  *
778
- * Because every field is optional and `formKey` is accepted-and-ignored,
779
- * `ValidationError` is a subtype of `ErrorInput`: a `ValidationError[]`
780
- * you read back, or a server response that already emits the shape, pipes
781
- * straight into `form.setErrors` with no adapter and no excess-property
782
- * friction.
940
+ * Because every field is optional, `ValidationError` is a subtype of
941
+ * `ErrorInput`: a `ValidationError[]` you read back, or a server
942
+ * response that already emits the shape, pipes straight into
943
+ * `form.setErrors` with no adapter.
783
944
  */
784
945
  type ErrorInput = Error | {
785
946
  message?: string;
786
947
  path?: (string | number)[];
787
948
  code?: string;
788
949
  data?: Json | null;
789
- formKey?: FormKey;
790
950
  };
791
951
  /** Settled validation result when the form (or subtree) parsed successfully. */
792
952
  type ValidationResponseSuccess<TData> = {
@@ -831,10 +991,19 @@ type ValidationResponse<TData> = ValidationResponseSuccess<TData> | ValidationRe
831
991
  type DefaultValuesResponse<TData> = ValidationResponseSuccess<TData> | ValidationResponseErrorWithData<TData>;
832
992
  /**
833
993
  * Trimmed `ValidationResponse` that omits the `data` payload. Used by
834
- * `validate()` / `validateAsync()` since consumers usually only need
835
- * the success flag and error list at those entry points.
994
+ * the reactive `validate()` status, whose consumers only need the
995
+ * success flag and error list.
836
996
  */
837
997
  type ValidationResponseWithoutValue<Form> = Omit<ValidationResponse<Form>, 'data'>;
998
+ /**
999
+ * Options bag for `form.parse`. `commit: true` turns the pure read
1000
+ * into an authoritative run: the verdict is committed to the error
1001
+ * store at the parsed scope and in-flight per-field validation runs
1002
+ * are cancelled first. Default `false`.
1003
+ */
1004
+ type ParseOptions = {
1005
+ readonly commit?: boolean;
1006
+ };
838
1007
  /**
839
1008
  * Sync-or-async return shape for `AbstractSchema.validateAtPath`. The
840
1009
  * adapter returns the response inline when the schema and the
@@ -998,7 +1167,7 @@ type AbstractSchema<Form, GetValueFormType> = {
998
1167
  * the gate accepts the consumer's raw value verbatim and stops
999
1168
  * walking children — storage holds the user's input, and the
1000
1169
  * normalizer fires during `safeParse` (handleSubmit / validate /
1001
- * validateAsync), not at `setValue` time.
1170
+ * parse), not at `setValue` time.
1002
1171
  *
1003
1172
  * Path-prefix semantic: returns true if ANY ancestor of `path`
1004
1173
  * resolves to such a wrapper, so descendants under a preprocess-
@@ -1006,29 +1175,50 @@ type AbstractSchema<Form, GetValueFormType> = {
1006
1175
  * the result by canonicalized path key.
1007
1176
  */
1008
1177
  isPreprocessOrCoerceLeaf(path: Path): boolean;
1178
+ /**
1179
+ * Reports whether `path` resolves to an opaque leaf: a schema that
1180
+ * declares a value without describing its shape. In Zod v4 that's
1181
+ * `z.any()`, `z.unknown()`, and `z.custom(...)` (the kind both
1182
+ * `z.instanceof(X)` and `z.custom<T>()` compile to); in Zod v3 it's
1183
+ * `z.any()` / `z.unknown()`, with `z.instanceof(X)` peeling through
1184
+ * `ZodEffects` to `ZodAny`.
1185
+ *
1186
+ * Consulted by the slim-primitive write gate. An opaque leaf admits
1187
+ * every kind, INCLUDING containers, and it declares no sub-paths.
1188
+ * Without this the gate accepts an array at the leaf and then walks
1189
+ * into it, checking `files.0` against a schema that never declared
1190
+ * that path; the empty accept set there reads as "not in your
1191
+ * schema" and no-ops the whole write (#542).
1192
+ *
1193
+ * Exact-path semantic, unlike `isPreprocessOrCoerceLeaf`: it answers
1194
+ * for the node at `path` only. Descendants stay unwritable on their
1195
+ * own, because the schema genuinely does not declare them and
1196
+ * fabricating them would put phantom nodes on `form.fields`. Writing
1197
+ * the whole value at the opaque leaf is the supported move.
1198
+ */
1199
+ isOpaqueLeafAtPath(path: Path): boolean;
1009
1200
  /**
1010
1201
  * Distinguish a tuple (fixed-length, position-typed) from an
1011
1202
  * unbounded array at `path`. The runtime calls this on every
1012
1203
  * `mergeStructural` / `setAtPathWithSchemaFill` write that descends
1013
- * into an array branch — caching the answer at the schema level
1014
- * replaces the per-write 1M-index probe + sequential probe loop
1015
- * (up to 1024 schema lookups) the runtime previously used.
1204
+ * into an array branch, and the answer is definitive — the runtime
1205
+ * never second-guesses it.
1016
1206
  *
1017
1207
  * Return values:
1018
1208
  * - `number` → tuple of this structural length. The runtime pads
1019
1209
  * the consumer to this length and recurses position-by-position.
1020
- * - `null` → unbounded array. The runtime uses the consumer's
1021
- * length and reuses one element default for every position.
1022
- * - `undefined` → the path doesn't resolve to an array OR the
1023
- * adapter can't determine the shape. The runtime falls back to
1024
- * a probe loop in this case (defensive — every built-in adapter
1025
- * returns `number` or `null`).
1210
+ * - `null` → not a tuple. Covers the unbounded array (the runtime
1211
+ * uses the consumer's length and reuses one element default for
1212
+ * every position) and every path that doesn't resolve to an
1213
+ * array at all — there `getDefaultAtPath` yields no element
1214
+ * default either, so the consumer's array passes through
1215
+ * unchanged.
1026
1216
  *
1027
1217
  * Wrappers (optional / nullable / default / readonly / catch /
1028
1218
  * pipe / lazy) are peeled transparently before the type check, so
1029
1219
  * `optional(z.tuple([...]))` reports its tuple length.
1030
1220
  */
1031
- arrayShapeAtPath(path: Path): number | null | undefined;
1221
+ arrayShapeAtPath(path: Path): number | null;
1032
1222
  /**
1033
1223
  * Whether the schema at `path` is a FIXED object: a closed set of
1034
1224
  * declared keys (`z.object`), as opposed to an open or union container
@@ -1052,6 +1242,29 @@ type AbstractSchema<Form, GetValueFormType> = {
1052
1242
  * `false`.
1053
1243
  */
1054
1244
  isFixedObjectAtPath(path: Path): boolean;
1245
+ /**
1246
+ * How the container at `path` spells the keys of its own entries:
1247
+ * `'number'` for an array or a tuple, `'string'` for an object or a
1248
+ * record, and for a `z.map` the kind its declared key type accepts.
1249
+ * `undefined` for anything else, a leaf and an undeclared path
1250
+ * included.
1251
+ *
1252
+ * The write walkers consult it at a `Map`, where a new entry has to
1253
+ * be filed under a key of the declared type and the path segment
1254
+ * alone cannot say which: an integer-looking segment canonicalises
1255
+ * to a number, so `scores.42` against a `z.map(z.string(), V)` would
1256
+ * otherwise take the number `42` as its key and fail the map's own
1257
+ * parse. An entry the map already holds needs no ruling — its
1258
+ * existing key wins.
1259
+ *
1260
+ * A map whose key type is neither string-ish nor number-ish, or
1261
+ * which admits both, reports `undefined`: no segment can spell such
1262
+ * a key, so the map stays a whole value with no addressable entries.
1263
+ *
1264
+ * Adapters MAY cache per path; the runtime calls this on the write
1265
+ * path.
1266
+ */
1267
+ entryKeyKindAtPath(path: Path): 'string' | 'number' | undefined;
1055
1268
  /**
1056
1269
  * Return every sub-schema that could resolve at the given structured
1057
1270
  * path. Multiple results are only expected for discriminated / union
@@ -1122,9 +1335,12 @@ type AbstractSchema<Form, GetValueFormType> = {
1122
1335
  */
1123
1336
  getSlimPrimitiveTypesAtPath(path: Path): Set<SlimPrimitiveKind>;
1124
1337
  /**
1125
- * Return `true` iff `path` resolves to a **leaf** in the schema — a
1126
- * path whose slim primitive set contains only primitive kinds (no
1127
- * `object`, `array`, `map`, `set`). The runtime proxies (`form.values`,
1338
+ * Return `true` iff `path` resolves to a **leaf** in the schema: a
1339
+ * path the schema declares no sub-paths under. That is every path
1340
+ * whose slim primitive set contains only primitive kinds (no
1341
+ * `object`, `array`, `map`, `set`), plus the opaque leaves, which
1342
+ * admit every kind and are classified by kind instead (below). The
1343
+ * runtime proxies (`form.values`,
1128
1344
  * `form.errors`, `form.fields`) query this at every step to decide
1129
1345
  * between **descend into a sub-proxy** (container) and **terminate
1130
1346
  * with a leaf value** (leaf).
@@ -1142,6 +1358,14 @@ type AbstractSchema<Form, GetValueFormType> = {
1142
1358
  * date/function) → `true`. `'date'` counts as a leaf (don't drill
1143
1359
  * into `Date`). `'function'` is a leaf for the same reason — opaque
1144
1360
  * value.
1361
+ * - **Opaque leaf** (`z.any()`, `z.unknown()`, `z.custom()`, and the
1362
+ * `z.instanceof(X)` that compiles to it) → `true`, and it answers
1363
+ * ahead of the kind test. An opaque leaf admits every kind
1364
+ * INCLUDING the container ones, so reading it off the slim
1365
+ * primitive set alone classifies it as a container and puts
1366
+ * phantom nodes under it on `form.fields` — see
1367
+ * `isOpaqueLeafAtPath`. What leafness asks is whether the schema
1368
+ * declares sub-paths here, and an opaque leaf declares none.
1145
1369
  * - **Optional / Nullable / Default / Catch** wrappers transparent —
1146
1370
  * adds `'null'` / `'undefined'` to the inner kind set without
1147
1371
  * changing the leaf classification.
@@ -1307,6 +1531,19 @@ type AbstractSchema<Form, GetValueFormType> = {
1307
1531
  * toward returning `true` when in doubt.
1308
1532
  */
1309
1533
  hasContainerOrRootRefine?(): boolean;
1534
+ /**
1535
+ * `true` when the schema tree contains at least one discriminated
1536
+ * union at any depth (inside arrays, tuples, records, and lazy
1537
+ * schemas included). The store computes its per-form DU capability
1538
+ * flag from this once at construction: `false` lets every write skip
1539
+ * the cross-variant ancestor guard and the variant-reshape dispatch,
1540
+ * and DU stub correction never runs. Optional: an adapter that omits
1541
+ * it is treated as containing unions, keeping the conservative
1542
+ * per-write probes on. Never return `false` for a schema that DOES
1543
+ * hold a discriminated union — that disables variant reshape and
1544
+ * stub correction for the form.
1545
+ */
1546
+ hasDiscriminatedUnions?(): boolean;
1310
1547
  };
1311
1548
  /**
1312
1549
  * Adapter-returned info for a discriminated union — its discriminator
@@ -1422,7 +1659,7 @@ type OnInvalidSubmitPolicy = 'none' | 'focus-first-error' | 'scroll-to-first-err
1422
1659
  * registered field. No debounce — `debounceMs` is rejected by the
1423
1660
  * type.
1424
1661
  * - `'submit'`: no live validation. `handleSubmit` and explicit
1425
- * `validate()` / `validateAsync()` calls are the only validation
1662
+ * `validate()` / `parse()` calls are the only validation
1426
1663
  * surfaces. `debounceMs` is rejected by the type.
1427
1664
  */
1428
1665
  type ValidateOn = 'change' | 'blur' | 'submit';
@@ -1499,8 +1736,8 @@ type WriteMeta = {
1499
1736
  readonly skipDiscriminatorReshape?: boolean;
1500
1737
  /**
1501
1738
  * Records an array structural mutation precisely enough to replay the
1502
- * exact index permutation it produced, set by `field-arrays.ts`
1503
- * helpers. `setValueAtPath` uses it to surgically clear variant memory
1739
+ * exact index permutation it produced, set by the typed array helpers
1740
+ * in `array-engine.ts`. `setValueAtPath` uses it to surgically clear variant memory
1504
1741
  * for the indices the operation invalidated. Without this hint, a raw
1505
1742
  * whole-array `setValue(arrayPath, [...])` clears all memory under the
1506
1743
  * array (the runtime can't tell which indices stayed put). Internal —
@@ -1551,19 +1788,68 @@ type WriteMeta = {
1551
1788
  readonly hydration?: boolean;
1552
1789
  };
1553
1790
  /**
1554
- * Undo/redo configuration passed via `useForm({ history })`.
1791
+ * The store slice the history runtime binds to. Structural on purpose:
1792
+ * `historyPlugin()` ships from the separate `attaform/history` entry, so
1793
+ * the runtime receives the store through this seam instead of importing
1794
+ * the store module (which would pull the history internals onto every
1795
+ * form's eager path). A FormStore satisfies it as-is.
1796
+ *
1797
+ * @internal
1798
+ */
1799
+ type HistoryKernel = {
1800
+ readonly form: Ref<unknown>;
1801
+ readonly blankPaths: Set<PathKey>;
1802
+ readonly errorCells: Map<PathKey, ErrorCell>;
1803
+ onFormChange(listener: (next: unknown, meta?: WriteMeta) => void): () => void;
1804
+ applyFormReplacement(next: unknown): void;
1805
+ restoreErrorCells(entries: ReadonlyArray<readonly [PathKey, ErrorCell]>): void;
1806
+ };
1807
+ /**
1808
+ * The live undo/redo runtime a {@link HistoryPlugin} attaches to one
1809
+ * form. Cached on the FormStore so every `useForm` / `injectForm`
1810
+ * consumer of the same key shares one chain; `buildFormApi` adapts it
1811
+ * into the public `form.history` namespace.
1555
1812
  *
1556
- * - `true` — enable with the default position cap (`max: 128`).
1557
- * - `{ max }` — enable and tune the bounded history size.
1813
+ * @internal
1814
+ */
1815
+ type HistoryModule = {
1816
+ undo(): boolean;
1817
+ redo(): boolean;
1818
+ clear(): void;
1819
+ canUndo: Readonly<ComputedRef<boolean>>;
1820
+ canRedo: Readonly<ComputedRef<boolean>>;
1821
+ historySize: Readonly<ComputedRef<number>>;
1822
+ dispose(): void;
1823
+ };
1824
+ /**
1825
+ * Opt-in undo/redo, created by `historyPlugin()` from `attaform/history`
1826
+ * and passed via `useForm({ history })`:
1827
+ *
1828
+ * ```ts
1829
+ * import { historyPlugin } from 'attaform/history'
1830
+ *
1831
+ * const form = useForm({ schema, history: historyPlugin({ max: 200 }) })
1832
+ * ```
1558
1833
  *
1559
- * When enabled, every mutation records a forward delta; `form.history.undo()`
1834
+ * When enabled, every mutation records a position; `form.history.undo()`
1560
1835
  * / `form.history.redo()` walk the chain. `reset()` is itself a mutation —
1561
1836
  * the pre-reset state stays one undo away. Persistence hydration is the
1562
1837
  * floor: after hydrate applies, the chain reseeds with the hydrated value
1563
1838
  * and `undo()` cannot reach the transient pre-hydration default.
1839
+ *
1840
+ * One plugin instance is a reusable configuration, not per-form state:
1841
+ * passing the same instance to several forms (or setting it once via
1842
+ * `createAttaform({ defaults: { history } })`) gives each form its own
1843
+ * independent chain.
1564
1844
  */
1565
- type HistoryConfig = true | {
1566
- max?: number;
1845
+ type HistoryPlugin = {
1846
+ /**
1847
+ * Bind a fresh history runtime to one form's store. Called by
1848
+ * `useForm` when the store is first created.
1849
+ *
1850
+ * @internal
1851
+ */
1852
+ readonly attach: (kernel: HistoryKernel) => HistoryModule;
1567
1853
  };
1568
1854
  /**
1569
1855
  * Consolidated undo/redo namespace at `form.history`. All history-related
@@ -1781,16 +2067,17 @@ type UseFormConfiguration<Form extends GenericForm, GetValueFormType, Schema ext
1781
2067
  */
1782
2068
  debounceMs?: number;
1783
2069
  /**
1784
- * Opt-in undo/redo. Off by default. `true` enables with a 128-position
1785
- * cap; `{ max: N }` tunes the cap.
2070
+ * Opt-in undo/redo. Off by default. Pass `historyPlugin()` from
2071
+ * `attaform/history` — a 128-position cap by default,
2072
+ * `historyPlugin({ max: N })` to tune it.
1786
2073
  *
1787
- * Every mutation records a forward delta. `form.history.undo()` walks
2074
+ * Every mutation records a position. `form.history.undo()` walks
1788
2075
  * one step back; `form.history.redo()` walks one step forward.
1789
2076
  * `reset()` is itself a mutation, so the pre-reset state stays one
1790
2077
  * undo away. The consolidated `form.history` namespace also exposes
1791
2078
  * `clear()`, `canUndo`, `canRedo`, and `size`.
1792
2079
  */
1793
- history?: HistoryConfig;
2080
+ history?: HistoryPlugin;
1794
2081
  /**
1795
2082
  * Whether to remember the typed state of each discriminated-union
1796
2083
  * variant across switches. Default `true`.
@@ -1936,8 +2223,8 @@ type AttaformDefaults = {
1936
2223
  * `validateOn` resolves to `'change'`. Default `0` (synchronous).
1937
2224
  */
1938
2225
  debounceMs?: number;
1939
- /** Default for `useForm({ history })`. */
1940
- history?: HistoryConfig;
2226
+ /** Default for `useForm({ history })` — a `historyPlugin()` instance. */
2227
+ history?: HistoryPlugin;
1941
2228
  /** Default for `useForm({ rememberVariants })`. */
1942
2229
  rememberVariants?: boolean;
1943
2230
  /** Default for `useForm({ disabled })` — freeze the form's data. */
@@ -2016,7 +2303,7 @@ type AttaformDefaults = {
2016
2303
  *
2017
2304
  * "Permissive fallback" means storage and reads keep working at any
2018
2305
  * depth; only the per-write type gate stops checking past the cap.
2019
- * Full schema validation (`validateAsync`, `handleSubmit`) still runs
2306
+ * Full schema validation (`parse`, `handleSubmit`) still runs
2020
2307
  * against the real schema, so refinement errors at any depth still
2021
2308
  * surface — the cap only affects the *write-time gate*.
2022
2309
  *
@@ -2425,6 +2712,49 @@ type RegisterOptions = {
2425
2712
  */
2426
2713
  autoAria?: boolean;
2427
2714
  };
2715
+ /**
2716
+ * The narrow kernel surface the DOM binding drives. Structurally a
2717
+ * subset of the form store: the field-record connect/disconnect
2718
+ * transitions, focus marking (which owns blur-validation), the record
2719
+ * and merged-error reads the focus walk needs, and the async-transform
2720
+ * abort for a fully-detached path.
2721
+ * @internal
2722
+ */
2723
+ type DomBindingKernel = {
2724
+ readonly noteDomConnected: (path: Path) => void;
2725
+ readonly noteDomDisconnected: (path: Path) => void;
2726
+ readonly markFocused: (path: Path, focused: boolean, meta?: {
2727
+ readonly instance?: WriteMeta['instance'];
2728
+ }) => void;
2729
+ readonly getFieldRecord: (path: Path) => FieldRecord | undefined;
2730
+ readonly getErrorsForPath: (path: Path) => ValidationError[];
2731
+ readonly cancelTransformsUnder: (prefix: Path) => void;
2732
+ };
2733
+ /**
2734
+ * The form store's DOM slice: the element registry backing
2735
+ * `field.element` / `field.elements`, no-latch host focus anchors, and
2736
+ * first-error focus resolution. Implemented in the directive cluster's
2737
+ * lazy graph and armed into the store's `domBinding` slot on first use
2738
+ * (see `RegisterValue.ensureDomBinding`); a `null` slot means nothing
2739
+ * in the app ever registered an element.
2740
+ * @internal
2741
+ */
2742
+ type AttaformDomBinding = {
2743
+ readonly elements: Map<PathKey, ElementRecord>;
2744
+ readonly attach: (segments: Path, element: HTMLElement, formInstanceId: string, instanceMeta: WriteMeta['instance'] | undefined) => void;
2745
+ readonly detach: (segments: Path, element: HTMLElement) => void;
2746
+ readonly markHostConnected: (segments: Path, connected: boolean, hostEl: HTMLElement, formInstanceId: string) => void;
2747
+ readonly getFirstErrorElement: (formInstanceId: string) => {
2748
+ path: Path;
2749
+ element: HTMLElement;
2750
+ } | null;
2751
+ };
2752
+ /**
2753
+ * Factory the directive / `useRegister` inject through
2754
+ * `RegisterValue.ensureDomBinding` to arm a store's `domBinding` slot.
2755
+ * @internal
2756
+ */
2757
+ type DomBindingFactory = (kernel: DomBindingKernel) => AttaformDomBinding;
2428
2758
  /**
2429
2759
  * The object returned by `form.register(path)`. Pass it to a native
2430
2760
  * input via `v-register`:
@@ -2530,6 +2860,17 @@ type RegisterValue<Value = unknown> = Readonly<{
2530
2860
  * @internal
2531
2861
  */
2532
2862
  hasRegisteredDescendant: (hostElement: HTMLElement) => boolean;
2863
+ /**
2864
+ * Arm this binding's form store with the DOM-binding implementation
2865
+ * (element registry, focus listeners, first-error focus resolution).
2866
+ * The implementation lives in the directive cluster's lazy graph, so
2867
+ * the directive and `useRegister` inject its factory here before any
2868
+ * element call; once armed, the store's `domBinding` slot serves every
2869
+ * later registration. Optional so hand-rolled RegisterValues, which
2870
+ * own their element handling, don't have to declare it.
2871
+ * @internal
2872
+ */
2873
+ ensureDomBinding?: (factory: DomBindingFactory) => void;
2533
2874
  /**
2534
2875
  * Canonical, JSON-encoded path key for this binding (e.g.
2535
2876
  * `'["items",0,"name"]'`). Useful for stable Map / Set keys, log
@@ -2958,10 +3299,10 @@ type RegisterModelDynamicCustomDirective = ObjectDirective<HTMLInputElement | HT
2958
3299
  * See `RegisterTextModifier` / `RegisterSelectModifier` for
2959
3300
  * per-modifier semantics.
2960
3301
  *
2961
- * Registered globally by `createAttaform()` (and by the
2962
- * `attaform/nuxt` module). Most consumers don't import the
2963
- * directive itself — it's exposed for integrations that install
2964
- * directives manually.
3302
+ * Delivered by the Vite / Nuxt plugin's compile-time binding, or by
3303
+ * `installVRegister(app)` from `attaform/directive` everywhere else.
3304
+ * Most consumers don't import the directive itself — it's exposed for
3305
+ * integrations that install directives manually.
2965
3306
  */
2966
3307
  type RegisterDirective = RegisterTextCustomDirective | RegisterCheckboxCustomDirective | RegisterSelectCustomDirective | RegisterRadioCustomDirective | RegisterModelDynamicCustomDirective;
2967
3308
  /**
@@ -3015,9 +3356,11 @@ declare module 'vue' {
3015
3356
  * form.setValue((prev) => ({ ...prev, name: 'Ada' }))
3016
3357
  * ```
3017
3358
  *
3018
- * The library fills any missing structural slots (e.g. nested
3019
- * objects) against the schema's defaults after the callback returns,
3020
- * so partial returns are safe.
3359
+ * A whole-form callback replaces the whole form. Any key the return
3360
+ * omits is refilled from the SCHEMA's declared defaults (the slim
3361
+ * value where none is declared), so an omitted key is not carried
3362
+ * over from the previous value or from `defaultValues` — spread
3363
+ * `prev` to keep the rest of the form.
3021
3364
  */
3022
3365
  type SetValueCallback<Read, Write = Read> = (prev: Read) => Read | Write;
3023
3366
  /**
@@ -3206,7 +3549,7 @@ type FieldState<Value = unknown> = {
3206
3549
  * `true` while a per-field validation run is in flight at this path.
3207
3550
  * Reflects field-level debounced runs (`validate-on-change`) and
3208
3551
  * cross-field re-validations targeting this path. Whole-form
3209
- * `validate()` / `validateAsync()` calls drive `form.meta.validating`
3552
+ * `validate()` / `parse()` calls drive `form.meta.validating`
3210
3553
  * only — they don't flip per-field flags.
3211
3554
  *
3212
3555
  * Per-field analogue of `form.meta.validating`. Use for a tight
@@ -3650,7 +3993,7 @@ type FieldStateMap<Form extends GenericForm> = LeafWalker<Form, 'field'> & {
3650
3993
  * dot/bracket access (`form.fields.users[i].email`), which is what
3651
3994
  * descends.
3652
3995
  */
3653
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): FieldState<NestedType<Form, JoinSegments<S>>>;
3996
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>)): FieldState<NestedType<Form, JoinSegments<S>>>;
3654
3997
  /**
3655
3998
  * Dynamic-array fallback for callers passing `Path`-typed (runtime)
3656
3999
  * segment arrays — e.g. forwarding `RegisterValue.segments` to
@@ -3721,7 +4064,7 @@ type FormErrorsSurface<Form> = ErrorsProxyShape<Form> & {
3721
4064
  * tuples that don't resolve to a known path fail at the call site.
3722
4065
  * Dynamic `Path`-typed inputs hit the untyped fallback overload below.
3723
4066
  */
3724
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): readonly ValidationError[];
4067
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>)): readonly ValidationError[];
3725
4068
  (segments: ReadonlyArray<string | number>): readonly ValidationError[];
3726
4069
  /**
3727
4070
  * No-arg call returns the whole-form error aggregate, the same as
@@ -3766,6 +4109,27 @@ type ErrorsProxyShape<T> = LeafWalker<T, 'errors', false>;
3766
4109
  * form.values() // the whole form value (root)
3767
4110
  * ```
3768
4111
  *
4112
+ * The two shapes answer different questions. Dot access is the
4113
+ * REACTIVE view: per-key tracking, no copying, always the live value.
4114
+ * The call form returns a SNAPSHOT: a detached plain object that keeps
4115
+ * what it held at capture time, so it is the shape to hand an async
4116
+ * call, a serialiser, or a diff.
4117
+ *
4118
+ * ```ts
4119
+ * const before = form.values() // detached; survives later writes
4120
+ * await api.save(before) // cannot mutate underneath the call
4121
+ * form.values.email // reactive read; use this in computed
4122
+ * ```
4123
+ *
4124
+ * Prefer dot access inside a `computed`, `watchEffect`, or template:
4125
+ * it tracks the one key you read, where the call form depends on the
4126
+ * whole form and re-runs the consumer on any change.
4127
+ *
4128
+ * The copy is deep across plain objects and arrays. Non-plain
4129
+ * instances (Map, Set, File, Date) are shared by reference, matching
4130
+ * `JSON.stringify` behaviour; `structuredClone(form.values())` gives a
4131
+ * fully detached copy when one is needed.
4132
+ *
3769
4133
  * Single-bracket dotted access (`form.values['address.city']`) is
3770
4134
  * intentionally NOT supported — JS object semantics treat the dotted
3771
4135
  * string as a single key. Use chained dot/bracket or the callable
@@ -3809,7 +4173,9 @@ type ValuesSurface<F> = Readonly<LiftedValueShape<F>> & {
3809
4173
  * `form.fields.<path>`; this is the aggregate view across the
3810
4174
  * whole form.
3811
4175
  *
3812
- * Read-only at runtime — assignments throw. Destructuring snapshots
4176
+ * Read-only at runtime — an assignment is refused with a dev-console
4177
+ * warning and never lands (Attaform does not throw from a read
4178
+ * surface). Destructuring snapshots
3813
4179
  * the current values; use `toRefs()` if you need reactive handles
3814
4180
  * to individual fields.
3815
4181
  */
@@ -4153,7 +4519,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4153
4519
  * `form.setValue([prefix, 'line1'], 'value')`. The resolved leaf
4154
4520
  * type is exact, matching the dotted-string form.
4155
4521
  */
4156
- <const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never), value: Value): boolean;
4522
+ <const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>), value: Value): boolean;
4157
4523
  };
4158
4524
  /**
4159
4525
  * Reactive validation status. Re-runs whenever the form (or the
@@ -4173,19 +4539,6 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4173
4539
  * settles to results from the most recent call.
4174
4540
  */
4175
4541
  validate: (path?: FlatPath<Form>) => Readonly<Ref<ReactiveValidationStatus<Form>>>;
4176
- /**
4177
- * Run validation once and return the result. Unlike `validate()`,
4178
- * this does not subscribe to form reactivity.
4179
- *
4180
- * ```ts
4181
- * const result = await form.validateAsync()
4182
- * if (!result.success) showErrors(result.errors)
4183
- * ```
4184
- *
4185
- * Pass a path to validate a subtree. `state.validating` flips
4186
- * `true` while the promise is in flight.
4187
- */
4188
- validateAsync: (path?: FlatPath<Form>) => Promise<ValidationResponseWithoutValue<Form>>;
4189
4542
  /**
4190
4543
  * Resolve once every in-flight async `register({ transforms })` run
4191
4544
  * has settled — globally, or (with `path`) only at-or-under that path.
@@ -4207,9 +4560,9 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4207
4560
  */
4208
4561
  settleTransforms: (path?: FlatPath<Form>) => Promise<void>;
4209
4562
  /**
4210
- * Imperative one-shot parse. Same pipeline as `validateAsync` —
4211
- * runs refinements, applies `.transform()`s, composes blank-required
4212
- * errors — but RETAINS the parsed data instead of stripping it.
4563
+ * Imperative one-shot parse. Runs the full pipeline — refinements,
4564
+ * `.transform()`s, blank-required composition — against the current
4565
+ * form snapshot and RETAINS the parsed data.
4213
4566
  *
4214
4567
  * Storage holds the "honest input view" — values you wrote, with
4215
4568
  * preprocess normalization applied but `.transform()` deferred. For
@@ -4227,16 +4580,31 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4227
4580
  * }
4228
4581
  * ```
4229
4582
  *
4583
+ * By default the call is a PURE read: nothing is written to
4584
+ * `form.errors`, and in-flight per-field validation runs are left
4585
+ * alone. Pass `{ commit: true }` to make the run authoritative —
4586
+ * the verdict is committed to the error store at the parsed scope
4587
+ * and any in-flight per-field runs are cancelled first (mirroring
4588
+ * `handleSubmit`), so `await form.parse('email', { commit: true })`
4589
+ * lands a deterministic view of `form.errors.email`:
4590
+ *
4591
+ * ```ts
4592
+ * const result = await form.parse({ commit: true })
4593
+ * if (!result.success) showErrors(result.errors)
4594
+ * ```
4595
+ *
4230
4596
  * Always async, and there is no synchronous variant by design: a
4231
4597
  * schema can carry async refinements or transforms, so a sync parse
4232
4598
  * would silently miss them the moment one is added. One always-
4233
4599
  * awaited `parse` closes that category of bug entirely. The returned
4234
4600
  * promise never rejects (a thrown adapter lands as a `success: false`
4235
4601
  * response). Pass a path to parse a subtree only. `meta.validating`
4236
- * flips `true` while the promise is in flight (shared with
4237
- * validateAsync).
4602
+ * flips `true` while the promise is in flight.
4238
4603
  */
4239
- parse: (path?: FlatPath<Form>) => Promise<ValidationResponse<GetValueFormType>>;
4604
+ parse: {
4605
+ (path?: FlatPath<Form>, options?: ParseOptions): Promise<ValidationResponse<GetValueFormType>>;
4606
+ (options: ParseOptions): Promise<ValidationResponse<GetValueFormType>>;
4607
+ };
4240
4608
  /**
4241
4609
  * Bind a path to a native input via `v-register`. Returns a
4242
4610
  * `RegisterValue` carrying the live ref and event handlers the
@@ -4263,7 +4631,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4263
4631
  */
4264
4632
  register: {
4265
4633
  <Path extends RegisterFlatPath<Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, Path>>;
4266
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>;
4634
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form>] ? unknown : SegmentRegisterRejection<JoinSegments<S>>), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>;
4267
4635
  };
4268
4636
  /**
4269
4637
  * The form's identifier — either the explicit `key` passed to
@@ -4344,8 +4712,12 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4344
4712
  *
4345
4713
  * Resolves after `hydrating` flips back to `false`. Throws
4346
4714
  * synchronously when the form was constructed with a plain-value
4347
- * `defaultValues` (nothing to re-fire). Does NOT clear dirty /
4348
- * touched / submit state — chain `form.reset()` for that.
4715
+ * `defaultValues` (nothing to re-fire).
4716
+ *
4717
+ * The payload becomes the form's defaults, the same way a
4718
+ * `reset(next)` argument does, so `form.reset()` afterwards lands on
4719
+ * the values just fetched. Does NOT clear touched / submit state;
4720
+ * chain `form.reset()` for that.
4349
4721
  */
4350
4722
  rehydrate(): Promise<void>;
4351
4723
  /**
@@ -4403,7 +4775,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4403
4775
  */
4404
4776
  toRef: {
4405
4777
  <Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, Path>>>;
4406
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>>;
4778
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>)): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>>;
4407
4779
  };
4408
4780
  /**
4409
4781
  * Set the form's manual error layer. One surface for server-side
@@ -4473,10 +4845,10 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4473
4845
  */
4474
4846
  meta: FormMeta<Form>;
4475
4847
  /**
4476
- * Restore the form to its initial state. Without arguments,
4477
- * re-applies the schema defaults (and any `defaultValues` passed
4478
- * to `useForm`). Pass `nextDefaultValues` to seed the reset with
4479
- * a fresh set of overrides.
4848
+ * Restore the form to its defaults. Without arguments, re-applies
4849
+ * whatever the defaults currently are: `useForm({ defaultValues })`
4850
+ * on a fresh form, or the last values a `reset(next)` or an async
4851
+ * `defaultValues` factory settled on.
4480
4852
  *
4481
4853
  * Resets:
4482
4854
  * - the form value back to defaults;
@@ -4485,6 +4857,26 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4485
4857
  * - touched / focused / blurred per-field flags;
4486
4858
  * - submission state (`submitting` / `submissionAttempts` /
4487
4859
  * `submitted` / `submitError`).
4860
+ *
4861
+ * `nextDefaultValues` RE-SEATS the defaults rather than applying for
4862
+ * one call, so the form has a single set of defaults that `reset()`,
4863
+ * `resetField(path)`, and `dirty` all read. That is what makes the
4864
+ * save-then-discard shape work: reset from the resource the server
4865
+ * returned, and a later Discard returns to the save instead of
4866
+ * rolling back across it.
4867
+ *
4868
+ * ```ts
4869
+ * const saved = await api.save(form.values())
4870
+ * form.reset(toValues(saved)) // the saved resource is now the baseline
4871
+ * // …later…
4872
+ * form.reset() // back to the saved resource
4873
+ * ```
4874
+ *
4875
+ * The argument is sparse: it folds over the defaults already in
4876
+ * force, so paths it does not name keep the value they had, and
4877
+ * `reset({})` changes nothing. Arrays are replaced wholesale rather
4878
+ * than merged element-wise. Pass `unset` at a path to withdraw its
4879
+ * value and mark it blank.
4488
4880
  */
4489
4881
  reset: (nextDefaultValues?: DefaultValuesInput<Form>) => void;
4490
4882
  /**
@@ -4539,7 +4931,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4539
4931
  clear: {
4540
4932
  (): boolean;
4541
4933
  <Path extends FlatPath<Form> | ''>(path: Path): boolean;
4542
- <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown : never)): boolean;
4934
+ <const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown : SegmentPathRejection<JoinSegments<S>>)): boolean;
4543
4935
  };
4544
4936
  /**
4545
4937
  * Consolidated undo/redo namespace — `form.history.{undo, redo,
@@ -4759,5 +5151,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
4759
5151
  blankPaths: ComputedRef<BlankPathsView>;
4760
5152
  };
4761
5153
 
4762
- export { ROOT_PATH as X, ROOT_PATH_KEY as Y, canonicalizePath as al, isPathPrefix as am, isUnset as an, parseDottedPath as ao, unset as ap };
4763
- export type { RegisterFlatPath as $, AbstractSchema as A, NestedType as B, CoercionEntry as C, DefaultValuesInput as D, ErrorInput as E, FormKey as F, GenericForm as G, HandleSubmit as H, IsTuple as I, JoinSegments as J, KeyofUnion as K, LiftedValueShape as L, MetaTrackerValue as M, NestedReadType as N, OnError as O, OnInvalidSubmitPolicy as P, OnSubmit as Q, PartialFlatPath as R, Path as S, PathKey as T, UseFormConfiguration as U, PendingValidationStatus as V, Primitive as W, ReactiveValidationStatus as Z, RegisterDirective as _, UseFormReturnType as a, RegisterOptions as a0, RegisterSelectModifier as a1, RegisterTextModifier as a2, RegisterTransform as a3, RegisterValue as a4, Segment as a5, SetValueCallback as a6, SetValuePayload as a7, SettledValidationStatus as a8, SlimPrimitiveKind as a9, SlimRuntimeOf as aa, SubmitHandler as ab, Unset as ac, ValidateOn as ad, ValidateOnConfig as ae, ValidationError as af, ValidationResponse as ag, ValidationResponseWithoutValue as ah, ValueOfUnion as ai, WriteMeta as aj, WriteShape as ak, AcceptableDefaults as aq, SchemaFactoryOptions as ar, TransformAbortHolder as as, RegisterModelDynamicCustomDirective as at, ArrayItem as b, ArrayPath as c, AttaformDefaults as d, CoercionRegistry as e, CoercionResult as f, CustomDirectiveRegisterAssignerFn as g, DeepPartial as h, DefaultValuesResponse as i, DefaultValuesShape as j, DisplayCtx as k, DisplayMachine as l, DisplayState as m, ErrorsProxyShape as n, FieldMetaPayload as o, FieldState as p, FieldStateMap as q, FieldStateMapEntry as r, FlatPath as s, FormErrorRecord as t, FormErrorsSurface as u, FormMeta as v, GetDisplayState as w, HistoryConfig as x, IsUnion as y, Json as z };
5154
+ export { ROOT_PATH as Y, ROOT_PATH_KEY as Z, canonicalizePath as ao, isPathPrefix as ap, isUnset as aq, parseDottedPath as ar, unset as as };
5155
+ export type { RecordPath as $, AbstractSchema as A, NestedType as B, CoercionEntry as C, DefaultValuesInput as D, ErrorInput as E, FormKey as F, GenericForm as G, HandleSubmit as H, IsTuple as I, JoinSegments as J, KeyofUnion as K, LiftedValueShape as L, MetaTrackerValue as M, NestedReadType as N, OnError as O, OnInvalidSubmitPolicy as P, OnSubmit as Q, ParseOptions as R, PartialFlatPath as S, Path as T, UseFormConfiguration as U, PathKey as V, PendingValidationStatus as W, Primitive as X, ReactiveValidationStatus as _, UseFormReturnType as a, RecordValue as a0, RegisterDirective as a1, RegisterFlatPath as a2, RegisterOptions as a3, RegisterSelectModifier as a4, RegisterTextModifier as a5, RegisterTransform as a6, RegisterValue as a7, Segment as a8, SetValueCallback as a9, TransformAbortHolder as aA, SetValuePayload as aa, SettledValidationStatus as ab, SlimPrimitiveKind as ac, SlimRuntimeOf as ad, SubmitHandler as ae, Unset as af, ValidateOn as ag, ValidateOnConfig as ah, ValidationError as ai, ValidationResponse as aj, ValidationResponseWithoutValue as ak, ValueOfUnion as al, WriteMeta as am, WriteShape as an, RegisterModelDynamicCustomDirective as at, SchemaFactoryOptions as au, AcceptableDefaults as av, FieldRecord as aw, ErrorCell as ax, OriginalsRecord as ay, AttaformDomBinding as az, ArrayItem as b, ArrayPath as c, AttaformDefaults as d, CoercionRegistry as e, CoercionResult as f, CustomDirectiveRegisterAssignerFn as g, DeepPartial as h, DefaultValuesResponse as i, DefaultValuesShape as j, DisplayCtx as k, DisplayMachine as l, DisplayState as m, ErrorsProxyShape as n, FieldMetaPayload as o, FieldState as p, FieldStateMap as q, FieldStateMapEntry as r, FlatPath as s, FormErrorRecord as t, FormErrorsSurface as u, FormMeta as v, GetDisplayState as w, HistoryPlugin as x, IsUnion as y, Json as z };