attaform 0.25.0 → 0.27.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.
Files changed (163) hide show
  1. package/README.md +21 -11
  2. package/bin/attaform.mjs +78 -0
  3. package/dist/abstract.cjs +47 -0
  4. package/dist/abstract.cjs.map +1 -0
  5. package/dist/abstract.d.cts +42 -0
  6. package/dist/abstract.d.mts +42 -0
  7. package/dist/abstract.d.ts +42 -0
  8. package/dist/abstract.mjs +4 -0
  9. package/dist/abstract.mjs.map +1 -0
  10. package/dist/chunks/devtools.cjs +2 -2
  11. package/dist/chunks/devtools.cjs.map +1 -1
  12. package/dist/chunks/devtools.mjs +1 -1
  13. package/dist/chunks/fingerprint2.cjs +1 -1
  14. package/dist/chunks/fingerprint2.mjs +1 -1
  15. package/dist/esbuild.cjs +2 -2
  16. package/dist/esbuild.cjs.map +1 -1
  17. package/dist/esbuild.d.cts +3 -3
  18. package/dist/esbuild.d.mts +3 -3
  19. package/dist/esbuild.d.ts +3 -3
  20. package/dist/esbuild.mjs +2 -2
  21. package/dist/esbuild.mjs.map +1 -1
  22. package/dist/index.cjs +41 -56
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +194 -282
  25. package/dist/index.d.mts +194 -282
  26. package/dist/index.d.ts +194 -282
  27. package/dist/index.mjs +4 -25
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/nuxt.cjs +3 -1
  30. package/dist/nuxt.cjs.map +1 -1
  31. package/dist/nuxt.d.cts +17 -4
  32. package/dist/nuxt.d.mts +17 -4
  33. package/dist/nuxt.d.ts +17 -4
  34. package/dist/nuxt.mjs +4 -2
  35. package/dist/nuxt.mjs.map +1 -1
  36. package/dist/rollup.cjs +2 -2
  37. package/dist/rollup.cjs.map +1 -1
  38. package/dist/rollup.d.cts +3 -3
  39. package/dist/rollup.d.mts +3 -3
  40. package/dist/rollup.d.ts +3 -3
  41. package/dist/rollup.mjs +2 -2
  42. package/dist/rollup.mjs.map +1 -1
  43. package/dist/rspack.cjs +1 -1
  44. package/dist/rspack.d.cts +1 -1
  45. package/dist/rspack.d.mts +1 -1
  46. package/dist/rspack.d.ts +1 -1
  47. package/dist/rspack.mjs +1 -1
  48. package/dist/runtime/plugins/attaform.cjs +4 -5
  49. package/dist/runtime/plugins/attaform.cjs.map +1 -1
  50. package/dist/runtime/plugins/attaform.mjs +1 -2
  51. package/dist/runtime/plugins/attaform.mjs.map +1 -1
  52. package/dist/shared/{attaform.BRzKBj2g.cjs → attaform.8tFZu1Ub.cjs} +2 -2
  53. package/dist/shared/{attaform.BRzKBj2g.cjs.map → attaform.8tFZu1Ub.cjs.map} +1 -1
  54. package/dist/shared/{attaform.k9V0py0s.mjs → attaform.BERt5YMU.mjs} +2 -2
  55. package/dist/shared/{attaform.k9V0py0s.mjs.map → attaform.BERt5YMU.mjs.map} +1 -1
  56. package/dist/shared/{attaform.CN4ZEGo6.mjs → attaform.BceJrhQ7.mjs} +5 -5
  57. package/dist/shared/{attaform.CN4ZEGo6.mjs.map → attaform.BceJrhQ7.mjs.map} +1 -1
  58. package/dist/shared/{attaform.i_LA3X9o.d.cts → attaform.C3WnCDXz.d.cts} +81 -24
  59. package/dist/shared/{attaform.i_LA3X9o.d.ts → attaform.C3WnCDXz.d.mts} +81 -24
  60. package/dist/shared/{attaform.i_LA3X9o.d.mts → attaform.C3WnCDXz.d.ts} +81 -24
  61. package/dist/shared/{attaform.DuzQYscR.d.ts → attaform.C9fPTxjB.d.cts} +5 -5
  62. package/dist/shared/{attaform.DuzQYscR.d.cts → attaform.C9fPTxjB.d.mts} +5 -5
  63. package/dist/shared/{attaform.DuzQYscR.d.mts → attaform.C9fPTxjB.d.ts} +5 -5
  64. package/dist/shared/{attaform.B3cgZE3c.d.ts → attaform.CC_y1_Ej.d.ts} +33 -33
  65. package/dist/shared/{attaform.DS_zBcdr.d.ts → attaform.CEXUlUkc.d.ts} +1588 -1190
  66. package/dist/shared/{attaform.Xe8dATED.cjs → attaform.C__F01CE.cjs} +15 -15
  67. package/dist/shared/{attaform.Xe8dATED.cjs.map → attaform.C__F01CE.cjs.map} +1 -1
  68. package/dist/shared/{attaform.3heDHayA.cjs → attaform.Co5LNRnv.cjs} +186 -129
  69. package/dist/shared/attaform.Co5LNRnv.cjs.map +1 -0
  70. package/dist/shared/{attaform.BJt4ZCkM.d.mts → attaform.CpXHK60W.d.cts} +33 -33
  71. package/dist/shared/{attaform.DmKLa4tL.d.cts → attaform.CvVYOvZF.d.mts} +33 -33
  72. package/dist/shared/{attaform.DK3xUBkj.mjs → attaform.CyQxTOdX.mjs} +162 -79
  73. package/dist/shared/attaform.CyQxTOdX.mjs.map +1 -0
  74. package/dist/shared/{attaform.B5GFS3Su.d.cts → attaform.D99pd7JG.d.cts} +1588 -1190
  75. package/dist/shared/{attaform.CwXXbZIQ.mjs → attaform.DDAmSFnl.mjs} +4 -4
  76. package/dist/shared/{attaform.CwXXbZIQ.mjs.map → attaform.DDAmSFnl.mjs.map} +1 -1
  77. package/dist/shared/{attaform.BkUzunyB.cjs → attaform.DQT7_-FO.cjs} +371 -287
  78. package/dist/shared/attaform.DQT7_-FO.cjs.map +1 -0
  79. package/dist/shared/{attaform.CqwcTExO.mjs → attaform.Da8EdI2t.mjs} +182 -129
  80. package/dist/shared/attaform.Da8EdI2t.mjs.map +1 -0
  81. package/dist/shared/{attaform.sks1MFVO.cjs → attaform.DhVgG2jh.cjs} +16 -16
  82. package/dist/shared/{attaform.sks1MFVO.cjs.map → attaform.DhVgG2jh.cjs.map} +1 -1
  83. package/dist/shared/{attaform.sHkHv_98.mjs → attaform.DhnPb6nK.mjs} +6 -3
  84. package/dist/shared/attaform.DhnPb6nK.mjs.map +1 -0
  85. package/dist/shared/attaform.DkD0DR7R.mjs +42 -0
  86. package/dist/shared/attaform.DkD0DR7R.mjs.map +1 -0
  87. package/dist/shared/{attaform.DMNnfQq_.mjs → attaform.DlSu08F5.mjs} +4 -4
  88. package/dist/shared/{attaform.DMNnfQq_.mjs.map → attaform.DlSu08F5.mjs.map} +1 -1
  89. package/dist/shared/{attaform.LEWUFqUw.cjs → attaform.DoQm_Vkd.cjs} +7 -3
  90. package/dist/shared/attaform.DoQm_Vkd.cjs.map +1 -0
  91. package/dist/shared/{attaform.B5YcWrKi.cjs → attaform.Drsi43GG.cjs} +19 -19
  92. package/dist/shared/{attaform.B5YcWrKi.cjs.map → attaform.Drsi43GG.cjs.map} +1 -1
  93. package/dist/shared/attaform.K6Thc6By.cjs +46 -0
  94. package/dist/shared/attaform.K6Thc6By.cjs.map +1 -0
  95. package/dist/shared/{attaform.Vp2-CWZB.mjs → attaform.KvlEedlF.mjs} +3 -3
  96. package/dist/shared/{attaform.Vp2-CWZB.mjs.map → attaform.KvlEedlF.mjs.map} +1 -1
  97. package/dist/shared/{attaform.BRGIpZo4.cjs → attaform.RaTzp1WF.cjs} +3 -3
  98. package/dist/shared/attaform.RaTzp1WF.cjs.map +1 -0
  99. package/dist/shared/{attaform.8vmdOURQ.d.mts → attaform.kBkYlKP_.d.mts} +1588 -1190
  100. package/dist/shared/{attaform.C3Doa9Pt.mjs → attaform.v0fQtWyA.mjs} +3 -3
  101. package/dist/shared/attaform.v0fQtWyA.mjs.map +1 -0
  102. package/dist/shared/{attaform.ZXZ6dH72.cjs → attaform.yUrz7C2z.cjs} +3 -3
  103. package/dist/shared/{attaform.ZXZ6dH72.cjs.map → attaform.yUrz7C2z.cjs.map} +1 -1
  104. package/dist/transforms.cjs +1 -1
  105. package/dist/transforms.mjs +1 -1
  106. package/dist/vite.cjs +21 -3
  107. package/dist/vite.cjs.map +1 -1
  108. package/dist/vite.d.cts +70 -17
  109. package/dist/vite.d.mts +70 -17
  110. package/dist/vite.d.ts +70 -17
  111. package/dist/vite.mjs +20 -4
  112. package/dist/vite.mjs.map +1 -1
  113. package/dist/webpack.cjs +1 -1
  114. package/dist/webpack.d.cts +1 -1
  115. package/dist/webpack.d.mts +1 -1
  116. package/dist/webpack.d.ts +1 -1
  117. package/dist/webpack.mjs +1 -1
  118. package/dist/zod-v3.cjs +41 -10
  119. package/dist/zod-v3.cjs.map +1 -1
  120. package/dist/zod-v3.d.cts +5 -5
  121. package/dist/zod-v3.d.mts +5 -5
  122. package/dist/zod-v3.d.ts +5 -5
  123. package/dist/zod-v3.mjs +4 -2
  124. package/dist/zod-v3.mjs.map +1 -1
  125. package/dist/zod-v4.cjs +41 -10
  126. package/dist/zod-v4.cjs.map +1 -1
  127. package/dist/zod-v4.d.cts +7 -7
  128. package/dist/zod-v4.d.mts +7 -7
  129. package/dist/zod-v4.d.ts +7 -7
  130. package/dist/zod-v4.mjs +4 -2
  131. package/dist/zod-v4.mjs.map +1 -1
  132. package/dist/zod.cjs +44 -49
  133. package/dist/zod.cjs.map +1 -1
  134. package/dist/zod.d.cts +6 -248
  135. package/dist/zod.d.mts +6 -248
  136. package/dist/zod.d.ts +6 -248
  137. package/dist/zod.mjs +4 -42
  138. package/dist/zod.mjs.map +1 -1
  139. package/package.json +12 -2
  140. package/skills/attaform/SKILL.md +128 -0
  141. package/skills/attaform/references/custom-components.md +72 -0
  142. package/skills/attaform/references/errors.md +62 -0
  143. package/skills/attaform/references/ssr.md +26 -0
  144. package/skills/attaform/references/validation.md +40 -0
  145. package/skills/attaform/references/wizards.md +104 -0
  146. package/dist/shared/attaform.3heDHayA.cjs.map +0 -1
  147. package/dist/shared/attaform.BRGIpZo4.cjs.map +0 -1
  148. package/dist/shared/attaform.BkUzunyB.cjs.map +0 -1
  149. package/dist/shared/attaform.C3Doa9Pt.mjs.map +0 -1
  150. package/dist/shared/attaform.CO0e7YVY.d.cts +0 -94
  151. package/dist/shared/attaform.CO0e7YVY.d.mts +0 -94
  152. package/dist/shared/attaform.CO0e7YVY.d.ts +0 -94
  153. package/dist/shared/attaform.CqwcTExO.mjs.map +0 -1
  154. package/dist/shared/attaform.DK3xUBkj.mjs.map +0 -1
  155. package/dist/shared/attaform.LEWUFqUw.cjs.map +0 -1
  156. package/dist/shared/attaform.OLtKd9gM.mjs +0 -35
  157. package/dist/shared/attaform.OLtKd9gM.mjs.map +0 -1
  158. package/dist/shared/attaform.sHkHv_98.mjs.map +0 -1
  159. package/dist/shared/attaform.xBDo0Ko0.cjs +0 -39
  160. package/dist/shared/attaform.xBDo0Ko0.cjs.map +0 -1
  161. package/dist/shared/{attaform.DdjDqTah.d.mts → attaform.DRUT703x.d.cts} +14 -14
  162. package/dist/shared/{attaform.DdjDqTah.d.ts → attaform.DRUT703x.d.mts} +14 -14
  163. package/dist/shared/{attaform.DdjDqTah.d.cts → attaform.DRUT703x.d.ts} +14 -14
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const vue = require('vue');
4
- const paths = require('./attaform.3heDHayA.cjs');
5
- const registerProtocol = require('./attaform.ZXZ6dH72.cjs');
4
+ const devtoolsShared = require('./attaform.Co5LNRnv.cjs');
5
+ const registerProtocol = require('./attaform.yUrz7C2z.cjs');
6
6
 
