attaform 0.20.2 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/chunks/dev-key-collision-warnings.cjs +58 -0
  2. package/dist/chunks/dev-key-collision-warnings.cjs.map +1 -0
  3. package/dist/chunks/dev-key-collision-warnings.mjs +55 -0
  4. package/dist/chunks/dev-key-collision-warnings.mjs.map +1 -0
  5. package/dist/chunks/devtools.cjs +1 -1
  6. package/dist/chunks/devtools.mjs +1 -1
  7. package/dist/chunks/fingerprint.cjs +186 -0
  8. package/dist/chunks/fingerprint.cjs.map +1 -0
  9. package/dist/chunks/fingerprint.mjs +184 -0
  10. package/dist/chunks/fingerprint.mjs.map +1 -0
  11. package/dist/chunks/fingerprint2.cjs +162 -0
  12. package/dist/chunks/fingerprint2.cjs.map +1 -0
  13. package/dist/chunks/fingerprint2.mjs +160 -0
  14. package/dist/chunks/fingerprint2.mjs.map +1 -0
  15. package/dist/chunks/indexeddb.cjs +1 -1
  16. package/dist/chunks/indexeddb.mjs +1 -1
  17. package/dist/chunks/local-storage.cjs +1 -1
  18. package/dist/chunks/local-storage.mjs +1 -1
  19. package/dist/chunks/multi-tab-sync.cjs +367 -0
  20. package/dist/chunks/multi-tab-sync.cjs.map +1 -0
  21. package/dist/chunks/multi-tab-sync.mjs +364 -0
  22. package/dist/chunks/multi-tab-sync.mjs.map +1 -0
  23. package/dist/chunks/session-storage.cjs +1 -1
  24. package/dist/chunks/session-storage.mjs +1 -1
  25. package/dist/chunks/wire-persistence.cjs +396 -0
  26. package/dist/chunks/wire-persistence.cjs.map +1 -0
  27. package/dist/chunks/wire-persistence.mjs +394 -0
  28. package/dist/chunks/wire-persistence.mjs.map +1 -0
  29. package/dist/esbuild.cjs +28 -0
  30. package/dist/esbuild.cjs.map +1 -0
  31. package/dist/esbuild.d.cts +56 -0
  32. package/dist/esbuild.d.mts +56 -0
  33. package/dist/esbuild.d.ts +56 -0
  34. package/dist/esbuild.mjs +26 -0
  35. package/dist/esbuild.mjs.map +1 -0
  36. package/dist/index.cjs +5 -3
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +66 -70
  39. package/dist/index.d.mts +66 -70
  40. package/dist/index.d.ts +66 -70
  41. package/dist/index.mjs +5 -5
  42. package/dist/nuxt.d.cts +1 -1
  43. package/dist/nuxt.d.mts +1 -1
  44. package/dist/nuxt.d.ts +1 -1
  45. package/dist/rollup.cjs +24 -0
  46. package/dist/rollup.cjs.map +1 -0
  47. package/dist/rollup.d.cts +35 -0
  48. package/dist/rollup.d.mts +35 -0
  49. package/dist/rollup.d.ts +35 -0
  50. package/dist/rollup.mjs +22 -0
  51. package/dist/rollup.mjs.map +1 -0
  52. package/dist/rspack.cjs +10 -0
  53. package/dist/rspack.cjs.map +1 -0
  54. package/dist/rspack.d.cts +40 -0
  55. package/dist/rspack.d.mts +40 -0
  56. package/dist/rspack.d.ts +40 -0
  57. package/dist/rspack.mjs +8 -0
  58. package/dist/rspack.mjs.map +1 -0
  59. package/dist/runtime/plugins/attaform.cjs +2 -2
  60. package/dist/runtime/plugins/attaform.mjs +2 -2
  61. package/dist/shared/attaform.BJGA_UOS.mjs +37 -0
  62. package/dist/shared/attaform.BJGA_UOS.mjs.map +1 -0
  63. package/dist/shared/attaform.BRGIpZo4.cjs +26 -0
  64. package/dist/shared/attaform.BRGIpZo4.cjs.map +1 -0
  65. package/dist/shared/{attaform.DAKrGhxc.cjs → attaform.BSkvn43g.cjs} +101 -417
  66. package/dist/shared/attaform.BSkvn43g.cjs.map +1 -0
  67. package/dist/shared/{attaform.sWm8B15V.d.mts → attaform.BWfliRIK.d.cts} +172 -2
  68. package/dist/shared/{attaform.BGk8cfw2.mjs → attaform.Be8NZG9M.mjs} +178 -21
  69. package/dist/shared/attaform.Be8NZG9M.mjs.map +1 -0
  70. package/dist/shared/{attaform.D2SCCd4O.cjs → attaform.Bq5sX7TF.cjs} +2 -2
  71. package/dist/shared/{attaform.D2SCCd4O.cjs.map → attaform.Bq5sX7TF.cjs.map} +1 -1
  72. package/dist/shared/{attaform.ceGEAEMk.d.ts → attaform.Bv7dRDWK.d.ts} +172 -2
  73. package/dist/shared/attaform.C3Doa9Pt.mjs +24 -0
  74. package/dist/shared/attaform.C3Doa9Pt.mjs.map +1 -0
  75. package/dist/shared/{attaform.B_hph5AE.cjs → attaform.CICFZ1iS.cjs} +178 -20
  76. package/dist/shared/attaform.CICFZ1iS.cjs.map +1 -0
  77. package/dist/shared/attaform.CQN9R62B.cjs +39 -0
  78. package/dist/shared/attaform.CQN9R62B.cjs.map +1 -0
  79. package/dist/shared/{attaform.CwLjUqmQ.cjs → attaform.ClXwitZj.cjs} +735 -960
  80. package/dist/shared/attaform.ClXwitZj.cjs.map +1 -0
  81. package/dist/shared/{attaform.99cfHcIt.d.cts → attaform.D0dWZsJt.d.cts} +349 -77
  82. package/dist/shared/{attaform.99cfHcIt.d.mts → attaform.D0dWZsJt.d.mts} +349 -77
  83. package/dist/shared/{attaform.99cfHcIt.d.ts → attaform.D0dWZsJt.d.ts} +349 -77
  84. package/dist/shared/{attaform.z5j3LwJz.cjs → attaform.D32WwKk6.cjs} +216 -35
  85. package/dist/shared/attaform.D32WwKk6.cjs.map +1 -0
  86. package/dist/shared/{attaform.C5aYC_T8.mjs → attaform.DMEP_ENr.mjs} +39 -392
  87. package/dist/shared/attaform.DMEP_ENr.mjs.map +1 -0
  88. package/dist/shared/{attaform.tiWEVznj.mjs → attaform.DR6RmxWZ.mjs} +725 -962
  89. package/dist/shared/attaform.DR6RmxWZ.mjs.map +1 -0
  90. package/dist/shared/{attaform.Dt7dEcHk.mjs → attaform.DozgVlCE.mjs} +89 -405
  91. package/dist/shared/attaform.DozgVlCE.mjs.map +1 -0
  92. package/dist/shared/{attaform.DN5CvZrg.d.ts → attaform.Duecg2NO.d.mts} +2 -2
  93. package/dist/shared/attaform.DuzQYscR.d.cts +41 -0
  94. package/dist/shared/attaform.DuzQYscR.d.mts +41 -0
  95. package/dist/shared/attaform.DuzQYscR.d.ts +41 -0
  96. package/dist/shared/{attaform.BXinSW2T.d.mts → attaform.FudOcHaa.d.cts} +2 -2
  97. package/dist/shared/attaform.LEWUFqUw.cjs +54 -0
  98. package/dist/shared/attaform.LEWUFqUw.cjs.map +1 -0
  99. package/dist/shared/{attaform.CywE4y8x.d.cts → attaform.MtrpT6Ki.d.ts} +2 -2
  100. package/dist/shared/{attaform.DbRgDFa7.d.cts → attaform.NQ8mybyW.d.mts} +172 -2
  101. package/dist/shared/{attaform.Cd4AOfwu.cjs → attaform.S-pYLSo4.cjs} +68 -402
  102. package/dist/shared/attaform.S-pYLSo4.cjs.map +1 -0
  103. package/dist/shared/{attaform.CnrxbkB6.mjs → attaform.Y1ZGhM4k.mjs} +2 -2
  104. package/dist/shared/{attaform.CnrxbkB6.mjs.map → attaform.Y1ZGhM4k.mjs.map} +1 -1
  105. package/dist/shared/{attaform.QG5TG8lB.mjs → attaform.pmtahXKy.mjs} +216 -36
  106. package/dist/shared/attaform.pmtahXKy.mjs.map +1 -0
  107. package/dist/shared/attaform.sHkHv_98.mjs +51 -0
  108. package/dist/shared/attaform.sHkHv_98.mjs.map +1 -0
  109. package/dist/vite.cjs +9 -45
  110. package/dist/vite.cjs.map +1 -1
  111. package/dist/vite.d.cts +36 -0
  112. package/dist/vite.d.mts +36 -0
  113. package/dist/vite.d.ts +36 -0
  114. package/dist/vite.mjs +8 -44
  115. package/dist/vite.mjs.map +1 -1
  116. package/dist/webpack.cjs +10 -0
  117. package/dist/webpack.cjs.map +1 -0
  118. package/dist/webpack.d.cts +37 -0
  119. package/dist/webpack.d.mts +37 -0
  120. package/dist/webpack.d.ts +37 -0
  121. package/dist/webpack.mjs +8 -0
  122. package/dist/webpack.mjs.map +1 -0
  123. package/dist/zod-v3.cjs +3 -3
  124. package/dist/zod-v3.d.cts +3 -3
  125. package/dist/zod-v3.d.mts +3 -3
  126. package/dist/zod-v3.d.ts +3 -3
  127. package/dist/zod-v3.mjs +3 -3
  128. package/dist/zod-v4.cjs +3 -3
  129. package/dist/zod-v4.d.cts +4 -4
  130. package/dist/zod-v4.d.mts +4 -4
  131. package/dist/zod-v4.d.ts +4 -4
  132. package/dist/zod-v4.mjs +3 -3
  133. package/dist/zod.cjs +8 -8
  134. package/dist/zod.cjs.map +1 -1
  135. package/dist/zod.d.cts +52 -10
  136. package/dist/zod.d.mts +52 -10
  137. package/dist/zod.d.ts +52 -10
  138. package/dist/zod.mjs +6 -6
  139. package/dist/zod.mjs.map +1 -1
  140. package/package.json +19 -5
  141. package/dist/shared/attaform.BGk8cfw2.mjs.map +0 -1
  142. package/dist/shared/attaform.B_hph5AE.cjs.map +0 -1
  143. package/dist/shared/attaform.C5aYC_T8.mjs.map +0 -1
  144. package/dist/shared/attaform.Cd4AOfwu.cjs.map +0 -1
  145. package/dist/shared/attaform.CwLjUqmQ.cjs.map +0 -1
  146. package/dist/shared/attaform.DAKrGhxc.cjs.map +0 -1
  147. package/dist/shared/attaform.Dt7dEcHk.mjs.map +0 -1
  148. package/dist/shared/attaform.QG5TG8lB.mjs.map +0 -1
  149. package/dist/shared/attaform.tiWEVznj.mjs.map +0 -1
  150. package/dist/shared/attaform.z5j3LwJz.cjs.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  const vue = require('vue');
