attaform 0.20.2 → 0.21.1
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/chunks/dev-key-collision-warnings.cjs +58 -0
- package/dist/chunks/dev-key-collision-warnings.cjs.map +1 -0
- package/dist/chunks/dev-key-collision-warnings.mjs +55 -0
- package/dist/chunks/dev-key-collision-warnings.mjs.map +1 -0
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/fingerprint.cjs +186 -0
- package/dist/chunks/fingerprint.cjs.map +1 -0
- package/dist/chunks/fingerprint.mjs +184 -0
- package/dist/chunks/fingerprint.mjs.map +1 -0
- package/dist/chunks/fingerprint2.cjs +162 -0
- package/dist/chunks/fingerprint2.cjs.map +1 -0
- package/dist/chunks/fingerprint2.mjs +160 -0
- package/dist/chunks/fingerprint2.mjs.map +1 -0
- package/dist/chunks/indexeddb.cjs +1 -1
- package/dist/chunks/indexeddb.mjs +1 -1
- package/dist/chunks/local-storage.cjs +1 -1
- package/dist/chunks/local-storage.mjs +1 -1
- package/dist/chunks/multi-tab-sync.cjs +367 -0
- package/dist/chunks/multi-tab-sync.cjs.map +1 -0
- package/dist/chunks/multi-tab-sync.mjs +364 -0
- package/dist/chunks/multi-tab-sync.mjs.map +1 -0
- package/dist/chunks/session-storage.cjs +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/chunks/wire-persistence.cjs +396 -0
- package/dist/chunks/wire-persistence.cjs.map +1 -0
- package/dist/chunks/wire-persistence.mjs +394 -0
- package/dist/chunks/wire-persistence.mjs.map +1 -0
- package/dist/esbuild.cjs +28 -0
- package/dist/esbuild.cjs.map +1 -0
- package/dist/esbuild.d.cts +56 -0
- package/dist/esbuild.d.mts +56 -0
- package/dist/esbuild.d.ts +56 -0
- package/dist/esbuild.mjs +26 -0
- package/dist/esbuild.mjs.map +1 -0
- package/dist/index.cjs +5 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -70
- package/dist/index.d.mts +66 -70
- package/dist/index.d.ts +66 -70
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/rollup.cjs +24 -0
- package/dist/rollup.cjs.map +1 -0
- package/dist/rollup.d.cts +35 -0
- package/dist/rollup.d.mts +35 -0
- package/dist/rollup.d.ts +35 -0
- package/dist/rollup.mjs +22 -0
- package/dist/rollup.mjs.map +1 -0
- package/dist/rspack.cjs +10 -0
- package/dist/rspack.cjs.map +1 -0
- package/dist/rspack.d.cts +40 -0
- package/dist/rspack.d.mts +40 -0
- package/dist/rspack.d.ts +40 -0
- package/dist/rspack.mjs +8 -0
- package/dist/rspack.mjs.map +1 -0
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/attaform.BJGA_UOS.mjs +37 -0
- package/dist/shared/attaform.BJGA_UOS.mjs.map +1 -0
- package/dist/shared/attaform.BRGIpZo4.cjs +26 -0
- package/dist/shared/attaform.BRGIpZo4.cjs.map +1 -0
- package/dist/shared/{attaform.DAKrGhxc.cjs → attaform.BSkvn43g.cjs} +101 -417
- package/dist/shared/attaform.BSkvn43g.cjs.map +1 -0
- package/dist/shared/{attaform.sWm8B15V.d.mts → attaform.BWfliRIK.d.cts} +172 -2
- package/dist/shared/{attaform.BGk8cfw2.mjs → attaform.Be8NZG9M.mjs} +178 -21
- package/dist/shared/attaform.Be8NZG9M.mjs.map +1 -0
- package/dist/shared/{attaform.D2SCCd4O.cjs → attaform.Bq5sX7TF.cjs} +2 -2
- package/dist/shared/{attaform.D2SCCd4O.cjs.map → attaform.Bq5sX7TF.cjs.map} +1 -1
- package/dist/shared/{attaform.ceGEAEMk.d.ts → attaform.Bv7dRDWK.d.ts} +172 -2
- package/dist/shared/attaform.C3Doa9Pt.mjs +24 -0
- package/dist/shared/attaform.C3Doa9Pt.mjs.map +1 -0
- package/dist/shared/{attaform.B_hph5AE.cjs → attaform.CICFZ1iS.cjs} +178 -20
- package/dist/shared/attaform.CICFZ1iS.cjs.map +1 -0
- package/dist/shared/attaform.CQN9R62B.cjs +39 -0
- package/dist/shared/attaform.CQN9R62B.cjs.map +1 -0
- package/dist/shared/{attaform.CwLjUqmQ.cjs → attaform.ClXwitZj.cjs} +735 -960
- package/dist/shared/attaform.ClXwitZj.cjs.map +1 -0
- package/dist/shared/{attaform.99cfHcIt.d.cts → attaform.D0dWZsJt.d.cts} +349 -77
- package/dist/shared/{attaform.99cfHcIt.d.mts → attaform.D0dWZsJt.d.mts} +349 -77
- package/dist/shared/{attaform.99cfHcIt.d.ts → attaform.D0dWZsJt.d.ts} +349 -77
- package/dist/shared/{attaform.z5j3LwJz.cjs → attaform.D32WwKk6.cjs} +216 -35
- package/dist/shared/attaform.D32WwKk6.cjs.map +1 -0
- package/dist/shared/{attaform.C5aYC_T8.mjs → attaform.DMEP_ENr.mjs} +39 -392
- package/dist/shared/attaform.DMEP_ENr.mjs.map +1 -0
- package/dist/shared/{attaform.tiWEVznj.mjs → attaform.DR6RmxWZ.mjs} +725 -962
- package/dist/shared/attaform.DR6RmxWZ.mjs.map +1 -0
- package/dist/shared/{attaform.Dt7dEcHk.mjs → attaform.DozgVlCE.mjs} +89 -405
- package/dist/shared/attaform.DozgVlCE.mjs.map +1 -0
- package/dist/shared/{attaform.DN5CvZrg.d.ts → attaform.Duecg2NO.d.mts} +2 -2
- package/dist/shared/attaform.DuzQYscR.d.cts +41 -0
- package/dist/shared/attaform.DuzQYscR.d.mts +41 -0
- package/dist/shared/attaform.DuzQYscR.d.ts +41 -0
- package/dist/shared/{attaform.BXinSW2T.d.mts → attaform.FudOcHaa.d.cts} +2 -2
- package/dist/shared/attaform.LEWUFqUw.cjs +54 -0
- package/dist/shared/attaform.LEWUFqUw.cjs.map +1 -0
- package/dist/shared/{attaform.CywE4y8x.d.cts → attaform.MtrpT6Ki.d.ts} +2 -2
- package/dist/shared/{attaform.DbRgDFa7.d.cts → attaform.NQ8mybyW.d.mts} +172 -2
- package/dist/shared/{attaform.Cd4AOfwu.cjs → attaform.S-pYLSo4.cjs} +68 -402
- package/dist/shared/attaform.S-pYLSo4.cjs.map +1 -0
- package/dist/shared/{attaform.CnrxbkB6.mjs → attaform.Y1ZGhM4k.mjs} +2 -2
- package/dist/shared/{attaform.CnrxbkB6.mjs.map → attaform.Y1ZGhM4k.mjs.map} +1 -1
- package/dist/shared/{attaform.QG5TG8lB.mjs → attaform.pmtahXKy.mjs} +216 -36
- package/dist/shared/attaform.pmtahXKy.mjs.map +1 -0
- package/dist/shared/attaform.sHkHv_98.mjs +51 -0
- package/dist/shared/attaform.sHkHv_98.mjs.map +1 -0
- package/dist/vite.cjs +9 -45
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +36 -0
- package/dist/vite.d.mts +36 -0
- package/dist/vite.d.ts +36 -0
- package/dist/vite.mjs +8 -44
- package/dist/vite.mjs.map +1 -1
- package/dist/webpack.cjs +10 -0
- package/dist/webpack.cjs.map +1 -0
- package/dist/webpack.d.cts +37 -0
- package/dist/webpack.d.mts +37 -0
- package/dist/webpack.d.ts +37 -0
- package/dist/webpack.mjs +8 -0
- package/dist/webpack.mjs.map +1 -0
- package/dist/zod-v3.cjs +3 -3
- package/dist/zod-v3.d.cts +3 -3
- package/dist/zod-v3.d.mts +3 -3
- package/dist/zod-v3.d.ts +3 -3
- package/dist/zod-v3.mjs +3 -3
- package/dist/zod-v4.cjs +3 -3
- package/dist/zod-v4.d.cts +4 -4
- package/dist/zod-v4.d.mts +4 -4
- package/dist/zod-v4.d.ts +4 -4
- package/dist/zod-v4.mjs +3 -3
- package/dist/zod.cjs +8 -8
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +52 -10
- package/dist/zod.d.mts +52 -10
- package/dist/zod.d.ts +52 -10
- package/dist/zod.mjs +6 -6
- package/dist/zod.mjs.map +1 -1
- package/package.json +19 -5
- package/dist/shared/attaform.BGk8cfw2.mjs.map +0 -1
- package/dist/shared/attaform.B_hph5AE.cjs.map +0 -1
- package/dist/shared/attaform.C5aYC_T8.mjs.map +0 -1
- package/dist/shared/attaform.Cd4AOfwu.cjs.map +0 -1
- package/dist/shared/attaform.CwLjUqmQ.cjs.map +0 -1
- package/dist/shared/attaform.DAKrGhxc.cjs.map +0 -1
- package/dist/shared/attaform.Dt7dEcHk.mjs.map +0 -1
- package/dist/shared/attaform.QG5TG8lB.mjs.map +0 -1
- package/dist/shared/attaform.tiWEVznj.mjs.map +0 -1
- package/dist/shared/attaform.z5j3LwJz.cjs.map +0 -1
|
@@ -230,6 +230,21 @@ type KeyofUnion<T> = T extends unknown ? keyof T : never;
|
|
|
230
230
|
* variants and the runtime returns a stable stub there.
|
|
231
231
|
*/
|
|
232
232
|
type ValueOfUnion<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : undefined : never;
|
|
233
|
+
/**
|
|
234
|
+
* Value at key `K` across union members of `T`, dropping members that
|
|
235
|
+
* LACK `K` entirely (they contribute `never`, not `undefined`). The
|
|
236
|
+
* counterpart to `ValueOfUnion`: where that injects a SYNTHETIC
|
|
237
|
+
* `undefined` for absent-variant keys (so chained reads stay safe),
|
|
238
|
+
* this yields only the PRESENT value type.
|
|
239
|
+
*
|
|
240
|
+
* `form.fields` uses it at discriminated-union keys so a variant-only
|
|
241
|
+
* field types as node-optional `FieldState<X> | undefined` (the node is
|
|
242
|
+
* absent when its variant isn't active) rather than value-optional
|
|
243
|
+
* `FieldState<X | undefined>` (which would falsely promise a readable
|
|
244
|
+
* node). A genuine `undefined` from an OPTIONAL declaration survives —
|
|
245
|
+
* only the synthetic absent-variant `undefined` is stripped.
|
|
246
|
+
*/
|
|
247
|
+
type PresentValueOfUnion<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : never : never;
|
|
233
248
|
/**
|
|
234
249
|
* Apply the discriminated-union "lift" to a value shape (i.e., a
|
|
235
250
|
* shape carrying actual values, not metadata leaves like
|
|
@@ -814,6 +829,12 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
814
829
|
* Structural fingerprint of the schema. Same shape → same string;
|
|
815
830
|
* different shape → (best-effort) different string.
|
|
816
831
|
*
|
|
832
|
+
* Resolves a `Promise` so adapters can defer the structural walk (and
|
|
833
|
+
* its `canonicalStringify` helper) onto a dynamic import. The framework
|
|
834
|
+
* only ever needs the fingerprint on opt-in async paths (the multi-tab
|
|
835
|
+
* channel name, the persistence storage key) plus a dev-only mismatch
|
|
836
|
+
* warning, so none of those bytes belong on the eager `useForm` path.
|
|
837
|
+
*
|
|
817
838
|
* The library uses this to detect schema mismatches at a shared
|
|
818
839
|
* form key: two `useForm({ key: 'x', schema })` calls are allowed
|
|
819
840
|
* to land on the same `FormStore` (the "shared store" semantic),
|
|
@@ -841,7 +862,7 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
841
862
|
* look identical. The warning is a footgun catcher, not a
|
|
842
863
|
* soundness guarantee.
|
|
843
864
|
*/
|
|
844
|
-
fingerprint(): string
|
|
865
|
+
fingerprint(): Promise<string>;
|
|
845
866
|
getDefaultValues(config: GetDefaultValuesConfig<Form>): DefaultValuesResponse<Form>;
|
|
846
867
|
/**
|
|
847
868
|
* Return the schema-prescribed default value at the given path. The
|
|
@@ -938,6 +959,29 @@ type AbstractSchema<Form, GetValueFormType> = {
|
|
|
938
959
|
* `optional(z.tuple([...]))` reports its tuple length.
|
|
939
960
|
*/
|
|
940
961
|
arrayShapeAtPath(path: Path): number | null | undefined;
|
|
962
|
+
/**
|
|
963
|
+
* Whether the schema at `path` is a FIXED object: a closed set of
|
|
964
|
+
* declared keys (`z.object`), as opposed to an open or union container
|
|
965
|
+
* (array / record / map / set / union / discriminated union) whose
|
|
966
|
+
* element schema matches any segment.
|
|
967
|
+
*
|
|
968
|
+
* The surface proxies (`form.fields` / `form.errors`) use this to
|
|
969
|
+
* resolve a collision: a fixed object's declared keys are known ahead
|
|
970
|
+
* of any data, so a key the schema owns descends to a real terminal
|
|
971
|
+
* even when the live value hasn't been populated yet (a declared-but-
|
|
972
|
+
* absent `optional` field stays registrable). An open container can't
|
|
973
|
+
* make that promise — its element schema accepts ANY segment, so the
|
|
974
|
+
* proxy must fall back to the keys the data currently holds and read
|
|
975
|
+
* a genuinely-absent key (out-of-bounds index, missing record key,
|
|
976
|
+
* inactive variant key) as `undefined` rather than a phantom node.
|
|
977
|
+
*
|
|
978
|
+
* The empty path (the root form) is always a fixed object. Wrappers
|
|
979
|
+
* (optional / nullable / default / readonly / catch / pipe / lazy)
|
|
980
|
+
* are peeled before the kind check, so `z.object({...}).optional()`
|
|
981
|
+
* still reports `true`. A path the schema doesn't declare reports
|
|
982
|
+
* `false`.
|
|
983
|
+
*/
|
|
984
|
+
isFixedObjectAtPath(path: Path): boolean;
|
|
941
985
|
/**
|
|
942
986
|
* Return every sub-schema that could resolve at the given structured
|
|
943
987
|
* path. Multiple results are only expected for discriminated / union
|
|
@@ -2047,29 +2091,31 @@ type AttaformDefaults = {
|
|
|
2047
2091
|
* useForm({ getDisplayState }) > AttaformDefaults > library default
|
|
2048
2092
|
*
|
|
2049
2093
|
* The library default opens one timing gate, then resolves by
|
|
2050
|
-
* precedence: gate closed → `'idle'`; a run in flight →
|
|
2051
|
-
*
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2094
|
+
* precedence: gate closed → `'idle'`; a run in flight → a delayed
|
|
2095
|
+
* `'pending'` (held briefly to smooth fast validations, then held a
|
|
2096
|
+
* minimum so it never flashes); an own-path error → `'error'`;
|
|
2097
|
+
* otherwise earned `valid` → `'success'`, else `'idle'`. The gate opens
|
|
2098
|
+
* after the first submit attempt OR once the field is edited and left:
|
|
2054
2099
|
*
|
|
2055
2100
|
* ```ts
|
|
2056
|
-
* (
|
|
2101
|
+
* (prev, ctx) => {
|
|
2057
2102
|
* const gateOpen =
|
|
2058
|
-
* formMeta.submissionAttempts > 0 ||
|
|
2059
|
-
*
|
|
2060
|
-
* if (!gateOpen) return 'idle'
|
|
2061
|
-
*
|
|
2062
|
-
* //
|
|
2103
|
+
* ctx.formMeta.submissionAttempts > 0 ||
|
|
2104
|
+
* ctx.field.blurredAfterInteraction === true
|
|
2105
|
+
* if (!gateOpen) return { display: 'idle' }
|
|
2106
|
+
* // ...timed 'pending' while validating; own-path error → 'error';
|
|
2107
|
+
* // earned valid → 'success'; else 'idle'
|
|
2063
2108
|
* }
|
|
2064
2109
|
* ```
|
|
2065
2110
|
*
|
|
2066
2111
|
* Compose with the library default via the public `defaultDisplayState`
|
|
2067
|
-
* export
|
|
2112
|
+
* export, or retune its timing via `makeDefaultDisplayState`. The
|
|
2113
|
+
* reducer runs on every field-state read, so it owns the
|
|
2068
2114
|
* idle / pending / error / success decision outright.
|
|
2069
2115
|
*
|
|
2070
|
-
* The
|
|
2071
|
-
* `show*` / `firstError` keys (see
|
|
2072
|
-
* a self-referential
|
|
2116
|
+
* The reducer's `ctx.field` / `ctx.formMeta` are `Omit`'d of the
|
|
2117
|
+
* derived `displayState` / `show*` / `firstError` keys (see
|
|
2118
|
+
* `FieldStateDerivedKey`) to prevent a self-referential reducer.
|
|
2073
2119
|
*/
|
|
2074
2120
|
getDisplayState?: GetDisplayState;
|
|
2075
2121
|
/**
|
|
@@ -2230,16 +2276,64 @@ type DisplayState = 'idle' | 'pending' | 'error' | 'success';
|
|
|
2230
2276
|
*/
|
|
2231
2277
|
type FieldStateDerivedKey = 'displayState' | 'showErrors' | 'showPending' | 'showSuccess' | 'showIdle' | 'firstError';
|
|
2232
2278
|
/**
|
|
2233
|
-
*
|
|
2234
|
-
*
|
|
2235
|
-
* `
|
|
2236
|
-
*
|
|
2237
|
-
*
|
|
2238
|
-
*
|
|
2239
|
-
*
|
|
2279
|
+
* One step of the display state machine: the verdict the field should
|
|
2280
|
+
* render right now (`display`, projected to `displayState` and the
|
|
2281
|
+
* `show*` booleans) plus two optional timing cells the engine reads.
|
|
2282
|
+
*
|
|
2283
|
+
* - `reviewAt` — an absolute `Date.now()` millisecond stamp telling the
|
|
2284
|
+
* engine "re-evaluate this field no later than here." The engine keeps
|
|
2285
|
+
* a single timer per form aimed at the nearest `reviewAt` across all
|
|
2286
|
+
* active fields; when it fires, the dependent field computeds re-run
|
|
2287
|
+
* and call the reducer again. A machine with no `reviewAt` and a
|
|
2288
|
+
* non-pending `display` is terminal — the engine evicts it.
|
|
2289
|
+
* - `pendingShownAt` — the stamp at which `'pending'` was first shown,
|
|
2290
|
+
* the memory the min-visible hold needs so a spinner that just appeared
|
|
2291
|
+
* is not yanked away the instant validation resolves. Opaque to the
|
|
2292
|
+
* engine; a custom reducer may carry its own extra memory fields too.
|
|
2293
|
+
*/
|
|
2294
|
+
type DisplayMachine = {
|
|
2295
|
+
readonly display: DisplayState;
|
|
2296
|
+
readonly reviewAt?: number;
|
|
2297
|
+
readonly pendingShownAt?: number;
|
|
2298
|
+
};
|
|
2299
|
+
/**
|
|
2300
|
+
* Inputs to a `getDisplayState` reducer. `field` and `formMeta` are the
|
|
2301
|
+
* same reactive snapshots a predicate has always received (still minus
|
|
2302
|
+
* the derived `displayState` / `show*` / `firstError` keys — see
|
|
2303
|
+
* `FieldStateDerivedKey` — so a reducer can never read its own output and
|
|
2304
|
+
* form a cycle), now joined by:
|
|
2305
|
+
*
|
|
2306
|
+
* - `validatingSince` — `Date.now()` at which the field's current
|
|
2307
|
+
* validation streak opened, or `null` when nothing is in flight. This,
|
|
2308
|
+
* not `field.validating`, is the timing anchor: the elapsed wait is
|
|
2309
|
+
* `now - validatingSince`. Pinned to the start of the streak, so
|
|
2310
|
+
* overlapping sub-runs do not reset it.
|
|
2311
|
+
* - `transformingSince` — the same anchor for an in-flight async
|
|
2312
|
+
* `register` transform, or `null` when none is running. Folds into the
|
|
2313
|
+
* one in-flight clock the reducer already runs for validation, so a
|
|
2314
|
+
* deferred transform rides the anti-flash spinner timing identically.
|
|
2315
|
+
* `null` for a sync-only chain, which never defers.
|
|
2316
|
+
* - `now` — the engine's clock, injected so the reducer stays pure and
|
|
2317
|
+
* deterministic (and frozen to `0` under SSR, where there is no clock).
|
|
2318
|
+
*/
|
|
2319
|
+
type DisplayCtx = {
|
|
2320
|
+
readonly field: Omit<FieldState, FieldStateDerivedKey>;
|
|
2321
|
+
readonly formMeta: Omit<FormMeta, FieldStateDerivedKey>;
|
|
2322
|
+
readonly validatingSince: number | null;
|
|
2323
|
+
readonly transformingSince: number | null;
|
|
2324
|
+
readonly now: number;
|
|
2325
|
+
};
|
|
2326
|
+
/**
|
|
2327
|
+
* Pure transition reducer that resolves a path's `displayState`. Given
|
|
2328
|
+
* the field's previous `DisplayMachine` and the current `DisplayCtx`, it
|
|
2329
|
+
* returns the next machine; the engine owns the clock and the timers, the
|
|
2330
|
+
* reducer owns the timing policy. Runs on every field-state read (and
|
|
2331
|
+
* again whenever a `reviewAt` deadline fires), so the whole app's
|
|
2332
|
+
* validation-display behavior flows from this one function.
|
|
2240
2333
|
*
|
|
2241
|
-
* The library default — `defaultDisplayState` — is publicly exported so
|
|
2242
|
-
*
|
|
2334
|
+
* The library default — `defaultDisplayState` — is publicly exported so a
|
|
2335
|
+
* layered reducer can compose with it, and `makeDefaultDisplayState`
|
|
2336
|
+
* builds a default with custom anti-flash timings:
|
|
2243
2337
|
*
|
|
2244
2338
|
* ```ts
|
|
2245
2339
|
* import { defaultDisplayState } from 'attaform'
|
|
@@ -2247,14 +2341,16 @@ type FieldStateDerivedKey = 'displayState' | 'showErrors' | 'showPending' | 'sho
|
|
|
2247
2341
|
* useForm({
|
|
2248
2342
|
* schema,
|
|
2249
2343
|
* // Defer to the default everywhere, but never show a success check on `username`.
|
|
2250
|
-
* getDisplayState: (
|
|
2251
|
-
* const
|
|
2252
|
-
* return
|
|
2344
|
+
* getDisplayState: (prev, ctx) => {
|
|
2345
|
+
* const next = defaultDisplayState(prev, ctx)
|
|
2346
|
+
* return next.display === 'success' && ctx.field.path[0] === 'username'
|
|
2347
|
+
* ? { display: 'idle' }
|
|
2348
|
+
* : next
|
|
2253
2349
|
* },
|
|
2254
2350
|
* })
|
|
2255
2351
|
* ```
|
|
2256
2352
|
*/
|
|
2257
|
-
type GetDisplayState = (
|
|
2353
|
+
type GetDisplayState = (prev: DisplayMachine, ctx: DisplayCtx) => DisplayMachine;
|
|
2258
2354
|
/**
|
|
2259
2355
|
* Submit handler returned by `handleSubmit(onSubmit, onError)`. Bind
|
|
2260
2356
|
* it to a `<form>`:
|
|
@@ -2340,7 +2436,7 @@ type MetaTrackerValue = {
|
|
|
2340
2436
|
};
|
|
2341
2437
|
type RegisterFlatPath<Form, Key extends keyof Form = keyof Form> = FlatPathBuilder<Form, 'register', Key>;
|
|
2342
2438
|
/**
|
|
2343
|
-
*
|
|
2439
|
+
* A transformation applied to a field's value as user input flows
|
|
2344
2440
|
* from DOM through the directive's assigner. Composes left-to-right
|
|
2345
2441
|
* via the `transforms: [...]` array on `register()`.
|
|
2346
2442
|
*
|
|
@@ -2360,19 +2456,33 @@ type RegisterFlatPath<Form, Key extends keyof Form = keyof Form> = FlatPathBuild
|
|
|
2360
2456
|
* doesn't accept gets rejected at write time with a standard
|
|
2361
2457
|
* diagnostic.
|
|
2362
2458
|
*
|
|
2363
|
-
* Transforms
|
|
2364
|
-
*
|
|
2365
|
-
*
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2368
|
-
*
|
|
2369
|
-
*
|
|
2370
|
-
*
|
|
2371
|
-
*
|
|
2372
|
-
*
|
|
2373
|
-
*
|
|
2459
|
+
* Transforms may be sync or async. The chain stays fully synchronous —
|
|
2460
|
+
* the value reaches form state in the same tick — until a transform
|
|
2461
|
+
* returns a thenable; from there the write defers, the field reads
|
|
2462
|
+
* `busy` / `transforming` while the chain settles, and the resolved
|
|
2463
|
+
* value commits to canonical state once it lands. Rapid edits discard
|
|
2464
|
+
* all but the latest (latest-request-wins), and a rejection surfaces on
|
|
2465
|
+
* `field.transformError` rather than throwing or logging:
|
|
2466
|
+
*
|
|
2467
|
+
* ```ts
|
|
2468
|
+
* export const normalize: RegisterTransform = async (v, ctx) => {
|
|
2469
|
+
* const res = await fetch(`/normalize?q=${v}`, { signal: ctx?.signal })
|
|
2470
|
+
* return res.text()
|
|
2471
|
+
* }
|
|
2472
|
+
* ```
|
|
2473
|
+
*
|
|
2474
|
+
* `ctx.signal` is an `AbortSignal` aborted when the run is superseded by
|
|
2475
|
+
* a newer edit, or torn down by `reset()` / unmount — thread it into
|
|
2476
|
+
* cancellable I/O so a stale request is dropped. A sync chain never
|
|
2477
|
+
* touches it and allocates no controller.
|
|
2478
|
+
*
|
|
2479
|
+
* A synchronous throw is caught and aborts the pipeline: subsequent
|
|
2480
|
+
* transforms don't run, nothing is written to form state, and the
|
|
2481
|
+
* assigner returns `false` — so a buggy or defensive-throw transform
|
|
2482
|
+
* never crashes the host app. (An async rejection is the
|
|
2483
|
+
* `transformError` channel above, not a throw into the host app.)
|
|
2374
2484
|
*/
|
|
2375
|
-
type RegisterTransform = (value: unknown) => unknown;
|
|
2485
|
+
type RegisterTransform = (value: unknown, ctx?: TransformContext) => unknown;
|
|
2376
2486
|
/**
|
|
2377
2487
|
* Runtime type for a slim primitive kind. Used to narrow the
|
|
2378
2488
|
* `transform` parameter and return value on a `CoercionEntry` so
|
|
@@ -2497,9 +2607,11 @@ type RegisterOptions = {
|
|
|
2497
2607
|
* form.setValue('email', slugify(lowercase(rawValue)))
|
|
2498
2608
|
* ```
|
|
2499
2609
|
*
|
|
2500
|
-
* Transforms
|
|
2501
|
-
*
|
|
2502
|
-
* the
|
|
2610
|
+
* Transforms may be sync or async: the chain stays synchronous until
|
|
2611
|
+
* one returns a thenable, then the write defers and commits the
|
|
2612
|
+
* resolved value (the field reads `busy` meanwhile). A sync throw
|
|
2613
|
+
* aborts the write; an async rejection lands on `field.transformError`
|
|
2614
|
+
* (see `RegisterTransform` for the full contract).
|
|
2503
2615
|
*
|
|
2504
2616
|
* For patterns that need to inspect the `RegisterValue` itself
|
|
2505
2617
|
* (rejection-with-side-effect, redirection to other fields, custom
|
|
@@ -2817,6 +2929,64 @@ type RegisterValue<Value = unknown> = Readonly<{
|
|
|
2817
2929
|
*/
|
|
2818
2930
|
ariaDisplayState?: Readonly<Ref<DisplayState>>;
|
|
2819
2931
|
}>;
|
|
2932
|
+
/**
|
|
2933
|
+
* Internal extension of `RegisterValue` that includes directive-private
|
|
2934
|
+
* coordination state. Imported by the directive runtime; not part of
|
|
2935
|
+
* the public surface.
|
|
2936
|
+
*
|
|
2937
|
+
* `lastTypedForm` is the user's most recently typed string form for a
|
|
2938
|
+
* numeric field while mid-typing, or `null` once the field has been
|
|
2939
|
+
* blurred / cleared. The directive populates it on every committable
|
|
2940
|
+
* input event and clears it on the change (blur) event so:
|
|
2941
|
+
*
|
|
2942
|
+
* - Mid-typing: `displayValue` returns the typed form (e.g.
|
|
2943
|
+
* `'1e2'`) when it parses back to current storage. Vue's
|
|
2944
|
+
* `:value` patch then targets the typed form, which already
|
|
2945
|
+
* equals the DOM — idempotent, no cursor reset.
|
|
2946
|
+
* - On blur: `displayValue` falls back to `String(storage)`
|
|
2947
|
+
* (`'100'`), Vue patches the DOM to match. The user sees
|
|
2948
|
+
* exactly what's stored.
|
|
2949
|
+
*
|
|
2950
|
+
* Why a separate field: JavaScript's Number carries no representation
|
|
2951
|
+
* info — `1e2 === 100`, so `String(parseFloat('1e2'))` yields `'100'`.
|
|
2952
|
+
* Tracking the typed form lets us avoid Vue's mid-typing DOM yank
|
|
2953
|
+
* without lying about storage. Only meaningful for `.number` text
|
|
2954
|
+
* inputs and `<input type="number">`; other bindings ignore it.
|
|
2955
|
+
*
|
|
2956
|
+
* @internal
|
|
2957
|
+
*/
|
|
2958
|
+
/**
|
|
2959
|
+
* Mutable holder for an async-transform run's `AbortController`, shared
|
|
2960
|
+
* between the directive — which lazily creates the controller the first
|
|
2961
|
+
* time a transform reaches for `ctx.signal` — and the store, which
|
|
2962
|
+
* aborts it when the run is superseded, cancelled, or reset.
|
|
2963
|
+
* `controller` stays `null` until `ctx.signal` is actually touched, so a
|
|
2964
|
+
* purely-sync chain never allocates one. `aborted` latches `true` the
|
|
2965
|
+
* moment the store tears the run down, so a signal accessed AFTER
|
|
2966
|
+
* teardown still resolves to an already-aborted signal rather than a
|
|
2967
|
+
* live one.
|
|
2968
|
+
*/
|
|
2969
|
+
type TransformAbortHolder = {
|
|
2970
|
+
controller: AbortController | null;
|
|
2971
|
+
aborted: boolean;
|
|
2972
|
+
};
|
|
2973
|
+
/**
|
|
2974
|
+
* The second argument handed to every transform in a `transforms: [...]`
|
|
2975
|
+
* chain. `signal` is an `AbortSignal` that aborts when the run is
|
|
2976
|
+
* superseded by a newer input, or torn down by a reset / cancel — so a
|
|
2977
|
+
* transform doing cancellable I/O (a `fetch`, a worker round-trip) can
|
|
2978
|
+
* pass `ctx.signal` through and bail the moment its result is no longer
|
|
2979
|
+
* wanted.
|
|
2980
|
+
*
|
|
2981
|
+
* The signal is lazy: the backing `AbortController` is allocated only on
|
|
2982
|
+
* first access, so a purely-synchronous chain that never reaches for
|
|
2983
|
+
* `ctx.signal` allocates nothing. It is meaningful for async transforms;
|
|
2984
|
+
* a sync chain has no in-flight I/O to cancel, so its `signal` simply
|
|
2985
|
+
* never aborts.
|
|
2986
|
+
*/
|
|
2987
|
+
type TransformContext = {
|
|
2988
|
+
readonly signal: AbortSignal;
|
|
2989
|
+
};
|
|
2820
2990
|
/**
|
|
2821
2991
|
* Custom assigner installed on an element via the directive's
|
|
2822
2992
|
* `[assignKey]` slot OR an `@update:registerValue` listener. Called
|
|
@@ -2876,6 +3046,15 @@ type CustomRegisterDirective<T, Modifiers extends string = string> = ObjectDirec
|
|
|
2876
3046
|
* from the user's input.
|
|
2877
3047
|
*/
|
|
2878
3048
|
_lastAppliedModel?: unknown;
|
|
3049
|
+
/**
|
|
3050
|
+
* Variant-specific "repaint the DOM from current storage" closure,
|
|
3051
|
+
* stashed by each input directive's `created` hook (it mirrors that
|
|
3052
|
+
* variant's post-write force-sync block). The deferred async-transform
|
|
3053
|
+
* orchestrator calls it once the resolved value has committed, so a
|
|
3054
|
+
* bare `<input v-register>` with no other reactive reader still paints
|
|
3055
|
+
* the normalized result without depending on a parent re-render.
|
|
3056
|
+
*/
|
|
3057
|
+
_syncFromStorage?: () => void;
|
|
2879
3058
|
[S: symbol]: CustomDirectiveRegisterAssignerFn;
|
|
2880
3059
|
}, RegisterValue | undefined, Modifiers, string>;
|
|
2881
3060
|
/**
|
|
@@ -3211,8 +3390,38 @@ type FieldState<Value = unknown> = {
|
|
|
3211
3390
|
* is in flight (`errors.length === 0 && !validating`). Confidence
|
|
3212
3391
|
* that "we've checked, and we have no problems right now." Use for
|
|
3213
3392
|
* green-checkmark / `aria-invalid` UX.
|
|
3393
|
+
*
|
|
3394
|
+
* Validation-only: an in-flight async transform does NOT clamp
|
|
3395
|
+
* `valid` to `false`. `valid` is the verdict on the last committed
|
|
3396
|
+
* value; `busy` is the union "work in flight" signal.
|
|
3214
3397
|
*/
|
|
3215
3398
|
readonly valid: boolean;
|
|
3399
|
+
/**
|
|
3400
|
+
* `true` while an async `register` transform is in flight at this
|
|
3401
|
+
* path: a transform returned a thenable and the resolved value has
|
|
3402
|
+
* not yet committed to form state. Always `false` for a sync-only
|
|
3403
|
+
* chain, which reaches form state in the same tick with no deferral.
|
|
3404
|
+
* Containers roll it up as a disjunction (any descendant transforming).
|
|
3405
|
+
*/
|
|
3406
|
+
readonly transforming: boolean;
|
|
3407
|
+
/**
|
|
3408
|
+
* `transforming || validating` — the union "work is in flight at this
|
|
3409
|
+
* path" signal. Drives `aria-busy` through `displayState` on a
|
|
3410
|
+
* revealed field, and is the surface to bind for a busy indicator on a
|
|
3411
|
+
* field not yet revealed (where `displayState` stays idle by the
|
|
3412
|
+
* reveal gate). Containers roll it up as a disjunction.
|
|
3413
|
+
*/
|
|
3414
|
+
readonly busy: boolean;
|
|
3415
|
+
/**
|
|
3416
|
+
* The `Error` from the most recent async transform that rejected at
|
|
3417
|
+
* this path, else `null`. A per-field normalization-failure channel
|
|
3418
|
+
* separate from validation `errors`: a transform that rejects (a
|
|
3419
|
+
* failed fetch, a parse error) surfaces here instead of crashing the
|
|
3420
|
+
* host app or logging. Cleared when a fresh transform starts or a
|
|
3421
|
+
* write supersedes it. Leaf-only — containers do not roll it up (it is
|
|
3422
|
+
* always `null` at a container path).
|
|
3423
|
+
*/
|
|
3424
|
+
readonly transformError: Error | null;
|
|
3216
3425
|
/**
|
|
3217
3426
|
* The single display-state verdict at this path: `'idle'`,
|
|
3218
3427
|
* `'pending'`, `'error'`, or `'success'`. The source of truth the
|
|
@@ -3481,15 +3690,33 @@ interface LeafSchemeFor<T> {
|
|
|
3481
3690
|
*/
|
|
3482
3691
|
type LeafWalker<T, Kind extends keyof LeafSchemeFor<unknown>, StripOptional extends boolean = true> = [T] extends [string | number | boolean | bigint | symbol | null | undefined | Date | File] ? LeafSchemeFor<T>[Kind] : [T] extends [ReadonlyArray<infer U>] ? {
|
|
3483
3692
|
readonly [K: number]: LeafWalker<U, Kind, StripOptional>;
|
|
3484
|
-
} & ContainerSelfErrorsSlot<T, Kind> : [T] extends [object] ?
|
|
3485
|
-
readonly [K in
|
|
3693
|
+
} & ContainerSelfErrorsSlot<T, Kind> : [T] extends [object] ? string extends keyof T ? {
|
|
3694
|
+
readonly [K in keyof T]: LeafWalker<T[K], Kind, StripOptional>;
|
|
3695
|
+
} & ContainerSelfErrorsSlot<T, Kind> : [IsUnion<T>] extends [true] ? StripOptional extends true ? {
|
|
3696
|
+
readonly [K in KeyofUnion<T>]-?: DiscriminatedLeaf<T, K, Kind, StripOptional>;
|
|
3486
3697
|
} & ContainerSelfErrorsSlot<T, Kind> : {
|
|
3487
|
-
readonly [K in KeyofUnion<T>]:
|
|
3698
|
+
readonly [K in KeyofUnion<T>]: DiscriminatedLeaf<T, K, Kind, StripOptional>;
|
|
3488
3699
|
} & ContainerSelfErrorsSlot<T, Kind> : StripOptional extends true ? {
|
|
3489
3700
|
readonly [K in keyof T]-?: LeafWalker<T[K], Kind, StripOptional>;
|
|
3490
3701
|
} & ContainerSelfErrorsSlot<T, Kind> : {
|
|
3491
3702
|
readonly [K in keyof T]: LeafWalker<T[K], Kind, StripOptional>;
|
|
3492
3703
|
} & ContainerSelfErrorsSlot<T, Kind> : LeafSchemeFor<T>[Kind];
|
|
3704
|
+
/**
|
|
3705
|
+
* One key of a discriminated-union container in `LeafWalker`. A key
|
|
3706
|
+
* present (and required) in EVERY variant is universal — its node is
|
|
3707
|
+
* always reachable. A variant-only or optional-in-some key is a dynamic
|
|
3708
|
+
* hop: its node is `undefined` when its variant isn't active, so it
|
|
3709
|
+
* carries node-optionality (`LeafWalker<…> | undefined`), NOT value-
|
|
3710
|
+
* optionality (`LeafWalker<… | undefined>`). `PresentValueOfUnion`
|
|
3711
|
+
* strips the synthetic absent-variant `undefined` so the present node
|
|
3712
|
+
* resolves to the precise value type; a genuine `undefined` from an
|
|
3713
|
+
* `optional` declaration survives.
|
|
3714
|
+
*
|
|
3715
|
+
* Universality is `[T] extends [Record<K, unknown>]` — true iff `T`
|
|
3716
|
+
* (the whole union) satisfies "has K, required", which holds only when
|
|
3717
|
+
* every variant declares K as a required property.
|
|
3718
|
+
*/
|
|
3719
|
+
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;
|
|
3493
3720
|
/**
|
|
3494
3721
|
* Intersection augmenting every container in the `form.errors` walker
|
|
3495
3722
|
* with a `''` sentinel slot — the per-container home for cross-field
|
|
@@ -3504,6 +3731,22 @@ type ContainerSelfErrorsSlot<T, Kind> = Kind extends 'errors' ? '' extends keyof
|
|
|
3504
3731
|
readonly ['']: readonly ValidationError[];
|
|
3505
3732
|
} : unknown;
|
|
3506
3733
|
type FieldStateMapEntry<T> = LeafWalker<T, 'field'>;
|
|
3734
|
+
/**
|
|
3735
|
+
* Result of the `form.fields(path)` string call-form. A path the schema
|
|
3736
|
+
* declares resolves to its `FieldState` — a leaf's value type, or a
|
|
3737
|
+
* container's rolled-up aggregate (every FieldState property exists
|
|
3738
|
+
* regardless of the value type). A path the schema lacks resolves to
|
|
3739
|
+
* `undefined`, because a typo is not a field and the runtime hands back
|
|
3740
|
+
* `undefined` rather than a phantom stub. A non-literal `string` could
|
|
3741
|
+
* be either, so it widens to `FieldState<unknown> | undefined`.
|
|
3742
|
+
*
|
|
3743
|
+
* Named (rather than inlined into the `FieldStateMap` call signature) so
|
|
3744
|
+
* the conditional is one cached type — keeps two structurally-identical
|
|
3745
|
+
* `FieldStateMap` instantiations (e.g. the unified `attaform/zod` return
|
|
3746
|
+
* and `UseFormReturnV4`) relatable instead of collapsing to a nominal
|
|
3747
|
+
* "two different types with this name" mismatch.
|
|
3748
|
+
*/
|
|
3749
|
+
type FieldCallResult<Form, P extends string> = [P] extends [FlatPath<Form>] ? FieldState<NestedType<Form, P>> : string extends P ? FieldState<unknown> | undefined : undefined;
|
|
3507
3750
|
/**
|
|
3508
3751
|
* Type of `form.fields` — leaf-aware drillable callable Proxy. At
|
|
3509
3752
|
* a leaf path the proxy resolves to a `FieldState<Value>`; at
|
|
@@ -3524,18 +3767,14 @@ type FieldStateMapEntry<T> = LeafWalker<T, 'field'>;
|
|
|
3524
3767
|
* string as a single key. Use chained dot/bracket or the callable
|
|
3525
3768
|
* form.
|
|
3526
3769
|
*/
|
|
3527
|
-
type FieldStateMap<Form extends GenericForm> =
|
|
3528
|
-
readonly [K in KeyofUnion<Form>]-?: FieldStateMapEntry<ValueOfUnion<Form, K>>;
|
|
3529
|
-
} : {
|
|
3530
|
-
readonly [K in keyof Form]-?: FieldStateMapEntry<Form[K]>;
|
|
3531
|
-
}) & {
|
|
3770
|
+
type FieldStateMap<Form extends GenericForm> = LeafWalker<Form, 'field'> & {
|
|
3532
3771
|
/**
|
|
3533
|
-
*
|
|
3534
|
-
*
|
|
3535
|
-
*
|
|
3536
|
-
* `FieldState<
|
|
3772
|
+
* String-path form (dynamic / programmatic). See {@link FieldCallResult}:
|
|
3773
|
+
* a path the schema declares resolves to its precise `FieldState`, a
|
|
3774
|
+
* path it lacks to `undefined`, and a non-literal `string` to
|
|
3775
|
+
* `FieldState<unknown> | undefined`.
|
|
3537
3776
|
*/
|
|
3538
|
-
(path:
|
|
3777
|
+
<P extends string>(path: P): FieldCallResult<Form, P>;
|
|
3539
3778
|
/**
|
|
3540
3779
|
* Tuple-segment form. Returns the typed `FieldStateMapEntry` for
|
|
3541
3780
|
* the resolved path when the tuple resolves to a known path.
|
|
@@ -3546,10 +3785,10 @@ type FieldStateMap<Form extends GenericForm> = ([IsUnion<Form>] extends [true] ?
|
|
|
3546
3785
|
/**
|
|
3547
3786
|
* Dynamic-array fallback for callers passing `Path`-typed (runtime)
|
|
3548
3787
|
* segment arrays — e.g. forwarding `RegisterValue.segments` to
|
|
3549
|
-
* resolve a field view.
|
|
3550
|
-
* the value type is known.
|
|
3788
|
+
* resolve a field view. The path may not resolve, so the result
|
|
3789
|
+
* widens with `| undefined`; cast when the value type is known.
|
|
3551
3790
|
*/
|
|
3552
|
-
(segments: ReadonlyArray<string | number>): FieldState<unknown
|
|
3791
|
+
(segments: ReadonlyArray<string | number>): FieldState<unknown> | undefined;
|
|
3553
3792
|
/**
|
|
3554
3793
|
* No-arg call returns the root FieldState — same as
|
|
3555
3794
|
* `form.fields([])`. Aggregates over the whole form (one
|
|
@@ -3796,15 +4035,23 @@ type FormMeta<F = unknown> = FieldState<F> & {
|
|
|
3796
4035
|
*/
|
|
3797
4036
|
readonly departAttempts: number;
|
|
3798
4037
|
/**
|
|
3799
|
-
* The error thrown or rejected by the most recent submit callback
|
|
3800
|
-
*
|
|
3801
|
-
*
|
|
4038
|
+
* The error thrown or rejected by the most recent submit callback (or
|
|
4039
|
+
* its `onError` handler), coerced to a real `Error` (a non-`Error`
|
|
4040
|
+
* throw keeps its origin on `.cause`). Cleared to `null` at the start
|
|
4041
|
+
* of each new submission attempt; stays `null` on success.
|
|
3802
4042
|
*
|
|
3803
|
-
* The submit handler
|
|
3804
|
-
*
|
|
3805
|
-
* `
|
|
4043
|
+
* The submit handler does NOT re-throw — its returned promise always
|
|
4044
|
+
* resolves, so binding it to `@submit.prevent` never manufactures a
|
|
4045
|
+
* `window` unhandledrejection. This is the single channel for "the
|
|
4046
|
+
* submit failed", read the same way in templates and after an
|
|
4047
|
+
* imperative `await submit()`. Like `hydrateError`, it stays distinct
|
|
4048
|
+
* from the curated user-error store: render it where you choose:
|
|
4049
|
+
*
|
|
4050
|
+
* ```vue
|
|
4051
|
+
* <p v-if="form.meta.submitError">{{ form.meta.submitError.message }}</p>
|
|
4052
|
+
* ```
|
|
3806
4053
|
*/
|
|
3807
|
-
readonly submitError:
|
|
4054
|
+
readonly submitError: Error | null;
|
|
3808
4055
|
/**
|
|
3809
4056
|
* Scalar mirror of `meta.errors.length`. Read it from templates and
|
|
3810
4057
|
* `watch()` without indexing the underlying array.
|
|
@@ -3874,7 +4121,7 @@ type FormMeta<F = unknown> = FieldState<F> & {
|
|
|
3874
4121
|
*
|
|
3875
4122
|
* - `GetValueFormType` — the **output / parsed shape**
|
|
3876
4123
|
* (`z.output<Schema>`). Used by `handleSubmit`'s `onSubmit`
|
|
3877
|
-
* callback and by `form.
|
|
4124
|
+
* callback and by `form.parse()`'s success payload. This is the
|
|
3878
4125
|
* shape after refinements have fired and transforms have run.
|
|
3879
4126
|
*
|
|
3880
4127
|
* - `ReadForm` — the **read / storage shape**. Used by `values`,
|
|
@@ -3971,7 +4218,7 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
3971
4218
|
* `z.input<Schema>` shape — `.transform()`s have NOT run, so for
|
|
3972
4219
|
* a schema like `z.string().transform(v => v.length > 10)` the
|
|
3973
4220
|
* value reads as `string`, not `boolean`. Use `handleSubmit` or
|
|
3974
|
-
* `form.
|
|
4221
|
+
* `form.parse()` when you need the post-transform output shape.
|
|
3975
4222
|
*/
|
|
3976
4223
|
values: ValuesSurface<WriteShape<ReadForm>>;
|
|
3977
4224
|
/**
|
|
@@ -4098,6 +4345,26 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4098
4345
|
* `true` while the promise is in flight.
|
|
4099
4346
|
*/
|
|
4100
4347
|
validateAsync: (path?: FlatPath<Form>) => Promise<ValidationResponseWithoutValue<Form>>;
|
|
4348
|
+
/**
|
|
4349
|
+
* Resolve once every in-flight async `register({ transforms })` run
|
|
4350
|
+
* has settled — globally, or (with `path`) only at-or-under that path.
|
|
4351
|
+
* Resolve-never-reject: a transform that throws still settles the
|
|
4352
|
+
* field (its failure lands on `field.transformError`), so the returned
|
|
4353
|
+
* promise always resolves.
|
|
4354
|
+
*
|
|
4355
|
+
* `handleSubmit` awaits this internally before parsing, so a submit
|
|
4356
|
+
* fired the instant after an async transform still validates the
|
|
4357
|
+
* resolved value. Reach for it directly when you need the same
|
|
4358
|
+
* guarantee outside submit — e.g. before reading `form.values` in an
|
|
4359
|
+
* imperative flow or a test:
|
|
4360
|
+
*
|
|
4361
|
+
* ```ts
|
|
4362
|
+
* input.value = ' a@b.com '
|
|
4363
|
+
* await form.settleTransforms('email')
|
|
4364
|
+
* // form.values.email is now the normalized value
|
|
4365
|
+
* ```
|
|
4366
|
+
*/
|
|
4367
|
+
settleTransforms: (path?: FlatPath<Form>) => Promise<void>;
|
|
4101
4368
|
/**
|
|
4102
4369
|
* Imperative one-shot parse. Same pipeline as `validateAsync` —
|
|
4103
4370
|
* runs refinements, applies `.transform()`s, composes blank-required
|
|
@@ -4107,11 +4374,11 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4107
4374
|
* preprocess normalization applied but `.transform()` deferred. For
|
|
4108
4375
|
* schemas where the input type differs from the output type (e.g.,
|
|
4109
4376
|
* `z.string().transform(v => v.length > 10)`), `form.values.X` is
|
|
4110
|
-
* the input shape and `(await form.
|
|
4377
|
+
* the input shape and `(await form.parse()).data?.X` is the
|
|
4111
4378
|
* output shape.
|
|
4112
4379
|
*
|
|
4113
4380
|
* ```ts
|
|
4114
|
-
* const result = await form.
|
|
4381
|
+
* const result = await form.parse()
|
|
4115
4382
|
* if (result.success) {
|
|
4116
4383
|
* // result.data matches z.output<typeof schema>
|
|
4117
4384
|
* } else {
|
|
@@ -4119,11 +4386,16 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4119
4386
|
* }
|
|
4120
4387
|
* ```
|
|
4121
4388
|
*
|
|
4122
|
-
*
|
|
4123
|
-
*
|
|
4124
|
-
*
|
|
4389
|
+
* Always async, and there is no synchronous variant by design: a
|
|
4390
|
+
* schema can carry async refinements or transforms, so a sync parse
|
|
4391
|
+
* would silently miss them the moment one is added. One always-
|
|
4392
|
+
* awaited `parse` closes that category of bug entirely. The returned
|
|
4393
|
+
* promise never rejects (a thrown adapter lands as a `success: false`
|
|
4394
|
+
* response). Pass a path to parse a subtree only. `meta.validating`
|
|
4395
|
+
* flips `true` while the promise is in flight (shared with
|
|
4396
|
+
* validateAsync).
|
|
4125
4397
|
*/
|
|
4126
|
-
|
|
4398
|
+
parse: (path?: FlatPath<Form>) => Promise<ValidationResponse<GetValueFormType>>;
|
|
4127
4399
|
/**
|
|
4128
4400
|
* Bind a path to a native input via `v-register`. Returns a
|
|
4129
4401
|
* `RegisterValue` carrying the live ref and event handlers the
|
|
@@ -4644,5 +4916,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4644
4916
|
blankPaths: ComputedRef<BlankPathsView>;
|
|
4645
4917
|
};
|
|
4646
4918
|
|
|
4647
|
-
export {
|
|
4648
|
-
export type { AbstractSchema as A,
|
|
4919
|
+
export { ROOT_PATH as a0, ROOT_PATH_KEY as a1, canonicalizePath as av, isPathPrefix as aw, isUnset as ax, parseDottedPath as ay, unset as az };
|
|
4920
|
+
export type { Primitive as $, AbstractSchema as A, HistoryConfig as B, CoercionEntry as C, DeepPartial as D, ErrorsProxyShape as E, FieldMetaPayload as F, GenericForm as G, HandleSubmit as H, IsTuple as I, IsUnion as J, JoinSegments as K, KeyofUnion as L, LiftedValueShape as M, MetaTrackerValue as N, NestedReadType as O, NestedType as P, OnError as Q, OnInvalidSubmitPolicy as R, OnSubmit as S, PartialFlatPath as T, Path as U, PathKey as V, PendingValidationStatus as W, PersistConfig as X, PersistConfigOptions as Y, PersistIncludeMode as Z, PersistOptInRegistry as _, ApiErrorDetails as a, ReactiveValidationStatus as a2, RegisterDirective as a3, RegisterFlatPath as a4, RegisterModelDynamicCustomDirective as a5, RegisterOptions as a6, RegisterSelectModifier as a7, RegisterTextModifier as a8, RegisterTransform as a9, RegisterValue as aa, SchemaFactoryOptions as ab, Segment as ac, SetValueCallback as ad, SetValuePayload as ae, SettledValidationStatus as af, SlimPrimitiveKind as ag, SlimRuntimeOf as ah, SubmitHandler as ai, TransformAbortHolder as aj, Unset as ak, UseFormConfiguration as al, UseFormReturnType as am, ValidateOn as an, ValidateOnConfig as ao, ValidationError as ap, ValidationResponse as aq, ValidationResponseWithoutValue as ar, ValueOfUnion as as, WriteMeta as at, WriteShape as au, ApiErrorEntry as b, ApiErrorEnvelope as c, ArrayItem as d, ArrayPath as e, AttaformDefaults as f, CoercionRegistry as g, CoercionResult as h, CustomDirectiveRegisterAssignerFn as i, DefaultValuesInput as j, DefaultValuesResponse as k, DefaultValuesShape as l, DisplayCtx as m, DisplayMachine as n, DisplayState as o, FieldState as p, FieldStateMap as q, FieldStateMapEntry as r, FlatPath as s, FormErrorRecord as t, FormErrorsSurface as u, FormKey as v, FormMeta as w, FormStorage as x, FormStorageKind as y, GetDisplayState as z };
|