attaform 0.23.0 → 0.24.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/README.md +1 -1
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/index.cjs +3 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -132
- package/dist/index.d.mts +6 -132
- package/dist/index.d.ts +6 -132
- package/dist/index.mjs +4 -150
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +2 -2
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.CzVta5o2.mjs → attaform.BJ_W7q3U.mjs} +8 -6
- package/dist/shared/attaform.BJ_W7q3U.mjs.map +1 -0
- package/dist/shared/{attaform.D52oJiYC.d.cts → attaform.BNmkKz0q.d.mts} +38 -6
- package/dist/shared/{attaform.CaYj3ZfY.cjs → attaform.BV_HyaMO.cjs} +6 -4
- package/dist/shared/attaform.BV_HyaMO.cjs.map +1 -0
- package/dist/shared/{attaform.Cmb_LCie.cjs → attaform.BnUXV01g.cjs} +4 -4
- package/dist/shared/attaform.BnUXV01g.cjs.map +1 -0
- package/dist/shared/{attaform.alpG7rT7.mjs → attaform.C-dAB90u.mjs} +4 -4
- package/dist/shared/attaform.C-dAB90u.mjs.map +1 -0
- package/dist/shared/{attaform.DsQkXE3o.cjs → attaform.C42wL7EJ.cjs} +195 -179
- package/dist/shared/attaform.C42wL7EJ.cjs.map +1 -0
- package/dist/shared/{attaform.BGMRvckW.d.ts → attaform.C6eE50re.d.ts} +18 -11
- package/dist/shared/{attaform.Dx9-QQE2.mjs → attaform.CAWKNCzc.mjs} +2 -2
- package/dist/shared/{attaform.Dx9-QQE2.mjs.map → attaform.CAWKNCzc.mjs.map} +1 -1
- package/dist/shared/{attaform.CtJOd7ox.mjs → attaform.CuBdtfbe.mjs} +196 -179
- package/dist/shared/attaform.CuBdtfbe.mjs.map +1 -0
- package/dist/shared/{attaform.WEwfXcHq.d.ts → attaform.CwFZGv5-.d.ts} +38 -6
- package/dist/shared/{attaform.DuPneYR0.d.cts → attaform.DdUYEhkV.d.cts} +18 -11
- package/dist/shared/attaform.DdjDqTah.d.cts +56 -0
- package/dist/shared/attaform.DdjDqTah.d.mts +56 -0
- package/dist/shared/attaform.DdjDqTah.d.ts +56 -0
- package/dist/shared/{attaform.BhI9Icek.mjs → attaform.Df-s8j1X.mjs} +2 -4
- package/dist/shared/attaform.Df-s8j1X.mjs.map +1 -0
- package/dist/shared/{attaform.DrY8srOp.d.mts → attaform.DiWNbKWa.d.mts} +18 -11
- package/dist/shared/{attaform.Db4E4IW6.cjs → attaform.DwkU0oY9.cjs} +1 -5
- package/dist/shared/attaform.DwkU0oY9.cjs.map +1 -0
- package/dist/shared/{attaform.BJnNK75Y.d.cts → attaform.GJbSmwLB.d.cts} +181 -156
- package/dist/shared/{attaform.BJnNK75Y.d.mts → attaform.GJbSmwLB.d.mts} +181 -156
- package/dist/shared/{attaform.BJnNK75Y.d.ts → attaform.GJbSmwLB.d.ts} +181 -156
- package/dist/shared/{attaform.DCkSNnPr.d.mts → attaform.K-3glmiT.d.cts} +38 -6
- package/dist/shared/{attaform.DbyTD8N2.cjs → attaform.Z1qTwOYE.cjs} +8 -6
- package/dist/shared/attaform.Z1qTwOYE.cjs.map +1 -0
- package/dist/shared/{attaform.BibT5AS_.cjs → attaform.nycEksJn.cjs} +2 -2
- package/dist/shared/{attaform.BibT5AS_.cjs.map → attaform.nycEksJn.cjs.map} +1 -1
- package/dist/shared/{attaform.Dd1Kmmaj.mjs → attaform.o95Kjd3U.mjs} +6 -4
- package/dist/shared/attaform.o95Kjd3U.mjs.map +1 -0
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +12 -11
- package/dist/zod-v3.d.mts +12 -11
- package/dist/zod-v3.d.ts +12 -11
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +6 -5
- package/dist/zod-v4.d.mts +6 -5
- package/dist/zod-v4.d.ts +6 -5
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +5 -5
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +21 -52
- package/dist/zod.d.mts +21 -52
- package/dist/zod.d.ts +21 -52
- package/dist/zod.mjs +5 -5
- package/dist/zod.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/shared/attaform.BhI9Icek.mjs.map +0 -1
- package/dist/shared/attaform.CaYj3ZfY.cjs.map +0 -1
- package/dist/shared/attaform.Cmb_LCie.cjs.map +0 -1
- package/dist/shared/attaform.CtJOd7ox.mjs.map +0 -1
- package/dist/shared/attaform.CzVta5o2.mjs.map +0 -1
- package/dist/shared/attaform.Db4E4IW6.cjs.map +0 -1
- package/dist/shared/attaform.DbyTD8N2.cjs.map +0 -1
- package/dist/shared/attaform.Dd1Kmmaj.mjs.map +0 -1
- package/dist/shared/attaform.DsQkXE3o.cjs.map +0 -1
- package/dist/shared/attaform.alpG7rT7.mjs.map +0 -1
- package/dist/shared/attaform.nf83TIR5.d.cts +0 -35
- package/dist/shared/attaform.nf83TIR5.d.mts +0 -35
- package/dist/shared/attaform.nf83TIR5.d.ts +0 -35
|
@@ -101,10 +101,11 @@ type Path = readonly Segment[];
|
|
|
101
101
|
* parseDottedPath('') // [''] (the empty-string key)
|
|
102
102
|
* ```
|
|
103
103
|
*
|
|
104
|
-
* The empty-string input `''` is the **literal empty-key path
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* `
|
|
104
|
+
* The empty-string input `''` is the **literal empty-key path** `['']`,
|
|
105
|
+
* an ordinary (if rare) field address, not the root. Use the array
|
|
106
|
+
* form `[]` for the root. Form-level errors (root `.refine()`,
|
|
107
|
+
* `setErrors` with no path) live at the root path `[]` and are read via
|
|
108
|
+
* `errors([])`, never `errors('')`.
|
|
108
109
|
*
|
|
109
110
|
* Throws `InvalidPathError` for paths with empty INTERNAL segments
|
|
110
111
|
* (`'a..b'`, leading or trailing dots). For keys containing literal
|
|
@@ -132,8 +133,17 @@ declare function canonicalizePath(input: string | Path): {
|
|
|
132
133
|
key: PathKey;
|
|
133
134
|
};
|
|
134
135
|
/**
|
|
135
|
-
* The root path — an empty segment tuple. Pass to APIs that accept
|
|
136
|
-
*
|
|
136
|
+
* The root path — an empty segment tuple. Pass to APIs that accept a
|
|
137
|
+
* `Path` to address the form value as a whole, and the home for
|
|
138
|
+
* form-level (global) errors: root `.refine()` messages, hydration
|
|
139
|
+
* failures, and `setErrors` entries with no path all live at `[]`. Aggregate
|
|
140
|
+
* reads (`errors()`, `meta.errors`) surface them alongside field
|
|
141
|
+
* errors; `errors([])` returns the global bucket alone.
|
|
142
|
+
*
|
|
143
|
+
* The empty SEGMENT tuple `[]` is structurally unconstructible as a
|
|
144
|
+
* field path, so it can never collide with a schema key, unlike the
|
|
145
|
+
* empty STRING key `''` (path `['']`, key `'[""]'`), which is an
|
|
146
|
+
* ordinary field address.
|
|
137
147
|
*/
|
|
138
148
|
declare const ROOT_PATH: Path;
|
|
139
149
|
/** Stable string key for the root path. */
|
|
@@ -248,8 +258,17 @@ type FlatPathBuilder<Form, Mode extends 'partial' | 'register', Key extends keyo
|
|
|
248
258
|
* Inlining at consumer call sites compounds into TS2589 territory
|
|
249
259
|
* when multiple complex forms share a scope. Consumers should reach
|
|
250
260
|
* for `FlatPath` instead; this alias is not part of the stable surface.
|
|
261
|
+
*
|
|
262
|
+
* The `Form extends unknown` wrapper distributes over a top-level
|
|
263
|
+
* union so each member contributes its OWN `keyof` — a discriminated-
|
|
264
|
+
* union root (`z.discriminatedUnion`) thus exposes every variant's
|
|
265
|
+
* keys as addressable paths, not just the discriminator that naked
|
|
266
|
+
* `keyof (A | B)` would intersect to. For a single object / array /
|
|
267
|
+
* record `Form` it is a one-member no-op and stays byte-identical to
|
|
268
|
+
* the prior walk. Interior unions already distribute inside
|
|
269
|
+
* `FlatPathBuilder` via its `infer Value` step.
|
|
251
270
|
*/
|
|
252
|
-
type PartialFlatPath<Form
|
|
271
|
+
type PartialFlatPath<Form> = Form extends unknown ? FlatPathBuilder<Form, 'partial'> : never;
|
|
253
272
|
/**
|
|
254
273
|
* Union of dotted-string paths reachable inside `Form`, e.g. for
|
|
255
274
|
* `{ user: { email: string }, items: string[] }`:
|
|
@@ -260,7 +279,7 @@ type PartialFlatPath<Form, Key extends keyof Form = keyof Form> = FlatPathBuilde
|
|
|
260
279
|
* `register(path)`, `toRef(path)`, etc.) so paths autocomplete in
|
|
261
280
|
* the IDE and typos compile-error.
|
|
262
281
|
*/
|
|
263
|
-
type FlatPath<Form
|
|
282
|
+
type FlatPath<Form> = PartialFlatPath<Form>;
|
|
264
283
|
/**
|
|
265
284
|
* Convert a tuple of path segments to its dotted-string equivalent.
|
|
266
285
|
*
|
|
@@ -645,25 +664,45 @@ interface SchemaFactoryOptions {
|
|
|
645
664
|
/** Resolved recursion ceiling (per-form > app-default > library default). */
|
|
646
665
|
maxRecursionDepth: number;
|
|
647
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* A JSON-serialisable value: the recursive shape of anything that
|
|
669
|
+
* survives a `JSON.stringify` / `JSON.parse` round-trip unchanged.
|
|
670
|
+
* The type of `ValidationError.data`.
|
|
671
|
+
*
|
|
672
|
+
* The object arm is a named interface rather than an inline index
|
|
673
|
+
* signature: TypeScript expands an anonymous recursive alias eagerly
|
|
674
|
+
* and tips into a depth-limit error (TS2589) when `Json` is checked
|
|
675
|
+
* inside a large structural type (e.g. the form store). A named
|
|
676
|
+
* reference defers that expansion.
|
|
677
|
+
*/
|
|
678
|
+
type Json = string | number | boolean | null | JsonArray | JsonObject;
|
|
679
|
+
interface JsonArray extends Array<Json> {
|
|
680
|
+
}
|
|
681
|
+
interface JsonObject {
|
|
682
|
+
[key: string]: Json;
|
|
683
|
+
}
|
|
648
684
|
/**
|
|
649
685
|
* One validation failure. `path` points at the offending field as a
|
|
650
686
|
* structured array — `['user', 'address', 0, 'line1']` for a nested
|
|
651
|
-
* field, `[
|
|
652
|
-
*
|
|
653
|
-
* emitted form banners). `formKey` identifies which form
|
|
654
|
-
* the error so a single error list can be routed to multiple
|
|
687
|
+
* field, `[]` (the root path) for a form-level error (root `.refine()`
|
|
688
|
+
* messages, `setErrors` entries with no path, hydration failures,
|
|
689
|
+
* server-emitted form banners). `formKey` identifies which form
|
|
690
|
+
* produced the error so a single error list can be routed to multiple
|
|
691
|
+
* forms. The optional `data` slot carries an arbitrary server payload.
|
|
655
692
|
*
|
|
656
693
|
* Returned by `validate()` / `validateAsync()` / `handleSubmit`'s
|
|
657
|
-
* `onError` callback, and
|
|
694
|
+
* `onError` callback, and accepted (leniently, as `ErrorInput`) by
|
|
695
|
+
* `form.setErrors`.
|
|
658
696
|
*/
|
|
659
697
|
type ValidationError = {
|
|
660
698
|
/** Human-readable message describing the failure. */
|
|
661
699
|
message: string;
|
|
662
700
|
/**
|
|
663
|
-
* Structured path of the offending field. The
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
701
|
+
* Structured path of the offending field. The root path `[]` is the
|
|
702
|
+
* form-level bucket — the dedicated home for errors that don't belong
|
|
703
|
+
* to any specific field (root `.refine()`, `setErrors`, hydration
|
|
704
|
+
* failures). The empty-STRING path `['']` is unrelated: an ordinary
|
|
705
|
+
* literal empty-key field.
|
|
667
706
|
*/
|
|
668
707
|
path: (string | number)[];
|
|
669
708
|
/** Identifies which form produced this error. */
|
|
@@ -680,6 +719,38 @@ type ValidationError = {
|
|
|
680
719
|
* exact-message string matching.
|
|
681
720
|
*/
|
|
682
721
|
code: string;
|
|
722
|
+
/**
|
|
723
|
+
* Optional structured payload attached to the error. Attaform never
|
|
724
|
+
* sets or reads this; it is a passthrough slot for whatever a server
|
|
725
|
+
* sends alongside the message (a captcha challenge, a lockout
|
|
726
|
+
* `unlocks_at` timestamp, an MFA step-up descriptor) so the UI can
|
|
727
|
+
* act on it. Survives serialise / hydrate and undo / redo unchanged.
|
|
728
|
+
*/
|
|
729
|
+
data?: Json | null;
|
|
730
|
+
};
|
|
731
|
+
/**
|
|
732
|
+
* The lenient input shape `form.setErrors` accepts: a real `Error`, or
|
|
733
|
+
* a partial `ValidationError` where every field is optional.
|
|
734
|
+
*
|
|
735
|
+
* - `message`: omitted or empty coerces to `"Unknown error"`.
|
|
736
|
+
* - `path`: defaults to `[]` (a global, form-level error). Ignored by
|
|
737
|
+
* the path-scoped `setErrors(path, …)` form, which stamps its own.
|
|
738
|
+
* - `code`: defaults to `atta:user-error`.
|
|
739
|
+
* - `data`: forwarded verbatim onto the produced `ValidationError`.
|
|
740
|
+
* - `formKey`: accepted but ignored — the form always stamps its own.
|
|
741
|
+
*
|
|
742
|
+
* Because every field is optional and `formKey` is accepted-and-ignored,
|
|
743
|
+
* `ValidationError` is a subtype of `ErrorInput`: a `ValidationError[]`
|
|
744
|
+
* you read back, or a server response that already emits the shape, pipes
|
|
745
|
+
* straight into `form.setErrors` with no adapter and no excess-property
|
|
746
|
+
* friction.
|
|
747
|
+
*/
|
|
748
|
+
type ErrorInput = Error | {
|
|
749
|
+
message?: string;
|
|
750
|
+
path?: (string | number)[];
|
|
751
|
+
code?: string;
|
|
752
|
+
data?: Json | null;
|
|
753
|
+
formKey?: FormKey;
|
|
683
754
|
};
|
|
684
755
|
/** Settled validation result when the form (or subtree) parsed successfully. */
|
|
685
756
|
type ValidationResponseSuccess<TData> = {
|
|
@@ -2124,7 +2195,7 @@ type MetaTrackerValue = {
|
|
|
2124
2195
|
*/
|
|
2125
2196
|
blank: boolean;
|
|
2126
2197
|
};
|
|
2127
|
-
type RegisterFlatPath<Form
|
|
2198
|
+
type RegisterFlatPath<Form> = Form extends unknown ? FlatPathBuilder<Form, 'register'> : never;
|
|
2128
2199
|
/**
|
|
2129
2200
|
* A transformation applied to a field's value as user input flows
|
|
2130
2201
|
* from DOM through the directive's assigner. Composes left-to-right
|
|
@@ -3306,13 +3377,17 @@ type LeafWalker<T, Kind extends keyof LeafSchemeFor<unknown>, StripOptional exte
|
|
|
3306
3377
|
type DiscriminatedLeaf<T, K extends PropertyKey, Kind extends keyof LeafSchemeFor<unknown>, StripOptional extends boolean> = [T] extends [Record<K, unknown>] ? LeafWalker<PresentValueOfUnion<T, K>, Kind, StripOptional> : LeafWalker<PresentValueOfUnion<T, K>, Kind, StripOptional> | undefined;
|
|
3307
3378
|
/**
|
|
3308
3379
|
* Intersection augmenting every container in the `form.errors` walker
|
|
3309
|
-
* with a `''`
|
|
3310
|
-
*
|
|
3311
|
-
*
|
|
3312
|
-
*
|
|
3380
|
+
* with a `''` slot. At a depth >= 1 container it's the container-self
|
|
3381
|
+
* sentinel — the home for cross-field refine errors and server-side
|
|
3382
|
+
* container marks; at root the `''` property addresses the literal
|
|
3383
|
+
* empty-key field. Gated on `Kind extends 'errors'` so `form.values`
|
|
3384
|
+
* and `form.fields` surfaces stay untouched. Carve-out for schemas that
|
|
3313
3385
|
* legitimately declare a `''` field: the declared field type wins; at
|
|
3314
3386
|
* runtime the two collide harmlessly (errors at the literal leaf and
|
|
3315
3387
|
* any container-self errors share the slot via array concat).
|
|
3388
|
+
*
|
|
3389
|
+
* Global (root) errors are NOT this slot: they live at the root `[]`
|
|
3390
|
+
* and are read via the `errors([])` call-form, never `errors['']`.
|
|
3316
3391
|
*/
|
|
3317
3392
|
type ContainerSelfErrorsSlot<T, Kind> = Kind extends 'errors' ? '' extends keyof T ? unknown : {
|
|
3318
3393
|
readonly ['']: readonly ValidationError[];
|
|
@@ -3442,9 +3517,11 @@ type FormErrorsSurface<Form> = ErrorsProxyShape<Form> & {
|
|
|
3442
3517
|
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): readonly ValidationError[];
|
|
3443
3518
|
(segments: ReadonlyArray<string | number>): readonly ValidationError[];
|
|
3444
3519
|
/**
|
|
3445
|
-
* No-arg call returns the form
|
|
3446
|
-
* `form.
|
|
3447
|
-
*
|
|
3520
|
+
* No-arg call returns the whole-form error aggregate — same as
|
|
3521
|
+
* `form.meta.errors`: every field error plus the global bucket.
|
|
3522
|
+
* Distinct from `form.errors([])`, which returns ONLY the global
|
|
3523
|
+
* (root) bucket. Always a readonly array; empty when the form has no
|
|
3524
|
+
* errors.
|
|
3448
3525
|
*/
|
|
3449
3526
|
(): readonly ValidationError[];
|
|
3450
3527
|
};
|
|
@@ -3500,63 +3577,6 @@ type ValuesSurface<F> = Readonly<LiftedValueShape<F>> & {
|
|
|
3500
3577
|
(path: ReadonlyArray<string | number>): unknown;
|
|
3501
3578
|
(): Readonly<F>;
|
|
3502
3579
|
};
|
|
3503
|
-
/**
|
|
3504
|
-
* A single server-side error entry. Carries both the human-readable
|
|
3505
|
-
* `message` and a stable `code` identifier — both fields are required.
|
|
3506
|
-
* The `code` is stamped verbatim onto the produced `ValidationError`,
|
|
3507
|
-
* so consumers can branch on it without string-matching on `message`.
|
|
3508
|
-
*
|
|
3509
|
-
* Pick a prefix for your codes (`api:`, `auth:`, etc.) and stay
|
|
3510
|
-
* consistent so error-rendering UIs can switch on the code.
|
|
3511
|
-
*/
|
|
3512
|
-
type ApiErrorEntry = {
|
|
3513
|
-
/** Human-readable failure description. */
|
|
3514
|
-
message: string;
|
|
3515
|
-
/**
|
|
3516
|
-
* Stable machine identifier for the failure (e.g. `'api:duplicate-email'`).
|
|
3517
|
-
* Forwarded verbatim onto the produced `ValidationError`.
|
|
3518
|
-
*/
|
|
3519
|
-
code: string;
|
|
3520
|
-
};
|
|
3521
|
-
/**
|
|
3522
|
-
* Shape of a server-side error details record. Keys are dotted field
|
|
3523
|
-
* paths; values are either a single entry, an array of entries, or a
|
|
3524
|
-
* mix of structured and bare-string entries. Each entry is one of:
|
|
3525
|
-
*
|
|
3526
|
-
* - **Structured** — `{ message: string, code: string }`. The `code`
|
|
3527
|
-
* forwards verbatim onto the produced `ValidationError`.
|
|
3528
|
-
* - **Bare string** — a plain string. The Rails / Django REST
|
|
3529
|
-
* Framework / Laravel default JSON shape (`{ field: ["msg"] }`).
|
|
3530
|
-
* Synthesized into `{ message: <string>, code: <defaultCode> }` at
|
|
3531
|
-
* parse time, where `defaultCode` defaults to `'api:unknown'` and
|
|
3532
|
-
* is configurable via `parseApiErrors`'s options bag.
|
|
3533
|
-
*
|
|
3534
|
-
* Multiple entries at the same path produce multiple
|
|
3535
|
-
* `ValidationError`s — useful for a single field that fails multiple
|
|
3536
|
-
* checks (e.g. `password` is too short *and* missing a digit).
|
|
3537
|
-
*/
|
|
3538
|
-
type ApiErrorDetails = Record<string, ApiErrorValue>;
|
|
3539
|
-
/**
|
|
3540
|
-
* One entry inside an {@link ApiErrorDetails} value — either the
|
|
3541
|
-
* strict `{ message, code }` object, or a bare string (synthesised
|
|
3542
|
-
* with the parser's `defaultCode`).
|
|
3543
|
-
*/
|
|
3544
|
-
type ApiErrorValue = string | ApiErrorEntry | ReadonlyArray<string | ApiErrorEntry>;
|
|
3545
|
-
/**
|
|
3546
|
-
* Outer envelope `parseApiErrors` accepts. Both the wrapped form
|
|
3547
|
-
* (`{ error: { details } }`) and the unwrapped form (`{ details }`)
|
|
3548
|
-
* are recognised; raw detail records (`{ email: { message, code } }`)
|
|
3549
|
-
* are also accepted directly.
|
|
3550
|
-
*/
|
|
3551
|
-
type ApiErrorEnvelope = {
|
|
3552
|
-
/** Wrapped error envelope — `parseApiErrors` reads `details` from inside. */
|
|
3553
|
-
error?: {
|
|
3554
|
-
details?: ApiErrorDetails;
|
|
3555
|
-
[k: string]: unknown;
|
|
3556
|
-
};
|
|
3557
|
-
/** Unwrapped error envelope. */
|
|
3558
|
-
details?: ApiErrorDetails;
|
|
3559
|
-
};
|
|
3560
3580
|
/**
|
|
3561
3581
|
* Reactive form-level flags, counters, and aggregates returned as
|
|
3562
3582
|
* `form.meta`. "Meta" because every other surface (`form.values`,
|
|
@@ -3760,6 +3780,19 @@ interface BlankPathsView {
|
|
|
3760
3780
|
/** Iterates the blank-marked paths as segment arrays. */
|
|
3761
3781
|
[Symbol.iterator](): IterableIterator<Path>;
|
|
3762
3782
|
}
|
|
3783
|
+
/**
|
|
3784
|
+
* The no-arg `form.record()` call form, present only when the form root
|
|
3785
|
+
* is itself an open record (`z.record(K, V)`). `string extends keyof
|
|
3786
|
+
* Form` is the open-keyset probe: true for `Record<string, V>`, false
|
|
3787
|
+
* for a fixed `z.object` shape. On a fixed object this resolves to
|
|
3788
|
+
* `unknown`, which contributes nothing to the intersection in `record`
|
|
3789
|
+
* below, so the no-arg call form simply does not exist there (and
|
|
3790
|
+
* `form.record()` stays a compile error, as it should when the root has
|
|
3791
|
+
* a closed key set). On a record root it mirrors the path-addressed
|
|
3792
|
+
* `record(path)` overload: one `FieldState` per entry, keyed by the
|
|
3793
|
+
* record's own runtime keys.
|
|
3794
|
+
*/
|
|
3795
|
+
type RootRecordView<Form> = string extends keyof Form ? Form extends Record<string, infer RootValue> ? () => Readonly<Record<string, FieldState<RootValue>>> : unknown : unknown;
|
|
3763
3796
|
type UseFormReturnType<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form, K extends FormKey = FormKey> = {
|
|
3764
3797
|
/**
|
|
3765
3798
|
* Wraps your submit logic with validation and error routing.
|
|
@@ -4008,18 +4041,14 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4008
4041
|
* user-typed values before they reach form state.
|
|
4009
4042
|
*/
|
|
4010
4043
|
register: {
|
|
4011
|
-
<Path extends RegisterFlatPath<Form
|
|
4012
|
-
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form
|
|
4044
|
+
<Path extends RegisterFlatPath<Form>>(path: Path, options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, Path>>;
|
|
4045
|
+
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [RegisterFlatPath<Form>] ? unknown : never), options?: RegisterOptions): RegisterValue<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>;
|
|
4013
4046
|
};
|
|
4014
4047
|
/**
|
|
4015
4048
|
* The form's identifier — either the explicit `key` passed to
|
|
4016
4049
|
* `useForm` or an auto-generated unique id when `key` was omitted.
|
|
4017
|
-
*
|
|
4018
|
-
*
|
|
4019
|
-
* ```ts
|
|
4020
|
-
* const result = parseApiErrors(serverPayload, { formKey: form.key })
|
|
4021
|
-
* if (result.ok) form.setFieldErrors(result.errors)
|
|
4022
|
-
* ```
|
|
4050
|
+
* Every `ValidationError` this form produces carries it as `formKey`,
|
|
4051
|
+
* so a shared error list can be routed back to the right form.
|
|
4023
4052
|
*
|
|
4024
4053
|
* Typed as the literal `K` when an explicit `key` was passed; falls
|
|
4025
4054
|
* back to `FormKey` when omitted (auto-generated id).
|
|
@@ -4131,9 +4160,9 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4131
4160
|
* (`form.errors['user.profile.email']`) — JS dot notation splits
|
|
4132
4161
|
* on literal dots.
|
|
4133
4162
|
*
|
|
4134
|
-
* Read-only — populate via `
|
|
4135
|
-
* `
|
|
4136
|
-
* `
|
|
4163
|
+
* Read-only — populate via `setErrors` / `clearErrors`. A server
|
|
4164
|
+
* response that already emits `ValidationError[]` pipes straight into
|
|
4165
|
+
* `setErrors` with no adapter.
|
|
4137
4166
|
*/
|
|
4138
4167
|
errors: FormErrorsSurface<Form>;
|
|
4139
4168
|
/**
|
|
@@ -4156,76 +4185,61 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4156
4185
|
<const S extends ReadonlyArray<string | number>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never)): Readonly<Ref<NestedReadType<WriteShape<ReadForm>, JoinSegments<S>>>>;
|
|
4157
4186
|
};
|
|
4158
4187
|
/**
|
|
4159
|
-
*
|
|
4160
|
-
*
|
|
4161
|
-
*
|
|
4188
|
+
* Set the form's manual error layer. One surface for server-side
|
|
4189
|
+
* errors, optimistic-UI errors, and form-level banners: a field error
|
|
4190
|
+
* and a global (form-level) error are the same thing at different
|
|
4191
|
+
* paths, so there is no separate field/form split.
|
|
4162
4192
|
*
|
|
4163
|
-
*
|
|
4164
|
-
*
|
|
4165
|
-
*
|
|
4166
|
-
*
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
* Append errors to the existing set without clearing prior entries.
|
|
4171
|
-
* Use when reporting an additional issue alongside existing errors
|
|
4172
|
-
* (e.g. a partial server response).
|
|
4173
|
-
*/
|
|
4174
|
-
addFieldErrors: (errors: ValidationError[]) => void;
|
|
4175
|
-
/**
|
|
4176
|
-
* Clear errors. Pass a path to clear errors for a single field;
|
|
4177
|
-
* call with no arguments to clear every error on the form.
|
|
4193
|
+
* Input is lenient ({@link ErrorInput}): a real `Error`, a partial
|
|
4194
|
+
* `{ message?, path?, code?, data? }`, or an array of either. The form
|
|
4195
|
+
* stamps its own `formKey`, defaults a missing `code` to
|
|
4196
|
+
* `atta:user-error`, and coerces a missing or empty `message` to
|
|
4197
|
+
* `"Unknown error"` instead of throwing. A server that already emits
|
|
4198
|
+
* `ValidationError[]` satisfies the input shape directly, so
|
|
4199
|
+
* `form.setErrors(response.errors)` needs no adapter.
|
|
4178
4200
|
*
|
|
4179
|
-
*
|
|
4180
|
-
* form.clearFieldErrors('email') // clear one field
|
|
4181
|
-
* form.clearFieldErrors() // clear all
|
|
4182
|
-
* ```
|
|
4183
|
-
*/
|
|
4184
|
-
clearFieldErrors: (path?: string | (string | number)[]) => void;
|
|
4185
|
-
/**
|
|
4186
|
-
* Replace the form-level errors — the entries at the empty path
|
|
4187
|
-
* (`path: []`) — without disturbing any field-level errors. Pass an
|
|
4188
|
-
* empty array to clear them all.
|
|
4201
|
+
* Three call forms, mirroring `setValue`:
|
|
4189
4202
|
*
|
|
4190
4203
|
* ```ts
|
|
4191
|
-
*
|
|
4192
|
-
* form
|
|
4193
|
-
*
|
|
4194
|
-
*
|
|
4195
|
-
*
|
|
4196
|
-
*
|
|
4204
|
+
* // Whole-layer replace. An entry with no `path` is a global,
|
|
4205
|
+
* // form-level error (path `[]`); add a `path` to target a field.
|
|
4206
|
+
* form.setErrors([{ path: ['email'], message: 'Already taken' }])
|
|
4207
|
+
* form.setErrors({ message: 'Capacity exceeded' }) // global banner
|
|
4208
|
+
* form.setErrors(new Error('Network unreachable')) // message coerced
|
|
4209
|
+
*
|
|
4210
|
+
* // Functional update. `prev` is the current manual layer, flat.
|
|
4211
|
+
* form.setErrors((prev) => [...prev, { message: 'And one more' }])
|
|
4212
|
+
*
|
|
4213
|
+
* // Path-scoped. The path is stamped onto every entry, and only that
|
|
4214
|
+
* // path's bucket is replaced. `prev` is that path's manual errors.
|
|
4215
|
+
* form.setErrors('email', [{ message: 'Already taken' }])
|
|
4216
|
+
* form.setErrors(['profile', 'handle'], { message: 'Reserved' })
|
|
4217
|
+
* form.setErrors('email', (prev) => prev.slice(0, 1))
|
|
4197
4218
|
* ```
|
|
4198
4219
|
*
|
|
4199
|
-
*
|
|
4200
|
-
*
|
|
4201
|
-
*
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4220
|
+
* Replaces only the manual layer; schema/validation errors live in a
|
|
4221
|
+
* separate store and merge on read. Pass `[]` to clear the manual
|
|
4222
|
+
* layer (or use `clearErrors`, which also clears the schema layer).
|
|
4223
|
+
*/
|
|
4224
|
+
setErrors: {
|
|
4225
|
+
(update: (prev: ValidationError[]) => ErrorInput | ErrorInput[]): void;
|
|
4226
|
+
(errors: ErrorInput | ErrorInput[]): void;
|
|
4227
|
+
(path: string | (string | number)[], errors: ErrorInput | ErrorInput[] | ((prev: ValidationError[]) => ErrorInput | ErrorInput[])): void;
|
|
4228
|
+
};
|
|
4229
|
+
/**
|
|
4230
|
+
* Clear errors at one path, or everywhere. Clears BOTH the manual
|
|
4231
|
+
* layer (set through `setErrors`) and the schema/validation layer at
|
|
4232
|
+
* the target. With always-on validation the schema half re-populates
|
|
4233
|
+
* on the next mutation if the value is still invalid, so the cleared
|
|
4234
|
+
* state is short-lived for a field that is still wrong.
|
|
4205
4235
|
*
|
|
4206
4236
|
* ```ts
|
|
4207
|
-
*
|
|
4208
|
-
*
|
|
4237
|
+
* form.clearErrors('email') // one field
|
|
4238
|
+
* form.clearErrors([]) // the global, form-level bucket
|
|
4239
|
+
* form.clearErrors() // every error on the form
|
|
4209
4240
|
* ```
|
|
4210
|
-
*
|
|
4211
|
-
* Form-level errors land at the empty-string path bucket
|
|
4212
|
-
* (`path: ['']`). They surface in `form.meta.errors` (alongside
|
|
4213
|
-
* field errors), in `form.errors()` / `form.errors([])` (whole-form
|
|
4214
|
-
* subtree aggregates), and — uniquely — in `form.errors('')`,
|
|
4215
|
-
* which returns ONLY the form-level bucket. They're excluded from
|
|
4216
|
-
* the path-keyed `form.errors` drill proxy because no nested-object
|
|
4217
|
-
* key represents the empty-string path. Read them via
|
|
4218
|
-
* `meta.errors.filter(e => e.path.length === 1 && e.path[0] === '')`
|
|
4219
|
-
* if you need a programmatic split.
|
|
4220
4241
|
*/
|
|
4221
|
-
|
|
4222
|
-
message: string;
|
|
4223
|
-
}>) => void;
|
|
4224
|
-
/**
|
|
4225
|
-
* Clear every form-level error. Equivalent to `setFormErrors([])`;
|
|
4226
|
-
* field errors are untouched.
|
|
4227
|
-
*/
|
|
4228
|
-
clearFormErrors: () => void;
|
|
4242
|
+
clearErrors: (path?: string | (string | number)[]) => void;
|
|
4229
4243
|
/**
|
|
4230
4244
|
* Form-level reactive flags, counters, and aggregates (`dirty`,
|
|
4231
4245
|
* `valid`, `submitting`, `submissionAttempts`, and the flat `errors`
|
|
@@ -4436,8 +4450,19 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4436
4450
|
* when the key leaves. `form.fields(path)` remains the single
|
|
4437
4451
|
* aggregated container for the whole record; `record` is the
|
|
4438
4452
|
* per-entry view.
|
|
4453
|
+
*
|
|
4454
|
+
* When the form root is itself a record (`useForm({ schema:
|
|
4455
|
+
* z.record(K, V) })` — a dictionary form), call `form.record()` with
|
|
4456
|
+
* no argument for the root entry view:
|
|
4457
|
+
*
|
|
4458
|
+
* ```vue
|
|
4459
|
+
* <div v-for="(member, id) in form.record()" :key="id">
|
|
4460
|
+
* <input v-register="form.register(id)" />
|
|
4461
|
+
* <p v-if="member.showErrors">{{ member.firstError?.message }}</p>
|
|
4462
|
+
* </div>
|
|
4463
|
+
* ```
|
|
4439
4464
|
*/
|
|
4440
|
-
record: <Path extends RecordPath<Form>>(path: Path) => Readonly<Record<string, FieldState<RecordValue<Form, Path
|
|
4465
|
+
record: RootRecordView<Form> & (<Path extends RecordPath<Form>>(path: Path) => Readonly<Record<string, FieldState<RecordValue<Form, Path>>>>);
|
|
4441
4466
|
/**
|
|
4442
4467
|
* Read-only view of the form's blank path set. Reactive — Vue 3.5
|
|
4443
4468
|
* tracks `.has()` / `for..of` / size accesses, so consumers can drive
|
|
@@ -4465,5 +4490,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4465
4490
|
blankPaths: ComputedRef<BlankPathsView>;
|
|
4466
4491
|
};
|
|
4467
4492
|
|
|
4468
|
-
export { ROOT_PATH as
|
|
4469
|
-
export type { AttaformDefaults as A,
|
|
4493
|
+
export { ROOT_PATH as Z, ROOT_PATH_KEY as _, canonicalizePath as am, isPathPrefix as an, isUnset as ao, parseDottedPath as ap, unset as aq };
|
|
4494
|
+
export type { ReactiveValidationStatus as $, AttaformDefaults as A, Json 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, NestedType as O, OnError as P, OnInvalidSubmitPolicy as Q, RegisterModelDynamicCustomDirective as R, OnSubmit as S, PartialFlatPath as T, UseFormConfiguration as U, Path as V, PathKey as W, PendingValidationStatus as X, Primitive as Y, AbstractSchema as a, RegisterDirective as a0, RegisterFlatPath as a1, RegisterOptions as a2, RegisterSelectModifier as a3, RegisterTextModifier as a4, RegisterTransform as a5, Segment as a6, SetValueCallback as a7, SetValuePayload as a8, SettledValidationStatus as a9, SlimPrimitiveKind as aa, SlimRuntimeOf as ab, SubmitHandler as ac, Unset as ad, ValidateOn as ae, ValidateOnConfig as af, ValidationError as ag, ValidationResponse as ah, ValidationResponseWithoutValue as ai, ValueOfUnion as aj, WriteMeta as ak, WriteShape as al, SchemaFactoryOptions as ar, TransformAbortHolder as as, UseFormReturnType as b, RegisterValue as c, GetDisplayState as d, ArrayItem as e, ArrayPath as f, CoercionRegistry as g, CoercionResult as h, CustomDirectiveRegisterAssignerFn as i, DeepPartial as j, DefaultValuesResponse as k, DefaultValuesShape as l, DisplayCtx as m, DisplayMachine as n, DisplayState as o, ErrorsProxyShape as p, FieldMetaPayload as q, FieldState as r, FieldStateMap as s, FieldStateMapEntry as t, FlatPath as u, FormErrorRecord as v, FormErrorsSurface as w, FormMeta as x, HistoryConfig as y, IsUnion as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { G as GenericForm,
|
|
2
|
+
import { G as GenericForm, u as FlatPath, O as NestedType, F as FormKey, U as UseFormConfiguration, a as AbstractSchema, D as DefaultValuesInput, af as ValidateOnConfig, b as UseFormReturnType } from './attaform.GJbSmwLB.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The shape `form.values.<key>` returns at runtime.
|
|
@@ -120,6 +120,38 @@ type StorageLeaf<L> = InputIsUnknown<L> extends true ? unknown : L extends {
|
|
|
120
120
|
};
|
|
121
121
|
} ? Out : never;
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The Zod v4 schema roots `useForm` accepts. A fixed-shape
|
|
125
|
+
* `z.object({ … })` is the common case; `z.record(K, V)` admits a
|
|
126
|
+
* dictionary form (a homogeneous map with runtime-known keys);
|
|
127
|
+
* `z.discriminatedUnion(disc, [...])` admits a variant form (one of
|
|
128
|
+
* several object shapes, picked by a discriminator). Each projects to
|
|
129
|
+
* a `GenericForm`-shaped value the form engine drives: an object root
|
|
130
|
+
* descends into its fixed keys, a record root treats its entries as an
|
|
131
|
+
* open live-keyed container, a variant root lifts the active variant's
|
|
132
|
+
* keys into one addressable surface.
|
|
133
|
+
*
|
|
134
|
+
* Other roots (a bare `z.union`, a root `z.array`, primitives,
|
|
135
|
+
* `z.map` / `z.set`) are not form roots; wrap them under a key. The
|
|
136
|
+
* adapter's runtime construction rejects them with a legible error.
|
|
137
|
+
*
|
|
138
|
+
* `z.ZodObject` MUST keep its `z.ZodRawShape` argument, and the
|
|
139
|
+
* discriminated-union arm MUST stay fully applied. The unified entry's
|
|
140
|
+
* v4 overload constrains on `SupportedRootSchema & ZodV4Internals` to
|
|
141
|
+
* keep v3 schemas out (see `../unified/types-zod-major.ts`). In a
|
|
142
|
+
* single-major (v3-only) consumer install, the published `.d.mts`
|
|
143
|
+
* resolves this `z` to v3, where a bare or under-applied Zod class is
|
|
144
|
+
* missing its required arguments and degrades to an `any`-like error
|
|
145
|
+
* type; `any` then absorbs the union and `any & ZodV4Internals`
|
|
146
|
+
* collapses back to `any`, so the marker stops excluding v3 schemas and
|
|
147
|
+
* the read slot poisons to `never`. `z.ZodRecord` carries defaults for
|
|
148
|
+
* both arguments, so it stays concrete in either major.
|
|
149
|
+
* `z.ZodDiscriminatedUnion` does NOT (v3 requires both arguments, and
|
|
150
|
+
* its parameter order is the reverse of v4's), so the arm is written
|
|
151
|
+
* fully applied; the v3-only bundled-types fixture guards it.
|
|
152
|
+
*/
|
|
153
|
+
type SupportedRootSchema = z.ZodObject<z.ZodRawShape> | z.ZodRecord | z.ZodDiscriminatedUnion<readonly z.ZodObject<z.ZodRawShape>[], string>;
|
|
154
|
+
|
|
123
155
|
/**
|
|
124
156
|
* Zod v4 adapter entry point. Re-exports the adapter + the useForm
|
|
125
157
|
* wrapper that threads zod-v4-specific schema types through
|
|
@@ -188,12 +220,12 @@ type PathOutput<Schema extends z.ZodType, Path extends string> = z.output<Schema
|
|
|
188
220
|
* generics ride on the alias rather than re-evaluating the
|
|
189
221
|
* conditional from scratch.
|
|
190
222
|
*/
|
|
191
|
-
type FormOf<Schema extends
|
|
192
|
-
type OutOf<Schema extends
|
|
193
|
-
type ReadOf<Schema extends
|
|
194
|
-
declare function useForm<Schema extends
|
|
223
|
+
type FormOf<Schema extends SupportedRootSchema> = z.input<Schema> extends GenericForm ? z.input<Schema> : never;
|
|
224
|
+
type OutOf<Schema extends SupportedRootSchema> = z.output<Schema> extends GenericForm ? z.output<Schema> : never;
|
|
225
|
+
type ReadOf<Schema extends SupportedRootSchema> = StorageShape<Schema> extends GenericForm ? StorageShape<Schema> : never;
|
|
226
|
+
declare function useForm<Schema extends SupportedRootSchema, K extends FormKey = FormKey>(configuration: Omit<UseFormConfiguration<FormOf<Schema>, OutOf<Schema>, AbstractSchema<FormOf<Schema>, OutOf<Schema>>, DefaultValuesInput<FormOf<Schema>>, K>, 'schema' | 'validateOn' | 'debounceMs'> & {
|
|
195
227
|
schema: Schema;
|
|
196
228
|
} & ValidateOnConfig): UseFormReturnType<FormOf<Schema>, OutOf<Schema>, ReadOf<Schema>, K>;
|
|
197
229
|
|
|
198
230
|
export { useForm as u };
|
|
199
|
-
export type { PathInput as P,
|
|
231
|
+
export type { PathInput as P, SupportedRootSchema as S, PathOutput as a, StorageShape as b };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const walkFieldMeta = require('./attaform.
|
|
4
|
-
const injectWizard = require('./attaform.
|
|
5
|
-
const paths = require('./attaform.
|
|
3
|
+
const walkFieldMeta = require('./attaform.BV_HyaMO.cjs');
|
|
4
|
+
const injectWizard = require('./attaform.C42wL7EJ.cjs');
|
|
5
|
+
const paths = require('./attaform.DwkU0oY9.cjs');
|
|
6
6
|
|
|
7
7
|
const fieldMeta = walkFieldMeta.fieldMetaStore;
|
|
8
8
|
function withMeta(schema, payload) {
|
|
@@ -848,9 +848,11 @@ function zodAdapter(zodSchema) {
|
|
|
848
848
|
stripZodEffects: true,
|
|
849
849
|
stripZodRefinements: true
|
|
850
850
|
});
|
|
851
|
-
if (!isZodSchemaType(_strippedRoot, "ZodObject")) {
|
|
851
|
+
if (!isZodSchemaType(_strippedRoot, "ZodObject") && !isZodSchemaType(_strippedRoot, "ZodRecord") && !isZodSchemaType(_strippedRoot, "ZodDiscriminatedUnion")) {
|
|
852
852
|
const name = getTypeName(_strippedRoot);
|
|
853
|
-
throw new Error(
|
|
853
|
+
throw new Error(
|
|
854
|
+
`Attaform: useForm schema root must be a ZodObject, ZodRecord, or ZodDiscriminatedUnion (got ${name}). Wrap other shapes under a key.`
|
|
855
|
+
);
|
|
854
856
|
}
|
|
855
857
|
return (formKey, options) => walkFieldMeta.createAbstractSchema(
|
|
856
858
|
zodSchema,
|
|
@@ -1632,4 +1634,4 @@ exports.isZodSchemaType = isZodSchemaType;
|
|
|
1632
1634
|
exports.useForm = useForm;
|
|
1633
1635
|
exports.withMeta = withMeta;
|
|
1634
1636
|
exports.zodAdapter = zodAdapter;
|
|
1635
|
-
//# sourceMappingURL=attaform.
|
|
1637
|
+
//# sourceMappingURL=attaform.Z1qTwOYE.cjs.map
|