attaform 0.21.0 → 0.21.2

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.
Files changed (108) hide show
  1. package/dist/chunks/dev-key-collision-warnings.cjs +1 -1
  2. package/dist/chunks/dev-key-collision-warnings.mjs +1 -1
  3. package/dist/chunks/devtools.cjs +1 -1
  4. package/dist/chunks/devtools.mjs +1 -1
  5. package/dist/chunks/fingerprint2.cjs +1 -1
  6. package/dist/chunks/fingerprint2.mjs +1 -1
  7. package/dist/chunks/indexeddb.cjs +1 -1
  8. package/dist/chunks/indexeddb.mjs +1 -1
  9. package/dist/chunks/local-storage.cjs +1 -1
  10. package/dist/chunks/local-storage.mjs +1 -1
  11. package/dist/chunks/multi-tab-sync.cjs +2 -2
  12. package/dist/chunks/multi-tab-sync.mjs +2 -2
  13. package/dist/chunks/session-storage.cjs +1 -1
  14. package/dist/chunks/session-storage.mjs +1 -1
  15. package/dist/chunks/wire-persistence.cjs +2 -2
  16. package/dist/chunks/wire-persistence.mjs +2 -2
  17. package/dist/index.cjs +37 -24
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +31 -28
  20. package/dist/index.d.mts +31 -28
  21. package/dist/index.d.ts +31 -28
  22. package/dist/index.mjs +38 -25
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/nuxt.d.cts +1 -1
  25. package/dist/nuxt.d.mts +1 -1
  26. package/dist/nuxt.d.ts +1 -1
  27. package/dist/runtime/components/AttaformDevtoolsPanel.vue +396 -216
  28. package/dist/runtime/components/DevtoolsValueTree.vue +176 -114
  29. package/dist/runtime/plugins/attaform.cjs +2 -2
  30. package/dist/runtime/plugins/attaform.mjs +2 -2
  31. package/dist/shared/{attaform.BA3vRDos.cjs → attaform.B5LNzqQh.cjs} +349 -277
  32. package/dist/shared/attaform.B5LNzqQh.cjs.map +1 -0
  33. package/dist/shared/{attaform.PnqML3xW.cjs → attaform.BBDIKtKY.cjs} +13 -16
  34. package/dist/shared/attaform.BBDIKtKY.cjs.map +1 -0
  35. package/dist/shared/{attaform.CRsXyy-Y.d.ts → attaform.BCcrLApm.d.mts} +131 -64
  36. package/dist/shared/{attaform.BupwXkj_.mjs → attaform.BFWb6hDk.mjs} +29 -23
  37. package/dist/shared/attaform.BFWb6hDk.mjs.map +1 -0
  38. package/dist/shared/{attaform.7lzO9pdM.d.mts → attaform.BGf_J22U.d.ts} +131 -64
  39. package/dist/shared/{attaform.BnK_bfcb.mjs → attaform.BVeLgfEh.mjs} +14 -17
  40. package/dist/shared/attaform.BVeLgfEh.mjs.map +1 -0
  41. package/dist/shared/{attaform.BK1RE2ha.d.ts → attaform.BYgioWLF.d.ts} +2 -2
  42. package/dist/shared/{attaform.F8LMHHWV.d.cts → attaform.BkjJfMvJ.d.cts} +131 -64
  43. package/dist/shared/{attaform.BDIEq9qP.d.cts → attaform.BoY6RZUl.d.cts} +2 -2
  44. package/dist/shared/{attaform.CEf6wYfD.cjs → attaform.BwLp9KM7.cjs} +2 -2
  45. package/dist/shared/{attaform.CEf6wYfD.cjs.map → attaform.BwLp9KM7.cjs.map} +1 -1
  46. package/dist/shared/{attaform._rsCZy2j.cjs → attaform.BwrowMp2.cjs} +25 -45
  47. package/dist/shared/attaform.BwrowMp2.cjs.map +1 -0
  48. package/dist/shared/{attaform.ezb5Nh2t.mjs → attaform.C41gjp-a.mjs} +2 -2
  49. package/dist/shared/{attaform.ezb5Nh2t.mjs.map → attaform.C41gjp-a.mjs.map} +1 -1
  50. package/dist/shared/{attaform.BM6YD9kZ.cjs → attaform.CR6wGvNu.cjs} +29 -23
  51. package/dist/shared/attaform.CR6wGvNu.cjs.map +1 -0
  52. package/dist/shared/{attaform.DSqO6Db7.mjs → attaform.CTheKoTc.mjs} +705 -282
  53. package/dist/shared/attaform.CTheKoTc.mjs.map +1 -0
  54. package/dist/shared/{attaform.BzvOdiSI.cjs → attaform.CcnF1AKJ.cjs} +4 -4
  55. package/dist/shared/attaform.CcnF1AKJ.cjs.map +1 -0
  56. package/dist/shared/{attaform.BQ6drorq.d.mts → attaform.CnEl--PF.d.mts} +2 -2
  57. package/dist/shared/{attaform.CkjTapyq.mjs → attaform.CrD73S4m.mjs} +4 -4
  58. package/dist/shared/attaform.CrD73S4m.mjs.map +1 -0
  59. package/dist/shared/{attaform.BUszFoKq.cjs → attaform.D2ZuIOCf.cjs} +711 -287
  60. package/dist/shared/attaform.D2ZuIOCf.cjs.map +1 -0
  61. package/dist/shared/{attaform.r3PePkDR.mjs → attaform.D6GYGshL.mjs} +25 -45
  62. package/dist/shared/attaform.D6GYGshL.mjs.map +1 -0
  63. package/dist/shared/{attaform.Y_Mgg0Yp.mjs → attaform.DP-u7_tk.mjs} +348 -277
  64. package/dist/shared/attaform.DP-u7_tk.mjs.map +1 -0
  65. package/dist/shared/{attaform.B1nyO4ec.d.cts → attaform.ory-3WhV.d.cts} +395 -176
  66. package/dist/shared/{attaform.B1nyO4ec.d.mts → attaform.ory-3WhV.d.mts} +395 -176
  67. package/dist/shared/{attaform.B1nyO4ec.d.ts → attaform.ory-3WhV.d.ts} +395 -176
  68. package/dist/transforms.cjs +1 -1
  69. package/dist/transforms.mjs +1 -1
  70. package/dist/vite.cjs +1 -1
  71. package/dist/vite.mjs +1 -1
  72. package/dist/zod-v3.cjs +3 -4
  73. package/dist/zod-v3.cjs.map +1 -1
  74. package/dist/zod-v3.d.cts +4 -4
  75. package/dist/zod-v3.d.mts +4 -4
  76. package/dist/zod-v3.d.ts +4 -4
  77. package/dist/zod-v3.mjs +2 -3
  78. package/dist/zod-v3.mjs.map +1 -1
  79. package/dist/zod-v4.cjs +3 -4
  80. package/dist/zod-v4.cjs.map +1 -1
  81. package/dist/zod-v4.d.cts +4 -4
  82. package/dist/zod-v4.d.mts +4 -4
  83. package/dist/zod-v4.d.ts +4 -4
  84. package/dist/zod-v4.mjs +2 -3
  85. package/dist/zod-v4.mjs.map +1 -1
  86. package/dist/zod.cjs +6 -6
  87. package/dist/zod.cjs.map +1 -1
  88. package/dist/zod.d.cts +77 -26
  89. package/dist/zod.d.mts +77 -26
  90. package/dist/zod.d.ts +77 -26
  91. package/dist/zod.mjs +5 -6
  92. package/dist/zod.mjs.map +1 -1
  93. package/package.json +3 -11
  94. package/dist/shared/attaform.BA3vRDos.cjs.map +0 -1
  95. package/dist/shared/attaform.BM6YD9kZ.cjs.map +0 -1
  96. package/dist/shared/attaform.BUszFoKq.cjs.map +0 -1
  97. package/dist/shared/attaform.BnK_bfcb.mjs.map +0 -1
  98. package/dist/shared/attaform.BupwXkj_.mjs.map +0 -1
  99. package/dist/shared/attaform.BzvOdiSI.cjs.map +0 -1
  100. package/dist/shared/attaform.CkjTapyq.mjs.map +0 -1
  101. package/dist/shared/attaform.DSqO6Db7.mjs.map +0 -1
  102. package/dist/shared/attaform.PnqML3xW.cjs.map +0 -1
  103. package/dist/shared/attaform.Y_Mgg0Yp.mjs.map +0 -1
  104. package/dist/shared/attaform._rsCZy2j.cjs.map +0 -1
  105. package/dist/shared/attaform.r3PePkDR.mjs.map +0 -1
  106. package/dist/shared/{attaform.DSD85fHb.d.cts → attaform.nf83TIR5.d.cts} +10 -10
  107. package/dist/shared/{attaform.DSD85fHb.d.mts → attaform.nf83TIR5.d.mts} +10 -10
  108. package/dist/shared/{attaform.DSD85fHb.d.ts → attaform.nf83TIR5.d.ts} +10 -10
