attaform 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abstract.d.mts +5 -5
- package/dist/abstract.mjs +4 -4
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/dev-key-collision-warnings.mjs +47 -8
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +1 -2
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +3 -3
- package/dist/dev/shared/{attaform-dev.BO-71R54.mjs → attaform-dev.BK6Ge2qR.mjs} +34 -188
- package/dist/dev/shared/{attaform-dev.A-TpJW0B.mjs → attaform-dev.BQc5QV3Y.mjs} +1 -19
- package/dist/dev/shared/{attaform-dev.DrzObAZo.mjs → attaform-dev.BcNtyOmf.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.ButTkwHd.mjs → attaform-dev.BcYT6tFh.mjs} +7 -8
- package/dist/dev/shared/{attaform-dev.BgM6FdtA.mjs → attaform-dev.BisFstxh.mjs} +91 -59
- package/dist/dev/shared/{attaform-dev.DHuydLAC.mjs → attaform-dev.CQ2rJiAX.mjs} +560 -631
- package/dist/dev/shared/{attaform-dev.D8aoKb89.mjs → attaform-dev.D6CLvaQT.mjs} +8 -8
- package/dist/dev/shared/{attaform-dev.q6UutkCx.mjs → attaform-dev.DTrHonpc.mjs} +69 -120
- package/dist/dev/shared/{attaform-dev.DD5m2W51.mjs → attaform-dev.DUZckyV8.mjs} +1 -3
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +2 -2
- package/dist/directive.mjs +1 -1
- package/dist/history.d.mts +1 -1
- package/dist/history.mjs +1 -2
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.mts +2 -11
- package/dist/nuxt.mjs +0 -1
- package/dist/runtime/plugins/attaform.mjs +3 -3
- package/dist/shared/{attaform.DffRL5pP.mjs → attaform.B3resMQ1.mjs} +8 -8
- package/dist/shared/{attaform.Cvao8bW5.mjs → attaform.BRDDQeHV.mjs} +6 -6
- package/dist/shared/{attaform.C2MVyuxC.mjs → attaform.BXneBxEj.mjs} +34 -188
- package/dist/shared/{attaform.BndjUUYX.mjs → attaform.ByWP6kSx.mjs} +4 -4
- package/dist/shared/{attaform.D1fnTifF.mjs → attaform.CJ8DpRGj.mjs} +69 -120
- package/dist/shared/{attaform.B0dKL8ST.mjs → attaform.CUfrMK7t.mjs} +91 -59
- package/dist/shared/{attaform.CZYt_5N_.mjs → attaform.CdZIEf7_.mjs} +1 -19
- package/dist/shared/{attaform.axHXVQO7.d.mts → attaform.Clz0ArIi.d.mts} +1 -1
- package/dist/shared/{attaform.CZMAYwSK.mjs → attaform.DNJOWjQw.mjs} +559 -588
- package/dist/shared/{attaform.CIWLMY-R.d.mts → attaform.Rc9u4Vfw.d.mts} +1 -1
- package/dist/shared/{attaform.DDtqHYv1.d.mts → attaform.UGyOK83T.d.mts} +115 -214
- package/dist/shared/{attaform.D0x-qSXm.mjs → attaform.WiGdIqgx.mjs} +1 -3
- package/dist/shared/{attaform.CsoeRi3P.d.mts → attaform.bKLzMU0o.d.mts} +99 -493
- package/dist/vite.mjs +5 -0
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +9 -9
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +3 -2
- package/skills/attaform/SKILL.md +1 -1
- package/skills/attaform/references/custom-components.md +1 -1
- package/dist/chunks/fingerprint.mjs +0 -183
- package/dist/chunks/fingerprint2.mjs +0 -159
- package/dist/dev/chunks/fingerprint.mjs +0 -183
- package/dist/dev/chunks/fingerprint2.mjs +0 -159
- package/dist/dev/shared/attaform-dev.BxfsuwBR.mjs +0 -44
- package/dist/shared/attaform.BxfsuwBR.mjs +0 -44
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { G as GenericForm,
|
|
2
|
+
import { G as GenericForm, l as FlatPath, s as NestedType, F as FormKey, U as UseFormConfiguration, A as AbstractSchema, aq as AcceptableDefaults, ac as ValidateOnConfig, a as UseFormReturnType } from './attaform.bKLzMU0o.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The Zod v4 schema roots `useForm` accepts. A fixed-shape
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GenericForm, F as FormKey, a as UseFormReturnType,
|
|
1
|
+
import { G as GenericForm, F as FormKey, a as UseFormReturnType, _ as RegisterValue, v as Path, w as PathKey, ar as DisplayCtx, as as GetDisplayState, at as DisplayMachine, au as FieldRecord, av as ErrorCell, ad as ValidationError, aw as OriginalsRecord, A as AbstractSchema, ah as WriteMeta, d as DeepPartial, ai as WriteShape, ax as AttaformDomBinding, ay as TransformAbortHolder } from './attaform.bKLzMU0o.mjs';
|
|
2
2
|
import { Ref, ComputedRef, ShallowRef, App, InjectionKey, Plugin } from 'vue';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -208,9 +208,26 @@ type UseRegisterOptions = {
|
|
|
208
208
|
};
|
|
209
209
|
declare function useRegister<V = unknown>(options?: UseRegisterOptions): UseRegisterReturn<V> | undefined;
|
|
210
210
|
|
|
211
|
+
type DynamicPathSweep = {
|
|
212
|
+
/**
|
|
213
|
+
* Note that a cache has just stored an entry for `segments` under
|
|
214
|
+
* `key`. Paths a schema shape bounds are ignored, so only the
|
|
215
|
+
* candidates the sweep could ever drop are walked.
|
|
216
|
+
*/
|
|
217
|
+
readonly track: (segments: Path, key: PathKey) => void;
|
|
218
|
+
/**
|
|
219
|
+
* Register a cache's own eviction. It receives the canonical
|
|
220
|
+
* `PathKey` of a path the form no longer has, and deletes whatever it
|
|
221
|
+
* files under that path. A cache keying by more than the path (a
|
|
222
|
+
* shape sigil, say) deletes every variant; a key it never held is a
|
|
223
|
+
* no-op.
|
|
224
|
+
*/
|
|
225
|
+
readonly onEvict: (evict: (key: PathKey) => void) => void;
|
|
226
|
+
};
|
|
227
|
+
|
|
211
228
|
/**
|
|
212
|
-
* Per-form display engine: owns the clock and the timers
|
|
213
|
-
*
|
|
229
|
+
* Per-form display engine: owns the clock and the timers the display
|
|
230
|
+
* reducer's timing policy needs, so the reducer itself stays a
|
|
214
231
|
* deterministic `(prev, ctx) => next` function.
|
|
215
232
|
*
|
|
216
233
|
* It keeps a `Map` of the machines that are still *active* (a spinner is
|
|
@@ -229,15 +246,15 @@ declare function useRegister<V = unknown>(options?: UseRegisterOptions): UseRegi
|
|
|
229
246
|
* retained set is bounded by the rendered non-idle fields; none of them
|
|
230
247
|
* arm a timer, so retention costs memory, never CPU.
|
|
231
248
|
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
249
|
+
* `setTimeout` invariants on the returned `reviewAt`, enforced here rather
|
|
250
|
+
* than trusted from the reducer. A non-finite deadline is ignored rather
|
|
251
|
+
* than handed to `setTimeout`, where it coerces to 0 and spins; an over-large
|
|
252
|
+
* finite deadline is clamped below the 32-bit `setTimeout` overflow; and the
|
|
253
|
+
* timer refuses to re-arm for a deadline it just fired that has also already
|
|
254
|
+
* passed. The last of those is not belt-and-braces: the library reducer's own
|
|
255
|
+
* min-visible hold re-emits ONE fixed instant for the length of the window,
|
|
256
|
+
* which is exactly the shape that stranded a field on `'pending'` forever (see
|
|
257
|
+
* `rearm`).
|
|
241
258
|
*
|
|
242
259
|
* Background tabs: `setTimeout` is throttled to >= 1s while a tab is hidden,
|
|
243
260
|
* so a min-visible hold can overshoot. A `visibilitychange` listener bumps
|
|
@@ -271,56 +288,64 @@ type DisplayEngine = {
|
|
|
271
288
|
};
|
|
272
289
|
|
|
273
290
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* `
|
|
292
|
-
*
|
|
293
|
-
* `
|
|
291
|
+
* The error stores, indexed by path prefix.
|
|
292
|
+
*
|
|
293
|
+
* `aggregateErrorsAt(state, prefix)` answers "every active error at or
|
|
294
|
+
* under this path", and it used to answer it by walking every entry in
|
|
295
|
+
* all three error stores, resolving each key back to segments and
|
|
296
|
+
* testing the prefix. That is fine for one call. A table asks for one
|
|
297
|
+
* per row: `form.list('rows')` on 400 rows with 800 errors did 320,000
|
|
298
|
+
* of those tests, and a keystroke in any single row re-did all of them,
|
|
299
|
+
* costing a quarter of a second per character typed.
|
|
300
|
+
*
|
|
301
|
+
* The cost is structural, not incidental: the work is O(rows x errors)
|
|
302
|
+
* where the answer is O(errors). So the keys are collected ONCE per
|
|
303
|
+
* change to the stores, resolved to segments once, and sorted, and a
|
|
304
|
+
* query binary-searches its own window instead of scanning.
|
|
305
|
+
*
|
|
306
|
+
* ## Why a sorted key array is the right index
|
|
307
|
+
*
|
|
308
|
+
* A `PathKey` is `JSON.stringify(segments)`, so a path's descendants
|
|
309
|
+
* all begin with the parent's key minus its closing bracket, plus a
|
|
310
|
+
* comma: every key under `["rows",0]` begins `["rows",0,`. Call that
|
|
311
|
+
* the marker. Two facts make a sorted array enough:
|
|
312
|
+
*
|
|
313
|
+
* - every descendant key is >= the marker, since it begins with it;
|
|
314
|
+
* - every descendant key is <= the parent's own key, since the two
|
|
315
|
+
* agree up to the last character, where `,` (0x2C) sorts before
|
|
316
|
+
* `]` (0x5D).
|
|
317
|
+
*
|
|
318
|
+
* So `[marker, parentKey]` is a contiguous window containing every
|
|
319
|
+
* descendant and the parent itself. It is a SUPERSET, not an exact
|
|
320
|
+
* answer, and the caller still applies `isPathPrefix` to what comes
|
|
321
|
+
* back: the window narrows the scan, it does not decide membership.
|
|
322
|
+
* That split is deliberate. Membership stays where it already was, so
|
|
323
|
+
* the encoding argument above cannot quietly become the definition of
|
|
324
|
+
* a prefix.
|
|
325
|
+
*
|
|
326
|
+
* The root prefix has no marker (`[]` minus its bracket plus a comma is
|
|
327
|
+
* `[,`, which nothing begins with), and the root matches everything
|
|
328
|
+
* anyway, so it is answered by handing back the whole index.
|
|
294
329
|
*/
|
|
295
330
|
|
|
296
|
-
/**
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
*
|
|
302
|
-
* Without this helper, authoring `{ input: 'string', output:
|
|
303
|
-
* 'number', transform: (s) => ... }` against the broader
|
|
304
|
-
* `CoercionEntry` widens `s` to `string | number | boolean | ...`,
|
|
305
|
-
* forcing a cast in every transform body. `defineCoercion` is the
|
|
306
|
-
* opaque-free idiom.
|
|
307
|
-
*/
|
|
308
|
-
declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimitiveKind>(entry: CoercionEntry<I, O>): CoercionEntry<I, O>;
|
|
309
|
-
/**
|
|
310
|
-
* Internal index built from a `CoercionRegistry` at config-resolve
|
|
311
|
-
* time. Keyed by `${input}->${output}` for O(1) per-keystroke
|
|
312
|
-
* dispatch. The authoring shape (array, ergonomic, type-narrowing-
|
|
313
|
-
* friendly) and the dispatch shape (Map, fast) decouple cleanly.
|
|
314
|
-
*/
|
|
315
|
-
type CoercionIndex = ReadonlyMap<`${SlimPrimitiveKind}->${SlimPrimitiveKind}`, CoercionEntry>;
|
|
316
|
-
/**
|
|
317
|
-
* The library's built-in registry. Two cells: string→number and
|
|
318
|
-
* string→boolean. Re-exported so consumers can spread it when
|
|
319
|
-
* supplying a custom registry that extends defaults.
|
|
320
|
-
*/
|
|
321
|
-
declare const defaultCoercionRules: CoercionRegistry;
|
|
331
|
+
/** One indexed path: its key, and the segments that key decodes to. */
|
|
332
|
+
type ErrorPathEntry = {
|
|
333
|
+
readonly key: PathKey;
|
|
334
|
+
readonly segments: Path;
|
|
335
|
+
};
|
|
322
336
|
|
|
323
337
|
type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
338
|
+
/**
|
|
339
|
+
* The form's single liveness sweep over every per-path cache. Owned by
|
|
340
|
+
* the store rather than by `buildFormApi` because the store's own
|
|
341
|
+
* per-path maps (`fields`, `originals`, `authoredPaths`,
|
|
342
|
+
* `fieldValidationState`) are the largest thing it evicts, and they
|
|
343
|
+
* exist whether or not a form API was ever built around them. Read
|
|
344
|
+
* surfaces register their own evictions into it, so one subscription
|
|
345
|
+
* and one liveness walk serve all of them. See
|
|
346
|
+
* `dynamic-path-sweep.ts`.
|
|
347
|
+
*/
|
|
348
|
+
readonly pathSweep: DynamicPathSweep;
|
|
324
349
|
readonly formKey: FormKey;
|
|
325
350
|
readonly form: Ref<F>;
|
|
326
351
|
readonly fields: Map<PathKey, FieldRecord>;
|
|
@@ -359,6 +384,22 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
359
384
|
* sentinel — see `docs/validation/blank.md`.
|
|
360
385
|
*/
|
|
361
386
|
readonly derivedBlankErrors: ComputedRef<ReadonlyMap<PathKey, ValidationError[]>>;
|
|
387
|
+
/**
|
|
388
|
+
* Every path carrying an error at or under `prefix`, sorted by key.
|
|
389
|
+
* `aggregateErrorsAt` takes its candidates from here instead of
|
|
390
|
+
* re-scanning all three error stores per call, which is what turns a
|
|
391
|
+
* table of N rows from O(N x errors) back into O(errors). See
|
|
392
|
+
* `error-path-index.ts`.
|
|
393
|
+
*
|
|
394
|
+
* Reading this rather than the form-global index is also what keeps
|
|
395
|
+
* containers isolated from each other. The index is one value for the
|
|
396
|
+
* whole form, so any path gaining or losing an error gives it a new
|
|
397
|
+
* identity; a container reading it directly woke on every other
|
|
398
|
+
* container's errors. Each prefix gets its own memoised `computed`
|
|
399
|
+
* that holds its previous array when its own window is unchanged, so
|
|
400
|
+
* the global change stops there. See `errorWindowAt` in the store.
|
|
401
|
+
*/
|
|
402
|
+
readonly errorWindowAt: (prefix: Path, prefixKey: PathKey) => readonly ErrorPathEntry[];
|
|
362
403
|
readonly originals: Map<PathKey, OriginalsRecord>;
|
|
363
404
|
/**
|
|
364
405
|
* Reactive set of paths whose displayed state should be EMPTY even
|
|
@@ -408,18 +449,9 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
408
449
|
* the eventual directive lifecycle remains the source of truth.
|
|
409
450
|
*/
|
|
410
451
|
readonly ssr: boolean;
|
|
411
|
-
/**
|
|
412
|
-
* Resolved `getDisplayState` predicate driving `field.displayState`,
|
|
413
|
-
* the `show*` booleans, and their `form.meta` rollups. Resolved once
|
|
414
|
-
* at construction via `resolveGetDisplayState(options.getDisplayState)`;
|
|
415
|
-
* `undefined` config falls through to `defaultDisplayState`. The
|
|
416
|
-
* field-state computeds read the resolved function directly on every
|
|
417
|
-
* read.
|
|
418
|
-
*/
|
|
419
|
-
readonly getDisplayState: GetDisplayState;
|
|
420
452
|
/**
|
|
421
453
|
* Per-form display engine: owns the clock and the single timer the timed
|
|
422
|
-
*
|
|
454
|
+
* display-reducer policy needs, keeping the reducer itself a
|
|
423
455
|
* pure `(prev, ctx) => next` function. The field-state computeds route
|
|
424
456
|
* every `displayState` read through `displayEngine.resolve(...)`, which
|
|
425
457
|
* threads the path's previous machine, persists or evicts the result, and
|
|
@@ -570,26 +602,10 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
570
602
|
* run yet — so without the gate, frame 1 paints the form as
|
|
571
603
|
* "valid" before the real verdict arrives a tick later.
|
|
572
604
|
*
|
|
573
|
-
* Initialized to `!strict`: non-strict consumers opt out of the
|
|
574
|
-
* validation pipeline by design, so locking them on
|
|
575
|
-
* `firstValidationDone === false` would defeat the opt-out.
|
|
576
605
|
* Reset is left untouched — the post-reset validation flips it
|
|
577
606
|
* back true on completion, same as the construction-time path.
|
|
578
607
|
*/
|
|
579
608
|
readonly firstValidationDone: Ref<boolean>;
|
|
580
|
-
/**
|
|
581
|
-
* `true` when the sub-schema rooted at `path` (or any of its
|
|
582
|
-
* descendants) declares async work — composes
|
|
583
|
-
* `schema.getSchemasAtPath(path)` with each candidate's
|
|
584
|
-
* `needsAsyncValidation()`, memoised per canonical path key for
|
|
585
|
-
* the lifetime of the FormStore. Used by `meta.valid` /
|
|
586
|
-
* `field.valid` to skip the `firstValidationDone` gate on subtrees
|
|
587
|
-
* that are fully synchronous: their verdict resolves at construction
|
|
588
|
-
* (or on the next per-field run) without waiting on a microtask, so
|
|
589
|
-
* honouring the form-wide gate would just play dumb about a known
|
|
590
|
-
* answer.
|
|
591
|
-
*/
|
|
592
|
-
pathHasAsyncValidation(path: Path): boolean;
|
|
593
609
|
/**
|
|
594
610
|
* Precomputed-key shortcut for `pathHasAsyncValidation`. The
|
|
595
611
|
* canonical key is required and must correspond to `segments`; the
|
|
@@ -809,17 +825,6 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
809
825
|
* source there).
|
|
810
826
|
*/
|
|
811
827
|
markConnectedOptimistically(path: Path): void;
|
|
812
|
-
/**
|
|
813
|
-
* Leaf-only pristine check. `originals` is populated via
|
|
814
|
-
* `diffAndApply`'s `added` patches, which fire only on primitive
|
|
815
|
-
* leaves — a container path (e.g. `['profile']`) that isn't in
|
|
816
|
-
* `originals` returns `true` here even when a descendant is dirty.
|
|
817
|
-
* Callers that need container semantics should either loop over
|
|
818
|
-
* leaves or walk `originals` manually. The public `getFieldState`
|
|
819
|
-
* surface is typed to accept leaf paths only, so in practice this
|
|
820
|
-
* isn't exposed to consumers.
|
|
821
|
-
*/
|
|
822
|
-
isPristineAtPath(path: Path): boolean;
|
|
823
828
|
/**
|
|
824
829
|
* Precomputed-key shortcut for `isPristineAtPath`. The canonical
|
|
825
830
|
* key is required and must correspond to `segments`; the helper
|
|
@@ -846,7 +851,6 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
846
851
|
*/
|
|
847
852
|
hasRemovedSubtreeUnder(path: Path): boolean;
|
|
848
853
|
getFieldRecord(path: Path): FieldRecord | undefined;
|
|
849
|
-
getOriginalAtPath(path: Path): unknown;
|
|
850
854
|
/**
|
|
851
855
|
* Cancel every in-flight field-level validation run — clears timers
|
|
852
856
|
* for debounced 'change' runs that haven't fired, latches `aborted`
|
|
@@ -871,12 +875,6 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
871
875
|
endTransform(key: PathKey, token: number): void;
|
|
872
876
|
/** Record a per-field normalization failure at `key` (`field.transformError`). */
|
|
873
877
|
setTransformError(key: PathKey, err: Error): void;
|
|
874
|
-
/**
|
|
875
|
-
* Abort + release every in-flight async-transform run (all paths) and
|
|
876
|
-
* clear `transformErrors`. Mirrors `cancelFieldValidation`; called by
|
|
877
|
-
* `reset()` and store teardown.
|
|
878
|
-
*/
|
|
879
|
-
cancelTransforms(): void;
|
|
880
878
|
/**
|
|
881
879
|
* Path-scoped counterpart to `cancelTransforms`: abort + release only
|
|
882
880
|
* the runs at-or-under `prefix`, clearing their `transformError`.
|
|
@@ -907,10 +905,7 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
907
905
|
* store's captured `debounceMs`. Used so sibling instances sharing a
|
|
908
906
|
* FormStore can each validate on their own cadence.
|
|
909
907
|
*/
|
|
910
|
-
scheduleFieldValidation(path: Path, immediate: boolean,
|
|
911
|
-
readonly mode?: ValidateOn;
|
|
912
|
-
readonly debounceMs?: number;
|
|
913
|
-
}): void;
|
|
908
|
+
scheduleFieldValidation(path: Path, immediate: boolean, instance?: WriteMeta['instance']): void;
|
|
914
909
|
/**
|
|
915
910
|
* Subscribe to every `applyFormReplacement`. Fires synchronously
|
|
916
911
|
* after `form.value` has been swapped to `next` and all field /
|
|
@@ -957,14 +952,12 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
957
952
|
*/
|
|
958
953
|
readonly modules: Map<string, unknown>;
|
|
959
954
|
/**
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
* by `buildCoerceFn` to bake the per-path coerce closure on
|
|
965
|
-
* `RegisterValue.coerce`.
|
|
955
|
+
* Whether schema-driven coercion runs for this form — `false` only
|
|
956
|
+
* when the consumer passed `useForm({ coerce: false })`. Read at
|
|
957
|
+
* `register()` time by `buildCoerceFn` to bake the per-path coerce
|
|
958
|
+
* closure on `RegisterValue.coerce`.
|
|
966
959
|
*/
|
|
967
|
-
readonly
|
|
960
|
+
readonly coerceEnabled: boolean;
|
|
968
961
|
/**
|
|
969
962
|
* Tear down non-reactive resources owned by this FormStore. Invoked
|
|
970
963
|
* by the registry when the last consumer unmounts. Cancels pending
|
|
@@ -1354,8 +1347,8 @@ type WizardOptions = {
|
|
|
1354
1347
|
/**
|
|
1355
1348
|
* When `wizard.handleSubmit` finds errors, automatically focus the
|
|
1356
1349
|
* first failing form: jump to its step and invoke its
|
|
1357
|
-
* `applyInvalidSubmitPolicy()` (
|
|
1358
|
-
* `
|
|
1350
|
+
* `applyInvalidSubmitPolicy()` (which honors that form's own
|
|
1351
|
+
* `focusOnInvalidSubmit` choice). Default `true`; pass `false` to
|
|
1359
1352
|
* keep the active step where the user left it and handle navigation
|
|
1360
1353
|
* manually in the `onError` callback.
|
|
1361
1354
|
*/
|
|
@@ -1730,8 +1723,6 @@ type AttaformRegistry = {
|
|
|
1730
1723
|
readonly pendingHydration: PendingHydration;
|
|
1731
1724
|
/** `true` while running on the server during SSR; `false` on the client. */
|
|
1732
1725
|
readonly ssr: boolean;
|
|
1733
|
-
/** App-level defaults applied to every `useForm` call. */
|
|
1734
|
-
readonly defaults: AttaformDefaults;
|
|
1735
1726
|
/**
|
|
1736
1727
|
* Track a consumer of `key`. Returns a dispose function — call it
|
|
1737
1728
|
* when the consumer unmounts. The form is evicted automatically
|
|
@@ -1787,13 +1778,7 @@ declare module 'vue' {
|
|
|
1787
1778
|
}
|
|
1788
1779
|
}
|
|
1789
1780
|
/** Options for `createRegistry`. */
|
|
1790
|
-
type CreateRegistryOptions = SSRDetectOptions
|
|
1791
|
-
/**
|
|
1792
|
-
* App-level defaults applied to every `useForm` call. Per-form
|
|
1793
|
-
* options always win. Omitted is equivalent to `{}`.
|
|
1794
|
-
*/
|
|
1795
|
-
defaults?: AttaformDefaults;
|
|
1796
|
-
};
|
|
1781
|
+
type CreateRegistryOptions = SSRDetectOptions;
|
|
1797
1782
|
/**
|
|
1798
1783
|
* Create a fresh `AttaformRegistry`. `createAttaform()` calls
|
|
1799
1784
|
* this internally — most consumers never need to call it directly.
|
|
@@ -2099,34 +2084,20 @@ type AttaformPluginOptions = SSRDetectOptions & {
|
|
|
2099
2084
|
* fails silently. Pass `false` to skip the integration even in dev.
|
|
2100
2085
|
*/
|
|
2101
2086
|
devtools?: boolean;
|
|
2102
|
-
/**
|
|
2103
|
-
* App-level defaults applied to every `useForm` call in this app.
|
|
2104
|
-
* Per-form options always win. See `AttaformDefaults` for
|
|
2105
|
-
* the supported option set and the merge rules.
|
|
2106
|
-
*
|
|
2107
|
-
* ```ts
|
|
2108
|
-
* app.use(
|
|
2109
|
-
* createAttaform({
|
|
2110
|
-
* defaults: { debounceMs: 100 },
|
|
2111
|
-
* })
|
|
2112
|
-
* )
|
|
2113
|
-
* ```
|
|
2114
|
-
*/
|
|
2115
|
-
defaults?: AttaformDefaults;
|
|
2116
2087
|
};
|
|
2117
2088
|
/**
|
|
2118
2089
|
* Create the Vue plugin that installs the form library on a Vue
|
|
2119
2090
|
* application. Required only when you want app-wide options
|
|
2120
|
-
* (`
|
|
2121
|
-
*
|
|
2122
|
-
*
|
|
2091
|
+
* (`devtools: false`, `ssr: true`) — for the default setup,
|
|
2092
|
+
* `useForm` / `injectForm` / `useRegister` lazy-install the registry
|
|
2093
|
+
* on first use.
|
|
2123
2094
|
*
|
|
2124
2095
|
* ```ts
|
|
2125
2096
|
* import { createApp } from 'vue'
|
|
2126
2097
|
* import { createAttaform } from 'attaform'
|
|
2127
2098
|
*
|
|
2128
2099
|
* createApp(App)
|
|
2129
|
-
* .use(createAttaform({
|
|
2100
|
+
* .use(createAttaform({ devtools: false }))
|
|
2130
2101
|
* .mount('#app')
|
|
2131
2102
|
* ```
|
|
2132
2103
|
*
|
|
@@ -2391,75 +2362,5 @@ declare class ReservedFormKeyError extends AttaformError {
|
|
|
2391
2362
|
constructor(key: string);
|
|
2392
2363
|
}
|
|
2393
2364
|
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
*
|
|
2397
|
-
* - `showDelay` — how long in-flight work (a validation run or an async
|
|
2398
|
-
* register transform) may run before its spinner is allowed to show. Work
|
|
2399
|
-
* that settles inside this window never reveals `'pending'` at all, so a
|
|
2400
|
-
* fast (often synchronous) check does not flash a spinner on every keystroke.
|
|
2401
|
-
* - `minVisible` — once shown, the minimum time the spinner stays up. Work
|
|
2402
|
-
* that lands just past `showDelay` is held here so the spinner does not
|
|
2403
|
-
* itself flash on and immediately off.
|
|
2404
|
-
*
|
|
2405
|
-
* Both are milliseconds.
|
|
2406
|
-
*/
|
|
2407
|
-
type DisplayTimings = {
|
|
2408
|
-
readonly showDelay: number;
|
|
2409
|
-
readonly minVisible: number;
|
|
2410
|
-
};
|
|
2411
|
-
/**
|
|
2412
|
-
* Library-default anti-flash timings. `showDelay: 120` cleanly swallows
|
|
2413
|
-
* synchronous, microtask-resolved, and tiny-async work (validation runs and
|
|
2414
|
-
* async register transforms alike) so none of them flash a spinner;
|
|
2415
|
-
* `minVisible: 120` keeps a shown spinner snappy once one does land.
|
|
2416
|
-
* Retune via {@link makeDefaultDisplayState} without touching the engine.
|
|
2417
|
-
*/
|
|
2418
|
-
declare const DEFAULT_TIMINGS: DisplayTimings;
|
|
2419
|
-
/**
|
|
2420
|
-
* Build a default `getDisplayState` reducer with custom anti-flash timing.
|
|
2421
|
-
* Power users who want a tighter or looser spinner than {@link DEFAULT_TIMINGS}
|
|
2422
|
-
* pass their own `{ showDelay, minVisible }`:
|
|
2423
|
-
*
|
|
2424
|
-
* ```ts
|
|
2425
|
-
* import { makeDefaultDisplayState } from 'attaform'
|
|
2426
|
-
*
|
|
2427
|
-
* useForm({
|
|
2428
|
-
* schema,
|
|
2429
|
-
* getDisplayState: makeDefaultDisplayState({ showDelay: 50, minVisible: 200 }),
|
|
2430
|
-
* })
|
|
2431
|
-
* ```
|
|
2432
|
-
*
|
|
2433
|
-
* The returned reducer is pure: the engine injects `now` and threads the
|
|
2434
|
-
* previous machine, so the same `(prev, ctx)` always yields the same next
|
|
2435
|
-
* machine. It shapes only the display projection — `errors`, `valid`,
|
|
2436
|
-
* `validating`, and the underlying validation run exactly as before.
|
|
2437
|
-
*/
|
|
2438
|
-
declare function makeDefaultDisplayState({ showDelay, minVisible, }: DisplayTimings): GetDisplayState;
|
|
2439
|
-
/**
|
|
2440
|
-
* Library-default `getDisplayState` reducer. Resolves every path's
|
|
2441
|
-
* `field.displayState` — and thus `field.show*` and the `form.meta`
|
|
2442
|
-
* rollups — whenever the consumer has not configured an override at the
|
|
2443
|
-
* per-form or plugin level. Built from {@link DEFAULT_TIMINGS}; publicly
|
|
2444
|
-
* re-exported so an override can compose with it (a layered reducer that
|
|
2445
|
-
* special-cases a subtree but otherwise defers picks up future
|
|
2446
|
-
* refinements for free):
|
|
2447
|
-
*
|
|
2448
|
-
* ```ts
|
|
2449
|
-
* import { defaultDisplayState } from 'attaform'
|
|
2450
|
-
*
|
|
2451
|
-
* useForm({
|
|
2452
|
-
* schema,
|
|
2453
|
-
* getDisplayState: (prev, ctx) => {
|
|
2454
|
-
* const next = defaultDisplayState(prev, ctx)
|
|
2455
|
-
* return next.display === 'success' && ctx.field.path[0] === 'username'
|
|
2456
|
-
* ? { display: 'idle' }
|
|
2457
|
-
* : next
|
|
2458
|
-
* },
|
|
2459
|
-
* })
|
|
2460
|
-
* ```
|
|
2461
|
-
*/
|
|
2462
|
-
declare const defaultDisplayState: GetDisplayState;
|
|
2463
|
-
|
|
2464
|
-
export { makeDefaultDisplayState as $, assignKey as B, DEFAULT_TIMINGS as D, createAttaform as E, createRegistry as H, defaultCoercionRules as J, defaultDisplayState as K, defineCoercion as M, escapeForInlineScript as N, OutsideSetupError as O, gate as P, getRegistryFromApp as Q, RegistryNotInstalledError as R, hydrateAttaformState as T, injectForm as V, injectWizard as X, isRegisterValue as Y, kAttaformRegistry as Z, lazy as _, renderAttaformState as a0, useRegister as a1, useRegistry as a2, useWizard as a3, AttaformError as c, AttaformErrorCode as d, DEVTOOLS_WINDOW_KEY as f, InvalidPathError as i, InvalidUseFormConfigError as j, ReservedFormKeyError as k, SubmitErrorHandlerError as n };
|
|
2465
|
-
export type { AttaformRegistry as A, CompiledStep as C, FormStatus as F, GateMarker as G, InjectWizardInput as I, LazyMarker as L, SerializedAttaformState as S, UseRegisterOptions as U, WizardAggregateError as W, AnyForm as a, AttaformDevtoolsBridge as b, AttaformPluginOptions as e, DisplayTimings as g, FormStatusSeed as h, SerializedFormData as l, StepSlot as m, UseRegisterReturn as o, UseWizardReturnType as p, WizardCtx as q, WizardCtxForm as r, WizardOnError as s, WizardOnSubmit as t, WizardOptions as u, WizardPersistFn as v, WizardRestoreFn as w, WizardRestoreState as x, WizardStatusesProxy as y, WizardSubmitContext as z };
|
|
2365
|
+
export { createRegistry as B, DEVTOOLS_WINDOW_KEY as D, escapeForInlineScript as E, gate as H, getRegistryFromApp as J, hydrateAttaformState as K, injectForm as M, injectWizard as N, OutsideSetupError as O, isRegisterValue as P, kAttaformRegistry as Q, RegistryNotInstalledError as R, lazy as T, renderAttaformState as V, useRegister as X, useRegistry as Y, useWizard as Z, AttaformError as c, AttaformErrorCode as d, InvalidPathError as g, InvalidUseFormConfigError as h, ReservedFormKeyError as i, SubmitErrorHandlerError as l, assignKey as y, createAttaform as z };
|
|
2366
|
+
export type { AttaformRegistry as A, CompiledStep as C, FormStatus as F, GateMarker as G, InjectWizardInput as I, LazyMarker as L, SerializedAttaformState as S, UseRegisterOptions as U, WizardAggregateError as W, AnyForm as a, AttaformDevtoolsBridge as b, AttaformPluginOptions as e, FormStatusSeed as f, SerializedFormData as j, StepSlot as k, UseRegisterReturn as m, UseWizardReturnType as n, WizardCtx as o, WizardCtxForm as p, WizardOnError as q, WizardOnSubmit as r, WizardOptions as s, WizardPersistFn as t, WizardRestoreFn as u, WizardRestoreState as v, WizardStatusesProxy as w, WizardSubmitContext as x };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as RegistryNotInstalledError, O as OutsideSetupError, g as pathKeyToDotted } from './attaform.
|
|
1
|
+
import { c as RegistryNotInstalledError, O as OutsideSetupError, g as pathKeyToDotted } from './attaform.CdZIEf7_.mjs';
|
|
2
2
|
import { shallowReactive, getCurrentInstance, inject } from 'vue';
|
|
3
3
|
|
|
4
4
|
function detectSSR(options = {}) {
|
|
@@ -17,7 +17,6 @@ const kFormContext = /* @__PURE__ */ Symbol.for("attaform:form-context");
|
|
|
17
17
|
const kFormInstanceId = /* @__PURE__ */ Symbol.for("attaform:form-instance-id");
|
|
18
18
|
function createRegistry(options = {}) {
|
|
19
19
|
const ssr = detectSSR(options);
|
|
20
|
-
const defaults = Object.freeze({ ...options.defaults ?? {} });
|
|
21
20
|
const forms = shallowReactive(/* @__PURE__ */ new Map());
|
|
22
21
|
const wizards = shallowReactive(/* @__PURE__ */ new Map());
|
|
23
22
|
const pendingHydration = shallowReactive(/* @__PURE__ */ new Map());
|
|
@@ -102,7 +101,6 @@ function createRegistry(options = {}) {
|
|
|
102
101
|
wizards,
|
|
103
102
|
pendingHydration,
|
|
104
103
|
ssr,
|
|
105
|
-
defaults,
|
|
106
104
|
trackConsumer,
|
|
107
105
|
trackWizardConsumer,
|
|
108
106
|
enqueuePrefetch,
|