7
7
  function safeAssign(target, key, value) {
8
8
  if (key === "__proto__") {
@@ -31,7 +31,7 @@ function safeOwnHas(target, key) {
31
31
  return Object.prototype.hasOwnProperty.call(target, key);
32
32
  }
33
33
 
34
- const NOT_FOUND = Symbol("NOT_FOUND");
34
+ const NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
35
35
  function descendStep(value, segment) {
36
36
  if (value === null || value === void 0) return NOT_FOUND;
37
37
  if (typeof value !== "object") return NOT_FOUND;
@@ -434,7 +434,7 @@ function applyChangedKeys(target, source, arrayOpPath, currentPath) {
434
434
  const targetIsArray = Array.isArray(target);
435
435
  const sourceIsArray = Array.isArray(source);
436
436
  if (targetIsArray !== sourceIsArray) return false;
437
- const ROOT_SENTINEL = Symbol.for("attaform.applyChangedKeys.rootMismatch");
437
+ const ROOT_SENTINEL = /* @__PURE__ */ Symbol.for("attaform.applyChangedKeys.rootMismatch");
438
438
  const changedFirstSegments = /* @__PURE__ */ new Set();
439
439
  diffAndApply(target, source, [], (patch) => {
440
440
  if (patch.path.length === 0) {
@@ -447,7 +447,7 @@ function applyChangedKeys(target, source, arrayOpPath, currentPath) {
447
447
  if (targetIsArray) {
448
448
  const t = target;
449
449
  const s = source;
450
- if (arrayOpPath === null || paths.pathsEqual(currentPath, arrayOpPath)) {
450
+ if (arrayOpPath === null || devtoolsShared.pathsEqual(currentPath, arrayOpPath)) {
451
451
  if (t.length > s.length) t.length = s.length;
452
452
  for (const idx of changedFirstSegments) {
453
453
  if (typeof idx === "symbol") continue;
@@ -463,7 +463,7 @@ function applyChangedKeys(target, source, arrayOpPath, currentPath) {
463
463
  const childPath = appendSegment(currentPath, i);
464
464
  const curEl = t[i];
465
465
  const nextEl = s[i];
466
- if (paths.isPathPrefix(childPath, arrayOpPath) && isDescendable(curEl) && isDescendable(nextEl) && applyChangedKeys(curEl, nextEl, arrayOpPath, childPath)) {
466
+ if (devtoolsShared.isPathPrefix(childPath, arrayOpPath) && isDescendable(curEl) && isDescendable(nextEl) && applyChangedKeys(curEl, nextEl, arrayOpPath, childPath)) {
467
467
  continue;
468
468
  }
469
469
  t[i] = nextEl;
@@ -584,7 +584,18 @@ const AttaformErrorCode = {
584
584
  * produced `ValidationError` carrying a stable, branchable identifier.
585
585
  * Override it per error by passing your own `code` (`api:…`, `auth:…`).
586
586
  */
587
- UserError: "atta:user-error"
587
+ UserError: "atta:user-error",
588
+ /**
589
+ * Stamped on a `ValidationError` synthesized from a throw or rejection
590
+ * out of a `handleSubmit` `onSubmit` callback. The raw error also lands
591
+ * on `form.meta.submitError` (a raw-`Error` inspection channel); this
592
+ * code marks the copy piped into the user-error layer so the failure
593
+ * also surfaces on `form.errors` / `meta.ownErrors` / `firstOwnError`
594
+ * where the UI already reads. A throw carrying its own `path` / `code`
595
+ * keeps them; a bare `Error` or a non-Error throw defaults here at the
596
+ * form-level path `[]`.
597
+ */
598
+ SubmitError: "atta:submit-error"
588
599
  };
589
600
  function makeBlankRequiredError(segments, formKey) {
590
601
  return {
@@ -660,7 +671,7 @@ function normalizeNumericOption(config) {
660
671
  const { value, source, allowInfinity, min, defaultValue } = config;
661
672
  if (allowInfinity && value === Infinity) return Infinity;
662
673
  if (typeof value !== "number" || Number.isNaN(value) || value === Infinity || value === -Infinity) {
663
- if (paths.__DEV__) {
674
+ if (devtoolsShared.__DEV__) {
664
675
  const acceptedDescription = allowInfinity ? "a non-negative integer or Infinity" : "a non-negative finite integer";
665
676
  console.warn(
666
677
  `[attaform] ${source} must be ${acceptedDescription}; got ${String(value)}. Falling back to ${String(defaultValue)}.`
@@ -739,7 +750,7 @@ function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, options
739
750
  const cache = /* @__PURE__ */ new Map();
740
751
  const predicate = options?.getDisplayState;
741
752
  return function getFieldState(pathInput) {
742
- const { segments, key } = paths.canonicalizePath(pathInput);
753
+ const { segments, key } = devtoolsShared.canonicalizePath(pathInput);
743
754
  const cached = cache.get(key);
744
755
  if (cached !== void 0) return cached;
745
756
  const c = vue.computed(
@@ -792,6 +803,11 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
792
803
  elements: elementsArr,
793
804
  updatedAt: record?.updatedAt ?? null,
794
805
  errors,
806
+ // A leaf has no descendants, so its own-bucket errors ARE its subtree
807
+ // errors. Reuse the same array reference: referential `ownErrors ===
808
+ // errors`, and no second read of the whole-form `derivedBlankErrors`
809
+ // map (preserves the P3 blank-reactivity optimization above).
810
+ ownErrors: errors,
795
811
  validating,
796
812
  valid,
797
813
  transforming,
@@ -871,7 +887,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
871
887
  const blurredLeafSegments = [];
872
888
  const descendantLeaves = [];
873
889
  visitActiveLeafPaths(value, segments, (leafSegments) => {
874
- const { key: leafKey } = paths.keyForSegments(leafSegments);
890
+ const { key: leafKey } = devtoolsShared.keyForSegments(leafSegments);
875
891
  const entry = state.originals.get(leafKey);
876
892
  if (entry === void 0) return;
877
893
  descendantLeaves.push({ key: leafKey, segments: entry.segments });
@@ -926,7 +942,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
926
942
  if (ePath.length === segments.length && ePath.every((s, i) => s === segments[i])) return false;
927
943
  if (submissionAttempts > 0) return true;
928
944
  if (ePath.length === 1 && ePath[0] === "") return blurredAfterInteraction;
929
- return blurredLeafSegments.some((s) => paths.isPathPrefix(ePath, s));
945
+ return blurredLeafSegments.some((s) => devtoolsShared.isPathPrefix(ePath, s));
930
946
  });
931
947
  if (!asyncPending && state.pathHasAsyncValidation(segments)) asyncPending = true;
932
948
  if ((state.fieldValidationCounts.get(key) ?? 0) > 0) {
@@ -970,6 +986,12 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
970
986
  elements: EMPTY_ELEMENTS,
971
987
  updatedAt,
972
988
  errors,
989
+ // The container's OWN bucket only (this exact path), excluding every
990
+ // descendant that `errors` rolls up: a cross-field `.refine()` here,
991
+ // or `setErrors` pinned at this node. The same raw union the leaf
992
+ // builds from the three stores; the container already depends on all
993
+ // three via `aggregateErrorsAt`, so there's no new reactivity cost.
994
+ ownErrors: state.getErrorsForPath(segments),
973
995
  validating,
974
996
  valid,
975
997
  transforming,
@@ -1008,6 +1030,7 @@ function buildContainerFieldState(state, segments, key, formInstanceId, getFormM
1008
1030
  }
1009
1031
  function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingSince, transformingSince, revealedDescendantError, isRoot, getDisplayState) {
1010
1032
  const firstError = base.errors[0];
1033
+ const firstOwnError = base.ownErrors[0];
1011
1034
  const predicate = getDisplayState ?? state.getDisplayState;
1012
1035
  const formMeta = getFormMetaBase();
1013
1036
  const ctx = {
@@ -1024,7 +1047,7 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
1024
1047
  try {
1025
1048
  machine = state.displayEngine.resolve(key, ctx, predicate);
1026
1049
  } catch (err) {
1027
- if (paths.__DEV__ && !warnedDisplayStatePredicates.has(predicate)) {
1050
+ if (devtoolsShared.__DEV__ && !warnedDisplayStatePredicates.has(predicate)) {
1028
1051
  warnedDisplayStatePredicates.add(predicate);
1029
1052
  console.warn(
1030
1053
  "[attaform] custom getDisplayState threw \u2014 falling back to defaultDisplayState. Subsequent throws from the same predicate will not warn again.",
@@ -1043,7 +1066,8 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
1043
1066
  showPending: displayState === "pending",
1044
1067
  showSuccess: displayState === "success",
1045
1068
  showIdle: displayState === "idle",
1046
- firstError
1069
+ firstError,
1070
+ firstOwnError
1047
1071
  };
1048
1072
  }
1049
1073
  function aggregateErrorsAt(state, prefix) {
@@ -1052,9 +1076,9 @@ function aggregateErrorsAt(state, prefix) {
1052
1076
  const collect = (errs) => {
1053
1077
  for (const [pathKey, list] of errs) {
1054
1078
  if (list.length === 0) continue;
1055
- const segs = paths.segmentsForPathKey(pathKey);
1079
+ const segs = devtoolsShared.segmentsForPathKey(pathKey);
1056
1080
  if (segs === null) continue;
1057
- if (!paths.isPathPrefix(prefix, segs)) continue;
1081
+ if (!devtoolsShared.isPathPrefix(prefix, segs)) continue;
1058
1082
  if (segs.length > 0 && !hasAtPath(formValue, segs)) continue;
1059
1083
  const ordinal = state.ensurePathOrdinal(pathKey);
1060
1084
  const existing = buckets.get(ordinal);
@@ -1096,7 +1120,7 @@ function isArrayPath(state, segments) {
1096
1120
  }
1097
1121
 
1098
1122
  function warnReadOnly(surface, action, key) {
1099
- if (!paths.__DEV__) return;
1123
+ if (!devtoolsShared.__DEV__) return;
1100
1124
  const phrase = action === "write" ? `write to "${String(key)}"` : `${action} of "${String(key)}"`;
1101
1125
  console.warn(
1102
1126
  `[attaform] ${surface} is read-only \u2014 ${phrase} was ignored. Mutate the form via setValue / the directive / field-array helpers instead.`
@@ -1180,7 +1204,7 @@ function buildSurfaceProxy(opts) {
1180
1204
  }
1181
1205
  return opts.resolveCallTarget(segments);
1182
1206
  }
1183
- const { segments: argSegs } = paths.canonicalizePath(arg);
1207
+ const { segments: argSegs } = devtoolsShared.canonicalizePath(arg);
1184
1208
  return opts.resolveCallTarget(argSegs);
1185
1209
  },
1186
1210
  get(_, key) {
@@ -1382,14 +1406,14 @@ function buildErrorsProxy(state) {
1382
1406
  const merged = [];
1383
1407
  if (isContainerSelfAccess) {
1384
1408
  const containerPath = path.slice(0, -1);
1385
- const containerKey = paths.canonicalizePath(containerPath).key;
1386
- const literalKey = paths.canonicalizePath(path).key;
1409
+ const containerKey = devtoolsShared.canonicalizePath(containerPath).key;
1410
+ const literalKey = devtoolsShared.canonicalizePath(path).key;
1387
1411
  const active2 = hasAtPath(state.form.value, containerPath);
1388
1412
  collectAtKey(containerKey, active2, merged);
1389
1413
  if (literalKey !== containerKey) collectAtKey(literalKey, active2, merged);
1390
1414
  return merged;
1391
1415
  }
1392
- const { key } = paths.canonicalizePath(path);
1416
+ const { key } = devtoolsShared.canonicalizePath(path);
1393
1417
  const active = hasAtPath(state.form.value, path);
1394
1418
  collectAtKey(key, active, merged);
1395
1419
  return merged;
@@ -1412,17 +1436,15 @@ function buildErrorsProxy(state) {
1412
1436
  // shared `aggregateErrorsAt` helper that `form.meta.errors` and
1413
1437
  // `form.fields(path).errors` also use, so the surfaces never drift.
1414
1438
  //
1415
- // The root is the one carve-out. An EXPLICIT root path
1416
- // (`errors([])`) returns ONLY the global `[]` bucket (root
1417
- // `.refine()`, hydration failures, `setErrors`) via
1418
- // `getErrorsForPath`, giving consumers a dedicated channel for
1419
- // global messages undiluted by field errors. The no-arg `errors()`
1420
- // instead resolves the FULL aggregate through `resolveRootCall`
1421
- // below (identical to `meta.errors`).
1422
- resolveCallTarget: (path) => path.length === 0 ? state.getErrorsForPath([]) : aggregateErrorsAt(state, path),
1439
+ // The root is uniform with every other path: `errors([])` is the
1440
+ // subtree aggregate at `[]`, which is the whole form, identical to
1441
+ // the no-arg `errors()` and to `meta.errors`. The root `[]` bucket
1442
+ // alone (root `.refine()`, hydration failures, path-less
1443
+ // `setErrors`) is read through `meta.ownErrors` / `meta.firstOwnError`,
1444
+ // the dedicated own-bucket accessor, not a call-form carve-out.
1445
+ resolveCallTarget: (path) => aggregateErrorsAt(state, path),
1423
1446
  // No-arg `errors()` = the whole-form aggregate, matching
1424
- // `meta.errors`. Distinct from `errors([])` (global bucket only);
1425
- // see `resolveCallTarget`.
1447
+ // `meta.errors` and `errors([])`. All three are the same aggregate.
1426
1448
  resolveRootCall: () => aggregateErrorsAt(state, []),
1427
1449
  // Enumeration unions the live form-data keys at this path with the
1428
1450
  // first-child segments drawn from every error store. Without the
@@ -1455,10 +1477,10 @@ function errorAwareContainerKeys(state, segments) {
1455
1477
  const walk = (store, applyActivePathFilter) => {
1456
1478
  for (const [pathKey, errors] of store) {
1457
1479
  if (errors.length === 0) continue;
1458
- const decoded = paths.segmentsForPathKey(pathKey);
1480
+ const decoded = devtoolsShared.segmentsForPathKey(pathKey);
1459
1481
  if (decoded === null) continue;
1460
1482
  if (decoded.length <= segments.length) continue;
1461
- if (!paths.isPathPrefix(segments, decoded)) continue;
1483
+ if (!devtoolsShared.isPathPrefix(segments, decoded)) continue;
1462
1484
  if (applyActivePathFilter && !hasAtPath(formValue, decoded)) continue;
1463
1485
  const nextSeg = decoded[segments.length];
1464
1486
  keys.add(typeof nextSeg === "number" ? String(nextSeg) : nextSeg);
@@ -1475,10 +1497,10 @@ function materializeErrors(state, containerSegments) {
1475
1497
  const collect = (store, applyActivePathFilter) => {
1476
1498
  entries: for (const [pathKey, errors] of store) {
1477
1499
  if (errors.length === 0) continue;
1478
- const fullPath = paths.segmentsForPathKey(pathKey);
1500
+ const fullPath = devtoolsShared.segmentsForPathKey(pathKey);
1479
1501
  if (fullPath === null) continue;
1480
1502
  if (fullPath.length === 0) {
1481
- if (containerSegments.length === 0) placeAt(tree, [paths.ROOT_PATH_KEY], errors);
1503
+ if (containerSegments.length === 0) placeAt(tree, [devtoolsShared.ROOT_PATH_KEY], errors);
1482
1504
  continue;
1483
1505
  }
1484
1506
  if (fullPath.length < containerSegments.length) continue;
@@ -1529,12 +1551,12 @@ function placeAt(tree, path, errors) {
1529
1551
 
1530
1552
  function buildFieldArrayApi(state) {
1531
1553
  function readArray(path) {
1532
- const segments = paths.canonicalizePath(path).segments;
1554
+ const segments = devtoolsShared.canonicalizePath(path).segments;
1533
1555
  const current = state.getValueAtPath(segments);
1534
1556
  return Array.isArray(current) ? current.slice() : [];
1535
1557
  }
1536
1558
  function writeArray(path, next, arrayOp) {
1537
- const { segments } = paths.canonicalizePath(path);
1559
+ const { segments } = devtoolsShared.canonicalizePath(path);
1538
1560
  const meta = {
1539
1561
  ...arrayOp !== void 0 ? { arrayOp } : {}
1540
1562
  };
@@ -1606,6 +1628,7 @@ const FIELD_STATE_KEYS = /* @__PURE__ */ new Set([
1606
1628
  "elements",
1607
1629
  "updatedAt",
1608
1630
  "errors",
1631
+ "ownErrors",
1609
1632
  "validating",
1610
1633
  "valid",
1611
1634
  "transforming",
@@ -1617,6 +1640,7 @@ const FIELD_STATE_KEYS = /* @__PURE__ */ new Set([
1617
1640
  "showSuccess",
1618
1641
  "showIdle",
1619
1642
  "firstError",
1643
+ "firstOwnError",
1620
1644
  "path",
1621
1645
  "id",
1622
1646
  "aria",
@@ -1686,7 +1710,7 @@ function buildFieldStateProxy(state, formInstanceId, getFormMetaBase, options) {
1686
1710
  // module), which would violate the documented "writes are
1687
1711
  // ignored" contract. Mirrors `values-proxy` / `wizard-statuses-proxy`.
1688
1712
  set: (_, key) => {
1689
- if (paths.__DEV__) {
1713
+ if (devtoolsShared.__DEV__) {
1690
1714
  console.warn(
1691
1715
  `[attaform] form.fields(path) is read-only \u2014 write to "${String(key)}" was ignored. Use form.setValue / the directive / field-array helpers instead.`
1692
1716
  );
@@ -1694,7 +1718,7 @@ function buildFieldStateProxy(state, formInstanceId, getFormMetaBase, options) {
1694
1718
  return true;
1695
1719
  },
1696
1720
  deleteProperty: (_, key) => {
1697
- if (paths.__DEV__) {
1721
+ if (devtoolsShared.__DEV__) {
1698
1722
  console.warn(
1699
1723
  `[attaform] form.fields(path) is read-only \u2014 delete of "${String(key)}" was ignored.`
1700
1724
  );
@@ -1702,7 +1726,7 @@ function buildFieldStateProxy(state, formInstanceId, getFormMetaBase, options) {
1702
1726
  return true;
1703
1727
  },
1704
1728
  defineProperty: (_, key) => {
1705
- if (paths.__DEV__) {
1729
+ if (devtoolsShared.__DEV__) {
1706
1730
  console.warn(
1707
1731
  `[attaform] form.fields(path) is read-only \u2014 define of "${String(key)}" was ignored.`
1708
1732
  );
@@ -1757,7 +1781,33 @@ function walk$1(value, basePath, schema, snapshotFieldStateAt) {
1757
1781
  return result;
1758
1782
  }
1759
1783
 
1760
- const warnedNoScopeStores = paths.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
1784
+ const warnedNoScopeStores = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
1785
+ function isErrorInputLike(value) {
1786
+ if (value instanceof Error) return true;
1787
+ if (typeof value !== "object" || value === null) return false;
1788
+ const shape = value;
1789
+ return typeof shape.message === "string" && shape.message.length > 0 || Array.isArray(shape.path);
1790
+ }
1791
+ function deriveSubmitErrors(err, formKey) {
1792
+ if (Array.isArray(err) && err.length > 0 && err.every(isErrorInputLike)) {
1793
+ return {
1794
+ entries: err.map(
1795
+ (item) => devtoolsShared.normalizeErrorInput(item, void 0, formKey, AttaformErrorCode.SubmitError)
1796
+ ),
1797
+ messageless: false
1798
+ };
1799
+ }
1800
+ if (isErrorInputLike(err)) {
1801
+ return {
1802
+ entries: [devtoolsShared.normalizeErrorInput(err, void 0, formKey, AttaformErrorCode.SubmitError)],
1803
+ messageless: false
1804
+ };
1805
+ }
1806
+ return {
1807
+ entries: [devtoolsShared.normalizeErrorInput({}, void 0, formKey, AttaformErrorCode.SubmitError)],
1808
+ messageless: true
1809
+ };
1810
+ }
1761
1811
  function buildProcessForm(state, formInstanceId, options = {}) {
1762
1812
  const invalidPolicy = options.onInvalidSubmit ?? "focus-first-error";
1763
1813
  function validate(pathInput) {
@@ -1809,7 +1859,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
1809
1859
  });
1810
1860
  if (vue.getCurrentScope() !== void 0) {
1811
1861
  vue.onScopeDispose(stop);
1812
- } else if (paths.__DEV__ && warnedNoScopeStores !== null && !warnedNoScopeStores.has(state)) {
1862
+ } else if (devtoolsShared.__DEV__ && warnedNoScopeStores !== null && !warnedNoScopeStores.has(state)) {
1813
1863
  warnedNoScopeStores.add(state);
1814
1864
  console.warn(
1815
1865
  "[attaform] validate() called outside a Vue effect scope; its reactive watcher will leak until the form is garbage-collected. Fix: call validate() inside setup() / a child component, or wrap the call in `effectScope().run(...)`."
@@ -1926,7 +1976,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
1926
1976
  try {
1927
1977
  await onError(merged.errors);
1928
1978
  } catch (cause) {
1929
- throw new paths.SubmitErrorHandlerError("User-provided onError threw", { cause });
1979
+ throw new devtoolsShared.SubmitErrorHandlerError("User-provided onError threw", { cause });
1930
1980
  }
1931
1981
  }
1932
1982
  return;
@@ -1939,13 +1989,6 @@ function buildProcessForm(state, formInstanceId, options = {}) {
1939
1989
  if (state.submissionGeneration.value === genAtEntry) {
1940
1990
  applyInvalidSubmitPolicy(state, formInstanceId, invalidPolicy);
1941
1991
  }
1942
- if (onError !== void 0) {
1943
- try {
1944
- await onError(Array.from(state.userErrors.values()).flat());
1945
- } catch (cause) {
1946
- throw new paths.SubmitErrorHandlerError("User-provided onError threw", { cause });
1947
- }
1948
- }
1949
1992
  return;
1950
1993
  }
1951
1994
  if (state.submissionGeneration.value === genAtEntry) {
@@ -1954,7 +1997,26 @@ function buildProcessForm(state, formInstanceId, options = {}) {
1954
1997
  state.emitSubmitSuccess();
1955
1998
  } catch (err) {
1956
1999
  if (state.submissionGeneration.value === genAtEntry) {
1957
- state.submitError.value = paths.toError(err);
2000
+ state.submitError.value = devtoolsShared.toError(err);
2001
+ if (!(err instanceof devtoolsShared.SubmitErrorHandlerError)) {
2002
+ const { entries, messageless } = deriveSubmitErrors(err, state.formKey);
2003
+ const byPath = /* @__PURE__ */ new Map();
2004
+ for (const entry of entries) {
2005
+ const { key } = devtoolsShared.canonicalizePath(entry.path);
2006
+ const bucket = byPath.get(key);
2007
+ if (bucket === void 0) byPath.set(key, { segments: entry.path, entries: [entry] });
2008
+ else bucket.entries.push(entry);
2009
+ }
2010
+ for (const { segments, entries: bucket } of byPath.values()) {
2011
+ state.setUserErrorsForPath(segments, bucket);
2012
+ }
2013
+ applyInvalidSubmitPolicy(state, formInstanceId, invalidPolicy);
2014
+ if (devtoolsShared.__DEV__ && messageless) {
2015
+ console.warn(
2016
+ "[attaform] handleSubmit callback threw a non-Error value; throw an Error or a ValidationError ({ message, path? }) so the failure surfaces with a usable message."
2017
+ );
2018
+ }
2019
+ }
1958
2020
  }
1959
2021
  } finally {
1960
2022
  if (!validationSettled) {
@@ -1972,7 +2034,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
1972
2034
  return { validate, validateAsync, parse, handleSubmit };
1973
2035
  }
1974
2036
  function toSegments(pathInput) {
1975
- return paths.canonicalizePath(pathInput).segments;
2037
+ return devtoolsShared.canonicalizePath(pathInput).segments;
1976
2038
  }
1977
2039
  function settled(response) {
1978
2040
  if (response.success) {
@@ -1996,7 +2058,7 @@ function collectScopedBlankErrors(state, scope) {
1996
2058
  const errors = [];
1997
2059
  for (const [pathKey, entries] of derived) {
1998
2060
  if (scope !== void 0) {
1999
- const segments = paths.segmentsForPathKey(pathKey);
2061
+ const segments = devtoolsShared.segmentsForPathKey(pathKey);
2000
2062
  if (segments === null) continue;
2001
2063
  if (!pathStartsWith(segments, scope)) continue;
2002
2064
  }
@@ -2027,7 +2089,7 @@ function applyInvalidSubmitPolicy(state, formInstanceId, policy) {
2027
2089
  target.element.focus({ preventScroll: true, focusVisible: true });
2028
2090
  }
2029
2091
 
2030
- const warnedRejections = paths.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
2092
+ const warnedRejections = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
2031
2093
  function shouldWarnOnce$1(store, key) {
2032
2094
  if (warnedRejections === null) return false;
2033
2095
  let set = warnedRejections.get(store);
@@ -2101,7 +2163,7 @@ function walk(schema, store, path, value) {
2101
2163
  return true;
2102
2164
  }
2103
2165
  function reportRejection(store, path, kind, accepted) {
2104
- if (!paths.__DEV__) return;
2166
+ if (!devtoolsShared.__DEV__) return;
2105
2167
  const dotted = path.map((s) => String(s)).join(".") || "(root)";
2106
2168
  const key = `${dotted}::${kind}`;
2107
2169
  if (!shouldWarnOnce$1(store, key)) return;
@@ -2175,13 +2237,13 @@ function indexRules(rules) {
2175
2237
  for (const entry of rules) {
2176
2238
  const candidate = entry;
2177
2239
  if (candidate === null || typeof candidate !== "object" || typeof candidate.transform !== "function") {
2178
- if (paths.__DEV__) {
2240
+ if (devtoolsShared.__DEV__) {
2179
2241
  console.warn("[attaform] coercion entry missing or invalid `transform` \u2014 skipped.");
2180
2242
  }
2181
2243
  continue;
2182
2244
  }
2183
2245
  const key = `${entry.input}->${entry.output}`;
2184
- if (idx.has(key) && paths.__DEV__) {
2246
+ if (idx.has(key) && devtoolsShared.__DEV__) {
2185
2247
  console.warn(`[attaform] duplicate coercion rule for '${key}' \u2014 last entry wins.`);
2186
2248
  }
2187
2249
  idx.set(key, entry);
@@ -2210,7 +2272,7 @@ function pickScalarTarget(accepted) {
2210
2272
  if (accepted.has("bigint")) return "bigint";
2211
2273
  return null;
2212
2274
  }
2213
- const warnedCoerce = paths.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
2275
+ const warnedCoerce = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
2214
2276
  const sharedWarnStore = {};
2215
2277
  function shouldWarnOnce(key) {
2216
2278
  if (warnedCoerce === null) return false;
@@ -2235,7 +2297,7 @@ function coerceScalar(value, accepted, index) {
2235
2297
  try {
2236
2298
  result = entry.transform(value);
2237
2299
  } catch (err) {
2238
- if (paths.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::throw`)) {
2300
+ if (devtoolsShared.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::throw`)) {
2239
2301
  console.warn(
2240
2302
  `[attaform] coercion '${entry.input}->${entry.output}' threw \u2014 write passes through.`,
2241
2303
  err
@@ -2246,7 +2308,7 @@ function coerceScalar(value, accepted, index) {
2246
2308
  if (!result.coerced) return value;
2247
2309
  const returnedKind = slimKindOf(result.value);
2248
2310
  if (returnedKind !== entry.output) {
2249
- if (paths.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::wrong-kind:${returnedKind}`)) {
2311
+ if (devtoolsShared.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::wrong-kind:${returnedKind}`)) {
2250
2312
  console.warn(
2251
2313
  `[attaform] coercion '${entry.input}->${entry.output}' produced a ${returnedKind} \u2014 write passes through.`
2252
2314
  );
@@ -2254,7 +2316,7 @@ function coerceScalar(value, accepted, index) {
2254
2316
  return value;
2255
2317
  }
2256
2318
  if (entry.output === "number" && !Number.isFinite(result.value)) {
2257
- if (paths.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::nan`)) {
2319
+ if (devtoolsShared.__DEV__ && shouldWarnOnce(`${entry.input}->${entry.output}::nan`)) {
2258
2320
  console.warn(
2259
2321
  `[attaform] coercion '${entry.input}->${entry.output}' produced a non-finite number \u2014 write passes through.`
2260
2322
  );
@@ -2297,7 +2359,7 @@ function coerceValue(value, accepted, elementAccepted, index) {
2297
2359
 
2298
2360
  const warnedMultiRootHosts = /* @__PURE__ */ new Set();
2299
2361
  const EMPTY_TRANSFORMS = Object.freeze([]);
2300
- const attaformListenersSymbol = Symbol.for("attaform:focus-listeners");
2362
+ const attaformListenersSymbol = /* @__PURE__ */ Symbol.for("attaform:focus-listeners");
2301
2363
  function attachFocusListeners(state, segments, element, instanceMeta) {
2302
2364
  const target = element;
2303
2365
  if (target[attaformListenersSymbol] !== void 0) return;
@@ -2332,7 +2394,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2332
2394
  };
2333
2395
  const lastTypedFormByPath = /* @__PURE__ */ new Map();
2334
2396
  return function register(pathInput, options) {
2335
- const { segments, key: pathKey } = paths.canonicalizePath(pathInput);
2397
+ const { segments, key: pathKey } = devtoolsShared.canonicalizePath(pathInput);
2336
2398
  const innerRef = vue.computed(() => state.getValueAtPath(segments));
2337
2399
  let lastTypedForm = lastTypedFormByPath.get(pathKey);
2338
2400
  if (lastTypedForm === void 0) {
@@ -2389,7 +2451,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2389
2451
  state.markInteracted(segments);
2390
2452
  },
2391
2453
  registerElement: (element) => {
2392
- if (!paths.INTERACTIVE_TAG_NAMES.has(element.tagName)) return;
2454
+ if (!devtoolsShared.INTERACTIVE_TAG_NAMES.has(element.tagName)) return;
2393
2455
  const added = state.registerElement(segments, element, formInstanceId);
2394
2456
  if (added) attachFocusListeners(state, segments, element, instanceMeta);
2395
2457
  },
@@ -2403,7 +2465,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2403
2465
  setValueFromHost: (value) => {
2404
2466
  state.markInteracted(segments);
2405
2467
  const accepted = state.setValueAtPath(segments, value, withInstanceMeta(void 0));
2406
- if (paths.__DEV__) {
2468
+ if (devtoolsShared.__DEV__) {
2407
2469
  const dedupeKey = `${formInstanceId}:${pathKey}`;
2408
2470
  const isWired = () => (state.elements.get(pathKey)?.elements.size ?? 0) > 0 || state.getFieldRecord(segments)?.connected === true;
2409
2471
  if (!warnedMultiRootHosts.has(dedupeKey) && !isWired()) {
@@ -2487,7 +2549,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2487
2549
  };
2488
2550
  }
2489
2551
 
2490
- const unset = Symbol.for("attaform/unset");
2552
+ const unset = /* @__PURE__ */ Symbol.for("attaform/unset");
2491
2553
  function isUnset(value) {
2492
2554
  return value === unset;
2493
2555
  }
@@ -2560,10 +2622,10 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
2560
2622
  }
2561
2623
  return input;
2562
2624
  }
2563
- function walkUnspecified(slim, segments, paths$1) {
2625
+ function walkUnspecified(slim, segments, paths) {
2564
2626
  if (isPrimitiveOrEmpty(slim)) {
2565
2627
  if (isSlimNumericPrimitive(slim)) {
2566
- paths$1.push(paths.canonicalizePath(segments).key);
2628
+ paths.push(devtoolsShared.canonicalizePath(segments).key);
2567
2629
  }
2568
2630
  return slim;
2569
2631
  }
@@ -2577,7 +2639,7 @@ function walkUnspecified(slim, segments, paths$1) {
2577
2639
  safeAssign(
2578
2640
  out,
2579
2641
  key,
2580
- walkUnspecified(slim[key], [...segments, key], paths$1)
2642
+ walkUnspecified(slim[key], [...segments, key], paths)
2581
2643
  );
2582
2644
  }
2583
2645
  return out;
@@ -2605,27 +2667,27 @@ function blankForKind(slimDefault) {
2605
2667
  if (slimDefault === null) return null;
2606
2668
  return void 0;
2607
2669
  }
2608
- function expandUnsetAt(segments, schema, paths$1) {
2670
+ function expandUnsetAt(segments, schema, paths) {
2609
2671
  const du = schema.getUnionDiscriminatorAtPath(segments);
2610
2672
  if (du !== void 0) {
2611
2673
  const discPath = [...segments, du.discriminatorKey];
2612
2674
  const discSlim = schema.getEmptyValueAtPath(discPath);
2613
- paths$1.push(paths.canonicalizePath(discPath).key);
2675
+ paths.push(devtoolsShared.canonicalizePath(discPath).key);
2614
2676
  return { [du.discriminatorKey]: blankForKind(discSlim) };
2615
2677
  }
2616
2678
  const slim = schema.getEmptyValueAtPath(segments);
2617
2679
  if (isPrimitiveOrEmpty(slim)) {
2618
- paths$1.push(paths.canonicalizePath(segments).key);
2680
+ paths.push(devtoolsShared.canonicalizePath(segments).key);
2619
2681
  return slim;
2620
2682
  }
2621
2683
  if (isOpaqueLeaf(slim)) {
2622
- paths$1.push(paths.canonicalizePath(segments).key);
2684
+ paths.push(devtoolsShared.canonicalizePath(segments).key);
2623
2685
  return slim;
2624
2686
  }
2625
2687
  if (Array.isArray(slim)) return slim;
2626
2688
  const result = {};
2627
2689
  for (const key of Object.keys(slim)) {
2628
- result[key] = expandUnsetAt([...segments, key], schema, paths$1);
2690
+ result[key] = expandUnsetAt([...segments, key], schema, paths);
2629
2691
  }
2630
2692
  return result;
2631
2693
  }
@@ -2729,7 +2791,7 @@ function buildValuesProxy(form) {
2729
2791
  // (`getAtPath`), so `form.values('a.hasOwnProperty')` resolves the
2730
2792
  // stored value. Per-level reads still propagate Vue's tracking for
2731
2793
  // ordinary keys.
2732
- resolveCall: (arg) => getAtPath(inner.value, paths.canonicalizePath(arg).segments),
2794
+ resolveCall: (arg) => getAtPath(inner.value, devtoolsShared.canonicalizePath(arg).segments),
2733
2795
  ownKeys: () => Reflect.ownKeys(inner.value),
2734
2796
  hasKey: (key) => Reflect.has(inner.value, key),
2735
2797
  describeKey: (key) => {
@@ -2752,9 +2814,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
2752
2814
  if (instanceMeta === void 0) return meta;
2753
2815
  return meta === void 0 ? { instance: instanceMeta } : { ...meta, instance: instanceMeta };
2754
2816
  };
2755
- const reMarkBlanksAfterSubstitution = (paths$1) => {
2756
- for (const pathKey of paths$1) {
2757
- const blankSegments = paths.segmentsForPathKey(pathKey);
2817
+ const reMarkBlanksAfterSubstitution = (paths) => {
2818
+ for (const pathKey of paths) {
2819
+ const blankSegments = devtoolsShared.segmentsForPathKey(pathKey);
2758
2820
  if (blankSegments === null) continue;
2759
2821
  state.setValueAtPath(
2760
2822
  blankSegments,
@@ -2767,8 +2829,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
2767
2829
  let rollup;
2768
2830
  const rootBase = () => rollup ?? (rollup = buildContainerFieldStateBase(
2769
2831
  state,
2770
- paths.ROOT_PATH,
2771
- paths.ROOT_PATH_KEY,
2832
+ devtoolsShared.ROOT_PATH,
2833
+ devtoolsShared.ROOT_PATH_KEY,
2772
2834
  formInstanceId
2773
2835
  ).base);
2774
2836
  return {
@@ -2816,6 +2878,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
2816
2878
  get errors() {
2817
2879
  return rootBase().errors;
2818
2880
  },
2881
+ get ownErrors() {
2882
+ return rootBase().ownErrors;
2883
+ },
2819
2884
  get validating() {
2820
2885
  return rootBase().validating;
2821
2886
  },
@@ -2905,7 +2970,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2905
2970
  const validateAsync = (pathInput) => validateAsyncBuilt(pathInput);
2906
2971
  const parse = (pathInput) => parseBuilt(pathInput);
2907
2972
  function pathToRef(pathInput) {
2908
- const segments = paths.canonicalizePath(pathInput).segments;
2973
+ const segments = devtoolsShared.canonicalizePath(pathInput).segments;
2909
2974
  return vue.computed(() => getAtPath(state.form.value, segments));
2910
2975
  }
2911
2976
  function setValueImpl(pathOrValue, maybeValue) {
@@ -2923,7 +2988,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2923
2988
  reMarkBlanksAfterSubstitution(walked2.paths);
2924
2989
  return true;
2925
2990
  }
2926
- const segments = paths.canonicalizePath(pathOrValue).segments;
2991
+ const segments = devtoolsShared.canonicalizePath(pathOrValue).segments;
2927
2992
  const writeUnsetAt = () => {
2928
2993
  const last = segments.length > 0 ? segments[segments.length - 1] : void 0;
2929
2994
  if (typeof last === "string") {
@@ -2941,14 +3006,14 @@ function buildFormApi(state, formInstanceId, options = {}) {
2941
3006
  state.schema,
2942
3007
  blankPaths
2943
3008
  );
2944
- const segmentsKey = paths.canonicalizePath(segments).key;
3009
+ const segmentsKey = devtoolsShared.canonicalizePath(segments).key;
2945
3010
  if (blankPaths.length === 1 && blankPaths[0] === segmentsKey) {
2946
3011
  return state.setValueAtPath(segments, expanded, writeMeta({ blank: true }));
2947
3012
  }
2948
3013
  const ok2 = state.setValueAtPath(segments, expanded, writeMeta());
2949
3014
  if (!ok2) return false;
2950
3015
  for (const pathKey of blankPaths) {
2951
- const blankSegments = paths.segmentsForPathKey(pathKey);
3016
+ const blankSegments = devtoolsShared.segmentsForPathKey(pathKey);
2952
3017
  if (blankSegments === null) continue;
2953
3018
  state.setValueAtPath(
2954
3019
  blankSegments,
@@ -2979,28 +3044,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
2979
3044
  return true;
2980
3045
  }
2981
3046
  const errorsProxy = buildErrorsProxy(state);
2982
- function normalizeErrorInput(item, scope) {
2983
- if (item instanceof Error) {
2984
- return {
2985
- message: item.message.length > 0 ? item.message : "Unknown error",
2986
- path: scope !== void 0 ? [...scope] : [],
2987
- formKey: state.formKey,
2988
- code: AttaformErrorCode.UserError
2989
- };
2990
- }
2991
- const entry = {
2992
- message: typeof item.message === "string" && item.message.length > 0 ? item.message : "Unknown error",
2993
- path: scope !== void 0 ? [...scope] : Array.isArray(item.path) ? [...item.path] : [],
2994
- formKey: state.formKey,
2995
- code: typeof item.code === "string" && item.code.length > 0 ? item.code : AttaformErrorCode.UserError
2996
- };
2997
- if (item.data !== void 0) entry.data = item.data;
2998
- return entry;
2999
- }
3000
- function normalizeErrorInputs(input, scope) {
3001
- const items = Array.isArray(input) ? input : [input];
3002
- return items.map((item) => normalizeErrorInput(item, scope));
3003
- }
3004
3047
  function flattenUserErrors() {
3005
3048
  const all = [];
3006
3049
  for (const errs of state.userErrors.values()) all.push(...errs);
@@ -3009,15 +3052,20 @@ function buildFormApi(state, formInstanceId, options = {}) {
3009
3052
  function setErrors(arg1, arg2) {
3010
3053
  const isScoped = arguments.length >= 2 && (typeof arg1 === "string" || Array.isArray(arg1));
3011
3054
  if (isScoped) {
3012
- const { segments, key } = paths.canonicalizePath(arg1);
3055
+ const { segments, key } = devtoolsShared.canonicalizePath(arg1);
3013
3056
  const input2 = arg2;
3014
3057
  const resolved2 = typeof input2 === "function" ? input2((state.userErrors.get(key) ?? []).slice()) : input2;
3015
- state.setUserErrorsForPath(segments, normalizeErrorInputs(resolved2, segments));
3058
+ state.setUserErrorsForPath(
3059
+ segments,
3060
+ devtoolsShared.normalizeErrorInputs(resolved2, segments, state.formKey, AttaformErrorCode.UserError)
3061
+ );
3016
3062
  return;
3017
3063
  }
3018
3064
  const input = arg1;
3019
3065
  const resolved = typeof input === "function" ? input(flattenUserErrors()) : input;
3020
- state.setAllUserErrors(normalizeErrorInputs(resolved, void 0));
3066
+ state.setAllUserErrors(
3067
+ devtoolsShared.normalizeErrorInputs(resolved, void 0, state.formKey, AttaformErrorCode.UserError)
3068
+ );
3021
3069
  }
3022
3070
  function clearErrors(path) {
3023
3071
  if (path === void 0) {
@@ -3025,7 +3073,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3025
3073
  state.clearUserErrors();
3026
3074
  return;
3027
3075
  }
3028
- const segments = paths.canonicalizePath(path).segments;
3076
+ const segments = devtoolsShared.canonicalizePath(path).segments;
3029
3077
  state.clearSchemaErrors(segments);
3030
3078
  state.clearUserErrors(segments);
3031
3079
  }
@@ -3112,6 +3160,17 @@ function buildFormApi(state, formInstanceId, options = {}) {
3112
3160
  // keep the explicit form-level computation for the gate.
3113
3161
  valid,
3114
3162
  errors: metaErrors,
3163
+ // The root `[]` bucket alone: form-level errors from a root
3164
+ // `.refine()` or a path-less `setErrors`, excluding every field error
3165
+ // that `errors` (the whole-form aggregate) rolls up. This is the
3166
+ // banner accessor. Mirrors `rootFieldState` rather than taking a
3167
+ // dedicated computed: `getFieldState([])` routes a container root
3168
+ // through `getErrorsForPath([])` and a primitive root through its own
3169
+ // bucket, and both equal the root bucket, so the root field state is
3170
+ // already the single source of truth.
3171
+ get ownErrors() {
3172
+ return rootFieldState.value.ownErrors;
3173
+ },
3115
3174
  // Whole-form transforming mirrors the global `activeTransforms`
3116
3175
  // counter ORed with any per-leaf transform in flight (the root
3117
3176
  // rollup), exactly as `validating` composes its lifecycle and
@@ -3150,6 +3209,11 @@ function buildFormApi(state, formInstanceId, options = {}) {
3150
3209
  get firstError() {
3151
3210
  return rootFieldState.value.firstError;
3152
3211
  },
3212
+ // `ownErrors[0]`: the form's first top-level error. Pair it with
3213
+ // `ownErrors` for the form-level banner.
3214
+ get firstOwnError() {
3215
+ return rootFieldState.value.firstOwnError;
3216
+ },
3153
3217
  get path() {
3154
3218
  return rootFieldState.value.path;
3155
3219
  },
@@ -3213,7 +3277,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3213
3277
  }
3214
3278
  };
3215
3279
  const resetField = (pathInput) => {
3216
- const segments = paths.canonicalizePath(pathInput).segments;
3280
+ const segments = devtoolsShared.canonicalizePath(pathInput).segments;
3217
3281
  state.resetField(segments);
3218
3282
  };
3219
3283
  function clear(pathInput) {
@@ -3223,7 +3287,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3223
3287
  return setValueImpl(pathInput, unset);
3224
3288
  }
3225
3289
  function touch(pathInput) {
3226
- const segments = pathInput === void 0 ? paths.ROOT_PATH : paths.canonicalizePath(pathInput).segments;
3290
+ const segments = pathInput === void 0 ? devtoolsShared.ROOT_PATH : devtoolsShared.canonicalizePath(pathInput).segments;
3227
3291
  state.touchAtPath(segments);
3228
3292
  }
3229
3293
  const focusFirstError = (options2) => {
@@ -3244,26 +3308,26 @@ function buildFormApi(state, formInstanceId, options = {}) {
3244
3308
  const fieldArrays = buildFieldArrayApi(state);
3245
3309
  const blankPathsView = vue.computed(() => {
3246
3310
  const keys = /* @__PURE__ */ new Set();
3247
- const paths$1 = [];
3311
+ const paths = [];
3248
3312
  for (const pk of state.blankPaths) {
3249
3313
  keys.add(pk);
3250
- const segs = paths.segmentsForPathKey(pk);
3251
- if (segs !== null) paths$1.push(segs);
3314
+ const segs = devtoolsShared.segmentsForPathKey(pk);
3315
+ if (segs !== null) paths.push(segs);
3252
3316
  }
3253
- Object.freeze(paths$1);
3317
+ Object.freeze(paths);
3254
3318
  const view = {
3255
3319
  get size() {
3256
3320
  return keys.size;
3257
3321
  },
3258
3322
  has(input) {
3259
- const { key } = paths.canonicalizePath(input);
3323
+ const { key } = devtoolsShared.canonicalizePath(input);
3260
3324
  return keys.has(key);
3261
3325
  },
3262
3326
  values() {
3263
- return paths$1;
3327
+ return paths;
3264
3328
  },
3265
3329
  [Symbol.iterator]() {
3266
- return paths$1[Symbol.iterator]();
3330
+ return paths[Symbol.iterator]();
3267
3331
  }
3268
3332
  };
3269
3333
  return Object.freeze(view);
@@ -3286,7 +3350,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3286
3350
  const callTerminal = fieldStateProxy;
3287
3351
  const EMPTY_FIELD_LIST = Object.freeze([]);
3288
3352
  function list(path) {
3289
- const { segments } = paths.canonicalizePath(path);
3353
+ const { segments } = devtoolsShared.canonicalizePath(path);
3290
3354
  const value = state.getValueAtPath(segments);
3291
3355
  if (!Array.isArray(value)) return EMPTY_FIELD_LIST;
3292
3356
  const out = new Array(value.length);
@@ -3295,7 +3359,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3295
3359
  }
3296
3360
  const EMPTY_FIELD_RECORD = Object.freeze({});
3297
3361
  function record(path) {
3298
- const segments = path === void 0 ? [] : paths.canonicalizePath(path).segments;
3362
+ const segments = path === void 0 ? [] : devtoolsShared.canonicalizePath(path).segments;
3299
3363
  const value = state.getValueAtPath(segments);
3300
3364
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
3301
3365
  return EMPTY_FIELD_RECORD;
@@ -3393,6 +3457,33 @@ function buildFormApi(state, formInstanceId, options = {}) {
3393
3457
  return api;
3394
3458
  }
3395
3459
 
3460
+ function captureUserCallSite() {
3461
+ const raw = new Error().stack;
3462
+ if (typeof raw !== "string") return void 0;
3463
+ const lines = raw.split("\n");
3464
+ for (let i = 1; i < lines.length; i++) {
3465
+ const frame = lines[i];
3466
+ if (frame === void 0) continue;
3467
+ if (/attaform[/-]forms?/i.test(frame)) continue;
3468
+ if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
3469
+ const trimmed = frame.trim();
3470
+ if (trimmed.length === 0) continue;
3471
+ return shortenSourceFrame(trimmed);
3472
+ }
3473
+ return void 0;
3474
+ }
3475
+ function shortenSourceFrame(frame) {
3476
+ const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
3477
+ if (match === null) return frame;
3478
+ const [, urlOrPath, line] = match;
3479
+ if (urlOrPath === void 0 || line === void 0) return frame;
3480
+ let path = urlOrPath;
3481
+ path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
3482
+ path = path.replace(/^_nuxt\//, "");
3483
+ path = path.replace(/^\//, "");
3484
+ return `(${path}:${line})`;
3485
+ }
3486
+
3396
3487
  const IDLE = Object.freeze({ display: "idle" });
3397
3488
  const MAX_DELAY = 2147483647;
3398
3489
  function createDisplayEngine(ssr) {
@@ -3498,7 +3589,7 @@ function walkDuStubs(schema, value, path, warned) {
3498
3589
  const discValue = rec[du.discriminatorKey];
3499
3590
  if (discValue !== void 0 && !du.isVariantSelected(discValue)) {
3500
3591
  const isKindBlank = discValue === "" || discValue === 0 || discValue === 0n || discValue === false || discValue === null;
3501
- if (!isKindBlank && warned !== void 0 && paths.__DEV__) {
3592
+ if (!isKindBlank && warned !== void 0 && devtoolsShared.__DEV__) {
3502
3593
  const dotted = path.map((s) => String(s)).join(".") || "(root)";
3503
3594
  const key = `${dotted}::${String(discValue)}`;
3504
3595
  if (!warned.has(key)) {
@@ -3524,9 +3615,9 @@ function createVariantMemory() {
3524
3615
  const memory = /* @__PURE__ */ new Map();
3525
3616
  function clearAtArrayIndices(arrayPath, indexFilter) {
3526
3617
  for (const memKey of [...memory.keys()]) {
3527
- const segs = paths.segmentsForPathKey(memKey);
3618
+ const segs = devtoolsShared.segmentsForPathKey(memKey);
3528
3619
  if (segs === null) continue;
3529
- if (!paths.isPathPrefix(arrayPath, segs)) continue;
3620
+ if (!devtoolsShared.isPathPrefix(arrayPath, segs)) continue;
3530
3621
  if (segs.length <= arrayPath.length) continue;
3531
3622
  const idxSeg = segs[arrayPath.length];
3532
3623
  if (typeof idxSeg !== "number") continue;
@@ -3539,9 +3630,9 @@ function createVariantMemory() {
3539
3630
  },
3540
3631
  clearUnderPath(parentPath) {
3541
3632
  for (const memKey of [...memory.keys()]) {
3542
- const segs = paths.segmentsForPathKey(memKey);
3633
+ const segs = devtoolsShared.segmentsForPathKey(memKey);
3543
3634
  if (segs === null) continue;
3544
- if (paths.isPathPrefix(parentPath, segs)) memory.delete(memKey);
3635
+ if (devtoolsShared.isPathPrefix(parentPath, segs)) memory.delete(memKey);
3545
3636
  }
3546
3637
  },
3547
3638
  applyArrayOp(arrayPath, op) {
@@ -3634,11 +3725,11 @@ function createArrayIdentity(getArrayLength) {
3634
3725
  tokenAt(arraySegs, index) {
3635
3726
  const len = getArrayLength(arraySegs);
3636
3727
  if (index < 0 || index >= len) return "";
3637
- const ids = ensure(paths.canonicalizePath(arraySegs).key, len);
3728
+ const ids = ensure(devtoolsShared.canonicalizePath(arraySegs).key, len);
3638
3729
  return ids[index] ?? "";
3639
3730
  },
3640
3731
  applyOp(arraySegs, op) {
3641
- const arrayKey = paths.canonicalizePath(arraySegs).key;
3732
+ const arrayKey = devtoolsShared.canonicalizePath(arraySegs).key;
3642
3733
  const postLen = getArrayLength(arraySegs);
3643
3734
  const preLen = op.kind === "insert" ? postLen - 1 : op.kind === "remove" ? postLen + 1 : postLen;
3644
3735
  const ids = ensure(arrayKey, Math.max(0, preLen));
@@ -3671,9 +3762,9 @@ function createArrayIdentity(getArrayLength) {
3671
3762
  const idxPos = arrayPath.length;
3672
3763
  const snapshots = [];
3673
3764
  for (const [key, value] of store) {
3674
- const segments = paths.segmentsForPathKey(key);
3765
+ const segments = devtoolsShared.segmentsForPathKey(key);
3675
3766
  if (segments === null) continue;
3676
- if (!paths.isPathPrefix(arrayPath, segments)) continue;
3767
+ if (!devtoolsShared.isPathPrefix(arrayPath, segments)) continue;
3677
3768
  if (segments.length <= idxPos) continue;
3678
3769
  const idxSeg = segments[idxPos];
3679
3770
  if (typeof idxSeg !== "number") continue;
@@ -3683,33 +3774,33 @@ function createArrayIdentity(getArrayLength) {
3683
3774
  snapshots.push({ segments: [...segments], index: idxSeg, value });
3684
3775
  }
3685
3776
  if (snapshots.length === 0) return;
3686
- for (const snap of snapshots) store.delete(paths.canonicalizePath(snap.segments).key);
3777
+ for (const snap of snapshots) store.delete(devtoolsShared.canonicalizePath(snap.segments).key);
3687
3778
  for (const snap of snapshots) {
3688
3779
  const target = remap.moved.get(snap.index);
3689
3780
  if (target === void 0) continue;
3690
3781
  const relocated = snap.segments.slice();
3691
3782
  relocated[idxPos] = target;
3692
- store.set(paths.canonicalizePath(relocated).key, snap.value);
3783
+ store.set(devtoolsShared.canonicalizePath(relocated).key, snap.value);
3693
3784
  }
3694
3785
  };
3695
3786
  relocate(tokens);
3696
3787
  relocate(baselines);
3697
3788
  },
3698
3789
  realign(arraySegs) {
3699
- ensure(paths.canonicalizePath(arraySegs).key, getArrayLength(arraySegs));
3790
+ ensure(devtoolsShared.canonicalizePath(arraySegs).key, getArrayLength(arraySegs));
3700
3791
  },
3701
3792
  hasStructuralChangeUnder(prefix) {
3702
3793
  for (const arrayKey of tokens.keys()) {
3703
3794
  if (orderPristineForKey(arrayKey)) continue;
3704
- const segs = paths.segmentsForPathKey(arrayKey);
3795
+ const segs = devtoolsShared.segmentsForPathKey(arrayKey);
3705
3796
  if (segs === null) continue;
3706
- if (paths.isPathPrefix(prefix, segs)) return true;
3797
+ if (devtoolsShared.isPathPrefix(prefix, segs)) return true;
3707
3798
  }
3708
3799
  return false;
3709
3800
  },
3710
3801
  rebaselineAll() {
3711
3802
  for (const arrayKey of [...tokens.keys()]) {
3712
- const segs = paths.segmentsForPathKey(arrayKey);
3803
+ const segs = devtoolsShared.segmentsForPathKey(arrayKey);
3713
3804
  if (segs === null) continue;
3714
3805
  const ids = ensure(arrayKey, getArrayLength(segs));
3715
3806
  baselines.set(arrayKey, [...ids]);
@@ -3763,9 +3854,9 @@ function changedIndices(remap) {
3763
3854
  return changed;
3764
3855
  }
3765
3856
  function elementIndexUnder(arrayPath, key, idxPos) {
3766
- const segments = paths.segmentsForPathKey(key);
3857
+ const segments = devtoolsShared.segmentsForPathKey(key);
3767
3858
  if (segments === null) return null;
3768
- if (!paths.isPathPrefix(arrayPath, segments)) return null;
3859
+ if (!devtoolsShared.isPathPrefix(arrayPath, segments)) return null;
3769
3860
  if (segments.length <= idxPos) return null;
3770
3861
  const index = segments[idxPos];
3771
3862
  return typeof index === "number" ? index : null;
@@ -3777,16 +3868,16 @@ function migrateMapSubtree(map, arrayPath, remap, rewriteValue) {
3777
3868
  const index = elementIndexUnder(arrayPath, key, idxPos);
3778
3869
  if (index === null) continue;
3779
3870
  if (!remap.moved.has(index) && !remap.vacated.has(index)) continue;
3780
- snapshots.push({ segments: [...paths.segmentsForPathKey(key)], index, value });
3871
+ snapshots.push({ segments: [...devtoolsShared.segmentsForPathKey(key)], index, value });
3781
3872
  }
3782
3873
  if (snapshots.length === 0) return;
3783
- for (const snap of snapshots) map.delete(paths.canonicalizePath(snap.segments).key);
3874
+ for (const snap of snapshots) map.delete(devtoolsShared.canonicalizePath(snap.segments).key);
3784
3875
  for (const snap of snapshots) {
3785
3876
  const target = remap.moved.get(snap.index);
3786
3877
  if (target === void 0) continue;
3787
3878
  const relocated = snap.segments.slice();
3788
3879
  relocated[idxPos] = target;
3789
- map.set(paths.canonicalizePath(relocated).key, rewriteValue(snap.value, relocated));
3880
+ map.set(devtoolsShared.canonicalizePath(relocated).key, rewriteValue(snap.value, relocated));
3790
3881
  }
3791
3882
  }
3792
3883
  function migrateSetSubtree(set, arrayPath, remap) {
@@ -3796,16 +3887,16 @@ function migrateSetSubtree(set, arrayPath, remap) {
3796
3887
  const index = elementIndexUnder(arrayPath, key, idxPos);
3797
3888
  if (index === null) continue;
3798
3889
  if (!remap.moved.has(index) && !remap.vacated.has(index)) continue;
3799
- snapshots.push({ segments: [...paths.segmentsForPathKey(key)], index });
3890
+ snapshots.push({ segments: [...devtoolsShared.segmentsForPathKey(key)], index });
3800
3891
  }
3801
3892
  if (snapshots.length === 0) return;
3802
- for (const snap of snapshots) set.delete(paths.canonicalizePath(snap.segments).key);
3893
+ for (const snap of snapshots) set.delete(devtoolsShared.canonicalizePath(snap.segments).key);
3803
3894
  for (const snap of snapshots) {
3804
3895
  const target = remap.moved.get(snap.index);
3805
3896
  if (target === void 0) continue;
3806
3897
  const relocated = snap.segments.slice();
3807
3898
  relocated[idxPos] = target;
3808
- set.add(paths.canonicalizePath(relocated).key);
3899
+ set.add(devtoolsShared.canonicalizePath(relocated).key);
3809
3900
  }
3810
3901
  }
3811
3902
 
@@ -3855,7 +3946,7 @@ function createArrayBookkeeping(deps) {
3855
3946
  const now = (/* @__PURE__ */ new Date()).toISOString();
3856
3947
  diffAndApply(void 0, getAtPath(form.value, elementPath), elementPath, (patch) => {
3857
3948
  if (patch.kind !== "added") return;
3858
- const { key } = paths.canonicalizePath(patch.path);
3949
+ const { key } = devtoolsShared.canonicalizePath(patch.path);
3859
3950
  if (!originals.has(key)) originals.set(key, { segments: patch.path, value: void 0 });
3860
3951
  touchFieldRecord(key, patch.path, { updatedAt: now });
3861
3952
  });
@@ -3865,9 +3956,9 @@ function createArrayBookkeeping(deps) {
3865
3956
  if (changed.size === 0) return;
3866
3957
  const idxPos = arrayPath.length;
3867
3958
  for (const key of [...schemaErrors.keys()]) {
3868
- const segs = paths.segmentsForPathKey(key);
3959
+ const segs = devtoolsShared.segmentsForPathKey(key);
3869
3960
  if (segs === null) continue;
3870
- if (!paths.isPathPrefix(arrayPath, segs)) continue;
3961
+ if (!devtoolsShared.isPathPrefix(arrayPath, segs)) continue;
3871
3962
  if (segs.length <= idxPos) continue;
3872
3963
  const idx = segs[idxPos];
3873
3964
  if (typeof idx === "number" && changed.has(idx)) schemaErrors.delete(key);
@@ -3877,9 +3968,9 @@ function createArrayBookkeeping(deps) {
3877
3968
  if (remap.vacated.size === 0) return;
3878
3969
  const idxPos = arrayPath.length;
3879
3970
  for (const [key, entry] of [...fieldValidationState]) {
3880
- const segs = paths.segmentsForPathKey(key);
3971
+ const segs = devtoolsShared.segmentsForPathKey(key);
3881
3972
  if (segs === null) continue;
3882
- if (!paths.isPathPrefix(arrayPath, segs)) continue;
3973
+ if (!devtoolsShared.isPathPrefix(arrayPath, segs)) continue;
3883
3974
  if (segs.length <= idxPos) continue;
3884
3975
  const idx = segs[idxPos];
3885
3976
  if (typeof idx !== "number" || !remap.vacated.has(idx)) continue;
@@ -3983,13 +4074,13 @@ function isHydratedValidationErrorArray(value) {
3983
4074
  return true;
3984
4075
  }
3985
4076
  function warnMalformedHydration(formKey, kind, rawKey) {
3986
- if (!paths.__DEV__) return;
4077
+ if (!devtoolsShared.__DEV__) return;
3987
4078
  console.warn(
3988
4079
  `[attaform] hydration: skipping malformed ${kind} entry at key '${rawKey}' on form '${formKey}'. This usually means the SSR bundle is on a different version than the client (rolling deploy / stale cache).`
3989
4080
  );
3990
4081
  }
3991
4082
  function isPathKeyUnder(existingKey, parentPath) {
3992
- const parsed = paths.segmentsForPathKey(existingKey);
4083
+ const parsed = devtoolsShared.segmentsForPathKey(existingKey);
3993
4084
  if (parsed === null) return false;
3994
4085
  if (parsed.length <= parentPath.length) return false;
3995
4086
  for (let i = 0; i < parentPath.length; i++) {
@@ -4024,7 +4115,7 @@ function stripSymbolsDeep(value) {
4024
4115
  return mutated ? out : value;
4025
4116
  }
4026
4117
  function walkAuthoredFromConstraints(value, prefix, out) {
4027
- if (prefix.length > 0) out.add(paths.canonicalizePath(prefix).key);
4118
+ if (prefix.length > 0) out.add(devtoolsShared.canonicalizePath(prefix).key);
4028
4119
  if (isPlainRecord(value)) {
4029
4120
  for (const k of Object.keys(value)) {
4030
4121
  walkAuthoredFromConstraints(value[k], [...prefix, k], out);
@@ -4066,7 +4157,7 @@ function walkAuthoredFromSchemaDiff(withDefaults, withoutDefaults, prefix, out)
4066
4157
  return;
4067
4158
  }
4068
4159
  if (!Object.is(withDefaults, withoutDefaults) && prefix.length > 0) {
4069
- out.add(paths.canonicalizePath(prefix).key);
4160
+ out.add(devtoolsShared.canonicalizePath(prefix).key);
4070
4161
  }
4071
4162
  }
4072
4163
  function createFormStore(options) {
@@ -4116,7 +4207,7 @@ function createFormStore(options) {
4116
4207
  if (pathSegments.length === 0) return true;
4117
4208
  const value = getAtPath(form.value, pathSegments);
4118
4209
  if (value !== void 0) return true;
4119
- if (authoredPaths.has(paths.canonicalizePath(pathSegments).key)) return true;
4210
+ if (authoredPaths.has(devtoolsShared.canonicalizePath(pathSegments).key)) return true;
4120
4211
  return !schema.isPreprocessOrCoerceLeaf(pathSegments);
4121
4212
  });
4122
4213
  }
@@ -4147,7 +4238,7 @@ function createFormStore(options) {
4147
4238
  const blankPaths = vue.reactive(/* @__PURE__ */ new Set());
4148
4239
  const originalBlankPaths = /* @__PURE__ */ new Set();
4149
4240
  for (const raw of initialTransientList) {
4150
- const key = paths.coerceToPathKey(raw);
4241
+ const key = devtoolsShared.coerceToPathKey(raw);
4151
4242
  blankPaths.add(key);
4152
4243
  originalBlankPaths.add(key);
4153
4244
  }
@@ -4167,7 +4258,7 @@ function createFormStore(options) {
4167
4258
  const result = /* @__PURE__ */ new Map();
4168
4259
  if (blankPaths.size === 0) return result;
4169
4260
  for (const pathKey of blankPaths) {
4170
- const segments = paths.segmentsForPathKey(pathKey);
4261
+ const segments = devtoolsShared.segmentsForPathKey(pathKey);
4171
4262
  if (segments === null) continue;
4172
4263
  if (!schema.isRequiredAtPath(segments)) continue;
4173
4264
  result.set(pathKey, [makeBlankRequiredError(segments, formKey)]);
@@ -4199,7 +4290,7 @@ function createFormStore(options) {
4199
4290
  });
4200
4291
  const pathAsyncCache = /* @__PURE__ */ new Map();
4201
4292
  function pathHasAsyncValidation(path) {
4202
- const { key } = paths.canonicalizePath(path);
4293
+ const { key } = devtoolsShared.canonicalizePath(path);
4203
4294
  return pathHasAsyncValidationByKey(key, path);
4204
4295
  }
4205
4296
  function pathHasAsyncValidationByKey(key, segments) {
@@ -4303,9 +4394,9 @@ function createFormStore(options) {
4303
4394
  }
4304
4395
  function cancelTransformsUnder(prefix) {
4305
4396
  for (const [key, run] of [...transformRuns]) {
4306
- const segs = paths.segmentsForPathKey(key);
4397
+ const segs = devtoolsShared.segmentsForPathKey(key);
4307
4398
  if (segs === null) continue;
4308
- if (!paths.isPathPrefix(prefix, segs)) continue;
4399
+ if (!devtoolsShared.isPathPrefix(prefix, segs)) continue;
4309
4400
  releaseTransformRun(key, run);
4310
4401
  transformRuns.delete(key);
4311
4402
  transformErrors.delete(key);
@@ -4319,7 +4410,7 @@ function createFormStore(options) {
4319
4410
  transformWaiters.push({ key: null, resolve });
4320
4411
  });
4321
4412
  }
4322
- const { key } = paths.canonicalizePath(path);
4413
+ const { key } = devtoolsShared.canonicalizePath(path);
4323
4414
  if ((fieldTransformCounts.get(key) ?? 0) === 0) return Promise.resolve();
4324
4415
  return new Promise((resolve) => {
4325
4416
  transformWaiters.push({ key, resolve });
@@ -4328,7 +4419,7 @@ function createFormStore(options) {
4328
4419
  const initStamp = (/* @__PURE__ */ new Date()).toISOString();
4329
4420
  diffAndApply({}, schemaInitialData, [], (patch) => {
4330
4421
  if (patch.kind !== "added") return;
4331
- const { key } = paths.canonicalizePath(patch.path);
4422
+ const { key } = devtoolsShared.canonicalizePath(patch.path);
4332
4423
  originals.set(key, { segments: patch.path, value: patch.newValue });
4333
4424
  ensurePathOrdinal(key);
4334
4425
  });
@@ -4357,7 +4448,7 @@ function createFormStore(options) {
4357
4448
  } else {
4358
4449
  diffAndApply({}, initialData, [], (patch) => {
4359
4450
  if (patch.kind !== "added") return;
4360
- const { key } = paths.canonicalizePath(patch.path);
4451
+ const { key } = devtoolsShared.canonicalizePath(patch.path);
4361
4452
  fields.set(key, {
4362
4453
  path: patch.path,
4363
4454
  updatedAt: initStamp,
@@ -4423,7 +4514,7 @@ function createFormStore(options) {
4423
4514
  function commitWritePatches(patches, meta) {
4424
4515
  const now = (/* @__PURE__ */ new Date()).toISOString();
4425
4516
  for (const patch of patches) {
4426
- const { key } = paths.canonicalizePath(patch.path);
4517
+ const { key } = devtoolsShared.canonicalizePath(patch.path);
4427
4518
  if (patch.kind === "added" && !originals.has(key)) {
4428
4519
  originals.set(key, { segments: patch.path, value: void 0 });
4429
4520
  }
@@ -4585,7 +4676,7 @@ function createFormStore(options) {
4585
4676
  }
4586
4677
  }
4587
4678
  const currentValue = getAtPath(form.value, path);
4588
- const pathKey = paths.canonicalizePath(path).key;
4679
+ const pathKey = devtoolsShared.canonicalizePath(path).key;
4589
4680
  if (meta?.blank === true) {
4590
4681
  blankPaths.add(pathKey);
4591
4682
  } else {
@@ -4645,7 +4736,7 @@ function createFormStore(options) {
4645
4736
  arrayIdentity.realign(path);
4646
4737
  } else if (isContainer(currentValue) && !isContainer(value)) {
4647
4738
  if (subtreeHadRealBaseline(path, currentValue)) {
4648
- removedSubtrees.add(paths.canonicalizePath(path).key);
4739
+ removedSubtrees.add(devtoolsShared.canonicalizePath(path).key);
4649
4740
  }
4650
4741
  }
4651
4742
  const effectiveModeAfterWrite = meta?.instance?.validateOn ?? fieldValidationMode;
@@ -4659,7 +4750,7 @@ function createFormStore(options) {
4659
4750
  }
4660
4751
  function reshapeUnionVariant(parentPath, oldDiscValue, newDiscValue, variantDefault, consumerOverrides, meta) {
4661
4752
  const sameDisc = Object.is(oldDiscValue, newDiscValue);
4662
- const parentKey = paths.canonicalizePath(parentPath).key;
4753
+ const parentKey = devtoolsShared.canonicalizePath(parentPath).key;
4663
4754
  let baseline = variantDefault;
4664
4755
  let restoredBlanks;
4665
4756
  const effectiveRemember = meta?.instance?.rememberVariants ?? rememberVariants;
@@ -4714,7 +4805,7 @@ function createFormStore(options) {
4714
4805
  path: [...parentPath, ...err.path]
4715
4806
  }));
4716
4807
  applySchemaErrorsForSubtree(parentPath, reStamped);
4717
- const { key: parentKey2 } = paths.canonicalizePath(parentPath);
4808
+ const { key: parentKey2 } = devtoolsShared.canonicalizePath(parentPath);
4718
4809
  const prevValidation = fieldValidationState.get(parentKey2);
4719
4810
  if (prevValidation !== void 0) {
4720
4811
  if (prevValidation.timer !== null) clearTimeout(prevValidation.timer);
@@ -4738,7 +4829,7 @@ function createFormStore(options) {
4738
4829
  const effectiveMode = override?.mode ?? fieldValidationMode;
4739
4830
  if (effectiveMode === "submit") return;
4740
4831
  const effectiveDebounce = override?.debounceMs ?? fieldValidationDebounceMs;
4741
- const { key } = paths.canonicalizePath(path);
4832
+ const { key } = devtoolsShared.canonicalizePath(path);
4742
4833
  const prev = fieldValidationState.get(key);
4743
4834
  if (prev !== void 0) {
4744
4835
  if (prev.timer !== null) clearTimeout(prev.timer);
@@ -4769,7 +4860,7 @@ function createFormStore(options) {
4769
4860
  const subtreeScope = path.length > 0 && schema.hasContainerOrRootRefine?.() === false;
4770
4861
  const scopePath = subtreeScope ? path : void 0;
4771
4862
  const dataAtScope = subtreeScope ? getAtPath(form.value, path) : form.value;
4772
- const scopeKey = subtreeScope ? paths.canonicalizePath(path).key : paths.ROOT_PATH_KEY;
4863
+ const scopeKey = subtreeScope ? devtoolsShared.canonicalizePath(path).key : devtoolsShared.ROOT_PATH_KEY;
4773
4864
  void Promise.resolve().then(() => schema.validateAtPath(dataAtScope, scopePath)).then((response) => {
4774
4865
  if (fresh.aborted) return;
4775
4866
  if (myEpoch <= lastCommittedEpoch) return;
@@ -4814,9 +4905,9 @@ function createFormStore(options) {
4814
4905
  }
4815
4906
  function cancelFieldValidationUnder(prefix) {
4816
4907
  for (const [key, entry] of [...fieldValidationState]) {
4817
- const segs = paths.segmentsForPathKey(key);
4908
+ const segs = devtoolsShared.segmentsForPathKey(key);
4818
4909
  if (segs === null) continue;
4819
- if (!paths.isPathPrefix(prefix, segs)) continue;
4910
+ if (!devtoolsShared.isPathPrefix(prefix, segs)) continue;
4820
4911
  if (entry.timer !== null) {
4821
4912
  clearTimeout(entry.timer);
4822
4913
  } else if (!entry.settled && !entry.released) {
@@ -4889,7 +4980,7 @@ function createFormStore(options) {
4889
4980
  }
4890
4981
  function appendErrorsTo(map, entries) {
4891
4982
  for (const raw of entries) {
4892
- const { key } = paths.canonicalizePath(raw.path);
4983
+ const { key } = devtoolsShared.canonicalizePath(raw.path);
4893
4984
  const current = map.get(key);
4894
4985
  if (current === void 0) {
4895
4986
  map.set(key, [raw]);
@@ -4907,11 +4998,11 @@ function createFormStore(options) {
4907
4998
  map.clear();
4908
4999
  return;
4909
5000
  }
4910
- const { key } = paths.canonicalizePath(path);
5001
+ const { key } = devtoolsShared.canonicalizePath(path);
4911
5002
  map.delete(key);
4912
5003
  }
4913
5004
  function setSchemaErrorsForPath(path, entries) {
4914
- const { key } = paths.canonicalizePath(path);
5005
+ const { key } = devtoolsShared.canonicalizePath(path);
4915
5006
  if (entries.length === 0) {
4916
5007
  schemaErrors.delete(key);
4917
5008
  return;
@@ -4919,10 +5010,10 @@ function createFormStore(options) {
4919
5010
  schemaErrors.set(key, [...entries]);
4920
5011
  }
4921
5012
  function applySchemaErrorsForSubtree(path, entries) {
4922
- const parentKey = paths.canonicalizePath(path).key;
5013
+ const parentKey = devtoolsShared.canonicalizePath(path).key;
4923
5014
  const grouped = /* @__PURE__ */ new Map();
4924
5015
  for (const raw of entries) {
4925
- const { key } = paths.canonicalizePath(raw.path);
5016
+ const { key } = devtoolsShared.canonicalizePath(raw.path);
4926
5017
  const list = grouped.get(key);
4927
5018
  if (list === void 0) grouped.set(key, [raw]);
4928
5019
  else list.push(raw);
@@ -4948,7 +5039,7 @@ function createFormStore(options) {
4948
5039
  replaceErrorsIn(userErrors, entries);
4949
5040
  }
4950
5041
  function setUserErrorsForPath(path, entries) {
4951
- const { key } = paths.canonicalizePath(path);
5042
+ const { key } = devtoolsShared.canonicalizePath(path);
4952
5043
  if (entries.length === 0) {
4953
5044
  userErrors.delete(key);
4954
5045
  return;
@@ -4959,7 +5050,7 @@ function createFormStore(options) {
4959
5050
  clearErrorsIn(userErrors, path);
4960
5051
  }
4961
5052
  function getErrorsForPath(path) {
4962
- const { key } = paths.canonicalizePath(path);
5053
+ const { key } = devtoolsShared.canonicalizePath(path);
4963
5054
  const schemaForKey = schemaErrors.get(key);
4964
5055
  const userForKey = userErrors.get(key);
4965
5056
  const blankForKey = derivedBlankErrors.value.get(key);
@@ -4973,7 +5064,7 @@ function createFormStore(options) {
4973
5064
  return result;
4974
5065
  }
4975
5066
  function registerElement(path, element, formInstanceId) {
4976
- const { key } = paths.canonicalizePath(path);
5067
+ const { key } = devtoolsShared.canonicalizePath(path);
4977
5068
  const record = elements.get(key);
4978
5069
  const raw = vue.markRaw(element);
4979
5070
  if (record === void 0) {
@@ -4993,7 +5084,7 @@ function createFormStore(options) {
4993
5084
  return true;
4994
5085
  }
4995
5086
  function deregisterElement(path, element) {
4996
- const { key } = paths.canonicalizePath(path);
5087
+ const { key } = devtoolsShared.canonicalizePath(path);
4997
5088
  const record = elements.get(key);
4998
5089
  if (record === void 0) return 0;
4999
5090
  const removed = record.elements.delete(element);
@@ -5011,7 +5102,7 @@ function createFormStore(options) {
5011
5102
  }
5012
5103
  function markConnectedOptimistically(path) {
5013
5104
  if (!ssr) return;
5014
- const { key } = paths.canonicalizePath(path);
5105
+ const { key } = devtoolsShared.canonicalizePath(path);
5015
5106
  const current = fields.get(key);
5016
5107
  if (current?.connected === true) return;
5017
5108
  touchFieldRecord(key, path, {
@@ -5021,7 +5112,7 @@ function createFormStore(options) {
5021
5112
  });
5022
5113
  }
5023
5114
  function markHostConnected(path, connected) {
5024
- const { key } = paths.canonicalizePath(path);
5115
+ const { key } = devtoolsShared.canonicalizePath(path);
5025
5116
  const current = fields.get(key);
5026
5117
  if (connected) {
5027
5118
  if (current?.connected === true) return;
@@ -5036,7 +5127,7 @@ function createFormStore(options) {
5036
5127
  }
5037
5128
  }
5038
5129
  function markFocused(path, focused, meta) {
5039
- const { key } = paths.canonicalizePath(path);
5130
+ const { key } = devtoolsShared.canonicalizePath(path);
5040
5131
  const current = fields.get(key);
5041
5132
  touchFieldRecord(key, path, {
5042
5133
  focused,
@@ -5056,7 +5147,7 @@ function createFormStore(options) {
5056
5147
  let snapshot = void 0;
5057
5148
  let snapshotScopeLength = 0;
5058
5149
  for (let i = path.length; i >= 0; i--) {
5059
- const ancestorKey = paths.canonicalizePath(path.slice(0, i)).key;
5150
+ const ancestorKey = devtoolsShared.canonicalizePath(path.slice(0, i)).key;
5060
5151
  const entry = pathSnapshots.get(ancestorKey);
5061
5152
  if (entry !== void 0) {
5062
5153
  snapshot = entry;
@@ -5083,7 +5174,7 @@ function createFormStore(options) {
5083
5174
  }
5084
5175
  }
5085
5176
  function markInteracted(path) {
5086
- const { key } = paths.canonicalizePath(path);
5177
+ const { key } = devtoolsShared.canonicalizePath(path);
5087
5178
  if (fields.get(key)?.interacted === true) return;
5088
5179
  touchFieldRecord(key, path, { interacted: true });
5089
5180
  }
@@ -5091,15 +5182,15 @@ function createFormStore(options) {
5091
5182
  const formValue = form.value;
5092
5183
  let touchedAny = false;
5093
5184
  for (const [, entry] of originals) {
5094
- if (!paths.isPathPrefix(segments, entry.segments)) continue;
5185
+ if (!devtoolsShared.isPathPrefix(segments, entry.segments)) continue;
5095
5186
  if (!hasAtPath(formValue, entry.segments)) continue;
5096
5187
  touchedAny = true;
5097
- const leafKey = paths.canonicalizePath(entry.segments).key;
5188
+ const leafKey = devtoolsShared.canonicalizePath(entry.segments).key;
5098
5189
  const current = fields.get(leafKey);
5099
5190
  if (current?.touched === true) continue;
5100
5191
  touchFieldRecord(leafKey, entry.segments, { touched: true });
5101
5192
  }
5102
- if (!touchedAny && paths.__DEV__) {
5193
+ if (!touchedAny && devtoolsShared.__DEV__) {
5103
5194
  console.warn(
5104
5195
  `[attaform] form.touch(): no fields resolved at path ${JSON.stringify(segments)}. Check the path matches an existing field or container.`
5105
5196
  );
@@ -5162,25 +5253,25 @@ function createFormStore(options) {
5162
5253
  }
5163
5254
  }
5164
5255
  function clearHydrationFailedEntry() {
5165
- const existing = schemaErrors.get(paths.ROOT_PATH_KEY);
5256
+ const existing = schemaErrors.get(devtoolsShared.ROOT_PATH_KEY);
5166
5257
  if (existing === void 0) return;
5167
5258
  const filtered = existing.filter((e) => e.code !== AttaformErrorCode.HydrationFailed);
5168
5259
  if (filtered.length === 0) {
5169
- schemaErrors.delete(paths.ROOT_PATH_KEY);
5260
+ schemaErrors.delete(devtoolsShared.ROOT_PATH_KEY);
5170
5261
  } else {
5171
- schemaErrors.set(paths.ROOT_PATH_KEY, filtered);
5262
+ schemaErrors.set(devtoolsShared.ROOT_PATH_KEY, filtered);
5172
5263
  }
5173
5264
  }
5174
5265
  function appendHydrationFailedEntry(error) {
5175
5266
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : "Hydration failed";
5176
5267
  const entry = {
5177
5268
  message,
5178
- path: [...paths.ROOT_PATH],
5269
+ path: [...devtoolsShared.ROOT_PATH],
5179
5270
  formKey,
5180
5271
  code: AttaformErrorCode.HydrationFailed
5181
5272
  };
5182
- const existing = schemaErrors.get(paths.ROOT_PATH_KEY) ?? [];
5183
- schemaErrors.set(paths.ROOT_PATH_KEY, [...existing, entry]);
5273
+ const existing = schemaErrors.get(devtoolsShared.ROOT_PATH_KEY) ?? [];
5274
+ schemaErrors.set(devtoolsShared.ROOT_PATH_KEY, [...existing, entry]);
5184
5275
  return entry;
5185
5276
  }
5186
5277
  function reset(nextDefaultValues) {
@@ -5199,7 +5290,7 @@ function createFormStore(options) {
5199
5290
  originals.clear();
5200
5291
  diffAndApply({}, next, [], (patch) => {
5201
5292
  if (patch.kind !== "added") return;
5202
- const { key } = paths.canonicalizePath(patch.path);
5293
+ const { key } = devtoolsShared.canonicalizePath(patch.path);
5203
5294
  originals.set(key, { segments: patch.path, value: patch.newValue });
5204
5295
  });
5205
5296
  if (nextDefaultValues !== void 0) {
@@ -5259,14 +5350,14 @@ function createFormStore(options) {
5259
5350
  }
5260
5351
  }
5261
5352
  function resetField(path) {
5262
- const { key: targetKey, segments: targetSegments } = paths.canonicalizePath(path);
5353
+ const { key: targetKey, segments: targetSegments } = devtoolsShared.canonicalizePath(path);
5263
5354
  variantMemory.clearUnderPath(targetSegments);
5264
5355
  cancelFieldValidationUnder(targetSegments);
5265
5356
  cancelTransformsUnder(targetSegments);
5266
5357
  for (const [snapKey] of [...pathSnapshots]) {
5267
- const segs = paths.segmentsForPathKey(snapKey);
5358
+ const segs = devtoolsShared.segmentsForPathKey(snapKey);
5268
5359
  if (segs === null) continue;
5269
- if (paths.isPathPrefix(targetSegments, segs)) pathSnapshots.delete(snapKey);
5360
+ if (devtoolsShared.isPathPrefix(targetSegments, segs)) pathSnapshots.delete(snapKey);
5270
5361
  }
5271
5362
  const leafEntry = originals.get(targetKey);
5272
5363
  if (leafEntry !== void 0) {
@@ -5281,7 +5372,7 @@ function createFormStore(options) {
5281
5372
  let anyMatch = false;
5282
5373
  for (const [, entry] of originals) {
5283
5374
  const leafSegments = entry.segments;
5284
- if (!paths.isPathPrefix(targetSegments, leafSegments)) continue;
5375
+ if (!devtoolsShared.isPathPrefix(targetSegments, leafSegments)) continue;
5285
5376
  if (leafSegments.length === targetSegments.length) continue;
5286
5377
  anyMatch = true;
5287
5378
  const relative = leafSegments.slice(targetSegments.length);
@@ -5302,14 +5393,14 @@ function createFormStore(options) {
5302
5393
  deleteErrorsUnderPrefix(schemaErrors, targetSegments);
5303
5394
  deleteErrorsUnderPrefix(userErrors, targetSegments);
5304
5395
  for (const [fieldKey, record] of Array.from(fields.entries())) {
5305
- if (paths.isPathPrefix(targetSegments, record.path)) clearFieldRecordFlags(fieldKey);
5396
+ if (devtoolsShared.isPathPrefix(targetSegments, record.path)) clearFieldRecordFlags(fieldKey);
5306
5397
  }
5307
5398
  }
5308
5399
  function deleteErrorsUnderPrefix(map, prefix) {
5309
5400
  for (const [errorKey, errs] of Array.from(map.entries())) {
5310
5401
  const first = errs[0];
5311
5402
  if (first === void 0) continue;
5312
- if (paths.isPathPrefix(prefix, first.path)) {
5403
+ if (devtoolsShared.isPathPrefix(prefix, first.path)) {
5313
5404
  map.delete(errorKey);
5314
5405
  }
5315
5406
  }
@@ -5320,7 +5411,7 @@ function createFormStore(options) {
5320
5411
  fields.set(pathKey, withClearedHistoryFlags(record, (/* @__PURE__ */ new Date()).toISOString()));
5321
5412
  }
5322
5413
  function isPristineAtPath(path) {
5323
- const { key, segments } = paths.canonicalizePath(path);
5414
+ const { key, segments } = devtoolsShared.canonicalizePath(path);
5324
5415
  return isPristineAtPathByKey(key, segments);
5325
5416
  }
5326
5417
  function isPristineAtPathByKey(key, segments) {
@@ -5336,7 +5427,7 @@ function createFormStore(options) {
5336
5427
  let had = false;
5337
5428
  diffAndApply(removedValue, void 0, prefix, (patch) => {
5338
5429
  if (had || patch.kind !== "removed") return;
5339
- const record = originals.get(paths.canonicalizePath(patch.path).key);
5430
+ const record = originals.get(devtoolsShared.canonicalizePath(patch.path).key);
5340
5431
  if (record?.value !== void 0) had = true;
5341
5432
  });
5342
5433
  return had;
@@ -5344,20 +5435,20 @@ function createFormStore(options) {
5344
5435
  function hasRemovedSubtreeUnder(prefix) {
5345
5436
  if (removedSubtrees.size === 0) return false;
5346
5437
  for (const key of removedSubtrees) {
5347
- const segments = paths.segmentsForPathKey(key);
5438
+ const segments = devtoolsShared.segmentsForPathKey(key);
5348
5439
  if (segments === null) continue;
5349
- if (!paths.isPathPrefix(prefix, segments)) continue;
5440
+ if (!devtoolsShared.isPathPrefix(prefix, segments)) continue;
5350
5441
  if (isContainer(getAtPath(vue.toRaw(form.value), segments))) continue;
5351
5442
  return true;
5352
5443
  }
5353
5444
  return false;
5354
5445
  }
5355
5446
  function getFieldRecord(path) {
5356
- const { key } = paths.canonicalizePath(path);
5447
+ const { key } = devtoolsShared.canonicalizePath(path);
5357
5448
  return fields.get(key);
5358
5449
  }
5359
5450
  function getOriginalAtPath(path) {
5360
- const { key } = paths.canonicalizePath(path);
5451
+ const { key } = devtoolsShared.canonicalizePath(path);
5361
5452
  return originals.get(key)?.value;
5362
5453
  }
5363
5454
  function getFirstErrorElement(formInstanceId) {
@@ -5473,33 +5564,6 @@ function createFormStore(options) {
5473
5564
  };
5474
5565
  }
5475
5566
 
5476
- function captureUserCallSite() {
5477
- const raw = new Error().stack;
5478
- if (typeof raw !== "string") return void 0;
5479
- const lines = raw.split("\n");
5480
- for (let i = 1; i < lines.length; i++) {
5481
- const frame = lines[i];
5482
- if (frame === void 0) continue;
5483
- if (/attaform[/-]forms?/i.test(frame)) continue;
5484
- if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
5485
- const trimmed = frame.trim();
5486
- if (trimmed.length === 0) continue;
5487
- return shortenSourceFrame(trimmed);
5488
- }
5489
- return void 0;
5490
- }
5491
- function shortenSourceFrame(frame) {
5492
- const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
5493
- if (match === null) return frame;
5494
- const [, urlOrPath, line] = match;
5495
- if (urlOrPath === void 0 || line === void 0) return frame;
5496
- let path = urlOrPath;
5497
- path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
5498
- path = path.replace(/^_nuxt\//, "");
5499
- path = path.replace(/^\//, "");
5500
- return `(${path}:${line})`;
5501
- }
5502
-
5503
5567
  function getComputedSchema(formKey, schemaOrCallback, options) {
5504
5568
  if (typeof schemaOrCallback === "function") return schemaOrCallback(formKey, options);
5505
5569
  return schemaOrCallback;
@@ -5540,7 +5604,7 @@ function errorFieldsEqual(av, bvi) {
5540
5604
  if (av.message !== bvi.message) return false;
5541
5605
  if (av.code !== bvi.code) return false;
5542
5606
  if (av.formKey !== bvi.formKey) return false;
5543
- if (av.path !== bvi.path && !paths.pathsEqual(av.path, bvi.path)) return false;
5607
+ if (av.path !== bvi.path && !devtoolsShared.pathsEqual(av.path, bvi.path)) return false;
5544
5608
  return dataEqual(av.data, bvi.data);
5545
5609
  }
5546
5610
  function errorsEqual(a, b) {
@@ -5715,12 +5779,12 @@ function resolveTrichotomy(input) {
5715
5779
 
5716
5780
  function useAbstractForm(configuration, options) {
5717
5781
  if (configuration === void 0 || configuration === null || configuration.schema === void 0) {
5718
- throw new paths.InvalidUseFormConfigError();
5782
+ throw new devtoolsShared.InvalidUseFormConfigError();
5719
5783
  }
5720
5784
  const key = resolveFormKey(configuration.key);
5721
5785
  const instance = vue.getCurrentInstance();
5722
- if (instance !== null) paths.ensureAttaformInstalled(instance.appContext.app);
5723
- const registry = options?.registry ?? paths.useRegistry();
5786
+ if (instance !== null) devtoolsShared.ensureAttaformInstalled(instance.appContext.app);
5787
+ const registry = options?.registry ?? devtoolsShared.useRegistry();
5724
5788
  const resolvedDefaults = resolveTrichotomy(configuration.defaultValues);
5725
5789
  const materialisedDefaults = resolvedDefaults.kind === "sync" ? resolvedDefaults.value : void 0;
5726
5790
  const { defaultValues: _droppedDefaults, ...configWithoutDefaults } = configuration;
@@ -5735,7 +5799,7 @@ function useAbstractForm(configuration, options) {
5735
5799
  });
5736
5800
  const resolvedSchema = getComputedSchema(key, configuration.schema, { maxRecursionDepth });
5737
5801
  const existing = registry.forms.get(key);
5738
- if (paths.__DEV__ && existing !== void 0) {
5802
+ if (devtoolsShared.__DEV__ && existing !== void 0) {
5739
5803
  void import('../chunks/dev-key-collision-warnings.cjs').then((m) => {
5740
5804
  void m.warnOnSchemaFingerprintMismatch(key, existing.schema, resolvedSchema);
5741
5805
  });
@@ -5772,11 +5836,11 @@ function useAbstractForm(configuration, options) {
5772
5836
  }
5773
5837
  if (configuration.key === void 0) {
5774
5838
  recordAmbientProvide(registry.ssr);
5775
- vue.provide(paths.kFormContext, state);
5839
+ vue.provide(devtoolsShared.kFormContext, state);
5776
5840
  }
5777
5841
  const formInstanceId = vue.getCurrentInstance() !== null ? vue.useId() : `atta:form-instance:${formInstanceCounter++}`;
5778
5842
  if (vue.getCurrentInstance() !== null) {
5779
- vue.provide(paths.kFormInstanceId, formInstanceId);
5843
+ vue.provide(devtoolsShared.kFormInstanceId, formInstanceId);
5780
5844
  }
5781
5845
  const apiOptions = {};
5782
5846
  if (merged.onInvalidSubmit !== void 0) {
@@ -5883,9 +5947,9 @@ function buildFreshState(key, schema, configuration, registry) {
5883
5947
  }
5884
5948
  let anonCounter = 0;
5885
5949
  let formInstanceCounter = 0;
5886
- const ambientProvideHistory = paths.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
5950
+ const ambientProvideHistory = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
5887
5951
  function recordAmbientProvide(ssr) {
5888
- if (!paths.__DEV__ || ssr || ambientProvideHistory === null) return;
5952
+ if (!devtoolsShared.__DEV__ || ssr || ambientProvideHistory === null) return;
5889
5953
  const instance = vue.getCurrentInstance();
5890
5954
  if (instance === null) return;
5891
5955
  const instanceKey = instance;
@@ -5902,7 +5966,7 @@ function recordAmbientProvide(ssr) {
5902
5966
  function resolveFormKey(key) {
5903
5967
  if (key !== void 0 && key !== null && key !== "") {
5904
5968
  if (key.startsWith(RESERVED_KEY_PREFIX)) {
5905
- throw new paths.ReservedFormKeyError(key);
5969
+ throw new devtoolsShared.ReservedFormKeyError(key);
5906
5970
  }
5907
5971
  return key;
5908
5972
  }
@@ -5917,8 +5981,8 @@ function injectForm(input) {
5917
5981
  const key = typeof input === "string" ? input : input?.key;
5918
5982
  const ssrAccessed = typeof input === "object" && input !== null ? input.__ssrAccessed === true : false;
5919
5983
  const instance = vue.getCurrentInstance();
5920
- if (instance !== null) paths.ensureAttaformInstalled(instance.appContext.app);
5921
- const registry = paths.useRegistry();
5984
+ if (instance !== null) devtoolsShared.ensureAttaformInstalled(instance.appContext.app);
5985
+ const registry = devtoolsShared.useRegistry();
5922
5986
  const state = resolveState(key, registry);
5923
5987
  if (state === null) return null;
5924
5988
  if (vue.getCurrentScope() !== void 0) {
@@ -5934,7 +5998,7 @@ function injectForm(input) {
5934
5998
  if (history !== void 0) {
5935
5999
  apiOptions.history = history;
5936
6000
  }
5937
- const ambientInstanceId = vue.getCurrentInstance() !== null ? vue.inject(paths.kFormInstanceId, null) : null;
6001
+ const ambientInstanceId = vue.getCurrentInstance() !== null ? vue.inject(devtoolsShared.kFormInstanceId, null) : null;
5938
6002
  const formInstanceId = ambientInstanceId ?? (vue.getCurrentInstance() !== null ? vue.useId() : `atta:form-instance-injected:${injectedInstanceCounter++}`);
5939
6003
  return buildFormApi(
5940
6004
  state,
@@ -5951,7 +6015,7 @@ function resolveState(key, registry) {
5951
6015
  }
5952
6016
  return stored;
5953
6017
  }
5954
- const ambient = vue.inject(paths.kFormContext, null);
6018
+ const ambient = vue.inject(devtoolsShared.kFormContext, null);
5955
6019
  if (ambient === null) return null;
5956
6020
  warnIfAmbientProviderHadDuplicates();
5957
6021
  return ambient;
@@ -5962,7 +6026,7 @@ function availableKeysHint$1(forms) {
5962
6026
  return `Registered keys: ${addressable.map((key) => `'${key}'`).join(", ")}.`;
5963
6027
  }
5964
6028
  function warnMiss$1(detail, ssr, forms) {
5965
- if (!paths.__DEV__ || ssr) return;
6029
+ if (!devtoolsShared.__DEV__ || ssr) return;
5966
6030
  const frame = captureUserCallSite();
5967
6031
  const parts = [`[attaform] injectForm: ${detail}. Returning null.`];
5968
6032
  const keys = availableKeysHint$1(forms);
@@ -5974,7 +6038,7 @@ function warnMiss$1(detail, ssr, forms) {
5974
6038
  console.warn(parts.join(" "));
5975
6039
  }
5976
6040
  function warnIfAmbientProviderHadDuplicates() {
5977
- if (!paths.__DEV__ || ambientProvideHistory === null) return;
6041
+ if (!devtoolsShared.__DEV__ || ambientProvideHistory === null) return;
5978
6042
  let ancestor = vue.getCurrentInstance()?.parent ?? null;
5979
6043
  while (ancestor !== null) {
5980
6044
  const history = ambientProvideHistory.get(ancestor);
@@ -5991,7 +6055,7 @@ function warnIfAmbientProviderHadDuplicates() {
5991
6055
  }
5992
6056
  }
5993
6057
 
5994
- const warnedNoParentRV = paths.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
6058
+ const warnedNoParentRV = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
5995
6059
  let warnedOutsideSetup = false;
5996
6060
  function makeRegisterValueProxy(capturedRegisterValue) {
5997
6061
  return new Proxy({}, {
@@ -6030,7 +6094,7 @@ function useRegister() {
6030
6094
  warnOutsideSetup();
6031
6095
  return makeRegisterValueProxy(vue.shallowRef(void 0));
6032
6096
  }
6033
- paths.ensureAttaformInstalled(instance.appContext.app);
6097
+ devtoolsShared.ensureAttaformInstalled(instance.appContext.app);
6034
6098
  const capturedRegisterValue = vue.shallowRef(void 0);
6035
6099
  const refreshAndStripBridgeAttrs = () => {
6036
6100
  const rawAttrs = instance.attrs;
@@ -6068,7 +6132,7 @@ function useRegister() {
6068
6132
  return makeRegisterValueProxy(capturedRegisterValue);
6069
6133
  }
6070
6134
  function warnOutsideSetup() {
6071
- if (!paths.__DEV__) return;
6135
+ if (!devtoolsShared.__DEV__) return;
6072
6136
  if (warnedOutsideSetup) return;
6073
6137
  warnedOutsideSetup = true;
6074
6138
  const frame = captureUserCallSite();
@@ -6077,7 +6141,7 @@ function warnOutsideSetup() {
6077
6141
  );
6078
6142
  }
6079
6143
  function warnNoParentRV(instance) {
6080
- if (!paths.__DEV__ || warnedNoParentRV === null) return;
6144
+ if (!devtoolsShared.__DEV__ || warnedNoParentRV === null) return;
6081
6145
  if (warnedNoParentRV.has(instance)) return;
6082
6146
  warnedNoParentRV.add(instance);
6083
6147
  const frame = captureUserCallSite();
@@ -6086,7 +6150,7 @@ function warnNoParentRV(instance) {
6086
6150
  );
6087
6151
  }
6088
6152
 
6089
- const LAZY_BRAND = Symbol.for("attaform/wizard-lazy");
6153
+ const LAZY_BRAND = /* @__PURE__ */ Symbol.for("attaform/wizard-lazy");
6090
6154
  function lazy(resolve) {
6091
6155
  return { [LAZY_BRAND]: true, resolve };
6092
6156
  }
@@ -6236,12 +6300,12 @@ function asHandleSubmitSource(form) {
6236
6300
  }
6237
6301
  function useWizard(options) {
6238
6302
  const rawSteps = Array.isArray(options.steps) ? options.steps : [];
6239
- if (rawSteps.length === 0 && paths.__DEV__) {
6303
+ if (rawSteps.length === 0 && devtoolsShared.__DEV__) {
6240
6304
  console.error(
6241
6305
  "[attaform] useWizard({ steps }): expected a non-empty array of step slots. Continuing with an empty step list \u2014 wizard.currentStep reads as undefined, navigation refuses, handleSubmit no-ops."
6242
6306
  );
6243
6307
  }
6244
- const registry = paths.useRegistry();
6308
+ const registry = devtoolsShared.useRegistry();
6245
6309
  const noopForms = /* @__PURE__ */ new Map();
6246
6310
  const lazyNoopScope = vue.effectScope(true);
6247
6311
  for (const slot of rawSteps) {
@@ -6372,7 +6436,7 @@ function useWizard(options) {
6372
6436
  const form = resolveSlot(slot, i, slotCtx);
6373
6437
  if (form === void 0) continue;
6374
6438
  if (seen.has(form.key)) {
6375
- if (paths.__DEV__) {
6439
+ if (devtoolsShared.__DEV__) {
6376
6440
  console.warn(
6377
6441
  `[attaform] useWizard: step "${form.key}" appears in more than one slot. The wizard treats the first occurrence as canonical and drops later duplicates.`
6378
6442
  );
@@ -6631,7 +6695,7 @@ function useWizard(options) {
6631
6695
  }
6632
6696
  });
6633
6697
  const statuses = buildWizardStatusesProxy(statusesRecord);
6634
- if (paths.__DEV__ && seedRef.value !== void 0) {
6698
+ if (devtoolsShared.__DEV__ && seedRef.value !== void 0) {
6635
6699
  const seedMap = seedRef.value;
6636
6700
  const known = new Set(compiledSteps.value.map((s) => s.key));
6637
6701
  const unknown = [];
@@ -6670,7 +6734,7 @@ function useWizard(options) {
6670
6734
  const visited = vue.ref([]);
6671
6735
  const wantsDefaultUrlSync = options.restore !== false || options.persist !== false;
6672
6736
  const historyHandle = wantsDefaultUrlSync ? createWizardHistory(DEFAULT_STEP_PARAM) : NOOP_WIZARD_HISTORY;
6673
- const injectedResolver = vue.inject(paths.kAttaformWizardActiveStepResolver, null);
6737
+ const injectedResolver = vue.inject(devtoolsShared.kAttaformWizardActiveStepResolver, null);
6674
6738
  const urlMirror = vue.ref(void 0);
6675
6739
  const initialUrlValue = injectedResolver !== null ? injectedResolver(DEFAULT_STEP_PARAM) : historyHandle.read();
6676
6740
  urlMirror.value = initialUrlValue;
@@ -6703,7 +6767,7 @@ function useWizard(options) {
6703
6767
  if (restoredStep !== void 0 && isCompiledKey(restoredStep)) {
6704
6768
  initialKey = restoredStep;
6705
6769
  } else {
6706
- if (paths.__DEV__ && restoredStep !== void 0 && restoredStep !== "" && !isCompiledKey(restoredStep)) {
6770
+ if (devtoolsShared.__DEV__ && restoredStep !== void 0 && restoredStep !== "" && !isCompiledKey(restoredStep)) {
6707
6771
  console.warn(
6708
6772
  `[attaform] useWizard: restore() yielded step "${restoredStep}" which is not in the compiled step list. Falling back to the first step.`
6709
6773
  );
@@ -6736,7 +6800,7 @@ function useWizard(options) {
6736
6800
  (step) => {
6737
6801
  if (step === void 0) return;
6738
6802
  if (!isCompiledKey(step)) {
6739
- if (paths.__DEV__) {
6803
+ if (devtoolsShared.__DEV__) {
6740
6804
  console.warn(
6741
6805
  `[attaform] useWizard: restore() yielded step "${step}" which is not in the compiled step list. Ignoring.`
6742
6806
  );
@@ -6793,7 +6857,7 @@ function useWizard(options) {
6793
6857
  }
6794
6858
  async function next() {
6795
6859
  if (submitting.value) {
6796
- if (paths.__DEV__) {
6860
+ if (devtoolsShared.__DEV__) {
6797
6861
  console.warn(
6798
6862
  `[attaform] wizard.next(): blocked while a submit is in flight. Wait for handleSubmit to settle.`
6799
6863
  );
@@ -6802,14 +6866,14 @@ function useWizard(options) {
6802
6866
  }
6803
6867
  const list = compiledSteps.value;
6804
6868
  if (list.length === 0) {
6805
- if (paths.__DEV__) {
6869
+ if (devtoolsShared.__DEV__) {
6806
6870
  console.warn(`[attaform] wizard.next(): wizard has no compiled steps; no-op.`);
6807
6871
  }
6808
6872
  return;
6809
6873
  }
6810
6874
  const idx = activeIndex.value;
6811
6875
  if (idx < 0 || idx >= list.length - 1) {
6812
- if (paths.__DEV__) {
6876
+ if (devtoolsShared.__DEV__) {
6813
6877
  console.warn(
6814
6878
  `[attaform] wizard.next(): already on the final step ("${activeKey.value}"). Use wizard.handleSubmit() to submit.`
6815
6879
  );
@@ -6822,21 +6886,21 @@ function useWizard(options) {
6822
6886
  }
6823
6887
  async function tryNext() {
6824
6888
  if (submitting.value) {
6825
- if (paths.__DEV__) {
6889
+ if (devtoolsShared.__DEV__) {
6826
6890
  console.warn(`[attaform] wizard.tryNext(): blocked while a submit is in flight.`);
6827
6891
  }
6828
6892
  return false;
6829
6893
  }
6830
6894
  const list = compiledSteps.value;
6831
6895
  if (list.length === 0) {
6832
- if (paths.__DEV__) {
6896
+ if (devtoolsShared.__DEV__) {
6833
6897
  console.warn(`[attaform] wizard.tryNext(): wizard has no compiled steps; no-op.`);
6834
6898
  }
6835
6899
  return false;
6836
6900
  }
6837
6901
  const idx = activeIndex.value;
6838
6902
  if (idx < 0 || idx >= list.length - 1) {
6839
- if (paths.__DEV__) {
6903
+ if (devtoolsShared.__DEV__) {
6840
6904
  console.warn(
6841
6905
  `[attaform] wizard.tryNext(): already on the final step ("${activeKey.value}"). Use wizard.handleSubmit() to submit.`
6842
6906
  );
@@ -6855,20 +6919,20 @@ function useWizard(options) {
6855
6919
  }
6856
6920
  function back() {
6857
6921
  if (submitting.value) {
6858
- if (paths.__DEV__) {
6922
+ if (devtoolsShared.__DEV__) {
6859
6923
  console.warn(`[attaform] wizard.back(): blocked while a submit is in flight.`);
6860
6924
  }
6861
6925
  return;
6862
6926
  }
6863
6927
  if (compiledSteps.value.length === 0) {
6864
- if (paths.__DEV__) {
6928
+ if (devtoolsShared.__DEV__) {
6865
6929
  console.warn(`[attaform] wizard.back(): wizard has no compiled steps; no-op.`);
6866
6930
  }
6867
6931
  return;
6868
6932
  }
6869
6933
  const idx = activeIndex.value;
6870
6934
  if (idx <= 0) {
6871
- if (paths.__DEV__) {
6935
+ if (devtoolsShared.__DEV__) {
6872
6936
  console.warn(`[attaform] wizard.back(): already on the first step ("${activeKey.value}").`);
6873
6937
  }
6874
6938
  return;
@@ -6879,13 +6943,13 @@ function useWizard(options) {
6879
6943
  }
6880
6944
  function goTo(key) {
6881
6945
  if (submitting.value) {
6882
- if (paths.__DEV__) {
6946
+ if (devtoolsShared.__DEV__) {
6883
6947
  console.warn(`[attaform] wizard.goTo(): blocked while a submit is in flight.`);
6884
6948
  }
6885
6949
  return;
6886
6950
  }
6887
6951
  if (!isCompiledKey(key)) {
6888
- if (paths.__DEV__) {
6952
+ if (devtoolsShared.__DEV__) {
6889
6953
  const known = compiledSteps.value.map((s) => `"${s.key}"`).join(", ");
6890
6954
  console.warn(`[attaform] wizard.goTo("${key}"): unknown step key. Known keys: ${known}.`);
6891
6955
  }
@@ -6969,13 +7033,13 @@ function useWizard(options) {
6969
7033
  event.preventDefault();
6970
7034
  }
6971
7035
  if (compiledSteps.value.length === 0) {
6972
- if (paths.__DEV__) {
7036
+ if (devtoolsShared.__DEV__) {
6973
7037
  console.warn(`[attaform] wizard.handleSubmit: wizard has no compiled steps; no-op.`);
6974
7038
  }
6975
7039
  return;
6976
7040
  }
6977
7041
  if (submitting.value) {
6978
- if (paths.__DEV__) {
7042
+ if (devtoolsShared.__DEV__) {
6979
7043
  console.warn(
6980
7044
  `[attaform] wizard.handleSubmit: re-entrant submit while a prior call is still in flight; resolving no-op.`
6981
7045
  );
@@ -7025,7 +7089,7 @@ function useWizard(options) {
7025
7089
  try {
7026
7090
  await onError(callbackErrors);
7027
7091
  } catch (cause) {
7028
- throw new paths.SubmitErrorHandlerError("User-provided onError threw", { cause });
7092
+ throw new devtoolsShared.SubmitErrorHandlerError("User-provided onError threw", { cause });
7029
7093
  }
7030
7094
  }
7031
7095
  return;
@@ -7037,12 +7101,12 @@ function useWizard(options) {
7037
7101
  try {
7038
7102
  await onError(errors);
7039
7103
  } catch (cause) {
7040
- throw new paths.SubmitErrorHandlerError("User-provided onError threw", { cause });
7104
+ throw new devtoolsShared.SubmitErrorHandlerError("User-provided onError threw", { cause });
7041
7105
  }
7042
7106
  }
7043
7107
  }
7044
7108
  } catch (err) {
7045
- submitError.value = paths.toError(err);
7109
+ submitError.value = devtoolsShared.toError(err);
7046
7110
  } finally {
7047
7111
  submitting.value = false;
7048
7112
  }
@@ -7138,7 +7202,7 @@ function useWizard(options) {
7138
7202
  const existing = registry.wizards.get(wizardKey);
7139
7203
  if (existing === void 0) {
7140
7204
  registry.wizards.set(wizardKey, handle);
7141
- } else if (paths.__DEV__ && explicitKey !== void 0) {
7205
+ } else if (devtoolsShared.__DEV__ && explicitKey !== void 0) {
7142
7206
  console.warn(
7143
7207
  `[attaform] useWizard({ key: "${wizardKey}" }): a wizard with this key is already registered. Keeping the existing handle. Pass a unique key to each useWizard call, or share the original handle via injectWizard("${wizardKey}").`
7144
7208
  );
@@ -7149,14 +7213,14 @@ function useWizard(options) {
7149
7213
  }
7150
7214
  if (vue.getCurrentInstance() !== null && explicitKey === void 0) {
7151
7215
  recordAmbientWizardProvide(registry.ssr);
7152
- vue.provide(paths.kAttaformAncestorWizard, handle);
7216
+ vue.provide(devtoolsShared.kAttaformAncestorWizard, handle);
7153
7217
  }
7154
7218
  return handle;
7155
7219
  }
7156
7220
  let anonWizardCounter = 0;
7157
- const ambientWizardProvideHistory = paths.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
7221
+ const ambientWizardProvideHistory = devtoolsShared.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
7158
7222
  function recordAmbientWizardProvide(ssr) {
7159
- if (!paths.__DEV__ || ssr || ambientWizardProvideHistory === null) return;
7223
+ if (!devtoolsShared.__DEV__ || ssr || ambientWizardProvideHistory === null) return;
7160
7224
  const instance = vue.getCurrentInstance();
7161
7225
  if (instance === null) return;
7162
7226
  const instanceKey = instance;
@@ -7186,8 +7250,8 @@ function isAnyForm(value) {
7186
7250
  function injectWizard(input) {
7187
7251
  const key = typeof input === "string" ? input : input?.key;
7188
7252
  const instance = vue.getCurrentInstance();
7189
- if (instance !== null) paths.ensureAttaformInstalled(instance.appContext.app);
7190
- const registry = paths.useRegistry();
7253
+ if (instance !== null) devtoolsShared.ensureAttaformInstalled(instance.appContext.app);
7254
+ const registry = devtoolsShared.useRegistry();
7191
7255
  if (key !== void 0) {
7192
7256
  const handle = registry.wizards.get(key);
7193
7257
  if (handle === void 0) {
@@ -7204,7 +7268,7 @@ function injectWizard(input) {
7204
7268
  }
7205
7269
  return handle;
7206
7270
  }
7207
- const ambient = vue.inject(paths.kAttaformAncestorWizard, null);
7271
+ const ambient = vue.inject(devtoolsShared.kAttaformAncestorWizard, null);
7208
7272
  if (ambient === null) return null;
7209
7273
  warnIfAmbientWizardProviderHadDuplicates();
7210
7274
  return ambient;
@@ -7215,7 +7279,7 @@ function availableKeysHint(wizards) {
7215
7279
  return `Registered keys: ${keys}.`;
7216
7280
  }
7217
7281
  function warnMiss(detail, ssr, hint) {
7218
- if (!paths.__DEV__ || ssr) return;
7282
+ if (!devtoolsShared.__DEV__ || ssr) return;
7219
7283
  const frame = captureUserCallSite();
7220
7284
  const parts = [`[attaform] injectWizard: ${detail}. Returning null.`];
7221
7285
  if (hint !== void 0) parts.push(hint);
@@ -7226,7 +7290,7 @@ function warnMiss(detail, ssr, hint) {
7226
7290
  console.warn(parts.join(" "));
7227
7291
  }
7228
7292
  function warnIfAmbientWizardProviderHadDuplicates() {
7229
- if (!paths.__DEV__ || ambientWizardProvideHistory === null) return;
7293
+ if (!devtoolsShared.__DEV__ || ambientWizardProvideHistory === null) return;
7230
7294
  let ancestor = vue.getCurrentInstance()?.parent ?? null;
7231
7295
  while (ancestor !== null) {
7232
7296
  const history = ambientWizardProvideHistory.get(ancestor);
@@ -7243,11 +7307,31 @@ function warnIfAmbientWizardProviderHadDuplicates() {
7243
7307
  }
7244
7308
  }
7245
7309
 
7310
+ function escapeForInlineScript(json) {
7311
+ return json.replace(/[<>&\u2028\u2029]/g, (char) => {
7312
+ switch (char) {
7313
+ case "<":
7314
+ return "\\u003c";
7315
+ case ">":
7316
+ return "\\u003e";
7317
+ case "&":
7318
+ return "\\u0026";
7319
+ case "\u2028":
7320
+ return "\\u2028";
7321
+ case "\u2029":
7322
+ return "\\u2029";
7323
+ default:
7324
+ return char;
7325
+ }
7326
+ });
7327
+ }
7328
+
7246
7329
  exports.AttaformErrorCode = AttaformErrorCode;
7247
7330
  exports.DEFAULT_TIMINGS = DEFAULT_TIMINGS;
7248
7331
  exports.defaultCoercionRules = defaultCoercionRules;
7249
7332
  exports.defaultDisplayState = defaultDisplayState;
7250
7333
  exports.defineCoercion = defineCoercion;
7334
+ exports.escapeForInlineScript = escapeForInlineScript;
7251
7335
  exports.getAtPath = getAtPath;
7252
7336
  exports.humanize = humanize;
7253
7337
  exports.injectForm = injectForm;
@@ -7264,4 +7348,4 @@ exports.unset = unset;
7264
7348
  exports.useAbstractForm = useAbstractForm;
7265
7349
  exports.useRegister = useRegister;
7266
7350
  exports.useWizard = useWizard;
7267
- //# sourceMappingURL=attaform.BkUzunyB.cjs.map
7351
+ //# sourceMappingURL=attaform.DQT7_-FO.cjs.map