4
4
 
5
- const __DEV__ = typeof process !== "undefined" && process.env["NODE_ENV"] !== "production";
5
+ const __DEV__ = (typeof process !== "undefined" ? process.env.NODE_ENV : "production") !== "production";
6
6
 
7
7
  var __defProp = Object.defineProperty;
8
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -24,6 +24,11 @@ class InvalidUseFormConfigError extends AttaformError {
24
24
  }
25
25
  class SubmitErrorHandlerError extends AttaformError {
26
26
  }
27
+ function toError(value) {
28
+ if (value instanceof Error) return value;
29
+ const message = typeof value === "string" && value.length > 0 ? value : `Submit callback threw a non-Error value (${typeof value})`;
30
+ return new Error(message, { cause: value });
31
+ }
27
32
  class RegistryNotInstalledError extends AttaformError {
28
33
  constructor() {
29
34
  super(
@@ -513,6 +518,11 @@ function isBlankFileValue(value) {
513
518
  return true;
514
519
  return false;
515
520
  }
521
+ function isMultipleInput(el, vnode) {
522
+ if (el.multiple) return true;
523
+ const authored = vnode.props?.["multiple"];
524
+ return authored === true || authored === "";
525
+ }
516
526
  function readFilesFromInput(el) {
517
527
  const files = el.files;
518
528
  if (el.multiple) {
@@ -538,21 +548,25 @@ function maybeWarnPersistedFile(value) {
538
548
  }
539
549
  const fileScopeKey = Symbol.for("attaform:file-scope");
540
550
  const vRegisterFile = {
541
- created(el, { value }) {
551
+ created(el, { value }, vnode) {
542
552
  if (!isRegisterValue(value)) return;
543
553
  const input = el;
544
554
  value.registerElement(input);
555
+ setAssignFunction(input, vnode, value);
545
556
  maybeWarnPersistedFile(value);
546
557
  const currentRaw = value.innerRef.value;
547
558
  if (isBlankFileValue(currentRaw)) {
548
- const blankShape = input.multiple ? [] : null;
559
+ const blankShape = isMultipleInput(input, vnode) ? [] : null;
549
560
  value.setValueWithInternalPath(blankShape, { blank: true });
550
561
  }
551
562
  addTrackedListener(input, "change", () => {
552
563
  noteInteraction(value);
553
564
  const next = readFilesFromInput(input);
554
- const blank = isBlankFileValue(next);
555
- value.setValueWithInternalPath(next, blank ? { blank: true } : void 0);
565
+ if (isBlankFileValue(next)) {
566
+ value.setValueWithInternalPath(next, { blank: true });
567
+ return;
568
+ }
569
+ fireAssigner(input, value, next);
556
570
  });
557
571
  const scope = vue.effectScope(true);
558
572
  scope.run(() => {
@@ -572,7 +586,7 @@ const vRegisterFile = {
572
586
  if (!isRegisterValue(value)) return;
573
587
  const input = el;
574
588
  const currentRaw = value.innerRef.value;
575
- if (isBlankFileValue(currentRaw)) {
589
+ if (isBlankFileValue(currentRaw) && !isTransforming(value)) {
576
590
  value.setValueWithInternalPath(currentRaw, { blank: true });
577
591
  if (input.value !== "") input.value = "";
578
592
  }
@@ -841,6 +855,36 @@ function syncElementRegistration(el, value, oldValue) {
841
855
  }
842
856
  }
843
857
 
858
+ const valueSyncScopeKey = Symbol.for("attaform:value-sync-scope");
859
+ function isElementFocused(el) {
860
+ const rootNode = el.getRootNode();
861
+ const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
862
+ return activeElement === el;
863
+ }
864
+ function setupValueSync(el, source, apply, options = {}) {
865
+ const skipWhileFocused = options.skipWhileFocused === true;
866
+ const scope = vue.effectScope(true);
867
+ scope.run(() => {
868
+ vue.watch(
869
+ source,
870
+ () => {
871
+ if (el.composing === true) return;
872
+ if (skipWhileFocused && isElementFocused(el)) return;
873
+ apply();
874
+ },
875
+ { flush: "post" }
876
+ );
877
+ });
878
+ el[valueSyncScopeKey] = () => scope.stop();
879
+ }
880
+ function teardownValueSync(el) {
881
+ const carrier = el;
882
+ const stop = carrier[valueSyncScopeKey];
883
+ if (stop === void 0) return;
884
+ stop();
885
+ delete carrier[valueSyncScopeKey];
886
+ }
887
+
844
888
  const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
845
889
 
846
890
  const assignKey = Symbol.for("attaform:assign-key");
@@ -875,6 +919,16 @@ function fireAssigner(el, registerValue, value) {
875
919
  return fn(value, void 0);
876
920
  }
877
921
  const r = runTransforms(value, registerValue);
922
+ if (r.kind === "async") {
923
+ kickoffAsyncTransform(
924
+ registerValue,
925
+ r.holder,
926
+ r.run,
927
+ (coerced2) => fn(coerced2, registerValue),
928
+ void 0
929
+ );
930
+ return true;
931
+ }
878
932
  if (!r.ok) return false;
879
933
  const coerced = applyCoerce(r.value, registerValue);
880
934
  return fn(coerced, registerValue);
@@ -883,26 +937,68 @@ function shouldBailListener(el) {
883
937
  if (INTERACTIVE_TAG_NAMES.has(el.tagName)) return false;
884
938
  return isDefaultAssigner(el[assignKey]);
885
939
  }
940
+ function isThenable(x) {
941
+ return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
942
+ }
943
+ function makeTransformContext() {
944
+ const holder = { controller: null, aborted: false };
945
+ const ctx = {
946
+ get signal() {
947
+ if (holder.controller === null) {
948
+ holder.controller = new AbortController();
949
+ if (holder.aborted) holder.controller.abort();
950
+ }
951
+ return holder.controller.signal;
952
+ }
953
+ };
954
+ return { ctx, holder };
955
+ }
886
956
  function runTransforms(initial, registerValue) {
887
957
  const transforms = registerValue.transforms;
888
958
  if (transforms === void 0 || transforms.length === 0) {
889
- return { ok: true, value: initial };
959
+ return { kind: "sync", ok: true, value: initial };
890
960
  }
961
+ const { ctx, holder } = makeTransformContext();
891
962
  let v = initial;
892
963
  for (let i = 0; i < transforms.length; i++) {
893
964
  const fn = transforms[i];
965
+ let out;
894
966
  try {
895
- v = fn(v);
967
+ out = fn(v, ctx);
896
968
  } catch (err) {
897
969
  logTransformFailure(registerValue.path, i, fn, err);
898
- return { ok: false };
970
+ return { kind: "sync", ok: false };
899
971
  }
900
- }
901
- if (v instanceof Promise) {
902
- logTransformAsync(registerValue.path);
903
- return { ok: false };
904
- }
905
- return { ok: true, value: v };
972
+ if (isThenable(out)) {
973
+ const rest = transforms.slice(i + 1);
974
+ const seed = out;
975
+ const run = () => rest.reduce(
976
+ (acc, next) => acc.then((value) => next(value, ctx)),
977
+ Promise.resolve(seed)
978
+ );
979
+ return { kind: "async", run, holder };
980
+ }
981
+ v = out;
982
+ }
983
+ return { kind: "sync", ok: true, value: v };
984
+ }
985
+ function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
986
+ const token = rv.beginTransform(holder);
987
+ void run().then(
988
+ (value) => {
989
+ const live = rv.isCurrentTransform(token);
990
+ rv.endTransform(token);
991
+ if (!live) return;
992
+ const coerced = applyCoerce(value, rv);
993
+ const wrote = commit(coerced);
994
+ if (wrote === false) rv.setTransformError(transformGateRejectedError(rv.path));
995
+ else syncDom?.();
996
+ },
997
+ (err) => {
998
+ if (rv.isCurrentTransform(token)) rv.setTransformError(toTransformError(err));
999
+ rv.endTransform(token);
1000
+ }
1001
+ );
906
1002
  }
907
1003
  function logTransformFailure(path, index, fn, err) {
908
1004
  if (__DEV__) {
@@ -923,23 +1019,37 @@ function applyCoerce(value, registerValue) {
923
1019
  function applyElementCoerce(value, registerValue) {
924
1020
  return registerValue.coerceElement !== void 0 ? registerValue.coerceElement(value) : value;
925
1021
  }
926
- function logTransformAsync(path) {
927
- if (__DEV__) {
928
- console.error(
929
- `[attaform] transform pipeline for path '${path}' returned a Promise \u2014 transforms must be sync. Use async field validation for canonicalize-before-write patterns. Write aborted.`
930
- );
931
- } else {
932
- console.error(
933
- `[attaform] transform error \u2014 write aborted (set NODE_ENV=development for details).`
934
- );
935
- }
1022
+ function toTransformError(value) {
1023
+ if (value instanceof Error) return value;
1024
+ const message = typeof value === "string" && value.length > 0 ? value : `Transform rejected with a non-Error value (${typeof value})`;
1025
+ return new Error(message, { cause: value });
1026
+ }
1027
+ function transformGateRejectedError(path) {
1028
+ return new Error(
1029
+ `[attaform] transform result for path '${path}' was rejected by the field's type gate (the resolved value did not fit the schema slot).`
1030
+ );
1031
+ }
1032
+ function isTransforming(value) {
1033
+ return isRegisterValue(value) && value.transforming;
936
1034
  }
937
- const getModelAssigner = (vnode, registerValue) => {
1035
+ const getModelAssigner = (el, vnode, registerValue) => {
938
1036
  const fn = vnode.props?.["onUpdate:registerValue"] ?? vnode.props?.["on:update:registerValue"];
939
1037
  if (isArray(fn)) {
940
1038
  const fnArr = fn.filter((x) => isFunction(x));
941
1039
  const wrapped = (value) => {
942
1040
  const r = runTransforms(value, registerValue);
1041
+ if (r.kind === "async") {
1042
+ kickoffAsyncTransform(
1043
+ registerValue,
1044
+ r.holder,
1045
+ r.run,
1046
+ (coerced2) => {
1047
+ invokeArrayFns(fnArr, coerced2, registerValue);
1048
+ },
1049
+ void 0
1050
+ );
1051
+ return true;
1052
+ }
943
1053
  if (!r.ok) return false;
944
1054
  const coerced = applyCoerce(r.value, registerValue);
945
1055
  invokeArrayFns(fnArr, coerced, registerValue);
@@ -952,6 +1062,16 @@ const getModelAssigner = (vnode, registerValue) => {
952
1062
  const handler = fn;
953
1063
  const wrapped = (value) => {
954
1064
  const r = runTransforms(value, registerValue);
1065
+ if (r.kind === "async") {
1066
+ kickoffAsyncTransform(
1067
+ registerValue,
1068
+ r.holder,
1069
+ r.run,
1070
+ (coerced2) => handler(coerced2, registerValue),
1071
+ void 0
1072
+ );
1073
+ return true;
1074
+ }
955
1075
  if (!r.ok) return false;
956
1076
  const coerced = applyCoerce(r.value, registerValue);
957
1077
  return handler(coerced, registerValue);
@@ -964,6 +1084,16 @@ const getModelAssigner = (vnode, registerValue) => {
964
1084
  return registerValue.setValueWithInternalPath(void 0);
965
1085
  }
966
1086
  const r = runTransforms(value, registerValue);
1087
+ if (r.kind === "async") {
1088
+ kickoffAsyncTransform(
1089
+ registerValue,
1090
+ r.holder,
1091
+ r.run,
1092
+ (coerced2) => registerValue.setValueWithInternalPath(coerced2),
1093
+ el._syncFromStorage
1094
+ );
1095
+ return true;
1096
+ }
967
1097
  if (!r.ok) return false;
968
1098
  const coerced = applyCoerce(r.value, registerValue);
969
1099
  return registerValue.setValueWithInternalPath(coerced);
@@ -1004,7 +1134,7 @@ function setAssignFunction(el, vnode, value) {
1004
1134
  el[assignKey] = makeNoopAssigner();
1005
1135
  return;
1006
1136
  }
1007
- el[assignKey] = getModelAssigner(vnode, value);
1137
+ el[assignKey] = getModelAssigner(el, vnode, value);
1008
1138
  }
1009
1139
  const vRegisterText = {
1010
1140
  created(el, { value, modifiers: { lazy, trim, number } }, vnode) {
@@ -1014,6 +1144,13 @@ const vRegisterText = {
1014
1144
  value.registerElement(el);
1015
1145
  setAssignFunction(el, vnode, value);
1016
1146
  }
1147
+ el._syncFromStorage = () => {
1148
+ if (!isRegisterValue(value)) return;
1149
+ const storage = value.innerRef.value;
1150
+ const display = storage == null ? "" : String(storage);
1151
+ if (el.value !== display) el.value = display;
1152
+ if (liveCastToNumber()) writeLastTypedForm(value, null);
1153
+ };
1017
1154
  addTrackedListener(el, lazy === true ? "change" : "input", (e) => {
1018
1155
  if (shouldBailListener(el)) return;
1019
1156
  const target = e.target;
@@ -1061,7 +1198,7 @@ const vRegisterText = {
1061
1198
  }
1062
1199
  const commit = domValue === "" && isRegisterValue(value) && value.acceptsUndefined ? void 0 : domValue;
1063
1200
  fireAssigner(el, value, commit);
1064
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1201
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1065
1202
  const storage = value.innerRef.value;
1066
1203
  if (storage !== domValue) {
1067
1204
  const display = storage == null ? "" : String(storage);
@@ -1121,6 +1258,15 @@ const vRegisterText = {
1121
1258
  mounted(el, { value }) {
1122
1259
  if (!isRegisterValue(value)) return;
1123
1260
  el.value = value.displayValue.value;
1261
+ setupValueSync(
1262
+ el,
1263
+ value.displayValue,
1264
+ () => {
1265
+ const next = value.displayValue.value;
1266
+ if (el.value !== next) el.value = next;
1267
+ },
1268
+ { skipWhileFocused: true }
1269
+ );
1124
1270
  },
1125
1271
  beforeUpdate(el, { value, oldValue, modifiers: { lazy, trim } }, vnode) {
1126
1272
  setAssignFunction(el, vnode, value);
@@ -1150,6 +1296,11 @@ const vRegisterCheckbox = {
1150
1296
  if (!isRegisterValue(value)) return;
1151
1297
  value.registerElement(el);
1152
1298
  setAssignFunction(el, vnode, value);
1299
+ el._syncFromStorage = () => {
1300
+ if (!isRegisterValue(value)) return;
1301
+ setChecked(el, value);
1302
+ el._lastAppliedModel = value.innerRef.value;
1303
+ };
1153
1304
  addTrackedListener(el, "change", () => {
1154
1305
  if (shouldBailListener(el)) return;
1155
1306
  noteInteraction(value);
@@ -1192,7 +1343,7 @@ const vRegisterCheckbox = {
1192
1343
  } else {
1193
1344
  fireAssigner(el, value, getCheckboxValue(el, checked));
1194
1345
  }
1195
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1346
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1196
1347
  setChecked(el, value);
1197
1348
  el._lastAppliedModel = value.innerRef.value;
1198
1349
  }
@@ -1201,7 +1352,12 @@ const vRegisterCheckbox = {
1201
1352
  // set initial checked on mount to wait for true-value/false-value
1202
1353
  mounted(el, { value }) {
1203
1354
  setChecked(el, value);
1204
- if (isRegisterValue(value)) el._lastAppliedModel = value.innerRef.value;
1355
+ if (!isRegisterValue(value)) return;
1356
+ el._lastAppliedModel = value.innerRef.value;
1357
+ setupValueSync(el, value.innerRef, () => {
1358
+ setChecked(el, value);
1359
+ el._lastAppliedModel = value.innerRef.value;
1360
+ });
1205
1361
  },
1206
1362
  // Skip the DOM sync when the model is identity-unchanged from the
1207
1363
  // last application. Pre-fix the scalar branch in `setChecked`
@@ -1247,11 +1403,18 @@ const vRegisterRadio = {
1247
1403
  if (!isRegisterValue(value)) return;
1248
1404
  value.registerElement(el);
1249
1405
  setAssignFunction(el, vnode, value);
1406
+ el._syncFromStorage = () => {
1407
+ if (!isRegisterValue(value)) return;
1408
+ const currentModel = value.innerRef.value;
1409
+ const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1410
+ if (el.checked !== target) el.checked = target;
1411
+ el._lastAppliedModel = currentModel;
1412
+ };
1250
1413
  addTrackedListener(el, "change", () => {
1251
1414
  if (shouldBailListener(el)) return;
1252
1415
  noteInteraction(value);
1253
1416
  fireAssigner(el, value, getValue(el));
1254
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1417
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1255
1418
  const currentModel = value.innerRef.value;
1256
1419
  const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1257
1420
  if (el.checked !== target) el.checked = target;
@@ -1270,6 +1433,10 @@ const vRegisterRadio = {
1270
1433
  if (!isRegisterValue(value)) return;
1271
1434
  el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
1272
1435
  el._lastAppliedModel = value.innerRef.value;
1436
+ setupValueSync(el, value.innerRef, () => {
1437
+ el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
1438
+ el._lastAppliedModel = value.innerRef.value;
1439
+ });
1273
1440
  },
1274
1441
  // Skip the DOM sync when the model is identity-unchanged from the
1275
1442
  // last application. Pre-fix the guard read `value.innerRef.value
@@ -1295,6 +1462,11 @@ const vRegisterSelect = {
1295
1462
  created(el, { value, modifiers: { number } }, vnode) {
1296
1463
  if (!isRegisterValue(value)) return;
1297
1464
  value.registerElement(el);
1465
+ el._syncFromStorage = () => {
1466
+ if (!isRegisterValue(value)) return;
1467
+ setSelected(el, value);
1468
+ el._lastAppliedModel = value.innerRef.value;
1469
+ };
1298
1470
  addTrackedListener(el, "change", () => {
1299
1471
  if (shouldBailListener(el)) return;
1300
1472
  noteInteraction(value);
@@ -1311,7 +1483,7 @@ const vRegisterSelect = {
1311
1483
  el._assigning = false;
1312
1484
  });
1313
1485
  }
1314
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1486
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1315
1487
  setSelected(el, value);
1316
1488
  el._lastAppliedModel = value.innerRef.value;
1317
1489
  }
@@ -1322,7 +1494,13 @@ const vRegisterSelect = {
1322
1494
  // <option>s.
1323
1495
  mounted(el, { value }) {
1324
1496
  setSelected(el, value);
1325
- if (isRegisterValue(value)) el._lastAppliedModel = value.innerRef.value;
1497
+ if (!isRegisterValue(value)) return;
1498
+ el._lastAppliedModel = value.innerRef.value;
1499
+ setupValueSync(el, value.innerRef, () => {
1500
+ if (el._assigning === true) return;
1501
+ setSelected(el, value);
1502
+ el._lastAppliedModel = value.innerRef.value;
1503
+ });
1326
1504
  },
1327
1505
  beforeUpdate(el, binding, vnode) {
1328
1506
  setAssignFunction(el, vnode, binding.value);
@@ -1465,6 +1643,7 @@ const vRegisterDynamic = {
1465
1643
  beforeUnmount(el, { value }) {
1466
1644
  removeTrackedListeners(el);
1467
1645
  teardownAria(el);
1646
+ teardownValueSync(el);
1468
1647
  if (isRegisterValue(value)) {
1469
1648
  value.persistOptIns.removeAllFor(getOrAssignElementId(el));
1470
1649
  value.unmarkNoSync?.();
@@ -1473,6 +1652,7 @@ const vRegisterDynamic = {
1473
1652
  value.deregisterElement(el);
1474
1653
  delete el.composing;
1475
1654
  delete el._assigning;
1655
+ delete el._syncFromStorage;
1476
1656
  delete el[assignKey];
1477
1657
  },
1478
1658
  // The lifecycle hooks above don't run on the server (Vue skips
@@ -1518,7 +1698,7 @@ function installAttaformOnApp(app, options, source) {
1518
1698
  const registry = createRegistry(options);
1519
1699
  attachRegistryToApp(app, registry);
1520
1700
  app.directive("register", vRegister);
1521
- if (options.devtools !== false && !registry.ssr) {
1701
+ if (__DEV__ && options.devtools !== false && !registry.ssr) {
1522
1702
  void (async () => {
1523
1703
  try {
1524
1704
  const { setupAttaformDevtools } = await import('../chunks/devtools.cjs');
@@ -1687,7 +1867,8 @@ exports.kFormInstanceId = kFormInstanceId;
1687
1867
  exports.parseDottedPath = parseDottedPath;
1688
1868
  exports.pathKeyToDotted = pathKeyToDotted;
1689
1869
  exports.segmentsForPathKey = segmentsForPathKey;
1870
+ exports.toError = toError;
1690
1871
  exports.useRegister = useRegister;
1691
1872
  exports.useRegistry = useRegistry;
1692
1873
  exports.vRegister = vRegister;
1693
- //# sourceMappingURL=attaform.z5j3LwJz.cjs.map
1874
+ //# sourceMappingURL=attaform.D32WwKk6.cjs.map