attaform 0.28.0 → 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.
- package/dist/abstract.d.mts +5 -5
- package/dist/abstract.mjs +4 -4
- package/dist/chunks/fingerprint.mjs +1 -1
- package/dist/chunks/fingerprint2.mjs +2 -2
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/chunks/fingerprint.mjs +1 -1
- package/dist/dev/chunks/fingerprint2.mjs +2 -2
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +1 -1
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +1 -1
- package/dist/dev/shared/{attaform-dev.Dr2YzS5B.mjs → attaform-dev.A-TpJW0B.mjs} +11 -1
- package/dist/dev/shared/{attaform-dev.oYrkP9dj.mjs → attaform-dev.BO-71R54.mjs} +51 -158
- package/dist/dev/shared/{attaform-dev.6qxD-Yqo.mjs → attaform-dev.BgM6FdtA.mjs} +143 -36
- package/dist/{shared/attaform.h0i6LijT.mjs → dev/shared/attaform-dev.ButTkwHd.mjs} +149 -16
- package/dist/{shared/attaform.BJGA_UOS.mjs → dev/shared/attaform-dev.BxfsuwBR.mjs} +8 -0
- package/dist/dev/shared/{attaform-dev.P7cseiEG.mjs → attaform-dev.D8aoKb89.mjs} +13 -4
- package/dist/dev/shared/{attaform-dev.BXE2cr0L.mjs → attaform-dev.DD5m2W51.mjs} +1 -1
- package/dist/dev/shared/{attaform-dev.WmuhD_CZ.mjs → attaform-dev.DHuydLAC.mjs} +344 -96
- package/dist/dev/shared/{attaform-dev.BR8u0YOZ.mjs → attaform-dev.DrzObAZo.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.D2I8e_Mm.mjs → attaform-dev.q6UutkCx.mjs} +170 -132
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +2 -2
- package/dist/directive.mjs +1 -1
- package/dist/history.d.mts +1 -1
- package/dist/history.mjs +1 -1
- package/dist/index.d.mts +9 -7
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.mts +10 -10
- package/dist/runtime/plugins/attaform.mjs +1 -1
- package/dist/shared/{attaform.C09fpdLS.mjs → attaform.B0dKL8ST.mjs} +143 -36
- package/dist/shared/{attaform.Cs2Rbdlo.mjs → attaform.BK0cgu2K.mjs} +123 -139
- package/dist/shared/{attaform.D6DCnnQu.mjs → attaform.BndjUUYX.mjs} +4 -4
- package/dist/{dev/shared/attaform-dev.BJGA_UOS.mjs → shared/attaform.BxfsuwBR.mjs} +8 -0
- package/dist/shared/{attaform.NLmerepI.mjs → attaform.C2MVyuxC.mjs} +42 -151
- package/dist/shared/{attaform.B4VkS43-.d.mts → attaform.CIWLMY-R.d.mts} +1 -1
- package/dist/shared/{attaform.B8k8JrmK.mjs → attaform.CZMAYwSK.mjs} +338 -95
- package/dist/shared/{attaform.wfY8XFvm.mjs → attaform.CZYt_5N_.mjs} +11 -1
- package/dist/shared/{attaform.Cgu-hdSb.d.mts → attaform.CsoeRi3P.d.mts} +224 -32
- package/dist/{dev/shared/attaform-dev.By4PRjt0.mjs → shared/attaform.Cvao8bW5.mjs} +132 -22
- package/dist/shared/{attaform.Dq4vWxuG.mjs → attaform.D0x-qSXm.mjs} +1 -1
- package/dist/shared/{attaform.CJP3RkGa.mjs → attaform.D1fnTifF.mjs} +168 -132
- package/dist/shared/{attaform.D5V4tZWq.d.mts → attaform.DDtqHYv1.d.mts} +88 -7
- package/dist/shared/{attaform.uLbun31C.mjs → attaform.DffRL5pP.mjs} +12 -4
- package/dist/shared/{attaform.JfSWdEcb.d.mts → attaform.axHXVQO7.d.mts} +1 -1
- package/dist/transforms.d.mts +0 -22
- package/dist/transforms.mjs +1 -1
- package/dist/vite.d.mts +13 -4
- package/dist/vite.mjs +3 -2
- package/dist/zod-v3.d.mts +6 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +14 -27
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +17 -14
- package/skills/attaform/SKILL.md +5 -2
- package/skills/attaform/references/custom-components.md +7 -2
- package/skills/attaform/references/errors.md +8 -3
- package/skills/attaform/references/saving.md +77 -0
- package/skills/attaform/references/wizards.md +10 -8
|
@@ -79,6 +79,16 @@ function groupErrorsByKey(entries) {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
|
|
82
|
+
const SET_MEMBER_SEGMENT = "__atta:member";
|
|
83
|
+
function mapSegmentKeys(value) {
|
|
84
|
+
const keys = [];
|
|
85
|
+
for (const key of value.keys()) {
|
|
86
|
+
if (typeof key === "string") keys.push(key);
|
|
87
|
+
else if (typeof key === "number" && Number.isInteger(key) && key >= 0) keys.push(key);
|
|
88
|
+
else return null;
|
|
89
|
+
}
|
|
90
|
+
return keys;
|
|
91
|
+
}
|
|
82
92
|
function normalizeSegment(raw) {
|
|
83
93
|
if (typeof raw === "number") {
|
|
84
94
|
if (!Number.isInteger(raw) || raw < 0) {
|
|
@@ -194,4 +204,4 @@ function pathsEqual(a, b) {
|
|
|
194
204
|
return true;
|
|
195
205
|
}
|
|
196
206
|
|
|
197
|
-
export { AttaformError as A, InvalidPathError as I, OutsideSetupError as O, ROOT_PATH as R, SubmitErrorHandlerError as S, InvalidUseFormConfigError as a, ROOT_PATH_KEY as b, RegistryNotInstalledError as c, ReservedFormKeyError as d, canonicalizePath as e, pathsEqual as f, pathKeyToDotted as g,
|
|
207
|
+
export { AttaformError as A, InvalidPathError as I, OutsideSetupError as O, ROOT_PATH as R, SubmitErrorHandlerError as S, InvalidUseFormConfigError as a, ROOT_PATH_KEY as b, RegistryNotInstalledError as c, ReservedFormKeyError as d, canonicalizePath as e, pathsEqual as f, pathKeyToDotted as g, SET_MEMBER_SEGMENT as h, isPathPrefix as i, cellEntriesFor as j, keyForSegments as k, groupErrorsByKey as l, mapSegmentKeys as m, normalizeErrorInput as n, normalizeErrorInputs as o, parseDottedPath as p, coerceToPathKey as q, segmentsForPathKey as s, toError as t };
|
|
@@ -359,6 +359,48 @@ type JoinSegments<S extends ReadonlyArray<string | number>, Acc extends string =
|
|
|
359
359
|
infer Head extends string | number,
|
|
360
360
|
...infer Rest extends ReadonlyArray<string | number>
|
|
361
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.`;
|
|
362
404
|
/**
|
|
363
405
|
* `true` when `T` is a union (multiple members), `false` when it's a
|
|
364
406
|
* single type. Used to gate non-homomorphic mapped-type forms so
|
|
@@ -523,44 +565,89 @@ type IsTuple<T extends readonly unknown[]> = number extends T['length'] ? false
|
|
|
523
565
|
* runtime possibility of a missing array position.
|
|
524
566
|
*/
|
|
525
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;
|
|
526
595
|
/**
|
|
527
596
|
* Filter FlatPath<Form> down to the subset of paths whose resolved leaf
|
|
528
597
|
* is an array. Used by the typed field-array helpers (append / remove /
|
|
529
598
|
* swap / ...) so those helpers only accept paths that actually address
|
|
530
599
|
* an array — calling `append('email', ...)` on a `{ email: string }`
|
|
531
|
-
* is a compile error.
|
|
600
|
+
* is a compile error. Optionality is not a disqualifier; see
|
|
601
|
+
* `ArrayLeafOf` for what "is an array" means here.
|
|
532
602
|
*
|
|
533
603
|
* `P extends string` re-triggers distribution over the `FlatPath<Form>`
|
|
534
604
|
* union so the conditional evaluates per member. Without it, the
|
|
535
605
|
* branch would reduce against the union as a whole and collapse to
|
|
536
606
|
* `never` whenever a single member failed the predicate.
|
|
537
607
|
*/
|
|
538
|
-
type ArrayPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ?
|
|
608
|
+
type ArrayPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? [ArrayLeafOf<Form, P>] extends [never] ? never : P : never;
|
|
539
609
|
/**
|
|
540
610
|
* Extract the element type of the array addressed by `Path`. Callers
|
|
541
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.
|
|
614
|
+
*/
|
|
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.
|
|
542
633
|
*/
|
|
543
|
-
type
|
|
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;
|
|
544
635
|
/**
|
|
545
636
|
* Companion to `ArrayPath`: filter `FlatPath<Form>` down to the subset
|
|
546
637
|
* of paths whose resolved leaf is a record (an object with an open
|
|
547
638
|
* string-keyed index signature, e.g. `z.record(z.string(), V)`). A
|
|
548
639
|
* fixed-shape object (`z.object({ ... })`) is excluded — its keys are
|
|
549
640
|
* statically known, so it has no `string` index signature.
|
|
550
|
-
*
|
|
551
|
-
* `string extends keyof T` is the index-signature probe: it holds for
|
|
552
|
-
* `Record<string, V>` (`keyof` is `string`) and fails for a fixed object
|
|
553
|
-
* (`keyof` is the literal key union). The leading array guard keeps
|
|
554
|
-
* arrays (which also satisfy the object check) out of the record set.
|
|
555
641
|
*/
|
|
556
|
-
type RecordPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ?
|
|
642
|
+
type RecordPath<Form, P extends FlatPath<Form> = FlatPath<Form>> = P extends string ? [RecordLeafOf<Form, P>] extends [never] ? never : P : never;
|
|
557
643
|
/**
|
|
558
644
|
* Value type of the record addressed by `Path` — the `V` in a
|
|
559
645
|
* `Record<string, V>`. Callers constrain `Path extends RecordPath<Form>`,
|
|
560
646
|
* so the leaf is always an open string-keyed record and this is
|
|
561
|
-
* well-defined.
|
|
647
|
+
* well-defined. Rides on `RecordLeafOf`, the same alias `RecordPath`
|
|
648
|
+
* admits the path with, so the two cannot disagree.
|
|
562
649
|
*/
|
|
563
|
-
type RecordValue<Form, Path extends RecordPath<Form>> =
|
|
650
|
+
type RecordValue<Form, Path extends RecordPath<Form>> = RecordLeafOf<Form, Path> extends Record<string, infer Value> ? Value : never;
|
|
564
651
|
/**
|
|
565
652
|
* Widens primitive-literal leaves to their primitive supertype to
|
|
566
653
|
* match the runtime "slim-primitive write contract."
|
|
@@ -1088,6 +1175,28 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
1088
1175
|
* the result by canonicalized path key.
|
|
1089
1176
|
*/
|
|
1090
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;
|
|
1091
1200
|
/**
|
|
1092
1201
|
* Distinguish a tuple (fixed-length, position-typed) from an
|
|
1093
1202
|
* unbounded array at `path`. The runtime calls this on every
|
|
@@ -1133,6 +1242,29 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
1133
1242
|
* `false`.
|
|
1134
1243
|
*/
|
|
1135
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;
|
|
1136
1268
|
/**
|
|
1137
1269
|
* Return every sub-schema that could resolve at the given structured
|
|
1138
1270
|
* path. Multiple results are only expected for discriminated / union
|
|
@@ -1203,9 +1335,12 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
1203
1335
|
*/
|
|
1204
1336
|
getSlimPrimitiveTypesAtPath(path: Path): Set<SlimPrimitiveKind>;
|
|
1205
1337
|
/**
|
|
1206
|
-
* Return `true` iff `path` resolves to a **leaf** in the schema
|
|
1207
|
-
* path
|
|
1208
|
-
*
|
|
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`,
|
|
1209
1344
|
* `form.errors`, `form.fields`) query this at every step to decide
|
|
1210
1345
|
* between **descend into a sub-proxy** (container) and **terminate
|
|
1211
1346
|
* with a leaf value** (leaf).
|
|
@@ -1223,6 +1358,14 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
1223
1358
|
* date/function) → `true`. `'date'` counts as a leaf (don't drill
|
|
1224
1359
|
* into `Date`). `'function'` is a leaf for the same reason — opaque
|
|
1225
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.
|
|
1226
1369
|
* - **Optional / Nullable / Default / Catch** wrappers transparent —
|
|
1227
1370
|
* adds `'null'` / `'undefined'` to the inner kind set without
|
|
1228
1371
|
* changing the leaf classification.
|
|
@@ -3213,9 +3356,11 @@ declare module 'vue' {
|
|
|
3213
3356
|
* form.setValue((prev) => ({ ...prev, name: 'Ada' }))
|
|
3214
3357
|
* ```
|
|
3215
3358
|
*
|
|
3216
|
-
*
|
|
3217
|
-
*
|
|
3218
|
-
* so
|
|
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.
|
|
3219
3364
|
*/
|
|
3220
3365
|
type SetValueCallback<Read, Write = Read> = (prev: Read) => Read | Write;
|
|
3221
3366
|
/**
|
|
@@ -3848,7 +3993,7 @@ type FieldStateMap<Form extends GenericForm> = LeafWalker<Form, 'field'> & {
|
|
|
3848
3993
|
* dot/bracket access (`form.fields.users[i].email`), which is what
|
|
3849
3994
|
* descends.
|
|
3850
3995
|
*/
|
|
3851
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown :
|
|
3996
|
+
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>)): FieldState<NestedType<Form, JoinSegments<S>>>;
|
|
3852
3997
|
/**
|
|
3853
3998
|
* Dynamic-array fallback for callers passing `Path`-typed (runtime)
|
|
3854
3999
|
* segment arrays — e.g. forwarding `RegisterValue.segments` to
|
|
@@ -3919,7 +4064,7 @@ type FormErrorsSurface<Form> = ErrorsProxyShape<Form> & {
|
|
|
3919
4064
|
* tuples that don't resolve to a known path fail at the call site.
|
|
3920
4065
|
* Dynamic `Path`-typed inputs hit the untyped fallback overload below.
|
|
3921
4066
|
*/
|
|
3922
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown :
|
|
4067
|
+
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : SegmentPathRejection<JoinSegments<S>>)): readonly ValidationError[];
|
|
3923
4068
|
(segments: ReadonlyArray<string | number>): readonly ValidationError[];
|
|
3924
4069
|
/**
|
|
3925
4070
|
* No-arg call returns the whole-form error aggregate, the same as
|
|
@@ -3964,6 +4109,27 @@ type ErrorsProxyShape<T> = LeafWalker<T, 'errors', false>;
|
|
|
3964
4109
|
* form.values() // the whole form value (root)
|
|
3965
4110
|
* ```
|
|
3966
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
|
+
*
|
|
3967
4133
|
* Single-bracket dotted access (`form.values['address.city']`) is
|
|
3968
4134
|
* intentionally NOT supported — JS object semantics treat the dotted
|
|
3969
4135
|
* string as a single key. Use chained dot/bracket or the callable
|
|
@@ -4007,7 +4173,9 @@ type ValuesSurface<F> = Readonly<LiftedValueShape<F>> & {
|
|
|
4007
4173
|
* `form.fields.<path>`; this is the aggregate view across the
|
|
4008
4174
|
* whole form.
|
|
4009
4175
|
*
|
|
4010
|
-
* Read-only at runtime —
|
|
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
|
|
4011
4179
|
* the current values; use `toRefs()` if you need reactive handles
|
|
4012
4180
|
* to individual fields.
|
|
4013
4181
|
*/
|
|
@@ -4351,7 +4519,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4351
4519
|
* `form.setValue([prefix, 'line1'], 'value')`. The resolved leaf
|
|
4352
4520
|
* type is exact, matching the dotted-string form.
|
|
4353
4521
|
*/
|
|
4354
|
-
<const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown :
|
|
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;
|
|
4355
4523
|
};
|
|
4356
4524
|
/**
|
|
4357
4525
|
* Reactive validation status. Re-runs whenever the form (or the
|
|
@@ -4463,7 +4631,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4463
4631
|
*/
|
|
4464
4632
|
register: {
|
|
4465
4633
|
<Path extends RegisterFlatPath<Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, Path>>;
|
|
4466
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form>] ? unknown :
|
|
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>>>;
|
|
4467
4635
|
};
|
|
4468
4636
|
/**
|
|
4469
4637
|
* The form's identifier — either the explicit `key` passed to
|
|
@@ -4544,8 +4712,12 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4544
4712
|
*
|
|
4545
4713
|
* Resolves after `hydrating` flips back to `false`. Throws
|
|
4546
4714
|
* synchronously when the form was constructed with a plain-value
|
|
4547
|
-
* `defaultValues` (nothing to re-fire).
|
|
4548
|
-
*
|
|
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.
|
|
4549
4721
|
*/
|
|
4550
4722
|
rehydrate(): Promise<void>;
|
|
4551
4723
|
/**
|
|
@@ -4603,7 +4775,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4603
4775
|
*/
|
|
4604
4776
|
toRef: {
|
|
4605
4777
|
<Path extends FlatPath<Form>>(path: Path): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, Path>>>;
|
|
4606
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown :
|
|
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>>>>;
|
|
4607
4779
|
};
|
|
4608
4780
|
/**
|
|
4609
4781
|
* Set the form's manual error layer. One surface for server-side
|
|
@@ -4673,10 +4845,10 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4673
4845
|
*/
|
|
4674
4846
|
meta: FormMeta<Form>;
|
|
4675
4847
|
/**
|
|
4676
|
-
* Restore the form to its
|
|
4677
|
-
*
|
|
4678
|
-
*
|
|
4679
|
-
*
|
|
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.
|
|
4680
4852
|
*
|
|
4681
4853
|
* Resets:
|
|
4682
4854
|
* - the form value back to defaults;
|
|
@@ -4685,6 +4857,26 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4685
4857
|
* - touched / focused / blurred per-field flags;
|
|
4686
4858
|
* - submission state (`submitting` / `submissionAttempts` /
|
|
4687
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.
|
|
4688
4880
|
*/
|
|
4689
4881
|
reset: (nextDefaultValues?: DefaultValuesInput<Form>) => void;
|
|
4690
4882
|
/**
|
|
@@ -4739,7 +4931,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4739
4931
|
clear: {
|
|
4740
4932
|
(): boolean;
|
|
4741
4933
|
<Path extends FlatPath<Form> | ''>(path: Path): boolean;
|
|
4742
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown :
|
|
4934
|
+
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form> | ''] ? unknown : SegmentPathRejection<JoinSegments<S>>)): boolean;
|
|
4743
4935
|
};
|
|
4744
4936
|
/**
|
|
4745
4937
|
* Consolidated undo/redo namespace — `form.history.{undo, redo,
|
|
@@ -4959,5 +5151,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4959
5151
|
blankPaths: ComputedRef<BlankPathsView>;
|
|
4960
5152
|
};
|
|
4961
5153
|
|
|
4962
|
-
export { ROOT_PATH as Y, ROOT_PATH_KEY as Z, canonicalizePath as
|
|
4963
|
-
export type {
|
|
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 };
|