@@ -1,4 +1,4 @@
1
- import { v as FormKey, V as PathKey, m as DisplayCtx, z as GetDisplayState, n as DisplayMachine, ag as SlimPrimitiveKind, C as CoercionEntry, g as CoercionRegistry, G as GenericForm, U as Path, ao as ValidationError, A as AbstractSchema, as as WriteMeta, D as DeepPartial, at as WriteShape, am as ValidateOn, _ as PersistOptInRegistry, f as AttaformDefaults, al as UseFormReturnType, aa as RegisterValue } from './attaform.B1nyO4ec.cjs';
1
+ import { F as FormKey, _ as PathKey, p as DisplayCtx, d as GetDisplayState, q as DisplayMachine, Z as Path, ah as SlimPrimitiveKind, C as CoercionEntry, j as CoercionRegistry, G as GenericForm, V as ValidationError, a as AbstractSchema, aq as WriteMeta, m as DeepPartial, ar as WriteShape, ay as TransformAbortHolder, al as ValidateOn, az as PersistOptInRegistry, A as AttaformDefaults, b as UseFormReturnType, c as RegisterValue } from './attaform.ory-3WhV.cjs';
2
2
  import { Ref, ComputedRef, App, InjectionKey } from 'vue';
3
3
 
4
4
  /**
@@ -414,6 +414,13 @@ type WizardForms<S> = FormsRecordOf<S> & Readonly<Record<FormKey, AnyForm>>;
414
414
  * - `submissionAttempts` — count of `wizard.handleSubmit` invocations
415
415
  * (success or failure). Always bumps, including on
416
416
  * noop-form steps.
417
+ * - `submitError` — the error thrown by the most recent
418
+ * `wizard.handleSubmit` callback (or its `onError`),
419
+ * coerced to a real `Error`. Mirrors
420
+ * `form.meta.submitError`: cleared at submit entry and
421
+ * by `reset()`, parked here rather than re-thrown, so
422
+ * the handler resolves and never manufactures a
423
+ * `window` unhandledrejection. `null` on success.
417
424
  * - `visited` — append-only breadcrumb of navigated step keys.
418
425
  * `back()` does not pop; the trail is the audit
419
426
  * log, not the back-stack.
@@ -447,6 +454,7 @@ type UseWizardReturnType<S extends ReadonlyArray<StepSlot> = ReadonlyArray<StepS
447
454
  readonly done: boolean;
448
455
  readonly submitting: boolean;
449
456
  readonly submissionAttempts: number;
457
+ readonly submitError: Error | null;
450
458
  readonly visited: readonly FormKey[];
451
459
  readonly next: () => Promise<void>;
452
460
  readonly back: () => void;
@@ -517,66 +525,6 @@ type DisplayEngine = {
517
525
  hasTimer(): boolean;
518
526
  };
519
527
 
520
- /**
521
- * Schema-driven coercion of user-typed DOM values at the v-register
522
- * directive layer. When the slim schema declares a numeric or
523
- * boolean type at a path, the directive coerces incoming string
524
- * values (`'25'` → `25`, `'true'` → `true`) before the slim-primitive
525
- * gate sees the write — making the schema authoritative for storage
526
- * shape and freeing consumers from sprinkling `.number` modifiers
527
- * across templates.
528
- *
529
- * Coercion is consumer-extensible: a `CoercionRegistry` is just an
530
- * `Array<CoercionEntry>` keyed at config time by `(input, output)`
531
- * `SlimPrimitiveKind` literals. The library ships
532
- * `defaultCoercionRules` (string→number, string→boolean) and
533
- * `defineCoercion` for type-narrowed authoring; consumers spread the
534
- * defaults to extend or supply their own array to replace.
535
- *
536
- * Coercion applies ONLY to user-typed DOM values flowing through
537
- * the directive's assigner. Programmatic writes (`form.setValue`,
538
- * `setValueWithInternalPath`) bypass coercion — they're authoritative
539
- * writes whose strict typing is on the caller. This mirrors the
540
- * `transforms` pipeline's user-input-only contract.
541
- */
542
-
543
- /**
544
- * Type-narrowing helper for authoring entries. At runtime it's
545
- * identity; at compile time it preserves the `input` / `output`
546
- * literal types so `transform`'s parameter is narrowed to the
547
- * runtime type instead of widening to `SlimRuntimeOf<SlimPrimitiveKind>`.
548
- *
549
- * Without this helper, authoring `{ input: 'string', output:
550
- * 'number', transform: (s) => ... }` against the broader
551
- * `CoercionEntry` widens `s` to `string | number | boolean | ...`,
552
- * forcing a cast in every transform body. `defineCoercion` is the
553
- * opaque-free idiom.
554
- */
555
- declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimitiveKind>(entry: CoercionEntry<I, O>): CoercionEntry<I, O>;
556
- /**
557
- * Internal index built from a `CoercionRegistry` at config-resolve
558
- * time. Keyed by `${input}->${output}` for O(1) per-keystroke
559
- * dispatch. The authoring shape (array, ergonomic, type-narrowing-
560
- * friendly) and the dispatch shape (Map, fast) decouple cleanly.
561
- */
562
- type CoercionIndex = ReadonlyMap<`${SlimPrimitiveKind}->${SlimPrimitiveKind}`, CoercionEntry>;
563
- /**
564
- * The library's built-in registry. Two cells: string→number and
565
- * string→boolean. Re-exported so consumers can spread it when
566
- * supplying a custom registry that extends defaults.
567
- */
568
- declare const defaultCoercionRules: CoercionRegistry;
569
-
570
- /**
571
- * Per-form closure state — the single store owned by each `useForm` call.
572
- * Bundles the form value, the summary record, element references, field
573
- * state, the meta tracker, and the error stores under one keyed-by-
574
- * `(formKey, path)` instance so cross-form DOM state cannot collide.
575
- *
576
- * This is NOT a singleton. Each call to `useForm` creates its own FormStore
577
- * instance and holds onto it via closure. The registry provides SSR
578
- * hydration; otherwise the state is per-component-per-form.
579
- */
580
528
  /**
581
529
  * Per-path field status. Replaced wholesale (not mutated in place) on
582
530
  * every change. Five semantic groups:
@@ -635,6 +583,57 @@ type OriginalsRecord = {
635
583
  readonly segments: Path;
636
584
  readonly value: unknown;
637
585
  };
586
+
587
+ /**
588
+ * Schema-driven coercion of user-typed DOM values at the v-register
589
+ * directive layer. When the slim schema declares a numeric or
590
+ * boolean type at a path, the directive coerces incoming string
591
+ * values (`'25'` → `25`, `'true'` → `true`) before the slim-primitive
592
+ * gate sees the write — making the schema authoritative for storage
593
+ * shape and freeing consumers from sprinkling `.number` modifiers
594
+ * across templates.
595
+ *
596
+ * Coercion is consumer-extensible: a `CoercionRegistry` is just an
597
+ * `Array<CoercionEntry>` keyed at config time by `(input, output)`
598
+ * `SlimPrimitiveKind` literals. The library ships
599
+ * `defaultCoercionRules` (string→number, string→boolean) and
600
+ * `defineCoercion` for type-narrowed authoring; consumers spread the
601
+ * defaults to extend or supply their own array to replace.
602
+ *
603
+ * Coercion applies ONLY to user-typed DOM values flowing through
604
+ * the directive's assigner. Programmatic writes (`form.setValue`,
605
+ * `setValueWithInternalPath`) bypass coercion — they're authoritative
606
+ * writes whose strict typing is on the caller. This mirrors the
607
+ * `transforms` pipeline's user-input-only contract.
608
+ */
609
+
610
+ /**
611
+ * Type-narrowing helper for authoring entries. At runtime it's
612
+ * identity; at compile time it preserves the `input` / `output`
613
+ * literal types so `transform`'s parameter is narrowed to the
614
+ * runtime type instead of widening to `SlimRuntimeOf<SlimPrimitiveKind>`.
615
+ *
616
+ * Without this helper, authoring `{ input: 'string', output:
617
+ * 'number', transform: (s) => ... }` against the broader
618
+ * `CoercionEntry` widens `s` to `string | number | boolean | ...`,
619
+ * forcing a cast in every transform body. `defineCoercion` is the
620
+ * opaque-free idiom.
621
+ */
622
+ declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimitiveKind>(entry: CoercionEntry<I, O>): CoercionEntry<I, O>;
623
+ /**
624
+ * Internal index built from a `CoercionRegistry` at config-resolve
625
+ * time. Keyed by `${input}->${output}` for O(1) per-keystroke
626
+ * dispatch. The authoring shape (array, ergonomic, type-narrowing-
627
+ * friendly) and the dispatch shape (Map, fast) decouple cleanly.
628
+ */
629
+ type CoercionIndex = ReadonlyMap<`${SlimPrimitiveKind}->${SlimPrimitiveKind}`, CoercionEntry>;
630
+ /**
631
+ * The library's built-in registry. Two cells: string→number and
632
+ * string→boolean. Re-exported so consumers can spread it when
633
+ * supplying a custom registry that extends defaults.
634
+ */
635
+ declare const defaultCoercionRules: CoercionRegistry;
636
+
638
637
  type FormStore<F extends GenericForm, G extends GenericForm = F> = {
639
638
  readonly formKey: FormKey;
640
639
  readonly form: Ref<F>;
@@ -751,7 +750,7 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
751
750
  * alongside the rest of the submission surface.
752
751
  */
753
752
  readonly submitted: Ref<boolean>;
754
- readonly submitError: Ref<unknown>;
753
+ readonly submitError: Ref<Error | null>;
755
754
  readonly departAttempts: Ref<number>;
756
755
  /**
757
756
  * `true` while a function-form `defaultValues` factory is in flight.
@@ -932,6 +931,39 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
932
931
  * the computed to both the streak start (set) and end (delete).
933
932
  */
934
933
  readonly fieldValidatingSince: Map<PathKey, number>;
934
+ /**
935
+ * Per-path counter of in-flight async-transform runs (the async
936
+ * branch of the `register({ transforms })` pipeline). `> 0` drives
937
+ * `field.transforming` / `field.busy`. Counter, not flag, for the
938
+ * same overlap reason as `fieldValidationCounts`, except a superseding
939
+ * input releases the prior run synchronously before incrementing the
940
+ * new one — so the count is the live in-flight depth at the path
941
+ * (effectively 0 or 1). Reactive Map, like the validation counters.
942
+ */
943
+ readonly fieldTransformCounts: Map<PathKey, number>;
944
+ /**
945
+ * Per-path `ssr ? 0 : Date.now()` stamp marking when the path's latest
946
+ * async transform opened; the display reducer reads it (as
947
+ * `ctx.transformingSince`) to time the gated busy spinner. Mirrors
948
+ * `fieldValidatingSince` exactly: re-anchored on each run start,
949
+ * deleted on the `→ 0` edge, reactive for the held-spinner reason.
950
+ */
951
+ readonly fieldTransformingSince: Map<PathKey, number>;
952
+ /**
953
+ * Per-path latest async-transform failure (a rejected transform, or a
954
+ * resolved value the write gate refused), surfaced as
955
+ * `field.transformError`. Cleared when a fresh run opens at the path
956
+ * and on `reset()`. A channel separate from validation `errors`.
957
+ */
958
+ readonly transformErrors: Map<PathKey, Error | null>;
959
+ /**
960
+ * Form-wide count of in-flight async-transform runs. Drives the
961
+ * `settleTransforms` quiescence guard and the `handleSubmit` drain
962
+ * barrier. `Math.max(0, …)`-clamped on release so a doubled decrement
963
+ * (a run's own `endTransform` after a synchronous cancel release)
964
+ * can't drive it negative.
965
+ */
966
+ readonly activeTransforms: Ref<number>;
935
967
  /**
936
968
  * Replace the form value wholesale. Optional `meta` is forwarded to
937
969
  * every `onFormChange` listener so they can decide whether THIS write
@@ -1099,6 +1131,41 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
1099
1131
  * at entry (submit validation is authoritative) and by `reset()`.
1100
1132
  */
1101
1133
  cancelFieldValidation(): void;
1134
+ /**
1135
+ * Open an async-transform run at `key` — bump the run token, increment
1136
+ * the in-flight counters, stamp `transformingSince`, clear any prior
1137
+ * `transformError`, register `holder` for later abort. Returns the run
1138
+ * token. See `InternalRegisterValue.beginTransform`.
1139
+ */
1140
+ beginTransform(key: PathKey, holder: TransformAbortHolder): number;
1141
+ /** `true` while `token` is the live async-transform run at `key`. */
1142
+ isCurrentTransform(key: PathKey, token: number): boolean;
1143
+ /**
1144
+ * Close the run `token` at `key`: release the counters (no-op if the
1145
+ * run was already released by a supersede / cancel) and flush settled
1146
+ * `settleTransforms` waiters.
1147
+ */
1148
+ endTransform(key: PathKey, token: number): void;
1149
+ /** Record a per-field normalization failure at `key` (`field.transformError`). */
1150
+ setTransformError(key: PathKey, err: Error): void;
1151
+ /**
1152
+ * Abort + release every in-flight async-transform run (all paths) and
1153
+ * clear `transformErrors`. Mirrors `cancelFieldValidation`; called by
1154
+ * `reset()` and store teardown.
1155
+ */
1156
+ cancelTransforms(): void;
1157
+ /**
1158
+ * Path-scoped counterpart to `cancelTransforms`: abort + release only
1159
+ * the runs at-or-under `prefix`, clearing their `transformError`.
1160
+ * Called by `resetField`.
1161
+ */
1162
+ cancelTransformsUnder(prefix: Path): void;
1163
+ /**
1164
+ * Resolve once async transforms are quiescent — globally (`path`
1165
+ * omitted) or at-or-under `path`. Resolve-never-reject. See
1166
+ * `UseFormReturnType.settleTransforms`.
1167
+ */
1168
+ settleTransforms(path?: string | Path): Promise<void>;
1102
1169
  /**
1103
1170
  * Kick off (or schedule) a field-level validation run for `path`. Pass
1104
1171
  * `path = []` to cover the whole form; `applySchemaErrorsForSubtree`
@@ -1782,5 +1849,5 @@ declare const AttaformErrorCode: {
1782
1849
  };
1783
1850
  type AttaformErrorCode = (typeof AttaformErrorCode)[keyof typeof AttaformErrorCode];
1784
1851
 
1785
- export { AttaformErrorCode as a, createRegistry as p, defaultCoercionRules as q, defineCoercion as r, getRegistryFromApp as s, injectForm as t, injectWizard as u, kAttaformRegistry as v, lazy as w, useRegister as x, useRegistry as y, useWizard as z };
1786
- export type { AnyForm as A, CompiledStep as C, FormStatus as F, InjectWizardInput as I, LazyMarker as L, SSRDetectOptions as S, UseRegisterReturn as U, WizardAggregateError as W, AttaformRegistry as b, SerializedFormData as c, StepSlot as d, UseWizardReturnType as e, WizardCtx as f, WizardCtxForm as g, WizardOnError as h, WizardOnSubmit as i, WizardOptions as j, WizardPersistFn as k, WizardRestoreFn as l, WizardRestoreState as m, WizardStatusesProxy as n, WizardSubmitContext as o };
1852
+ export { AttaformErrorCode as c, createRegistry as p, defaultCoercionRules as q, defineCoercion as r, getRegistryFromApp as s, injectForm as t, injectWizard as u, kAttaformRegistry as v, lazy as w, useRegister as x, useRegistry as y, useWizard as z };
1853
+ export type { AttaformRegistry as A, CompiledStep as C, FormStatus as F, InjectWizardInput as I, LazyMarker as L, SSRDetectOptions as S, UseRegisterReturn as U, WizardAggregateError as W, SerializedFormData as a, AnyForm as b, StepSlot as d, UseWizardReturnType as e, WizardCtx as f, WizardCtxForm as g, WizardOnError as h, WizardOnSubmit as i, WizardOptions as j, WizardPersistFn as k, WizardRestoreFn as l, WizardRestoreState as m, WizardStatusesProxy as n, WizardSubmitContext as o };
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { G as GenericForm, s as FlatPath, P as NestedType, v as FormKey, ak as UseFormConfiguration, A as AbstractSchema, j as DefaultValuesInput, an as ValidateOnConfig, al as UseFormReturnType } from './attaform.B1nyO4ec.cjs';
2
+ import { G as GenericForm, w as FlatPath, S as NestedType, F as FormKey, U as UseFormConfiguration, a as AbstractSchema, D as DefaultValuesInput, am as ValidateOnConfig, b as UseFormReturnType } from './attaform.ory-3WhV.cjs';
3
3
 
4
4
  /**
5
5
  * The shape `form.values.<key>` returns at runtime.
@@ -143,7 +143,7 @@ type PathInput<Schema extends z.ZodType, Path extends string> = z.input<Schema>
143
143
  /**
144
144
  * Type produced at `Path` after the full parse pipeline — the schema's
145
145
  * `z.output<Schema>` shape at that path. Matches the `data` payload of
146
- * `form.process()` and the value handed to `handleSubmit`'s callback.
146
+ * `form.parse()` and the value handed to `handleSubmit`'s callback.
147
147
  *
148
148
  * ```ts
149
149
  * const schema = z.object({
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const paths = require('./attaform.BA3vRDos.cjs');
3
+ const paths = require('./attaform.B5LNzqQh.cjs');
4
4
 
5
5
  function renderAttaformState(app) {
6
6
  const registry = paths.getRegistryFromApp(app);
@@ -36,4 +36,4 @@ const DEVTOOLS_WINDOW_KEY = "__attaform_devtools__";
36
36
  exports.DEVTOOLS_WINDOW_KEY = DEVTOOLS_WINDOW_KEY;
37
37
  exports.hydrateAttaformState = hydrateAttaformState;
38
38
  exports.renderAttaformState = renderAttaformState;
39
- //# sourceMappingURL=attaform.CEf6wYfD.cjs.map
39
+ //# sourceMappingURL=attaform.BwLp9KM7.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"attaform.CEf6wYfD.cjs","sources":["../../src/runtime/core/serialize.ts","../../src/runtime/core/devtools-shared.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormKey } from '../types/types-api'\nimport { pathKeyToDotted, type PathKey } from './paths'\nimport { getRegistryFromApp, type SerializedFormData } from './registry'\n\n/**\n * Serialised snapshot of every form in a Vue app, produced by\n * `renderAttaformState` and consumed by `hydrateAttaformState`.\n *\n * JSON-safe — pass to `JSON.stringify`, `devalue`, or any other\n * serialiser before embedding in your SSR payload.\n */\nexport type SerializedAttaformState = {\n /** Tuples of `[formKey, snapshot]` for every form in the app. */\n readonly forms: ReadonlyArray<readonly [FormKey, SerializedFormData]>\n}\n\n/**\n * Snapshot every form on a Vue app for SSR. Call from your server\n * entry after rendering the app:\n *\n * ```ts\n * import { renderToString } from '@vue/server-renderer'\n * import { renderAttaformState, escapeForInlineScript } from 'attaform'\n *\n * const html = await renderToString(app)\n * const state = renderAttaformState(app)\n * const payload = escapeForInlineScript(JSON.stringify(state))\n *\n * return `\n * ${html}\n * <script>window.__ATTAFORM_STATE__ = ${payload}</script>\n * `\n * ```\n *\n * Pair with `hydrateAttaformState` on the client to restore the\n * forms in their server-rendered state. Nuxt users don't need this —\n * `attaform/nuxt` wires SSR automatically.\n */\nexport function renderAttaformState(app: App): SerializedAttaformState {\n const registry = getRegistryFromApp(app)\n const forms: Array<readonly [FormKey, SerializedFormData]> = []\n for (const [key, state] of registry.forms) {\n // Skip the blank field when the set is empty so the\n // wire payload stays minimal for forms that don't use it. The\n // optional shape on the consuming side handles the absence\n // cleanly (defaults to \"no blank paths\"). PathKey → dotted at\n // the boundary so the wire shape matches the rest of the\n // public path notation.\n const transientList: string[] = []\n for (const pk of state.blankPaths) {\n const d = pathKeyToDotted(pk as PathKey)\n if (d !== null) transientList.push(d)\n }\n forms.push([\n key,\n {\n form: state.form.value,\n schemaErrors: Array.from(state.schemaErrors.entries()),\n userErrors: Array.from(state.userErrors.entries()),\n fields: Array.from(state.fields.entries()),\n ...(transientList.length > 0 ? { blankPaths: transientList } : {}),\n },\n ])\n }\n return { forms }\n}\n\n/**\n * Restore forms from a server-rendered snapshot on the client. Call\n * from your client entry before mounting:\n *\n * ```ts\n * import { createApp } from 'vue'\n * import { createAttaform, hydrateAttaformState } from 'attaform'\n *\n * const app = createApp(App).use(createAttaform())\n * hydrateAttaformState(app, window.__ATTAFORM_STATE__)\n * app.mount('#app')\n * ```\n *\n * The next `useForm({ key })` call for each serialised form picks up\n * the snapshot transparently — no further action is required.\n */\nexport function hydrateAttaformState(app: App, payload: SerializedAttaformState): void {\n const registry = getRegistryFromApp(app)\n for (const [key, data] of payload.forms) {\n registry.pendingHydration.set(key, data)\n }\n}\n","/**\n * Shared building blocks for Attaform's two devtools surfaces — the Vue\n * DevTools (Chrome-extension) inspector wired up in `./devtools.ts`, and\n * the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +\n * `../pages/_attaform_devtools.vue`.\n *\n * Houses the window-bridge contract both surfaces consume so a new\n * bridge field lands in one file. Both surfaces render RAW form values\n * by design — DevTools is a dev-only surface, and redaction across every\n * place a value surfaces is impractical security theater rather than a\n * real safeguard.\n */\nimport type { AttaformRegistry } from './registry'\n\n/**\n * Property key on `window` that the Nuxt-side dev plugin attaches the\n * bridge object to. The iframe-mounted overlay panel reads\n * `window.parent[DEVTOOLS_WINDOW_KEY]` to reach the host app's registry.\n *\n * Underscored + namespaced to make accidental collision with consumer\n * globals vanishingly unlikely. Stable across versions — bumping it\n * would silently disconnect older library builds from newer overlay\n * panels in the same browser tab during a library upgrade.\n */\nexport const DEVTOOLS_WINDOW_KEY = '__attaform_devtools__'\n\n/**\n * Shape of the object the host plugin attaches to `window` in dev mode.\n * The iframe overlay panel reads this to discover the live registry and\n * render its forms.\n *\n * Single-registry assumption: the latest `createAttaform()` install\n * wins. Multi-app pages (rare; typically only seen in micro-frontend\n * setups) will only see one app's forms in the panel. Documented but\n * not actively supported — the alternative (a Set of registries with\n * union-rendering) is a future call if a real consumer hits it.\n */\nexport interface AttaformDevtoolsBridge {\n registry: AttaformRegistry\n /**\n * The library version, surfaced in the panel's footer for support /\n * bug-report context. Read from `package.json` at host-plugin init.\n */\n version: string\n}\n\ndeclare global {\n interface Window {\n [DEVTOOLS_WINDOW_KEY]?: AttaformDevtoolsBridge\n }\n}\n"],"names":["getRegistryFromApp","pathKeyToDotted"],"mappings":";;;;AAuCO,SAAS,oBAAoB,GAAA,EAAmC;AACrE,EAAA,MAAM,QAAA,GAAWA,yBAAmB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,SAAS,KAAA,EAAO;AAOzC,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,EAAA,IAAM,MAAM,UAAA,EAAY;AACjC,MAAA,MAAM,CAAA,GAAIC,sBAAgB,EAAa,CAAA;AACvC,MAAA,IAAI,CAAA,KAAM,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA;AAAA,IACtC;AACA,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAM,IAAA,CAAK,KAAA;AAAA,QACjB,cAAc,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA;AAAA,QACrD,YAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAAA,QACjD,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAAA,QACzC,GAAI,cAAc,MAAA,GAAS,CAAA,GAAI,EAAE,UAAA,EAAY,aAAA,KAAkB;AAAC;AAClE,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAkBO,SAAS,oBAAA,CAAqB,KAAU,OAAA,EAAwC;AACrF,EAAA,MAAM,QAAA,GAAWD,yBAAmB,GAAG,CAAA;AACvC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,QAAQ,KAAA,EAAO;AACvC,IAAA,QAAA,CAAS,gBAAA,CAAiB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,EACzC;AACF;;ACjEO,MAAM,mBAAA,GAAsB;;;;;;"}
1
+ {"version":3,"file":"attaform.BwLp9KM7.cjs","sources":["../../src/runtime/core/serialize.ts","../../src/runtime/core/devtools-shared.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormKey } from '../types/types-api'\nimport { pathKeyToDotted, type PathKey } from './paths'\nimport { getRegistryFromApp, type SerializedFormData } from './registry'\n\n/**\n * Serialised snapshot of every form in a Vue app, produced by\n * `renderAttaformState` and consumed by `hydrateAttaformState`.\n *\n * JSON-safe — pass to `JSON.stringify`, `devalue`, or any other\n * serialiser before embedding in your SSR payload.\n */\nexport type SerializedAttaformState = {\n /** Tuples of `[formKey, snapshot]` for every form in the app. */\n readonly forms: ReadonlyArray<readonly [FormKey, SerializedFormData]>\n}\n\n/**\n * Snapshot every form on a Vue app for SSR. Call from your server\n * entry after rendering the app:\n *\n * ```ts\n * import { renderToString } from '@vue/server-renderer'\n * import { renderAttaformState, escapeForInlineScript } from 'attaform'\n *\n * const html = await renderToString(app)\n * const state = renderAttaformState(app)\n * const payload = escapeForInlineScript(JSON.stringify(state))\n *\n * return `\n * ${html}\n * <script>window.__ATTAFORM_STATE__ = ${payload}</script>\n * `\n * ```\n *\n * Pair with `hydrateAttaformState` on the client to restore the\n * forms in their server-rendered state. Nuxt users don't need this —\n * `attaform/nuxt` wires SSR automatically.\n */\nexport function renderAttaformState(app: App): SerializedAttaformState {\n const registry = getRegistryFromApp(app)\n const forms: Array<readonly [FormKey, SerializedFormData]> = []\n for (const [key, state] of registry.forms) {\n // Skip the blank field when the set is empty so the\n // wire payload stays minimal for forms that don't use it. The\n // optional shape on the consuming side handles the absence\n // cleanly (defaults to \"no blank paths\"). PathKey → dotted at\n // the boundary so the wire shape matches the rest of the\n // public path notation.\n const transientList: string[] = []\n for (const pk of state.blankPaths) {\n const d = pathKeyToDotted(pk as PathKey)\n if (d !== null) transientList.push(d)\n }\n forms.push([\n key,\n {\n form: state.form.value,\n schemaErrors: Array.from(state.schemaErrors.entries()),\n userErrors: Array.from(state.userErrors.entries()),\n fields: Array.from(state.fields.entries()),\n ...(transientList.length > 0 ? { blankPaths: transientList } : {}),\n },\n ])\n }\n return { forms }\n}\n\n/**\n * Restore forms from a server-rendered snapshot on the client. Call\n * from your client entry before mounting:\n *\n * ```ts\n * import { createApp } from 'vue'\n * import { createAttaform, hydrateAttaformState } from 'attaform'\n *\n * const app = createApp(App).use(createAttaform())\n * hydrateAttaformState(app, window.__ATTAFORM_STATE__)\n * app.mount('#app')\n * ```\n *\n * The next `useForm({ key })` call for each serialised form picks up\n * the snapshot transparently — no further action is required.\n */\nexport function hydrateAttaformState(app: App, payload: SerializedAttaformState): void {\n const registry = getRegistryFromApp(app)\n for (const [key, data] of payload.forms) {\n registry.pendingHydration.set(key, data)\n }\n}\n","/**\n * Shared building blocks for Attaform's two devtools surfaces — the Vue\n * DevTools (Chrome-extension) inspector wired up in `./devtools.ts`, and\n * the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +\n * `../pages/_attaform_devtools.vue`.\n *\n * Houses the window-bridge contract both surfaces consume so a new\n * bridge field lands in one file. Both surfaces render RAW form values\n * by design — DevTools is a dev-only surface, and redaction across every\n * place a value surfaces is impractical security theater rather than a\n * real safeguard.\n */\nimport type { AttaformRegistry } from './registry'\n\n/**\n * Property key on `window` that the Nuxt-side dev plugin attaches the\n * bridge object to. The iframe-mounted overlay panel reads\n * `window.parent[DEVTOOLS_WINDOW_KEY]` to reach the host app's registry.\n *\n * Underscored + namespaced to make accidental collision with consumer\n * globals vanishingly unlikely. Stable across versions — bumping it\n * would silently disconnect older library builds from newer overlay\n * panels in the same browser tab during a library upgrade.\n */\nexport const DEVTOOLS_WINDOW_KEY = '__attaform_devtools__'\n\n/**\n * Shape of the object the host plugin attaches to `window` in dev mode.\n * The iframe overlay panel reads this to discover the live registry and\n * render its forms.\n *\n * Single-registry assumption: the latest `createAttaform()` install\n * wins. Multi-app pages (rare; typically only seen in micro-frontend\n * setups) will only see one app's forms in the panel. Documented but\n * not actively supported — the alternative (a Set of registries with\n * union-rendering) is a future call if a real consumer hits it.\n */\nexport interface AttaformDevtoolsBridge {\n registry: AttaformRegistry\n /**\n * The library version, surfaced in the panel's footer for support /\n * bug-report context. Read from `package.json` at host-plugin init.\n */\n version: string\n}\n\ndeclare global {\n interface Window {\n [DEVTOOLS_WINDOW_KEY]?: AttaformDevtoolsBridge\n }\n}\n"],"names":["getRegistryFromApp","pathKeyToDotted"],"mappings":";;;;AAuCO,SAAS,oBAAoB,GAAA,EAAmC;AACrE,EAAA,MAAM,QAAA,GAAWA,yBAAmB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,SAAS,KAAA,EAAO;AAOzC,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,EAAA,IAAM,MAAM,UAAA,EAAY;AACjC,MAAA,MAAM,CAAA,GAAIC,sBAAgB,EAAa,CAAA;AACvC,MAAA,IAAI,CAAA,KAAM,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA;AAAA,IACtC;AACA,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAM,IAAA,CAAK,KAAA;AAAA,QACjB,cAAc,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA;AAAA,QACrD,YAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAAA,QACjD,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAAA,QACzC,GAAI,cAAc,MAAA,GAAS,CAAA,GAAI,EAAE,UAAA,EAAY,aAAA,KAAkB;AAAC;AAClE,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAkBO,SAAS,oBAAA,CAAqB,KAAU,OAAA,EAAwC;AACrF,EAAA,MAAM,QAAA,GAAWD,yBAAmB,GAAG,CAAA;AACvC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,QAAQ,KAAA,EAAO;AACvC,IAAA,QAAA,CAAS,gBAAA,CAAiB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,EACzC;AACF;;ACjEO,MAAM,mBAAA,GAAsB;;;;;;"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const injectWizard = require('./attaform.BUszFoKq.cjs');
4
- const paths = require('./attaform.BA3vRDos.cjs');
3
+ const injectWizard = require('./attaform.D2ZuIOCf.cjs');
4
+ const paths = require('./attaform.B5LNzqQh.cjs');
5
5
 
6
6
  const PATH_SEPARATOR = ".";
7
7
  function createAbstractSchema(rootSchema, intro, services, formKey, options) {
@@ -92,6 +92,12 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
92
92
  if (kind === "array") return null;
93
93
  return void 0;
94
94
  },
95
+ isFixedObjectAtPath(path) {
96
+ if (path.length === 0) return true;
97
+ const resolved = services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
98
+ if (resolved.length === 0) return false;
99
+ return resolved.every((s) => intro.kindOf(services.peelAllWrappers(s)) === "object");
100
+ },
95
101
  getSchemasAtPath(path) {
96
102
  const resolved = services.getNestedSchemasInSlimMode(rootSchema, path, maxRecursionDepth);
97
103
  if (resolved.length === 0) return [];
@@ -163,35 +169,25 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
163
169
  }
164
170
  }
165
171
  return runAsync();
172
+ function parseResultToResponse(result) {
173
+ return result.success ? { data: result.data, errors: void 0, success: true, formKey } : {
174
+ data: void 0,
175
+ errors: services.issuesToValidationErrors(result.issues, formKey),
176
+ success: false,
177
+ formKey
178
+ };
179
+ }
166
180
  function runSync() {
167
181
  if (path === void 0) {
168
- const result = services.safeParseSync(rootSchema, data);
169
- return result.success ? {
170
- data: result.data,
171
- errors: void 0,
172
- success: true,
173
- formKey
174
- } : {
175
- data: void 0,
176
- errors: services.issuesToValidationErrors(result.issues, formKey),
177
- success: false,
178
- formKey
179
- };
182
+ return parseResultToResponse(services.safeParseSync(rootSchema, data));
180
183
  }
181
184
  const resolved = services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
182
185
  if (resolved.length === 0) return pathNotFound(path);
183
186
  const aggregated = [];
184
187
  for (const candidate of resolved) {
185
- const result = services.safeParseSync(candidate, data);
186
- if (result.success) {
187
- return {
188
- data: result.data,
189
- errors: void 0,
190
- success: true,
191
- formKey
192
- };
193
- }
194
- aggregated.push(...services.issuesToValidationErrors(result.issues, formKey));
188
+ const response = parseResultToResponse(services.safeParseSync(candidate, data));
189
+ if (response.success) return response;
190
+ aggregated.push(...response.errors);
195
191
  }
196
192
  return { data: void 0, errors: aggregated, success: false, formKey };
197
193
  }
@@ -203,17 +199,7 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
203
199
  } catch (err) {
204
200
  return validatorThrewResponse(err, []);
205
201
  }
206
- return result.success ? {
207
- data: result.data,
208
- errors: void 0,
209
- success: true,
210
- formKey
211
- } : {
212
- data: void 0,
213
- errors: services.issuesToValidationErrors(result.issues, formKey),
214
- success: false,
215
- formKey
216
- };
202
+ return parseResultToResponse(result);
217
203
  }
218
204
  const resolved = services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
219
205
  if (resolved.length === 0) return pathNotFound(path);
@@ -225,15 +211,9 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
225
211
  } catch (err) {
226
212
  return validatorThrewResponse(err, path);
227
213
  }
228
- if (result.success) {
229
- return {
230
- data: result.data,
231
- errors: void 0,
232
- success: true,
233
- formKey
234
- };
235
- }
236
- aggregated.push(...services.issuesToValidationErrors(result.issues, formKey));
214
+ const response = parseResultToResponse(result);
215
+ if (response.success) return response;
216
+ aggregated.push(...response.errors);
237
217
  }
238
218
  return { data: void 0, errors: aggregated, success: false, formKey };
239
219
  }
@@ -934,4 +914,4 @@ exports.mergeDeep = mergeDeep;
934
914
  exports.peelEmbeddedDefault = peelEmbeddedDefault;
935
915
  exports.slimPrimitivesWalk = slimPrimitivesWalk;
936
916
  exports.walkPathSegments = walkPathSegments;
937
- //# sourceMappingURL=attaform._rsCZy2j.cjs.map
917
+ //# sourceMappingURL=attaform.BwrowMp2.cjs.map