attaform 0.21.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/dev-key-collision-warnings.cjs +1 -1
- package/dist/chunks/dev-key-collision-warnings.mjs +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/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 +2 -2
- package/dist/chunks/multi-tab-sync.mjs +2 -2
- package/dist/chunks/session-storage.cjs +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/chunks/wire-persistence.cjs +2 -2
- package/dist/chunks/wire-persistence.mjs +2 -2
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- 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/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.B5LNzqQh.cjs → attaform.01iKS_lz.cjs} +18 -5
- package/dist/shared/{attaform.DP-u7_tk.mjs.map → attaform.01iKS_lz.cjs.map} +1 -1
- package/dist/shared/{attaform.C41gjp-a.mjs → attaform.6xE0Lcfd.mjs} +2 -2
- package/dist/shared/{attaform.C41gjp-a.mjs.map → attaform.6xE0Lcfd.mjs.map} +1 -1
- package/dist/shared/{attaform.BBDIKtKY.cjs → attaform.AyujQoHp.cjs} +4 -4
- package/dist/shared/{attaform.BBDIKtKY.cjs.map → attaform.AyujQoHp.cjs.map} +1 -1
- package/dist/shared/{attaform.BGf_J22U.d.ts → attaform.BGwNZ9GV.d.cts} +10 -2
- package/dist/shared/{attaform.DP-u7_tk.mjs → attaform.BKFwekY2.mjs} +16 -6
- package/dist/shared/{attaform.B5LNzqQh.cjs.map → attaform.BKFwekY2.mjs.map} +1 -1
- package/dist/shared/{attaform.CcnF1AKJ.cjs → attaform.C-RtnCJM.cjs} +116 -47
- package/dist/shared/attaform.C-RtnCJM.cjs.map +1 -0
- package/dist/shared/{attaform.BkjJfMvJ.d.cts → attaform.CCCeEPwa.d.mts} +10 -2
- package/dist/shared/{attaform.BwLp9KM7.cjs → attaform.CRzpFCjV.cjs} +2 -2
- package/dist/shared/{attaform.BwLp9KM7.cjs.map → attaform.CRzpFCjV.cjs.map} +1 -1
- package/dist/shared/{attaform.D2ZuIOCf.cjs → attaform.CjMcwV7W.cjs} +557 -126
- package/dist/shared/attaform.CjMcwV7W.cjs.map +1 -0
- package/dist/shared/{attaform.CTheKoTc.mjs → attaform.CsB-iKbU.mjs} +557 -126
- package/dist/shared/attaform.CsB-iKbU.mjs.map +1 -0
- package/dist/shared/{attaform.BCcrLApm.d.mts → attaform.D4XYaasQ.d.ts} +10 -2
- package/dist/shared/{attaform.D6GYGshL.mjs → attaform.DCjgGir_.mjs} +3 -3
- package/dist/shared/{attaform.D6GYGshL.mjs.map → attaform.DCjgGir_.mjs.map} +1 -1
- package/dist/shared/{attaform.BVeLgfEh.mjs → attaform.DNuiFCXG.mjs} +4 -4
- package/dist/shared/{attaform.BVeLgfEh.mjs.map → attaform.DNuiFCXG.mjs.map} +1 -1
- package/dist/shared/{attaform.BYgioWLF.d.ts → attaform.DUMWQefY.d.ts} +1 -1
- package/dist/shared/{attaform.CrD73S4m.mjs → attaform.DgCfLqay.mjs} +116 -47
- package/dist/shared/attaform.DgCfLqay.mjs.map +1 -0
- package/dist/shared/{attaform.ory-3WhV.d.ts → attaform.DvUH4a3o.d.cts} +181 -6
- package/dist/shared/{attaform.ory-3WhV.d.cts → attaform.DvUH4a3o.d.mts} +181 -6
- package/dist/shared/{attaform.ory-3WhV.d.mts → attaform.DvUH4a3o.d.ts} +181 -6
- package/dist/shared/{attaform.BoY6RZUl.d.cts → attaform.FN0vaQAg.d.mts} +1 -1
- package/dist/shared/{attaform.BwrowMp2.cjs → attaform.Q3eAD2wD.cjs} +3 -3
- package/dist/shared/{attaform.BwrowMp2.cjs.map → attaform.Q3eAD2wD.cjs.map} +1 -1
- package/dist/shared/{attaform.CnEl--PF.d.mts → attaform.aekT7mMx.d.cts} +1 -1
- package/dist/zod-v3.cjs +2 -2
- 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 +2 -2
- package/dist/zod-v4.cjs +2 -2
- 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 +2 -2
- package/dist/zod.cjs +5 -5
- package/dist/zod.d.cts +5 -5
- package/dist/zod.d.mts +5 -5
- package/dist/zod.d.ts +5 -5
- package/dist/zod.mjs +5 -5
- package/package.json +2 -2
- package/dist/shared/attaform.CTheKoTc.mjs.map +0 -1
- package/dist/shared/attaform.CcnF1AKJ.cjs.map +0 -1
- package/dist/shared/attaform.CrD73S4m.mjs.map +0 -1
- package/dist/shared/attaform.D2ZuIOCf.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ObjectDirective, Ref, ComputedRef } from 'vue';
|
|
1
|
+
import { ObjectDirective, Ref, MaybeRefOrGetter, ComputedRef } from 'vue';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Schema-attached field metadata — the shared types used by both Zod
|
|
@@ -1540,6 +1540,132 @@ type WriteMeta = {
|
|
|
1540
1540
|
* consumer code.
|
|
1541
1541
|
*/
|
|
1542
1542
|
readonly crossTab?: boolean;
|
|
1543
|
+
/**
|
|
1544
|
+
* When `true`, this write lands normally (storage, validation,
|
|
1545
|
+
* persistence, history) but does NOT notify `form.onChange` handlers.
|
|
1546
|
+
* The side-channel reacts to user edits, not programmatic rebaselines:
|
|
1547
|
+
* `reset()` tags its replacement with this flag, and the public
|
|
1548
|
+
* `setValue(path, value, { silent: true })` option forwards it so a
|
|
1549
|
+
* consumer hydrating the form (loading a saved record into the fields)
|
|
1550
|
+
* can land values without echoing each one back through an autosave
|
|
1551
|
+
* loop. The store's internal taggers and that single consumer-facing
|
|
1552
|
+
* option are the only writers.
|
|
1553
|
+
*/
|
|
1554
|
+
readonly silent?: boolean;
|
|
1555
|
+
};
|
|
1556
|
+
/** Options for a `setValue` write. */
|
|
1557
|
+
type SetValueOptions = {
|
|
1558
|
+
/**
|
|
1559
|
+
* When `true`, the write lands normally (storage, validation, persistence,
|
|
1560
|
+
* history) but does NOT notify `form.onChange` handlers. Use it to hydrate
|
|
1561
|
+
* the form (load a saved record into the fields) without echoing every
|
|
1562
|
+
* field back through an autosave loop.
|
|
1563
|
+
*/
|
|
1564
|
+
readonly silent?: boolean;
|
|
1565
|
+
};
|
|
1566
|
+
/**
|
|
1567
|
+
* A source address for `form.onChange` — the subtree(s) a handler reacts to.
|
|
1568
|
+
*
|
|
1569
|
+
* - a dotted path string (`'user.email'`) — one leaf or subtree;
|
|
1570
|
+
* - a list of path strings (`['shipping', 'billing']`) — react to any of
|
|
1571
|
+
* several paths; the handler fires once per matched path, `ctx.path`
|
|
1572
|
+
* distinguishing which;
|
|
1573
|
+
* - a getter or ref / computed resolving to either — re-read on each write,
|
|
1574
|
+
* so the aim can follow a moving target (the active list row). Re-aiming
|
|
1575
|
+
* is never itself a trigger; only a real write dispatches.
|
|
1576
|
+
*
|
|
1577
|
+
* Omit the source entirely (`form.onChange(handler)`) to react to the whole
|
|
1578
|
+
* form. An empty list (`form.onChange([], handler)`) lists zero paths, so it
|
|
1579
|
+
* never fires — that is a deliberate no-op, NOT a shorthand for the root.
|
|
1580
|
+
*/
|
|
1581
|
+
type OnChangeSource = MaybeRefOrGetter<string | readonly string[]>;
|
|
1582
|
+
/**
|
|
1583
|
+
* Context handed to an `onChange` handler alongside the changed value.
|
|
1584
|
+
*
|
|
1585
|
+
* `onChange` is a pure side-channel: it reacts to value changes and runs
|
|
1586
|
+
* side effects, but never touches the form's own lifecycle. Nothing a
|
|
1587
|
+
* handler does here marks the form dirty, pending, or validating — autosave
|
|
1588
|
+
* status lives in the consumer's own state, validation in `.refine` and
|
|
1589
|
+
* `field.show*`.
|
|
1590
|
+
*/
|
|
1591
|
+
type OnChangeContext<FormApi = unknown> = {
|
|
1592
|
+
/**
|
|
1593
|
+
* The source path this fire is for, in dotted form (`'user.email'`).
|
|
1594
|
+
* The empty string `''` is the whole form (a root handler). For a
|
|
1595
|
+
* multi-path source, the handler fires once per matched path and `path`
|
|
1596
|
+
* names which one.
|
|
1597
|
+
*/
|
|
1598
|
+
readonly path: string;
|
|
1599
|
+
/**
|
|
1600
|
+
* The value at the source path BEFORE this change, seeded at registration.
|
|
1601
|
+
* Accurate for leaf sources. For a container or the whole form, an
|
|
1602
|
+
* in-place leaf edit preserves the container's reference, so `previous`
|
|
1603
|
+
* can be reference-equal to the current value (Vue's deep-watch gotcha) —
|
|
1604
|
+
* snapshot inside the handler if a true container diff is needed.
|
|
1605
|
+
*/
|
|
1606
|
+
readonly previous: unknown;
|
|
1607
|
+
/**
|
|
1608
|
+
* Aborted when a newer write to the same source supersedes this run. A
|
|
1609
|
+
* debounced or awaiting handler should bail on `signal.aborted` (or pass
|
|
1610
|
+
* `signal` straight to `fetch`) so superseded work cancels itself.
|
|
1611
|
+
*/
|
|
1612
|
+
readonly signal: AbortSignal;
|
|
1613
|
+
/** Retry counter — `0` on the first run, incremented by `onError`'s `retry()`. */
|
|
1614
|
+
readonly attempt: number;
|
|
1615
|
+
/**
|
|
1616
|
+
* The form handle, so a portable `useForm({ onChange })` handler can reach
|
|
1617
|
+
* back into the form (e.g. `ctx.form.validateAsync(ctx.path)` to gate an
|
|
1618
|
+
* autosave on validity). Typed precisely by the `form.onChange` overload.
|
|
1619
|
+
*/
|
|
1620
|
+
readonly form: FormApi;
|
|
1621
|
+
/**
|
|
1622
|
+
* The leaf path(s), in dotted form, that actually changed in this
|
|
1623
|
+
* dispatch. For a leaf source this is just `[path]`; for a container or
|
|
1624
|
+
* the whole form it is every changed descendant.
|
|
1625
|
+
*/
|
|
1626
|
+
readonly changed: readonly string[];
|
|
1627
|
+
};
|
|
1628
|
+
/**
|
|
1629
|
+
* Context handed to an `onChange` handler's `onError` callback when the
|
|
1630
|
+
* handler throws or rejects.
|
|
1631
|
+
*/
|
|
1632
|
+
type OnChangeErrorContext<FormApi = unknown> = {
|
|
1633
|
+
/** The source path this run was for, in dotted form (`''` for the whole form). */
|
|
1634
|
+
readonly path: string;
|
|
1635
|
+
/** The value passed to the handler that failed. */
|
|
1636
|
+
readonly value: unknown;
|
|
1637
|
+
/** The attempt number that failed (`0` on the first run). */
|
|
1638
|
+
readonly attempt: number;
|
|
1639
|
+
/**
|
|
1640
|
+
* Re-run the handler with the same value and `attempt + 1`. A no-op once a
|
|
1641
|
+
* newer write has superseded this run — stale work is never resurrected.
|
|
1642
|
+
* Backoff and a retry cap are the consumer's to impose.
|
|
1643
|
+
*/
|
|
1644
|
+
readonly retry: () => void;
|
|
1645
|
+
/** The form handle. Typed precisely by the `form.onChange` overload. */
|
|
1646
|
+
readonly form: FormApi;
|
|
1647
|
+
};
|
|
1648
|
+
/** A reaction to form value changes. Its return is ignored; throws route to `onError`. */
|
|
1649
|
+
type OnChangeHandler<Value = unknown, FormApi = unknown> = (value: Value, ctx: OnChangeContext<FormApi>) => void | Promise<void>;
|
|
1650
|
+
/** Handles a throw / rejection from an `onChange` handler. Must not throw. */
|
|
1651
|
+
type OnChangeErrorHandler<FormApi = unknown> = (error: unknown, ctx: OnChangeErrorContext<FormApi>) => void;
|
|
1652
|
+
/** Options for `form.onChange`. */
|
|
1653
|
+
type OnChangeOptions<FormApi = unknown> = {
|
|
1654
|
+
/**
|
|
1655
|
+
* Called when the handler throws or its promise rejects. Without it, a
|
|
1656
|
+
* failure is swallowed (logged in dev). `onChange` never throws into the
|
|
1657
|
+
* write that triggered it.
|
|
1658
|
+
*/
|
|
1659
|
+
readonly onError?: OnChangeErrorHandler<FormApi>;
|
|
1660
|
+
};
|
|
1661
|
+
/**
|
|
1662
|
+
* The `useForm({ onChange })` option — a whole-form handler registered at
|
|
1663
|
+
* construction, bound to the form's lifetime. Either a bare handler or a
|
|
1664
|
+
* `{ handler, onError }` pair.
|
|
1665
|
+
*/
|
|
1666
|
+
type OnChangeConfig<Value = unknown, FormApi = unknown> = OnChangeHandler<Value, FormApi> | {
|
|
1667
|
+
readonly handler: OnChangeHandler<Value, FormApi>;
|
|
1668
|
+
readonly onError?: OnChangeErrorHandler<FormApi>;
|
|
1543
1669
|
};
|
|
1544
1670
|
/**
|
|
1545
1671
|
* Undo/redo configuration passed via `useForm({ history })`.
|
|
@@ -1825,6 +1951,17 @@ type UseFormConfiguration<Form extends GenericForm, GetValueFormType, Schema ext
|
|
|
1825
1951
|
* per blur for `<input v-register.lazy>`).
|
|
1826
1952
|
*/
|
|
1827
1953
|
debounceMs?: number;
|
|
1954
|
+
/**
|
|
1955
|
+
* A whole-form `onChange` handler, registered at construction and bound to
|
|
1956
|
+
* the form's lifetime. The same side-channel as `form.onChange(handler)`,
|
|
1957
|
+
* but declared in the options bag so it travels with the form (handy for a
|
|
1958
|
+
* `useAutosave`-style composable). Pass a handler, or `{ handler, onError }`.
|
|
1959
|
+
*
|
|
1960
|
+
* For path-scoped reactions, call `form.onChange('path', handler)` on the
|
|
1961
|
+
* returned form instead. `onChange` never touches the form's own
|
|
1962
|
+
* lifecycle — keep validation in `.refine` and `field.show*`.
|
|
1963
|
+
*/
|
|
1964
|
+
onChange?: OnChangeConfig<Form, UseFormReturnType<Form>>;
|
|
1828
1965
|
/**
|
|
1829
1966
|
* Opt-in persistence of the form's draft state. Off by default —
|
|
1830
1967
|
* with no config, no reads, no writes, no storage code is loaded.
|
|
@@ -4285,8 +4422,11 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4285
4422
|
* type at a leaf). Refinement-level mismatches (out-of-enum
|
|
4286
4423
|
* values, failing format checks, etc.) succeed and surface as
|
|
4287
4424
|
* field errors instead.
|
|
4425
|
+
*
|
|
4426
|
+
* Pass `{ silent: true }` to land the write without notifying
|
|
4427
|
+
* `form.onChange` handlers (e.g. hydrating a saved record).
|
|
4288
4428
|
*/
|
|
4289
|
-
<Value extends SetValuePayload<DefaultValuesShape<Form>, WriteShape<Form>>>(value: Value): boolean;
|
|
4429
|
+
<Value extends SetValuePayload<DefaultValuesShape<Form>, WriteShape<Form>>>(value: Value, options?: SetValueOptions): boolean;
|
|
4290
4430
|
/**
|
|
4291
4431
|
* Write at a specific path. Pass a value or a callback receiving
|
|
4292
4432
|
* the previous value at that path.
|
|
@@ -4304,14 +4444,49 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4304
4444
|
* it blank (storage holds the slim default; UI displays
|
|
4305
4445
|
* empty; submit raises "No value supplied" for required schemas).
|
|
4306
4446
|
*/
|
|
4307
|
-
<Path extends FlatPath<Form>, Value extends PathSetValuePayload<NestedType<Form, Path>>>(path: Path, value: Value): boolean;
|
|
4447
|
+
<Path extends FlatPath<Form>, Value extends PathSetValuePayload<NestedType<Form, Path>>>(path: Path, value: Value, options?: SetValueOptions): boolean;
|
|
4308
4448
|
/**
|
|
4309
4449
|
* Tuple-segment form. Equivalent to the dotted-string overload —
|
|
4310
4450
|
* useful when paths are built from variables or arrays:
|
|
4311
4451
|
* `form.setValue([prefix, 'line1'], 'value')`. The resolved leaf
|
|
4312
4452
|
* type is exact, matching the dotted-string form.
|
|
4313
4453
|
*/
|
|
4314
|
-
<const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never), value: Value): boolean;
|
|
4454
|
+
<const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never), value: Value, options?: SetValueOptions): boolean;
|
|
4455
|
+
};
|
|
4456
|
+
/**
|
|
4457
|
+
* Subscribe to form value changes — the side-channel autosave is built on.
|
|
4458
|
+
* Three call forms:
|
|
4459
|
+
*
|
|
4460
|
+
* - `form.onChange(handler, options?)` — react to the whole form.
|
|
4461
|
+
* - `form.onChange('user.email', handler, options?)` — react to one path;
|
|
4462
|
+
* `value` is that path's value.
|
|
4463
|
+
* - `form.onChange(source, handler, options?)` — react to a list of paths,
|
|
4464
|
+
* or a getter / ref resolving to a path or list (re-read on each write,
|
|
4465
|
+
* so the aim can follow a moving target like the active list row).
|
|
4466
|
+
*
|
|
4467
|
+
* The handler runs AFTER the value lands. Its return is ignored, and a
|
|
4468
|
+
* throw or rejection routes to `options.onError`, never into the write that
|
|
4469
|
+
* triggered it. Returns an idempotent `stop()`; called inside a component's
|
|
4470
|
+
* setup it also stops automatically on unmount.
|
|
4471
|
+
*
|
|
4472
|
+
* `onChange` is a pure side-channel: nothing it does marks the form dirty,
|
|
4473
|
+
* pending, or validating. Keep validation feedback in `.refine` and
|
|
4474
|
+
* `field.show*`, and track autosave status in your own state.
|
|
4475
|
+
*
|
|
4476
|
+
* ```ts
|
|
4477
|
+
* form.onChange('user.email', async (email, ctx) => {
|
|
4478
|
+
* const verdict = await ctx.form.validateAsync(ctx.path)
|
|
4479
|
+
* if (verdict.success) await api.save({ email }, { signal: ctx.signal })
|
|
4480
|
+
* }, { onError: (error, ctx) => ctx.retry() })
|
|
4481
|
+
* ```
|
|
4482
|
+
*/
|
|
4483
|
+
onChange: {
|
|
4484
|
+
/** React to the whole form. `value` is the current form. */
|
|
4485
|
+
(handler: OnChangeHandler<ReadForm, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4486
|
+
/** React to one path. `value` is that path's value. */
|
|
4487
|
+
<P extends FlatPath<Form>>(source: P, handler: OnChangeHandler<NestedType<Form, P>, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4488
|
+
/** React to a list of paths, or a getter / ref / computed. `value` is unknown. */
|
|
4489
|
+
(source: OnChangeSource, handler: OnChangeHandler<unknown, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4315
4490
|
};
|
|
4316
4491
|
/**
|
|
4317
4492
|
* Reactive validation status. Re-runs whenever the form (or the
|
|
@@ -4915,5 +5090,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4915
5090
|
blankPaths: ComputedRef<BlankPathsView>;
|
|
4916
5091
|
};
|
|
4917
5092
|
|
|
4918
|
-
export {
|
|
4919
|
-
export type {
|
|
5093
|
+
export { canonicalizePath as aA, isPathPrefix as aB, isUnset as aC, parseDottedPath as aD, unset as aE, ROOT_PATH as ab, ROOT_PATH_KEY as ac };
|
|
5094
|
+
export type { OnChangeSource as $, AttaformDefaults as A, FormStorage as B, CoercionEntry as C, DefaultValuesInput as D, ErrorsProxyShape as E, FormKey as F, GenericForm as G, FormStorageKind as H, HandleSubmit as I, HistoryConfig as J, IsTuple as K, IsUnion as L, JoinSegments as M, KeyofUnion as N, LiftedValueShape as O, MetaTrackerValue as P, NestedReadType as Q, RegisterModelDynamicCustomDirective as R, NestedType as S, OnChangeConfig as T, UseFormConfiguration as U, ValidationError as V, OnChangeContext as W, OnChangeErrorContext as X, OnChangeErrorHandler as Y, OnChangeHandler as Z, OnChangeOptions as _, AbstractSchema as a, OnError as a0, OnInvalidSubmitPolicy as a1, OnSubmit as a2, PartialFlatPath as a3, Path as a4, PathKey as a5, PendingValidationStatus as a6, PersistConfig as a7, PersistConfigOptions as a8, PersistIncludeMode as a9, SchemaFactoryOptions as aF, TransformAbortHolder as aG, PersistOptInRegistry as aH, Primitive as aa, ReactiveValidationStatus as ad, RegisterDirective as ae, RegisterFlatPath as af, RegisterOptions as ag, RegisterSelectModifier as ah, RegisterTextModifier as ai, RegisterTransform as aj, Segment as ak, SetValueCallback as al, SetValueOptions as am, SetValuePayload as an, SettledValidationStatus as ao, SlimPrimitiveKind as ap, SlimRuntimeOf as aq, SubmitHandler as ar, Unset as as, ValidateOn as at, ValidateOnConfig as au, ValidationResponse as av, ValidationResponseWithoutValue as aw, ValueOfUnion as ax, WriteMeta as ay, WriteShape as az, UseFormReturnType as b, RegisterValue as c, GetDisplayState as d, ApiErrorEnvelope as e, ApiErrorDetails as f, ApiErrorEntry as g, ArrayItem as h, ArrayPath as i, CoercionRegistry as j, CoercionResult as k, CustomDirectiveRegisterAssignerFn as l, DeepPartial as m, DefaultValuesResponse as n, DefaultValuesShape as o, DisplayCtx as p, DisplayMachine as q, DisplayState as r, FieldMetaPayload as s, FieldState as t, FieldStateMap as u, FieldStateMapEntry as v, FlatPath as w, FormErrorRecord as x, FormErrorsSurface as y, FormMeta as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ObjectDirective, Ref, ComputedRef } from 'vue';
|
|
1
|
+
import { ObjectDirective, Ref, MaybeRefOrGetter, ComputedRef } from 'vue';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Schema-attached field metadata — the shared types used by both Zod
|
|
@@ -1540,6 +1540,132 @@ type WriteMeta = {
|
|
|
1540
1540
|
* consumer code.
|
|
1541
1541
|
*/
|
|
1542
1542
|
readonly crossTab?: boolean;
|
|
1543
|
+
/**
|
|
1544
|
+
* When `true`, this write lands normally (storage, validation,
|
|
1545
|
+
* persistence, history) but does NOT notify `form.onChange` handlers.
|
|
1546
|
+
* The side-channel reacts to user edits, not programmatic rebaselines:
|
|
1547
|
+
* `reset()` tags its replacement with this flag, and the public
|
|
1548
|
+
* `setValue(path, value, { silent: true })` option forwards it so a
|
|
1549
|
+
* consumer hydrating the form (loading a saved record into the fields)
|
|
1550
|
+
* can land values without echoing each one back through an autosave
|
|
1551
|
+
* loop. The store's internal taggers and that single consumer-facing
|
|
1552
|
+
* option are the only writers.
|
|
1553
|
+
*/
|
|
1554
|
+
readonly silent?: boolean;
|
|
1555
|
+
};
|
|
1556
|
+
/** Options for a `setValue` write. */
|
|
1557
|
+
type SetValueOptions = {
|
|
1558
|
+
/**
|
|
1559
|
+
* When `true`, the write lands normally (storage, validation, persistence,
|
|
1560
|
+
* history) but does NOT notify `form.onChange` handlers. Use it to hydrate
|
|
1561
|
+
* the form (load a saved record into the fields) without echoing every
|
|
1562
|
+
* field back through an autosave loop.
|
|
1563
|
+
*/
|
|
1564
|
+
readonly silent?: boolean;
|
|
1565
|
+
};
|
|
1566
|
+
/**
|
|
1567
|
+
* A source address for `form.onChange` — the subtree(s) a handler reacts to.
|
|
1568
|
+
*
|
|
1569
|
+
* - a dotted path string (`'user.email'`) — one leaf or subtree;
|
|
1570
|
+
* - a list of path strings (`['shipping', 'billing']`) — react to any of
|
|
1571
|
+
* several paths; the handler fires once per matched path, `ctx.path`
|
|
1572
|
+
* distinguishing which;
|
|
1573
|
+
* - a getter or ref / computed resolving to either — re-read on each write,
|
|
1574
|
+
* so the aim can follow a moving target (the active list row). Re-aiming
|
|
1575
|
+
* is never itself a trigger; only a real write dispatches.
|
|
1576
|
+
*
|
|
1577
|
+
* Omit the source entirely (`form.onChange(handler)`) to react to the whole
|
|
1578
|
+
* form. An empty list (`form.onChange([], handler)`) lists zero paths, so it
|
|
1579
|
+
* never fires — that is a deliberate no-op, NOT a shorthand for the root.
|
|
1580
|
+
*/
|
|
1581
|
+
type OnChangeSource = MaybeRefOrGetter<string | readonly string[]>;
|
|
1582
|
+
/**
|
|
1583
|
+
* Context handed to an `onChange` handler alongside the changed value.
|
|
1584
|
+
*
|
|
1585
|
+
* `onChange` is a pure side-channel: it reacts to value changes and runs
|
|
1586
|
+
* side effects, but never touches the form's own lifecycle. Nothing a
|
|
1587
|
+
* handler does here marks the form dirty, pending, or validating — autosave
|
|
1588
|
+
* status lives in the consumer's own state, validation in `.refine` and
|
|
1589
|
+
* `field.show*`.
|
|
1590
|
+
*/
|
|
1591
|
+
type OnChangeContext<FormApi = unknown> = {
|
|
1592
|
+
/**
|
|
1593
|
+
* The source path this fire is for, in dotted form (`'user.email'`).
|
|
1594
|
+
* The empty string `''` is the whole form (a root handler). For a
|
|
1595
|
+
* multi-path source, the handler fires once per matched path and `path`
|
|
1596
|
+
* names which one.
|
|
1597
|
+
*/
|
|
1598
|
+
readonly path: string;
|
|
1599
|
+
/**
|
|
1600
|
+
* The value at the source path BEFORE this change, seeded at registration.
|
|
1601
|
+
* Accurate for leaf sources. For a container or the whole form, an
|
|
1602
|
+
* in-place leaf edit preserves the container's reference, so `previous`
|
|
1603
|
+
* can be reference-equal to the current value (Vue's deep-watch gotcha) —
|
|
1604
|
+
* snapshot inside the handler if a true container diff is needed.
|
|
1605
|
+
*/
|
|
1606
|
+
readonly previous: unknown;
|
|
1607
|
+
/**
|
|
1608
|
+
* Aborted when a newer write to the same source supersedes this run. A
|
|
1609
|
+
* debounced or awaiting handler should bail on `signal.aborted` (or pass
|
|
1610
|
+
* `signal` straight to `fetch`) so superseded work cancels itself.
|
|
1611
|
+
*/
|
|
1612
|
+
readonly signal: AbortSignal;
|
|
1613
|
+
/** Retry counter — `0` on the first run, incremented by `onError`'s `retry()`. */
|
|
1614
|
+
readonly attempt: number;
|
|
1615
|
+
/**
|
|
1616
|
+
* The form handle, so a portable `useForm({ onChange })` handler can reach
|
|
1617
|
+
* back into the form (e.g. `ctx.form.validateAsync(ctx.path)` to gate an
|
|
1618
|
+
* autosave on validity). Typed precisely by the `form.onChange` overload.
|
|
1619
|
+
*/
|
|
1620
|
+
readonly form: FormApi;
|
|
1621
|
+
/**
|
|
1622
|
+
* The leaf path(s), in dotted form, that actually changed in this
|
|
1623
|
+
* dispatch. For a leaf source this is just `[path]`; for a container or
|
|
1624
|
+
* the whole form it is every changed descendant.
|
|
1625
|
+
*/
|
|
1626
|
+
readonly changed: readonly string[];
|
|
1627
|
+
};
|
|
1628
|
+
/**
|
|
1629
|
+
* Context handed to an `onChange` handler's `onError` callback when the
|
|
1630
|
+
* handler throws or rejects.
|
|
1631
|
+
*/
|
|
1632
|
+
type OnChangeErrorContext<FormApi = unknown> = {
|
|
1633
|
+
/** The source path this run was for, in dotted form (`''` for the whole form). */
|
|
1634
|
+
readonly path: string;
|
|
1635
|
+
/** The value passed to the handler that failed. */
|
|
1636
|
+
readonly value: unknown;
|
|
1637
|
+
/** The attempt number that failed (`0` on the first run). */
|
|
1638
|
+
readonly attempt: number;
|
|
1639
|
+
/**
|
|
1640
|
+
* Re-run the handler with the same value and `attempt + 1`. A no-op once a
|
|
1641
|
+
* newer write has superseded this run — stale work is never resurrected.
|
|
1642
|
+
* Backoff and a retry cap are the consumer's to impose.
|
|
1643
|
+
*/
|
|
1644
|
+
readonly retry: () => void;
|
|
1645
|
+
/** The form handle. Typed precisely by the `form.onChange` overload. */
|
|
1646
|
+
readonly form: FormApi;
|
|
1647
|
+
};
|
|
1648
|
+
/** A reaction to form value changes. Its return is ignored; throws route to `onError`. */
|
|
1649
|
+
type OnChangeHandler<Value = unknown, FormApi = unknown> = (value: Value, ctx: OnChangeContext<FormApi>) => void | Promise<void>;
|
|
1650
|
+
/** Handles a throw / rejection from an `onChange` handler. Must not throw. */
|
|
1651
|
+
type OnChangeErrorHandler<FormApi = unknown> = (error: unknown, ctx: OnChangeErrorContext<FormApi>) => void;
|
|
1652
|
+
/** Options for `form.onChange`. */
|
|
1653
|
+
type OnChangeOptions<FormApi = unknown> = {
|
|
1654
|
+
/**
|
|
1655
|
+
* Called when the handler throws or its promise rejects. Without it, a
|
|
1656
|
+
* failure is swallowed (logged in dev). `onChange` never throws into the
|
|
1657
|
+
* write that triggered it.
|
|
1658
|
+
*/
|
|
1659
|
+
readonly onError?: OnChangeErrorHandler<FormApi>;
|
|
1660
|
+
};
|
|
1661
|
+
/**
|
|
1662
|
+
* The `useForm({ onChange })` option — a whole-form handler registered at
|
|
1663
|
+
* construction, bound to the form's lifetime. Either a bare handler or a
|
|
1664
|
+
* `{ handler, onError }` pair.
|
|
1665
|
+
*/
|
|
1666
|
+
type OnChangeConfig<Value = unknown, FormApi = unknown> = OnChangeHandler<Value, FormApi> | {
|
|
1667
|
+
readonly handler: OnChangeHandler<Value, FormApi>;
|
|
1668
|
+
readonly onError?: OnChangeErrorHandler<FormApi>;
|
|
1543
1669
|
};
|
|
1544
1670
|
/**
|
|
1545
1671
|
* Undo/redo configuration passed via `useForm({ history })`.
|
|
@@ -1825,6 +1951,17 @@ type UseFormConfiguration<Form extends GenericForm, GetValueFormType, Schema ext
|
|
|
1825
1951
|
* per blur for `<input v-register.lazy>`).
|
|
1826
1952
|
*/
|
|
1827
1953
|
debounceMs?: number;
|
|
1954
|
+
/**
|
|
1955
|
+
* A whole-form `onChange` handler, registered at construction and bound to
|
|
1956
|
+
* the form's lifetime. The same side-channel as `form.onChange(handler)`,
|
|
1957
|
+
* but declared in the options bag so it travels with the form (handy for a
|
|
1958
|
+
* `useAutosave`-style composable). Pass a handler, or `{ handler, onError }`.
|
|
1959
|
+
*
|
|
1960
|
+
* For path-scoped reactions, call `form.onChange('path', handler)` on the
|
|
1961
|
+
* returned form instead. `onChange` never touches the form's own
|
|
1962
|
+
* lifecycle — keep validation in `.refine` and `field.show*`.
|
|
1963
|
+
*/
|
|
1964
|
+
onChange?: OnChangeConfig<Form, UseFormReturnType<Form>>;
|
|
1828
1965
|
/**
|
|
1829
1966
|
* Opt-in persistence of the form's draft state. Off by default —
|
|
1830
1967
|
* with no config, no reads, no writes, no storage code is loaded.
|
|
@@ -4285,8 +4422,11 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4285
4422
|
* type at a leaf). Refinement-level mismatches (out-of-enum
|
|
4286
4423
|
* values, failing format checks, etc.) succeed and surface as
|
|
4287
4424
|
* field errors instead.
|
|
4425
|
+
*
|
|
4426
|
+
* Pass `{ silent: true }` to land the write without notifying
|
|
4427
|
+
* `form.onChange` handlers (e.g. hydrating a saved record).
|
|
4288
4428
|
*/
|
|
4289
|
-
<Value extends SetValuePayload<DefaultValuesShape<Form>, WriteShape<Form>>>(value: Value): boolean;
|
|
4429
|
+
<Value extends SetValuePayload<DefaultValuesShape<Form>, WriteShape<Form>>>(value: Value, options?: SetValueOptions): boolean;
|
|
4290
4430
|
/**
|
|
4291
4431
|
* Write at a specific path. Pass a value or a callback receiving
|
|
4292
4432
|
* the previous value at that path.
|
|
@@ -4304,14 +4444,49 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4304
4444
|
* it blank (storage holds the slim default; UI displays
|
|
4305
4445
|
* empty; submit raises "No value supplied" for required schemas).
|
|
4306
4446
|
*/
|
|
4307
|
-
<Path extends FlatPath<Form>, Value extends PathSetValuePayload<NestedType<Form, Path>>>(path: Path, value: Value): boolean;
|
|
4447
|
+
<Path extends FlatPath<Form>, Value extends PathSetValuePayload<NestedType<Form, Path>>>(path: Path, value: Value, options?: SetValueOptions): boolean;
|
|
4308
4448
|
/**
|
|
4309
4449
|
* Tuple-segment form. Equivalent to the dotted-string overload —
|
|
4310
4450
|
* useful when paths are built from variables or arrays:
|
|
4311
4451
|
* `form.setValue([prefix, 'line1'], 'value')`. The resolved leaf
|
|
4312
4452
|
* type is exact, matching the dotted-string form.
|
|
4313
4453
|
*/
|
|
4314
|
-
<const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never), value: Value): boolean;
|
|
4454
|
+
<const S extends ReadonlyArray<string | number>, Value extends PathSetValuePayload<NestedType<Form, JoinSegments<S>>>>(segments: S & ([JoinSegments<S>] extends [FlatPath<Form>] ? unknown : never), value: Value, options?: SetValueOptions): boolean;
|
|
4455
|
+
};
|
|
4456
|
+
/**
|
|
4457
|
+
* Subscribe to form value changes — the side-channel autosave is built on.
|
|
4458
|
+
* Three call forms:
|
|
4459
|
+
*
|
|
4460
|
+
* - `form.onChange(handler, options?)` — react to the whole form.
|
|
4461
|
+
* - `form.onChange('user.email', handler, options?)` — react to one path;
|
|
4462
|
+
* `value` is that path's value.
|
|
4463
|
+
* - `form.onChange(source, handler, options?)` — react to a list of paths,
|
|
4464
|
+
* or a getter / ref resolving to a path or list (re-read on each write,
|
|
4465
|
+
* so the aim can follow a moving target like the active list row).
|
|
4466
|
+
*
|
|
4467
|
+
* The handler runs AFTER the value lands. Its return is ignored, and a
|
|
4468
|
+
* throw or rejection routes to `options.onError`, never into the write that
|
|
4469
|
+
* triggered it. Returns an idempotent `stop()`; called inside a component's
|
|
4470
|
+
* setup it also stops automatically on unmount.
|
|
4471
|
+
*
|
|
4472
|
+
* `onChange` is a pure side-channel: nothing it does marks the form dirty,
|
|
4473
|
+
* pending, or validating. Keep validation feedback in `.refine` and
|
|
4474
|
+
* `field.show*`, and track autosave status in your own state.
|
|
4475
|
+
*
|
|
4476
|
+
* ```ts
|
|
4477
|
+
* form.onChange('user.email', async (email, ctx) => {
|
|
4478
|
+
* const verdict = await ctx.form.validateAsync(ctx.path)
|
|
4479
|
+
* if (verdict.success) await api.save({ email }, { signal: ctx.signal })
|
|
4480
|
+
* }, { onError: (error, ctx) => ctx.retry() })
|
|
4481
|
+
* ```
|
|
4482
|
+
*/
|
|
4483
|
+
onChange: {
|
|
4484
|
+
/** React to the whole form. `value` is the current form. */
|
|
4485
|
+
(handler: OnChangeHandler<ReadForm, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4486
|
+
/** React to one path. `value` is that path's value. */
|
|
4487
|
+
<P extends FlatPath<Form>>(source: P, handler: OnChangeHandler<NestedType<Form, P>, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4488
|
+
/** React to a list of paths, or a getter / ref / computed. `value` is unknown. */
|
|
4489
|
+
(source: OnChangeSource, handler: OnChangeHandler<unknown, UseFormReturnType<Form, GetValueFormType, ReadForm, K>>, options?: OnChangeOptions<UseFormReturnType<Form, GetValueFormType, ReadForm, K>>): () => void;
|
|
4315
4490
|
};
|
|
4316
4491
|
/**
|
|
4317
4492
|
* Reactive validation status. Re-runs whenever the form (or the
|
|
@@ -4915,5 +5090,5 @@ type UseFormReturnType<Form extends GenericForm, GetValueFormType extends Generi
|
|
|
4915
5090
|
blankPaths: ComputedRef<BlankPathsView>;
|
|
4916
5091
|
};
|
|
4917
5092
|
|
|
4918
|
-
export {
|
|
4919
|
-
export type {
|
|
5093
|
+
export { canonicalizePath as aA, isPathPrefix as aB, isUnset as aC, parseDottedPath as aD, unset as aE, ROOT_PATH as ab, ROOT_PATH_KEY as ac };
|
|
5094
|
+
export type { OnChangeSource as $, AttaformDefaults as A, FormStorage as B, CoercionEntry as C, DefaultValuesInput as D, ErrorsProxyShape as E, FormKey as F, GenericForm as G, FormStorageKind as H, HandleSubmit as I, HistoryConfig as J, IsTuple as K, IsUnion as L, JoinSegments as M, KeyofUnion as N, LiftedValueShape as O, MetaTrackerValue as P, NestedReadType as Q, RegisterModelDynamicCustomDirective as R, NestedType as S, OnChangeConfig as T, UseFormConfiguration as U, ValidationError as V, OnChangeContext as W, OnChangeErrorContext as X, OnChangeErrorHandler as Y, OnChangeHandler as Z, OnChangeOptions as _, AbstractSchema as a, OnError as a0, OnInvalidSubmitPolicy as a1, OnSubmit as a2, PartialFlatPath as a3, Path as a4, PathKey as a5, PendingValidationStatus as a6, PersistConfig as a7, PersistConfigOptions as a8, PersistIncludeMode as a9, SchemaFactoryOptions as aF, TransformAbortHolder as aG, PersistOptInRegistry as aH, Primitive as aa, ReactiveValidationStatus as ad, RegisterDirective as ae, RegisterFlatPath as af, RegisterOptions as ag, RegisterSelectModifier as ah, RegisterTextModifier as ai, RegisterTransform as aj, Segment as ak, SetValueCallback as al, SetValueOptions as am, SetValuePayload as an, SettledValidationStatus as ao, SlimPrimitiveKind as ap, SlimRuntimeOf as aq, SubmitHandler as ar, Unset as as, ValidateOn as at, ValidateOnConfig as au, ValidationResponse as av, ValidationResponseWithoutValue as aw, ValueOfUnion as ax, WriteMeta as ay, WriteShape as az, UseFormReturnType as b, RegisterValue as c, GetDisplayState as d, ApiErrorEnvelope as e, ApiErrorDetails as f, ApiErrorEntry as g, ArrayItem as h, ArrayPath as i, CoercionRegistry as j, CoercionResult as k, CustomDirectiveRegisterAssignerFn as l, DeepPartial as m, DefaultValuesResponse as n, DefaultValuesShape as o, DisplayCtx as p, DisplayMachine as q, DisplayState as r, FieldMetaPayload as s, FieldState as t, FieldStateMap as u, FieldStateMapEntry as v, FlatPath as w, FormErrorRecord as x, FormErrorsSurface as y, FormMeta as z };
|