attaform 0.16.2 → 0.16.4
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 +7 -7
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/index.cjs +3 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -4
- package/dist/index.d.mts +33 -4
- package/dist/index.d.ts +33 -4
- package/dist/index.mjs +3 -3
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/shared/attaform.C8CyvYa_.cjs +36 -0
- package/dist/shared/attaform.C8CyvYa_.cjs.map +1 -0
- package/dist/shared/{attaform.CWCx2r0x.d.ts → attaform.CCQkY4Ta.d.ts} +1 -1
- package/dist/shared/{attaform.c_NzdRyc.cjs → attaform.CIwZtbGV.cjs} +6 -2
- package/dist/shared/attaform.CIwZtbGV.cjs.map +1 -0
- package/dist/shared/{attaform.CVv9Oh0a.d.mts → attaform.CMRmwGDt.d.cts} +1 -1
- package/dist/shared/{attaform.0Gxd_OOx.d.cts → attaform.CU3JperC.d.cts} +193 -27
- package/dist/shared/{attaform.0Gxd_OOx.d.mts → attaform.CU3JperC.d.mts} +193 -27
- package/dist/shared/{attaform.0Gxd_OOx.d.ts → attaform.CU3JperC.d.ts} +193 -27
- package/dist/shared/{attaform.Dq5BabH1.d.cts → attaform.CXMOheyZ.d.mts} +1 -1
- package/dist/shared/attaform.D13GMFgK.mjs +32 -0
- package/dist/shared/attaform.D13GMFgK.mjs.map +1 -0
- package/dist/shared/{attaform.jrxE_xZw.mjs → attaform.DZRj9s0s.mjs} +5 -3
- package/dist/shared/attaform.DZRj9s0s.mjs.map +1 -0
- package/dist/shared/{attaform.Bp1c-uGF.cjs → attaform.Dd_pWnmn.cjs} +17 -29
- package/dist/shared/attaform.Dd_pWnmn.cjs.map +1 -0
- package/dist/shared/{attaform.DILbdvfo.mjs → attaform.DyV1O4tI.mjs} +111 -22
- package/dist/shared/attaform.DyV1O4tI.mjs.map +1 -0
- package/dist/shared/{attaform.DdnithOf.mjs → attaform.UA19EF3J.mjs} +17 -29
- package/dist/shared/attaform.UA19EF3J.mjs.map +1 -0
- package/dist/shared/{attaform.C9Ph2SMx.cjs → attaform.fegmBJaq.cjs} +111 -21
- package/dist/shared/attaform.fegmBJaq.cjs.map +1 -0
- package/dist/shared/{attaform.CvOXSpCb.mjs → attaform.g7rfuXdz.mjs} +13 -16
- package/dist/shared/attaform.g7rfuXdz.mjs.map +1 -0
- package/dist/shared/{attaform.DfrYByDj.cjs → attaform.keLBaHB6.cjs} +13 -16
- package/dist/shared/attaform.keLBaHB6.cjs.map +1 -0
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +19 -14
- package/dist/zod-v3.d.mts +19 -14
- package/dist/zod-v3.d.ts +19 -14
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +94 -5
- package/dist/zod-v4.d.mts +94 -5
- package/dist/zod-v4.d.ts +94 -5
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +23 -5
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +51 -7
- package/dist/zod.d.mts +51 -7
- package/dist/zod.d.ts +51 -7
- package/dist/zod.mjs +22 -5
- package/dist/zod.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/shared/attaform.BAuJTWuT.d.mts +0 -84
- package/dist/shared/attaform.Bp1c-uGF.cjs.map +0 -1
- package/dist/shared/attaform.C9Ph2SMx.cjs.map +0 -1
- package/dist/shared/attaform.CvOXSpCb.mjs.map +0 -1
- package/dist/shared/attaform.DILbdvfo.mjs.map +0 -1
- package/dist/shared/attaform.DdnithOf.mjs.map +0 -1
- package/dist/shared/attaform.DfrYByDj.cjs.map +0 -1
- package/dist/shared/attaform.c_NzdRyc.cjs.map +0 -1
- package/dist/shared/attaform.jrxE_xZw.mjs.map +0 -1
- package/dist/shared/attaform.ls_7jBYc.d.ts +0 -84
- package/dist/shared/attaform.xIcmqscx.d.cts +0 -84
|
@@ -2,14 +2,22 @@ import { Ref, ObjectDirective, ComputedRef } from 'vue';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Schema-attached field metadata — the shared types used by both Zod
|
|
5
|
-
* adapters
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* adapters and the unified `attaform/zod` entry so a consumer's data
|
|
6
|
+
* flow reads the same shape regardless of which path runs at lookup.
|
|
7
|
+
*
|
|
8
|
+
* Storage lives in the cross-adapter `field-meta-store` core: a pair
|
|
9
|
+
* of WeakMaps (single-payload for last-write-wins reads, list-of-
|
|
10
|
+
* payloads for shared-schema disambiguation). Every entry's
|
|
11
|
+
* `fieldMeta` re-exports the same registry-shaped object, so
|
|
12
|
+
* `withMeta`/`fieldMeta.add` writes from one entry surface at lookup
|
|
13
|
+
* through any other.
|
|
14
|
+
*
|
|
15
|
+
* `withMeta(schema, payload)` clones the schema before registering,
|
|
16
|
+
* so each call gets fresh identity (the WeakMap keys on reference).
|
|
17
|
+
* The cloning strategy depends on the major: Zod 4 schemas use the
|
|
18
|
+
* native `.clone()`, Zod 3 schemas reconstruct via constructor +
|
|
19
|
+
* `_def`. The unified entry's `withMeta` runtime-branches on which
|
|
20
|
+
* one is in play.
|
|
13
21
|
*
|
|
14
22
|
* Reads are unified through `AbstractSchema.getFieldMetaAtPath(path)`,
|
|
15
23
|
* which returns a fully-resolved `ResolvedFieldMeta` (label /
|
|
@@ -90,10 +98,15 @@ type Path = readonly Segment[];
|
|
|
90
98
|
* ```ts
|
|
91
99
|
* parseDottedPath('user.address.line1') // ['user', 'address', 'line1']
|
|
92
100
|
* parseDottedPath('items.0.name') // ['items', 0, 'name']
|
|
93
|
-
* parseDottedPath('') // []
|
|
101
|
+
* parseDottedPath('') // [''] (the empty-string key)
|
|
94
102
|
* ```
|
|
95
103
|
*
|
|
96
|
-
*
|
|
104
|
+
* The empty-string input `''` is the **literal empty-key path**, not
|
|
105
|
+
* the root. Use the array form `[]` for root. Form-level errors
|
|
106
|
+
* (root `.refine()`) live at the empty-string path bucket so
|
|
107
|
+
* `errors('')` returns them without sweeping every field error too.
|
|
108
|
+
*
|
|
109
|
+
* Throws `InvalidPathError` for paths with empty INTERNAL segments
|
|
97
110
|
* (`'a..b'`, leading or trailing dots). For keys containing literal
|
|
98
111
|
* dots, pass an array form (`['user.name']`) instead.
|
|
99
112
|
*/
|
|
@@ -457,9 +470,10 @@ type FormKey = string;
|
|
|
457
470
|
/**
|
|
458
471
|
* One validation failure. `path` points at the offending field as a
|
|
459
472
|
* structured array — `['user', 'address', 0, 'line1']` for a nested
|
|
460
|
-
* field, `[]` for a form-level error
|
|
461
|
-
*
|
|
462
|
-
*
|
|
473
|
+
* field, `['']` (the empty-string path) for a form-level error
|
|
474
|
+
* (root `.refine()` messages, `setFormErrors()` entries, server-
|
|
475
|
+
* emitted form banners). `formKey` identifies which form produced
|
|
476
|
+
* the error so a single error list can be routed to multiple forms.
|
|
463
477
|
*
|
|
464
478
|
* Returned by `validate()` / `validateAsync()` / `handleSubmit`'s
|
|
465
479
|
* `onError` callback, and by `parseApiErrors` for server responses.
|
|
@@ -467,7 +481,12 @@ type FormKey = string;
|
|
|
467
481
|
type ValidationError = {
|
|
468
482
|
/** Human-readable message describing the failure. */
|
|
469
483
|
message: string;
|
|
470
|
-
/**
|
|
484
|
+
/**
|
|
485
|
+
* Structured path of the offending field. The empty-string path
|
|
486
|
+
* `['']` is the form-level bucket — the dedicated home for errors
|
|
487
|
+
* that don't belong to any specific field, distinct from the
|
|
488
|
+
* whole-form subtree address `[]`.
|
|
489
|
+
*/
|
|
471
490
|
path: (string | number)[];
|
|
472
491
|
/** Identifies which form produced this error. */
|
|
473
492
|
formKey: FormKey;
|
|
@@ -844,8 +863,8 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
844
863
|
* Return the resolved field metadata for the schema node at `path`
|
|
845
864
|
* — label, description, placeholder, plus the full registered
|
|
846
865
|
* payload as `meta` for consumer-augmented keys. Reads through the
|
|
847
|
-
* adapter
|
|
848
|
-
*
|
|
866
|
+
* shared cross-adapter field-meta store and applies these one-way
|
|
867
|
+
* fallbacks:
|
|
849
868
|
*
|
|
850
869
|
* - `label`: registry payload → `humanize(lastSegment)`
|
|
851
870
|
* - `description`: registry payload → `schema.description`
|
|
@@ -1386,6 +1405,17 @@ type UseFormConfiguration<Form extends GenericForm, GetValueFormType, Schema ext
|
|
|
1386
1405
|
* coerced.
|
|
1387
1406
|
*/
|
|
1388
1407
|
coerce?: boolean | CoercionRegistry;
|
|
1408
|
+
/**
|
|
1409
|
+
* Per-form override of the `shouldShowErrors` heuristic that drives
|
|
1410
|
+
* `field.showErrors` and `form.meta.showErrors`. Falls back to
|
|
1411
|
+
* `AttaformDefaults.shouldShowErrors`, then to the library default
|
|
1412
|
+
* (`defaultShouldShowErrors`). See `AttaformDefaults.shouldShowErrors`
|
|
1413
|
+
* for the resolution rules and predicate signature.
|
|
1414
|
+
*
|
|
1415
|
+
* Boolean shorthand: `true` → always show *when errors exist*;
|
|
1416
|
+
* `false` → never show.
|
|
1417
|
+
*/
|
|
1418
|
+
shouldShowErrors?: ShouldShowErrorsConfig;
|
|
1389
1419
|
};
|
|
1390
1420
|
/**
|
|
1391
1421
|
* App-level defaults applied to every `useForm` call. Set these once
|
|
@@ -1451,6 +1481,34 @@ type AttaformDefaults = {
|
|
|
1451
1481
|
* authoritative writes whose strict typing is on the caller.
|
|
1452
1482
|
*/
|
|
1453
1483
|
coerce?: boolean | CoercionRegistry;
|
|
1484
|
+
/**
|
|
1485
|
+
* Default for `useForm({ shouldShowErrors })`. Centralised heuristic
|
|
1486
|
+
* that drives `field.showErrors` (and `form.meta.showErrors`) — a
|
|
1487
|
+
* boolean that gates whether a path's errors are *ready* to render.
|
|
1488
|
+
*
|
|
1489
|
+
* Resolution order (per-form wins):
|
|
1490
|
+
*
|
|
1491
|
+
* useForm({ shouldShowErrors }) > AttaformDefaults > library default
|
|
1492
|
+
*
|
|
1493
|
+
* The library default reads "show after the first submit attempt OR
|
|
1494
|
+
* after the field has been interacted with AND changed":
|
|
1495
|
+
*
|
|
1496
|
+
* ```ts
|
|
1497
|
+
* (field, formMeta) =>
|
|
1498
|
+
* formMeta.submitCount > 0 || (field.touched === true && field.dirty)
|
|
1499
|
+
* ```
|
|
1500
|
+
*
|
|
1501
|
+
* Compose with the library default via the public
|
|
1502
|
+
* `defaultShouldShowErrors` export. Boolean shorthand is supported:
|
|
1503
|
+
* `true` → always show *when errors exist*; `false` → never show. The
|
|
1504
|
+
* predicate is invoked only when `errors.length > 0`, so authors
|
|
1505
|
+
* don't re-check inside.
|
|
1506
|
+
*
|
|
1507
|
+
* The predicate's args are `Omit`'d of `showErrors` / `firstError`
|
|
1508
|
+
* to prevent recursive predicates — those are derived FROM this
|
|
1509
|
+
* predicate, so reading them inside would be a self-reference.
|
|
1510
|
+
*/
|
|
1511
|
+
shouldShowErrors?: ShouldShowErrorsConfig;
|
|
1454
1512
|
};
|
|
1455
1513
|
/**
|
|
1456
1514
|
* Callback invoked by `handleSubmit` after the form parses successfully.
|
|
@@ -1465,6 +1523,46 @@ type OnSubmit<Form extends GenericForm> = (form: Form) => void | Promise<void>;
|
|
|
1465
1523
|
* automatic `onInvalidSubmit` UI nudge).
|
|
1466
1524
|
*/
|
|
1467
1525
|
type OnError = (error: ValidationError[]) => void | Promise<void>;
|
|
1526
|
+
/**
|
|
1527
|
+
* Predicate that drives `field.showErrors` (and `form.meta.showErrors`).
|
|
1528
|
+
* Receives the field's reactive state plus the form's reactive meta;
|
|
1529
|
+
* returns `true` to render the field's errors, `false` to keep them
|
|
1530
|
+
* hidden. The framework gates the call on `errors.length > 0`, so
|
|
1531
|
+
* authors don't re-check error presence inside.
|
|
1532
|
+
*
|
|
1533
|
+
* Both arguments are `Omit`'d of `showErrors` / `firstError` — those
|
|
1534
|
+
* are derived FROM this predicate, so reading them inside would be a
|
|
1535
|
+
* self-reference. The omit is enforced at the type level AND at
|
|
1536
|
+
* runtime: the keys literally are not present on the objects passed
|
|
1537
|
+
* in, so `as` casting in TS or vanilla-JS bypass cannot create a
|
|
1538
|
+
* cycle.
|
|
1539
|
+
*
|
|
1540
|
+
* The library default — `defaultShouldShowErrors` — is publicly
|
|
1541
|
+
* exported so a layered predicate can compose with it:
|
|
1542
|
+
*
|
|
1543
|
+
* ```ts
|
|
1544
|
+
* import { defaultShouldShowErrors } from 'attaform'
|
|
1545
|
+
*
|
|
1546
|
+
* useForm({
|
|
1547
|
+
* schema,
|
|
1548
|
+
* shouldShowErrors: (field, formMeta) =>
|
|
1549
|
+
* field.path[0] === 'urgent' || defaultShouldShowErrors(field, formMeta),
|
|
1550
|
+
* })
|
|
1551
|
+
* ```
|
|
1552
|
+
*/
|
|
1553
|
+
type ShouldShowErrors = (field: Omit<FieldState, 'showErrors' | 'firstError'>, formMeta: Omit<FormMeta, 'showErrors' | 'firstError'>) => boolean;
|
|
1554
|
+
/**
|
|
1555
|
+
* Configuration shape for `shouldShowErrors`. A predicate function or
|
|
1556
|
+
* a boolean shorthand:
|
|
1557
|
+
*
|
|
1558
|
+
* - `true` — always show errors (when any exist).
|
|
1559
|
+
* - `false` — never show errors.
|
|
1560
|
+
* - function — custom predicate, see `ShouldShowErrors`.
|
|
1561
|
+
*
|
|
1562
|
+
* Resolved through three tiers (per-form > plugin defaults > library
|
|
1563
|
+
* default).
|
|
1564
|
+
*/
|
|
1565
|
+
type ShouldShowErrorsConfig = ShouldShowErrors | boolean;
|
|
1468
1566
|
/**
|
|
1469
1567
|
* Submit handler returned by `handleSubmit(onSubmit, onError)`. Bind
|
|
1470
1568
|
* it to a `<form>`:
|
|
@@ -2067,13 +2165,58 @@ type FieldState<Value = unknown> = {
|
|
|
2067
2165
|
* green-checkmark / `aria-invalid` UX.
|
|
2068
2166
|
*/
|
|
2069
2167
|
readonly valid: boolean;
|
|
2168
|
+
/**
|
|
2169
|
+
* Centralised "should I render this field's errors right now?"
|
|
2170
|
+
* gate. Wraps `errors.length > 0 && shouldShowErrors(field, formMeta)`
|
|
2171
|
+
* so templates avoid re-spelling the heuristic at every error site:
|
|
2172
|
+
*
|
|
2173
|
+
* ```vue
|
|
2174
|
+
* <span v-if="form.fields.email.showErrors">
|
|
2175
|
+
* {{ form.fields.email.firstError?.message }}
|
|
2176
|
+
* </span>
|
|
2177
|
+
* ```
|
|
2178
|
+
*
|
|
2179
|
+
* The heuristic itself comes from `useForm({ shouldShowErrors })` →
|
|
2180
|
+
* `createAttaform({ defaults: { shouldShowErrors } })` → library
|
|
2181
|
+
* default (`defaultShouldShowErrors` — show after first submit OR
|
|
2182
|
+
* after touched-and-dirty). Override per form, app-wide, or
|
|
2183
|
+
* compose with `defaultShouldShowErrors` for a layered predicate.
|
|
2184
|
+
*
|
|
2185
|
+
* Falls back to `false` whenever there are no errors — the gate
|
|
2186
|
+
* skips the predicate entirely in that case.
|
|
2187
|
+
*
|
|
2188
|
+
* Available on container paths too: `form.fields.users[0].showErrors`
|
|
2189
|
+
* aggregates over the row's descendants (any descendant with a
|
|
2190
|
+
* qualifying error flips the container on).
|
|
2191
|
+
*/
|
|
2192
|
+
readonly showErrors: boolean;
|
|
2193
|
+
/**
|
|
2194
|
+
* The first `ValidationError` at this path in the deterministic
|
|
2195
|
+
* schema-declaration order — equivalent to `errors[0]`, exposed as
|
|
2196
|
+
* a sugar accessor for the common case of "show the highest-priority
|
|
2197
|
+
* error message and ignore the rest":
|
|
2198
|
+
*
|
|
2199
|
+
* ```vue
|
|
2200
|
+
* <span v-if="form.fields.email.showErrors">
|
|
2201
|
+
* {{ form.fields.email.firstError?.message }}
|
|
2202
|
+
* </span>
|
|
2203
|
+
* ```
|
|
2204
|
+
*
|
|
2205
|
+
* `undefined` when no errors exist. Independent of `showErrors` —
|
|
2206
|
+
* the data primitive is always available; the heuristic only
|
|
2207
|
+
* decides when to render it.
|
|
2208
|
+
*
|
|
2209
|
+
* On container paths, the first error in the aggregated subtree
|
|
2210
|
+
* (descendants sorted by `pathOrdinal`).
|
|
2211
|
+
*/
|
|
2212
|
+
readonly firstError: ValidationError | undefined;
|
|
2070
2213
|
readonly path: ReadonlyArray<string | number>;
|
|
2071
2214
|
readonly blank: boolean;
|
|
2072
2215
|
/**
|
|
2073
2216
|
* Presentational label for this field. Resolves through the
|
|
2074
|
-
* adapter
|
|
2075
|
-
*
|
|
2076
|
-
* `withMeta()` helper
|
|
2217
|
+
* shared cross-adapter field-meta store — written via
|
|
2218
|
+
* `schema.register(fieldMeta, {...})` (Zod 4 native chain) or the
|
|
2219
|
+
* `withMeta()` helper (works on both majors) — and falls back to
|
|
2077
2220
|
* a humanized form of the path's last segment when nothing has
|
|
2078
2221
|
* been registered. Always a string.
|
|
2079
2222
|
*
|
|
@@ -2782,12 +2925,15 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
2782
2925
|
* if (result.ok) form.setFormErrors(result.errors)
|
|
2783
2926
|
* ```
|
|
2784
2927
|
*
|
|
2785
|
-
* Form-level errors
|
|
2786
|
-
*
|
|
2787
|
-
* `form.errors`
|
|
2788
|
-
*
|
|
2789
|
-
*
|
|
2790
|
-
*
|
|
2928
|
+
* Form-level errors land at the empty-string path bucket
|
|
2929
|
+
* (`path: ['']`). They surface in `form.meta.errors` (alongside
|
|
2930
|
+
* field errors), in `form.errors()` / `form.errors([])` (whole-form
|
|
2931
|
+
* subtree aggregates), and — uniquely — in `form.errors('')`,
|
|
2932
|
+
* which returns ONLY the form-level bucket. They're excluded from
|
|
2933
|
+
* the path-keyed `form.errors` drill proxy because no nested-object
|
|
2934
|
+
* key represents the empty-string path. Read them via
|
|
2935
|
+
* `meta.errors.filter(e => e.path.length === 1 && e.path[0] === '')`
|
|
2936
|
+
* if you need a programmatic split.
|
|
2791
2937
|
*/
|
|
2792
2938
|
setFormErrors: (errors: ReadonlyArray<Partial<ValidationError> & {
|
|
2793
2939
|
message: string;
|
|
@@ -2897,6 +3043,26 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
2897
3043
|
* `options` is forwarded to `Element.scrollIntoView` unchanged.
|
|
2898
3044
|
*/
|
|
2899
3045
|
scrollToFirstError: (options?: ScrollIntoViewOptions) => boolean;
|
|
3046
|
+
/**
|
|
3047
|
+
* Programmatically mark fields as touched — the sticky flag the
|
|
3048
|
+
* standard "show errors after interaction" pattern reads. Closes
|
|
3049
|
+
* the gap when fields are populated without a DOM gesture (post-
|
|
3050
|
+
* import, paste, autofill, server-seeded values you want to
|
|
3051
|
+
* validate immediately).
|
|
3052
|
+
*
|
|
3053
|
+
* ```ts
|
|
3054
|
+
* form.touch('email') // one leaf
|
|
3055
|
+
* form.touch('profile') // every leaf under profile
|
|
3056
|
+
* form.touch(['profile', 'name']) // segment-array form
|
|
3057
|
+
* form.touch() // every leaf in the form
|
|
3058
|
+
* ```
|
|
3059
|
+
*
|
|
3060
|
+
* Pure flag write — does not mutate value, focused, blurred, or
|
|
3061
|
+
* trigger validation. Idempotent: re-calling on an already-touched
|
|
3062
|
+
* field is a no-op. Touched is sticky-true; pair with
|
|
3063
|
+
* `form.reset()` / `form.resetField()` to clear.
|
|
3064
|
+
*/
|
|
3065
|
+
touch: (path?: FlatPath<Form> | (string | number)[]) => void;
|
|
2900
3066
|
/**
|
|
2901
3067
|
* Append `value` to the array at `path`.
|
|
2902
3068
|
*
|
|
@@ -2948,5 +3114,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
2948
3114
|
blankPaths: ComputedRef<ReadonlySet<string>>;
|
|
2949
3115
|
};
|
|
2950
3116
|
|
|
2951
|
-
export {
|
|
2952
|
-
export type {
|
|
3117
|
+
export { ROOT_PATH_KEY as $, ROOT_PATH as _, canonicalizePath as am, isPathPrefix as an, isUnset as ao, parseDottedPath as ap, unset as aq };
|
|
3118
|
+
export type { AttaformDefaults as A, NestedType as B, CoercionRegistry as C, DeepPartial as D, OnInvalidSubmitPolicy 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, OnSubmit as P, Path as Q, RegisterValue as R, SlimPrimitiveKind as S, PathKey as T, UseFormConfiguration as U, ValidationError as V, PendingValidationStatus as W, PersistConfig as X, PersistConfigOptions as Y, PersistIncludeMode as Z, CoercionEntry as a, ReactiveValidationStatus as a0, RegisterDirective as a1, RegisterFlatPath as a2, RegisterOptions as a3, RegisterSelectModifier as a4, RegisterTextModifier as a5, RegisterTransform as a6, Segment as a7, SetValueCallback as a8, SetValuePayload as a9, SettledValidationStatus as aa, ShouldShowErrorsConfig as ab, SlimRuntimeOf as ac, SubmitHandler as ad, Unset as ae, ValidateOn as af, ValidateOnConfig as ag, ValidationResponse as ah, ValidationResponseWithoutValue as ai, ValueOfUnion as aj, WriteMeta as ak, WriteShape as al, AbstractSchema as b, DefaultValuesShape as c, UseFormReturnType as d, RegisterModelDynamicCustomDirective as e, ShouldShowErrors as f, ApiErrorEnvelope as g, ApiErrorDetails as h, ApiErrorEntry as i, ArrayItem as j, ArrayPath as k, CoercionResult as l, CustomDirectiveRegisterAssignerFn as m, DefaultValuesResponse 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, FormStorage as w, FormStorageKind as x, HistoryConfig as y, IsUnion as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform.
|
|
1
|
+
import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform.CU3JperC.mjs';
|
|
2
2
|
import { Ref } from 'vue';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const store = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
const lists = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const registry = {
|
|
4
|
+
add(schema, payload) {
|
|
5
|
+
store.set(schema, payload);
|
|
6
|
+
const list = lists.get(schema) ?? [];
|
|
7
|
+
list.push(payload);
|
|
8
|
+
lists.set(schema, list);
|
|
9
|
+
return registry;
|
|
10
|
+
},
|
|
11
|
+
get(schema) {
|
|
12
|
+
return store.get(schema);
|
|
13
|
+
},
|
|
14
|
+
has(schema) {
|
|
15
|
+
return store.has(schema);
|
|
16
|
+
},
|
|
17
|
+
remove(schema) {
|
|
18
|
+
store.delete(schema);
|
|
19
|
+
lists.delete(schema);
|
|
20
|
+
return registry;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const fieldMetaStore = registry;
|
|
24
|
+
function getFieldMetaForSchema(schema) {
|
|
25
|
+
return store.get(schema);
|
|
26
|
+
}
|
|
27
|
+
function getFieldMetaListForSchema(schema) {
|
|
28
|
+
return lists.get(schema) ?? [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { getFieldMetaListForSchema as a, fieldMetaStore as f, getFieldMetaForSchema as g };
|
|
32
|
+
//# sourceMappingURL=attaform.D13GMFgK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attaform.D13GMFgK.mjs","sources":["../../src/runtime/core/field-meta-store.ts"],"sourcesContent":["/**\n * Shared field-metadata storage. Both Zod adapters (v3 and v4) and the\n * unified `attaform/zod` entry read from the same `WeakMap`s so a\n * payload written via any entry's `withMeta` / `fieldMeta.add` is\n * visible to whichever adapter actually runs at lookup time.\n *\n * No `zod` runtime import — pure JavaScript primitives. The previous\n * v4 adapter built `fieldMeta` via `z.registry<FieldMetaPayload>()`,\n * which left a `z.registry` namespace reference reachable from\n * `attaform/zod`'s module graph; bundlers analysing a `zod@^3` consumer\n * resolved that against zod 3's exports map (no `registry` export) and\n * emitted an `IMPORT_IS_UNDEFINED` warning. Lifting storage here drops\n * that reference entirely so the unified entry behaves cleanly on any\n * Zod major.\n *\n * The native v4 chain `schema.register(fieldMeta, payload)` still\n * works against this shim — Zod 4's `.register()` only calls\n * `registry.add(this, payload)` and returns the schema; structural\n * matching is enough.\n *\n * Two parallel maps:\n * - `store` — last-write-wins single payload per schema reference.\n * Backs `fieldMeta.get(schema)` and the adapter's\n * `getFieldMetaAtPath` single-payload fallback.\n * - `lists` — every registration in order, per schema reference.\n * Backs the v4 adapter's path-walker disambiguation when the same\n * schema instance is bound at multiple form paths.\n */\n\nimport type { FieldMetaPayload } from './field-meta'\n\n/**\n * Minimal registry shape the shared store satisfies — `.add` / `.get`\n * / `.has` / `.remove`. Cast to `z.$ZodRegistry<FieldMetaPayload>` at\n * the v4 adapter's re-export so the native `schema.register(fieldMeta,\n * payload)` chain type-checks; the v3 adapter exports it as its own\n * registry-shaped surface.\n */\nexport type FieldMetaStore = {\n add(schema: object, payload: FieldMetaPayload): FieldMetaStore\n get(schema: object): FieldMetaPayload | undefined\n has(schema: object): boolean\n remove(schema: object): FieldMetaStore\n}\n\nconst store = new WeakMap<object, FieldMetaPayload>()\nconst lists = new WeakMap<object, FieldMetaPayload[]>()\n\nconst registry: FieldMetaStore = {\n add(schema, payload) {\n store.set(schema, payload)\n const list = lists.get(schema) ?? []\n list.push(payload)\n lists.set(schema, list)\n return registry\n },\n get(schema) {\n return store.get(schema)\n },\n has(schema) {\n return store.has(schema)\n },\n remove(schema) {\n store.delete(schema)\n lists.delete(schema)\n return registry\n },\n}\n\n/**\n * The shared registry every Attaform-aware Zod schema can register\n * field metadata against, regardless of Zod major. One module-scoped\n * instance — every adapter entry re-exports this same object so\n * writes from one entry are visible at lookup through any other.\n */\nexport const fieldMetaStore: FieldMetaStore = registry\n\n/**\n * Last-write-wins payload lookup for a schema reference. Returns\n * `undefined` if nothing has been registered.\n */\nexport function getFieldMetaForSchema(schema: object): FieldMetaPayload | undefined {\n return store.get(schema)\n}\n\n/**\n * Read every payload registered against `schema` in registration\n * order. Empty list when nothing has been registered. Used by the v4\n * adapter's path-resolver to disambiguate per occurrence when one\n * schema instance is bound at multiple form paths.\n */\nexport function getFieldMetaListForSchema(schema: object): readonly FieldMetaPayload[] {\n return lists.get(schema) ?? []\n}\n"],"names":[],"mappings":"AA6CA,MAAM,KAAA,uBAAY,OAAA,EAAkC;AACpD,MAAM,KAAA,uBAAY,OAAA,EAAoC;AAEtD,MAAM,QAAA,GAA2B;AAAA,EAC/B,GAAA,CAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,KAAA,CAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,GAAA,CAAI,MAAM,KAAK,EAAC;AACnC,IAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AACjB,IAAA,KAAA,CAAM,GAAA,CAAI,QAAQ,IAAI,CAAA;AACtB,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AAAA,EACA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO,KAAA,CAAM,IAAI,MAAM,CAAA;AAAA,EACzB,CAAA;AAAA,EACA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO,KAAA,CAAM,IAAI,MAAM,CAAA;AAAA,EACzB,CAAA;AAAA,EACA,OAAO,MAAA,EAAQ;AACb,IAAA,KAAA,CAAM,OAAO,MAAM,CAAA;AACnB,IAAA,KAAA,CAAM,OAAO,MAAM,CAAA;AACnB,IAAA,OAAO,QAAA;AAAA,EACT;AACF,CAAA;AAQO,MAAM,cAAA,GAAiC;AAMvC,SAAS,sBAAsB,MAAA,EAA8C;AAClF,EAAA,OAAO,KAAA,CAAM,IAAI,MAAM,CAAA;AACzB;AAQO,SAAS,0BAA0B,MAAA,EAA6C;AACrF,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA,IAAK,EAAC;AAC/B;;;;"}
|
|
@@ -14,7 +14,7 @@ function normalizeSegment(raw) {
|
|
|
14
14
|
return raw;
|
|
15
15
|
}
|
|
16
16
|
function parseDottedPath(path) {
|
|
17
|
-
if (path.length === 0) return [];
|
|
17
|
+
if (path.length === 0) return [""];
|
|
18
18
|
const rawSegments = path.split(".");
|
|
19
19
|
const segments = [];
|
|
20
20
|
for (const raw of rawSegments) {
|
|
@@ -78,6 +78,8 @@ function canonicalizePath(input) {
|
|
|
78
78
|
}
|
|
79
79
|
const ROOT_PATH = Object.freeze([]);
|
|
80
80
|
const ROOT_PATH_KEY = "[]";
|
|
81
|
+
const FORM_ERRORS_PATH = Object.freeze([""]);
|
|
82
|
+
const FORM_ERRORS_PATH_KEY = '[""]';
|
|
81
83
|
function isPathPrefix(prefix, path) {
|
|
82
84
|
if (path.length < prefix.length) return false;
|
|
83
85
|
for (let i = 0; i < prefix.length; i++) {
|
|
@@ -86,5 +88,5 @@ function isPathPrefix(prefix, path) {
|
|
|
86
88
|
return true;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
export { ROOT_PATH as R, ROOT_PATH_KEY as a, canonicalizePath as c, isPathPrefix as i, parseDottedPath as p, segmentsForPathKey as s };
|
|
90
|
-
//# sourceMappingURL=attaform.
|
|
91
|
+
export { FORM_ERRORS_PATH_KEY as F, ROOT_PATH as R, ROOT_PATH_KEY as a, FORM_ERRORS_PATH as b, canonicalizePath as c, isPathPrefix as i, parseDottedPath as p, segmentsForPathKey as s };
|
|
92
|
+
//# sourceMappingURL=attaform.DZRj9s0s.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attaform.DZRj9s0s.mjs","sources":["../../src/runtime/core/paths.ts"],"sourcesContent":["import { InvalidPathError } from './errors'\n\n/**\n * Path primitives for advanced integrations. The form library accepts\n * paths in dotted-string form (`'user.email'`) at every public API.\n * These primitives are exposed for adapter authors who need to\n * canonicalise user-provided paths.\n */\n\ndeclare const pathKeyBrand: unique symbol\n\n/**\n * Branded string identifier for a canonicalised path. Useful as a\n * `Map` key — two paths that resolve to the same canonical form\n * produce the same `PathKey`. Treat as opaque; don't try to parse.\n */\nexport type PathKey = string & { readonly [pathKeyBrand]: 'PathKey' }\n\n/** A single path segment — a property name or array index. */\nexport type Segment = string | number\n/** A structured path as a read-only sequence of segments. */\nexport type Path = readonly Segment[]\n\n/** Tests an integer-like string without leading zeros. `'0'` | `'1'` | `'42'` pass; `'01'`, `'-1'`, `'1.5'` do not. */\nconst INTEGER_SEGMENT = /^(?:0|[1-9]\\d*)$/\n\nfunction normalizeSegment(raw: Segment): Segment {\n if (typeof raw === 'number') {\n if (!Number.isInteger(raw) || raw < 0) {\n throw new InvalidPathError(\n `Path segments must be non-negative integers when numeric; got ${String(raw)}`\n )\n }\n return raw\n }\n // Integer-looking strings normalise to numbers so that dotted-form\n // `'items.0.name'` and array-form `['items', 0, 'name']` yield the same\n // canonical path (and PathKey).\n if (INTEGER_SEGMENT.test(raw)) return Number(raw)\n return raw\n}\n\n/**\n * Parse a dotted-string path into structured segments.\n *\n * ```ts\n * parseDottedPath('user.address.line1') // ['user', 'address', 'line1']\n * parseDottedPath('items.0.name') // ['items', 0, 'name']\n * parseDottedPath('') // [''] (the empty-string key)\n * ```\n *\n * The empty-string input `''` is the **literal empty-key path**, not\n * the root. Use the array form `[]` for root. Form-level errors\n * (root `.refine()`) live at the empty-string path bucket so\n * `errors('')` returns them without sweeping every field error too.\n *\n * Throws `InvalidPathError` for paths with empty INTERNAL segments\n * (`'a..b'`, leading or trailing dots). For keys containing literal\n * dots, pass an array form (`['user.name']`) instead.\n */\nexport function parseDottedPath(path: string): Segment[] {\n if (path.length === 0) return ['']\n const rawSegments = path.split('.')\n const segments: Segment[] = []\n for (const raw of rawSegments) {\n if (raw.length === 0) {\n throw new InvalidPathError(\n `Path '${path}' has an empty segment; use the array form for empty keys.`\n )\n }\n segments.push(normalizeSegment(raw))\n }\n return segments\n}\n\n/**\n * Bounded FIFO cache for canonicalizePath on dotted-string inputs.\n * Real forms re-canonicalise a small working-set of paths thousands\n * of times per session (every keystroke on a registered field, every\n * validate, every getValue), so a small cache amortises the parse +\n * stringify cost across repeat calls without pinning memory as apps\n * accumulate fields.\n *\n * Eviction is FIFO (oldest insertion wins), not LRU. The 128-entry\n * cap is generous relative to a typical form's working set\n * (playground: ~15 paths; the entire test suite: 45 unique register\n * patterns) — overflow doesn't fire in practice. On the rare overflow\n * a re-canonicalisation hit is still O(segments) and lands back in\n * the cache. Bumping recency on every hit (`delete` + `set`) costs\n * two Map operations per cache hit, in the hottest read-side loop in\n * the library, with no observable benefit at this cap — so we don't.\n *\n * Array inputs are not cached: callers in the runtime (unset-walker's\n * recursive `[...segments, i]`, devtools' inspector `payload.path.slice(...)`)\n * overwhelmingly pass freshly-allocated arrays per call, so a\n * WeakMap-keyed cache would miss on every call and pay the\n * lookup-then-set cost without benefit.\n */\nconst CANONICAL_STRING_CACHE_MAX = 128\nconst canonicalStringCache = new Map<string, { segments: readonly Segment[]; key: PathKey }>()\n\n/**\n * Inverse cache: PathKey → segments. Populated by `canonicalizePath`\n * (string and array branches) so any consumer holding a PathKey\n * produced through the canonical pipeline can recover its structured\n * segments without `JSON.parse`. Callers reach this through\n * `segmentsForPathKey` below.\n *\n * The store-side data structures keyed by PathKey (form-store error\n * maps, blank-paths set, variant-memory map, persistence opt-in\n * registry) all source their keys from `canonicalizePath`, so reads\n * are dominantly cache hits. Cold paths (PathKeys round-tripped from\n * a persisted payload that came from disk) still hit a single\n * `JSON.parse` on first lookup, then warm the cache.\n *\n * Bounded FIFO at 4096 entries — generous relative to a typical form's\n * working set (~tens to ~hundreds of paths per form) but small enough\n * that long-running multi-form apps don't accumulate unbounded\n * references. Eviction only fires on net-new entries; idempotent\n * overwrites (same key, same segments) don't count toward the cap.\n */\nconst PATHKEY_TO_SEGMENTS_MAX = 4096\nconst pathKeyToSegments = new Map<PathKey, readonly Segment[]>()\n\nfunction rememberSegmentsForPathKey(key: PathKey, segments: readonly Segment[]): void {\n if (!pathKeyToSegments.has(key) && pathKeyToSegments.size >= PATHKEY_TO_SEGMENTS_MAX) {\n const oldest = pathKeyToSegments.keys().next().value\n if (oldest !== undefined) pathKeyToSegments.delete(oldest)\n }\n pathKeyToSegments.set(key, segments)\n}\n\n/**\n * Recover the structured `Segment[]` for a `PathKey` produced by\n * `canonicalizePath`. O(1) on the hot path (cache hit); cold keys\n * fall back to `JSON.parse(key)` plus segment normalization, then\n * warm the cache so subsequent lookups hit.\n *\n * Returns `null` for malformed PathKeys (non-JSON, non-array, or\n * containing values that aren't strings/numbers). Keys produced by\n * `canonicalizePath` never trip this — corrupt persistence payloads\n * (or test fixtures crafting raw strings) are the only realistic\n * sources.\n */\nexport function segmentsForPathKey(key: PathKey): readonly Segment[] | null {\n const cached = pathKeyToSegments.get(key)\n if (cached !== undefined) return cached\n let parsed: unknown\n try {\n parsed = JSON.parse(key)\n } catch {\n return null\n }\n if (!Array.isArray(parsed)) return null\n const segments: Segment[] = []\n for (const raw of parsed) {\n if (typeof raw !== 'string' && typeof raw !== 'number') return null\n segments.push(normalizeSegment(raw))\n }\n rememberSegmentsForPathKey(key, segments)\n return segments\n}\n\n/**\n * Canonicalise a path into structured segments plus a stable string\n * key. Accepts either dotted-string or array form; integer-looking\n * segments normalise to numbers.\n *\n * ```ts\n * canonicalizePath('items.0.name')\n * // { segments: ['items', 0, 'name'], key: '[\"items\",0,\"name\"]' as PathKey }\n *\n * canonicalizePath(['items', 0, 'name'])\n * // → same result\n * ```\n *\n * The returned `key` is suitable as a `Map`/`Set` key — equal paths\n * produce equal keys regardless of input form.\n */\nexport function canonicalizePath(input: string | Path): {\n segments: readonly Segment[]\n key: PathKey\n} {\n if (typeof input === 'string') {\n const cached = canonicalStringCache.get(input)\n if (cached !== undefined) return cached\n // `parseDottedPath` already normalises each segment; the previous\n // `.map(normalizeSegment)` second pass was a no-op. We drop it here.\n const segments: readonly Segment[] = parseDottedPath(input)\n const key = JSON.stringify(segments) as PathKey\n const entry = { segments, key }\n if (canonicalStringCache.size >= CANONICAL_STRING_CACHE_MAX) {\n const oldest = canonicalStringCache.keys().next().value\n if (oldest !== undefined) canonicalStringCache.delete(oldest)\n }\n canonicalStringCache.set(input, entry)\n rememberSegmentsForPathKey(key, segments)\n return entry\n }\n const segments = Array.from(input).map(normalizeSegment)\n const key = JSON.stringify(segments) as PathKey\n rememberSegmentsForPathKey(key, segments)\n return { segments, key }\n}\n\n/**\n * The root path — an empty segment tuple. Pass to APIs that accept\n * a `Path` to address the form value as a whole.\n */\nexport const ROOT_PATH: Path = Object.freeze([])\n/** Stable string key for the root path. */\nexport const ROOT_PATH_KEY = '[]' as PathKey\n\n/**\n * The form-level path — a one-segment path with the empty-string\n * key. Conventionally home for errors that don't belong to any\n * specific field: root `.refine()` messages, server-emitted form\n * errors, capacity / availability / cross-field-summary banners.\n *\n * Distinct from `ROOT_PATH` (`[]`): the root is the whole-form\n * subtree address (e.g. `errors([])` returns every error). The\n * form-level path is a sibling-of-no-field path that aggregation\n * walks DON'T sweep into per-field reads — `errors('field')`\n * returns only the field's errors, never the form-level bucket,\n * and `errors('')` returns only the form-level bucket, never the\n * field errors.\n */\nexport const FORM_ERRORS_PATH: Path = Object.freeze([''])\n/** Stable string key for the form-level errors path. */\nexport const FORM_ERRORS_PATH_KEY = '[\"\"]' as PathKey\n\n/**\n * `true` when `path` starts with every segment of `prefix` (in order).\n * The empty `prefix` matches every path — ROOT prefix is universal.\n *\n * Walks segments rather than `PathKey` strings because the data this\n * helper operates on (e.g. `meta.errors[].path`) carries segment\n * arrays directly.\n *\n * ```ts\n * isPathPrefix(['cargo'], ['cargo', 'items', 0, 'sku']) // true\n * isPathPrefix(['cargo', 'items'], ['cargo']) // false (path shorter)\n * isPathPrefix([], ['anything']) // true (root prefix)\n * ```\n */\nexport function isPathPrefix(prefix: readonly Segment[], path: readonly Segment[]): boolean {\n if (path.length < prefix.length) return false\n for (let i = 0; i < prefix.length; i++) {\n if (path[i] !== prefix[i]) return false\n }\n return true\n}\n"],"names":["segments","key"],"mappings":"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"}
|
|
@@ -2,32 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
const lodashEs = require('lodash-es');
|
|
4
4
|
const zod = require('zod');
|
|
5
|
-
const useFormContext = require('./attaform.
|
|
6
|
-
const paths = require('./attaform.
|
|
5
|
+
const useFormContext = require('./attaform.fegmBJaq.cjs');
|
|
6
|
+
const paths = require('./attaform.CIwZtbGV.cjs');
|
|
7
|
+
const fieldMetaStore = require('./attaform.C8CyvYa_.cjs');
|
|
7
8
|
const plugin = require('./attaform.rIRYSUI1.cjs');
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
-
const fieldMeta = {
|
|
11
|
-
add(schema, payload) {
|
|
12
|
-
store.set(schema, payload);
|
|
13
|
-
return fieldMeta;
|
|
14
|
-
},
|
|
15
|
-
get(schema) {
|
|
16
|
-
return store.get(schema);
|
|
17
|
-
},
|
|
18
|
-
has(schema) {
|
|
19
|
-
return store.has(schema);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
10
|
+
const fieldMeta = fieldMetaStore.fieldMetaStore;
|
|
22
11
|
function withMeta(schema, payload) {
|
|
23
|
-
const existing =
|
|
12
|
+
const existing = fieldMetaStore.getFieldMetaForSchema(schema) ?? {};
|
|
24
13
|
const Ctor = schema.constructor;
|
|
25
14
|
const cloned = new Ctor(schema._def);
|
|
26
|
-
|
|
15
|
+
fieldMetaStore.fieldMetaStore.add(cloned, { ...existing, ...payload });
|
|
27
16
|
return cloned;
|
|
28
17
|
}
|
|
29
18
|
function getFieldMeta(schema) {
|
|
30
|
-
return
|
|
19
|
+
return fieldMetaStore.getFieldMetaForSchema(schema);
|
|
31
20
|
}
|
|
32
21
|
|
|
33
22
|
class UnsupportedSchemaError extends plugin.AttaformError {
|
|
@@ -798,16 +787,7 @@ function zodAdapter(zodSchema) {
|
|
|
798
787
|
return aggregatedFailure(accumulatedErrors);
|
|
799
788
|
}
|
|
800
789
|
function nestedSchemasAtPath(p) {
|
|
801
|
-
|
|
802
|
-
stripDefaultValues: true,
|
|
803
|
-
stripNullable: true,
|
|
804
|
-
stripOptional: true
|
|
805
|
-
});
|
|
806
|
-
const slimSchema = getSlimSchema({
|
|
807
|
-
schema: strippedSchema,
|
|
808
|
-
stripConfig: { stripDefaultValues: true }
|
|
809
|
-
});
|
|
810
|
-
return getNestedZodSchemasAtPath(slimSchema, p);
|
|
790
|
+
return getNestedZodSchemasAtPath(_zodSchema, p);
|
|
811
791
|
}
|
|
812
792
|
function pathNotFound(p) {
|
|
813
793
|
return {
|
|
@@ -855,6 +835,11 @@ function zodIssuesToValidationErrors(issues, formKey) {
|
|
|
855
835
|
// can smuggle a Symbol through — the public surface promised
|
|
856
836
|
// strings/numbers, so coerce defensively to keep the contract.
|
|
857
837
|
// Mirrors v4's behaviour at the same site.
|
|
838
|
+
//
|
|
839
|
+
// Adapter-side paths stay schema-relative — the validation
|
|
840
|
+
// pipeline in `create-form-store.ts` prepends the parent path
|
|
841
|
+
// to absolutise, then routes form-level (absolute path length 0)
|
|
842
|
+
// entries to the empty-string bucket at storage time.
|
|
858
843
|
path: coercePathSegments(issue.path),
|
|
859
844
|
formKey,
|
|
860
845
|
code
|
|
@@ -890,6 +875,9 @@ function getNestedZodSchemasAtPath(zodSchema, segments) {
|
|
|
890
875
|
let currentSchema = zodSchema;
|
|
891
876
|
for (let index = 0; index < segments.length; index++) {
|
|
892
877
|
const key = String(segments[index] ?? "");
|
|
878
|
+
if (currentSchema !== void 0) {
|
|
879
|
+
currentSchema = peelV3Wrappers(currentSchema);
|
|
880
|
+
}
|
|
893
881
|
if (isZodSchemaType(currentSchema, "ZodObject")) {
|
|
894
882
|
const shape = currentSchema._def.shape();
|
|
895
883
|
currentSchema = Object.hasOwn(shape, key) ? shape[key] : void 0;
|
|
@@ -1558,4 +1546,4 @@ exports.isZodSchemaType = isZodSchemaType;
|
|
|
1558
1546
|
exports.useForm = useForm;
|
|
1559
1547
|
exports.withMeta = withMeta;
|
|
1560
1548
|
exports.zodAdapter = zodAdapter;
|
|
1561
|
-
//# sourceMappingURL=attaform.
|
|
1549
|
+
//# sourceMappingURL=attaform.Dd_pWnmn.cjs.map
|