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
@@ -1,6 +1,6 @@
1
1
  import { shallowReactive, getCurrentInstance, inject, shallowRef, onBeforeMount, onBeforeUpdate, onMounted, effectScope, watch, warn, nextTick, isRef } from 'vue';
2
2
 
3
- const __DEV__ = typeof process !== "undefined" && process.env["NODE_ENV"] !== "production";
3
+ const __DEV__ = (typeof process !== "undefined" ? process.env.NODE_ENV : "production") !== "production";
4
4
 
5
5
  var __defProp = Object.defineProperty;
6
6
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -22,6 +22,11 @@ class InvalidUseFormConfigError extends AttaformError {
22
22
  }
23
23
  class SubmitErrorHandlerError extends AttaformError {
24
24
  }
25
+ function toError(value) {
26
+ if (value instanceof Error) return value;
27
+ const message = typeof value === "string" && value.length > 0 ? value : `Submit callback threw a non-Error value (${typeof value})`;
28
+ return new Error(message, { cause: value });
29
+ }
25
30
  class RegistryNotInstalledError extends AttaformError {
26
31
  constructor() {
27
32
  super(
@@ -511,6 +516,11 @@ function isBlankFileValue(value) {
511
516
  return true;
512
517
  return false;
513
518
  }
519
+ function isMultipleInput(el, vnode) {
520
+ if (el.multiple) return true;
521
+ const authored = vnode.props?.["multiple"];
522
+ return authored === true || authored === "";
523
+ }
514
524
  function readFilesFromInput(el) {
515
525
  const files = el.files;
516
526
  if (el.multiple) {
@@ -536,21 +546,25 @@ function maybeWarnPersistedFile(value) {
536
546
  }
537
547
  const fileScopeKey = Symbol.for("attaform:file-scope");
538
548
  const vRegisterFile = {
539
- created(el, { value }) {
549
+ created(el, { value }, vnode) {
540
550
  if (!isRegisterValue(value)) return;
541
551
  const input = el;
542
552
  value.registerElement(input);
553
+ setAssignFunction(input, vnode, value);
543
554
  maybeWarnPersistedFile(value);
544
555
  const currentRaw = value.innerRef.value;
545
556
  if (isBlankFileValue(currentRaw)) {
546
- const blankShape = input.multiple ? [] : null;
557
+ const blankShape = isMultipleInput(input, vnode) ? [] : null;
547
558
  value.setValueWithInternalPath(blankShape, { blank: true });
548
559
  }
549
560
  addTrackedListener(input, "change", () => {
550
561
  noteInteraction(value);
551
562
  const next = readFilesFromInput(input);
552
- const blank = isBlankFileValue(next);
553
- value.setValueWithInternalPath(next, blank ? { blank: true } : void 0);
563
+ if (isBlankFileValue(next)) {
564
+ value.setValueWithInternalPath(next, { blank: true });
565
+ return;
566
+ }
567
+ fireAssigner(input, value, next);
554
568
  });
555
569
  const scope = effectScope(true);
556
570
  scope.run(() => {
@@ -570,7 +584,7 @@ const vRegisterFile = {
570
584
  if (!isRegisterValue(value)) return;
571
585
  const input = el;
572
586
  const currentRaw = value.innerRef.value;
573
- if (isBlankFileValue(currentRaw)) {
587
+ if (isBlankFileValue(currentRaw) && !isTransforming(value)) {
574
588
  value.setValueWithInternalPath(currentRaw, { blank: true });
575
589
  if (input.value !== "") input.value = "";
576
590
  }
@@ -839,6 +853,36 @@ function syncElementRegistration(el, value, oldValue) {
839
853
  }
840
854
  }
841
855
 
856
+ const valueSyncScopeKey = Symbol.for("attaform:value-sync-scope");
857
+ function isElementFocused(el) {
858
+ const rootNode = el.getRootNode();
859
+ const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
860
+ return activeElement === el;
861
+ }
862
+ function setupValueSync(el, source, apply, options = {}) {
863
+ const skipWhileFocused = options.skipWhileFocused === true;
864
+ const scope = effectScope(true);
865
+ scope.run(() => {
866
+ watch(
867
+ source,
868
+ () => {
869
+ if (el.composing === true) return;
870
+ if (skipWhileFocused && isElementFocused(el)) return;
871
+ apply();
872
+ },
873
+ { flush: "post" }
874
+ );
875
+ });
876
+ el[valueSyncScopeKey] = () => scope.stop();
877
+ }
878
+ function teardownValueSync(el) {
879
+ const carrier = el;
880
+ const stop = carrier[valueSyncScopeKey];
881
+ if (stop === void 0) return;
882
+ stop();
883
+ delete carrier[valueSyncScopeKey];
884
+ }
885
+
842
886
  const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
843
887
 
844
888
  const assignKey = Symbol.for("attaform:assign-key");
@@ -873,6 +917,16 @@ function fireAssigner(el, registerValue, value) {
873
917
  return fn(value, void 0);
874
918
  }
875
919
  const r = runTransforms(value, registerValue);
920
+ if (r.kind === "async") {
921
+ kickoffAsyncTransform(
922
+ registerValue,
923
+ r.holder,
924
+ r.run,
925
+ (coerced2) => fn(coerced2, registerValue),
926
+ void 0
927
+ );
928
+ return true;
929
+ }
876
930
  if (!r.ok) return false;
877
931
  const coerced = applyCoerce(r.value, registerValue);
878
932
  return fn(coerced, registerValue);
@@ -881,26 +935,68 @@ function shouldBailListener(el) {
881
935
  if (INTERACTIVE_TAG_NAMES.has(el.tagName)) return false;
882
936
  return isDefaultAssigner(el[assignKey]);
883
937
  }
938
+ function isThenable(x) {
939
+ return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
940
+ }
941
+ function makeTransformContext() {
942
+ const holder = { controller: null, aborted: false };
943
+ const ctx = {
944
+ get signal() {
945
+ if (holder.controller === null) {
946
+ holder.controller = new AbortController();
947
+ if (holder.aborted) holder.controller.abort();
948
+ }
949
+ return holder.controller.signal;
950
+ }
951
+ };
952
+ return { ctx, holder };
953
+ }
884
954
  function runTransforms(initial, registerValue) {
885
955
  const transforms = registerValue.transforms;
886
956
  if (transforms === void 0 || transforms.length === 0) {
887
- return { ok: true, value: initial };
957
+ return { kind: "sync", ok: true, value: initial };
888
958
  }
959
+ const { ctx, holder } = makeTransformContext();
889
960
  let v = initial;
890
961
  for (let i = 0; i < transforms.length; i++) {
891
962
  const fn = transforms[i];
963
+ let out;
892
964
  try {
893
- v = fn(v);
965
+ out = fn(v, ctx);
894
966
  } catch (err) {
895
967
  logTransformFailure(registerValue.path, i, fn, err);
896
- return { ok: false };
968
+ return { kind: "sync", ok: false };
897
969
  }
898
- }
899
- if (v instanceof Promise) {
900
- logTransformAsync(registerValue.path);
901
- return { ok: false };
902
- }
903
- return { ok: true, value: v };
970
+ if (isThenable(out)) {
971
+ const rest = transforms.slice(i + 1);
972
+ const seed = out;
973
+ const run = () => rest.reduce(
974
+ (acc, next) => acc.then((value) => next(value, ctx)),
975
+ Promise.resolve(seed)
976
+ );
977
+ return { kind: "async", run, holder };
978
+ }
979
+ v = out;
980
+ }
981
+ return { kind: "sync", ok: true, value: v };
982
+ }
983
+ function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
984
+ const token = rv.beginTransform(holder);
985
+ void run().then(
986
+ (value) => {
987
+ const live = rv.isCurrentTransform(token);
988
+ rv.endTransform(token);
989
+ if (!live) return;
990
+ const coerced = applyCoerce(value, rv);
991
+ const wrote = commit(coerced);
992
+ if (wrote === false) rv.setTransformError(transformGateRejectedError(rv.path));
993
+ else syncDom?.();
994
+ },
995
+ (err) => {
996
+ if (rv.isCurrentTransform(token)) rv.setTransformError(toTransformError(err));
997
+ rv.endTransform(token);
998
+ }
999
+ );
904
1000
  }
905
1001
  function logTransformFailure(path, index, fn, err) {
906
1002
  if (__DEV__) {
@@ -921,23 +1017,37 @@ function applyCoerce(value, registerValue) {
921
1017
  function applyElementCoerce(value, registerValue) {
922
1018
  return registerValue.coerceElement !== void 0 ? registerValue.coerceElement(value) : value;
923
1019
  }
924
- function logTransformAsync(path) {
925
- if (__DEV__) {
926
- console.error(
927
- `[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.`
928
- );
929
- } else {
930
- console.error(
931
- `[attaform] transform error \u2014 write aborted (set NODE_ENV=development for details).`
932
- );
933
- }
1020
+ function toTransformError(value) {
1021
+ if (value instanceof Error) return value;
1022
+ const message = typeof value === "string" && value.length > 0 ? value : `Transform rejected with a non-Error value (${typeof value})`;
1023
+ return new Error(message, { cause: value });
1024
+ }
1025
+ function transformGateRejectedError(path) {
1026
+ return new Error(
1027
+ `[attaform] transform result for path '${path}' was rejected by the field's type gate (the resolved value did not fit the schema slot).`
1028
+ );
1029
+ }
1030
+ function isTransforming(value) {
1031
+ return isRegisterValue(value) && value.transforming;
934
1032
  }
935
- const getModelAssigner = (vnode, registerValue) => {
1033
+ const getModelAssigner = (el, vnode, registerValue) => {
936
1034
  const fn = vnode.props?.["onUpdate:registerValue"] ?? vnode.props?.["on:update:registerValue"];
937
1035
  if (isArray(fn)) {
938
1036
  const fnArr = fn.filter((x) => isFunction(x));
939
1037
  const wrapped = (value) => {
940
1038
  const r = runTransforms(value, registerValue);
1039
+ if (r.kind === "async") {
1040
+ kickoffAsyncTransform(
1041
+ registerValue,
1042
+ r.holder,
1043
+ r.run,
1044
+ (coerced2) => {
1045
+ invokeArrayFns(fnArr, coerced2, registerValue);
1046
+ },
1047
+ void 0
1048
+ );
1049
+ return true;
1050
+ }
941
1051
  if (!r.ok) return false;
942
1052
  const coerced = applyCoerce(r.value, registerValue);
943
1053
  invokeArrayFns(fnArr, coerced, registerValue);
@@ -950,6 +1060,16 @@ const getModelAssigner = (vnode, registerValue) => {
950
1060
  const handler = fn;
951
1061
  const wrapped = (value) => {
952
1062
  const r = runTransforms(value, registerValue);
1063
+ if (r.kind === "async") {
1064
+ kickoffAsyncTransform(
1065
+ registerValue,
1066
+ r.holder,
1067
+ r.run,
1068
+ (coerced2) => handler(coerced2, registerValue),
1069
+ void 0
1070
+ );
1071
+ return true;
1072
+ }
953
1073
  if (!r.ok) return false;
954
1074
  const coerced = applyCoerce(r.value, registerValue);
955
1075
  return handler(coerced, registerValue);
@@ -962,6 +1082,16 @@ const getModelAssigner = (vnode, registerValue) => {
962
1082
  return registerValue.setValueWithInternalPath(void 0);
963
1083
  }
964
1084
  const r = runTransforms(value, registerValue);
1085
+ if (r.kind === "async") {
1086
+ kickoffAsyncTransform(
1087
+ registerValue,
1088
+ r.holder,
1089
+ r.run,
1090
+ (coerced2) => registerValue.setValueWithInternalPath(coerced2),
1091
+ el._syncFromStorage
1092
+ );
1093
+ return true;
1094
+ }
965
1095
  if (!r.ok) return false;
966
1096
  const coerced = applyCoerce(r.value, registerValue);
967
1097
  return registerValue.setValueWithInternalPath(coerced);
@@ -1002,7 +1132,7 @@ function setAssignFunction(el, vnode, value) {
1002
1132
  el[assignKey] = makeNoopAssigner();
1003
1133
  return;
1004
1134
  }
1005
- el[assignKey] = getModelAssigner(vnode, value);
1135
+ el[assignKey] = getModelAssigner(el, vnode, value);
1006
1136
  }
1007
1137
  const vRegisterText = {
1008
1138
  created(el, { value, modifiers: { lazy, trim, number } }, vnode) {
@@ -1012,6 +1142,13 @@ const vRegisterText = {
1012
1142
  value.registerElement(el);
1013
1143
  setAssignFunction(el, vnode, value);
1014
1144
  }
1145
+ el._syncFromStorage = () => {
1146
+ if (!isRegisterValue(value)) return;
1147
+ const storage = value.innerRef.value;
1148
+ const display = storage == null ? "" : String(storage);
1149
+ if (el.value !== display) el.value = display;
1150
+ if (liveCastToNumber()) writeLastTypedForm(value, null);
1151
+ };
1015
1152
  addTrackedListener(el, lazy === true ? "change" : "input", (e) => {
1016
1153
  if (shouldBailListener(el)) return;
1017
1154
  const target = e.target;
@@ -1059,7 +1196,7 @@ const vRegisterText = {
1059
1196
  }
1060
1197
  const commit = domValue === "" && isRegisterValue(value) && value.acceptsUndefined ? void 0 : domValue;
1061
1198
  fireAssigner(el, value, commit);
1062
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1199
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1063
1200
  const storage = value.innerRef.value;
1064
1201
  if (storage !== domValue) {
1065
1202
  const display = storage == null ? "" : String(storage);
@@ -1119,6 +1256,15 @@ const vRegisterText = {
1119
1256
  mounted(el, { value }) {
1120
1257
  if (!isRegisterValue(value)) return;
1121
1258
  el.value = value.displayValue.value;
1259
+ setupValueSync(
1260
+ el,
1261
+ value.displayValue,
1262
+ () => {
1263
+ const next = value.displayValue.value;
1264
+ if (el.value !== next) el.value = next;
1265
+ },
1266
+ { skipWhileFocused: true }
1267
+ );
1122
1268
  },
1123
1269
  beforeUpdate(el, { value, oldValue, modifiers: { lazy, trim } }, vnode) {
1124
1270
  setAssignFunction(el, vnode, value);
@@ -1148,6 +1294,11 @@ const vRegisterCheckbox = {
1148
1294
  if (!isRegisterValue(value)) return;
1149
1295
  value.registerElement(el);
1150
1296
  setAssignFunction(el, vnode, value);
1297
+ el._syncFromStorage = () => {
1298
+ if (!isRegisterValue(value)) return;
1299
+ setChecked(el, value);
1300
+ el._lastAppliedModel = value.innerRef.value;
1301
+ };
1151
1302
  addTrackedListener(el, "change", () => {
1152
1303
  if (shouldBailListener(el)) return;
1153
1304
  noteInteraction(value);
@@ -1190,7 +1341,7 @@ const vRegisterCheckbox = {
1190
1341
  } else {
1191
1342
  fireAssigner(el, value, getCheckboxValue(el, checked));
1192
1343
  }
1193
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1344
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1194
1345
  setChecked(el, value);
1195
1346
  el._lastAppliedModel = value.innerRef.value;
1196
1347
  }
@@ -1199,7 +1350,12 @@ const vRegisterCheckbox = {
1199
1350
  // set initial checked on mount to wait for true-value/false-value
1200
1351
  mounted(el, { value }) {
1201
1352
  setChecked(el, value);
1202
- if (isRegisterValue(value)) el._lastAppliedModel = value.innerRef.value;
1353
+ if (!isRegisterValue(value)) return;
1354
+ el._lastAppliedModel = value.innerRef.value;
1355
+ setupValueSync(el, value.innerRef, () => {
1356
+ setChecked(el, value);
1357
+ el._lastAppliedModel = value.innerRef.value;
1358
+ });
1203
1359
  },
1204
1360
  // Skip the DOM sync when the model is identity-unchanged from the
1205
1361
  // last application. Pre-fix the scalar branch in `setChecked`
@@ -1245,11 +1401,18 @@ const vRegisterRadio = {
1245
1401
  if (!isRegisterValue(value)) return;
1246
1402
  value.registerElement(el);
1247
1403
  setAssignFunction(el, vnode, value);
1404
+ el._syncFromStorage = () => {
1405
+ if (!isRegisterValue(value)) return;
1406
+ const currentModel = value.innerRef.value;
1407
+ const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1408
+ if (el.checked !== target) el.checked = target;
1409
+ el._lastAppliedModel = currentModel;
1410
+ };
1248
1411
  addTrackedListener(el, "change", () => {
1249
1412
  if (shouldBailListener(el)) return;
1250
1413
  noteInteraction(value);
1251
1414
  fireAssigner(el, value, getValue(el));
1252
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1415
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1253
1416
  const currentModel = value.innerRef.value;
1254
1417
  const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1255
1418
  if (el.checked !== target) el.checked = target;
@@ -1268,6 +1431,10 @@ const vRegisterRadio = {
1268
1431
  if (!isRegisterValue(value)) return;
1269
1432
  el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
1270
1433
  el._lastAppliedModel = value.innerRef.value;
1434
+ setupValueSync(el, value.innerRef, () => {
1435
+ el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
1436
+ el._lastAppliedModel = value.innerRef.value;
1437
+ });
1271
1438
  },
1272
1439
  // Skip the DOM sync when the model is identity-unchanged from the
1273
1440
  // last application. Pre-fix the guard read `value.innerRef.value
@@ -1293,6 +1460,11 @@ const vRegisterSelect = {
1293
1460
  created(el, { value, modifiers: { number } }, vnode) {
1294
1461
  if (!isRegisterValue(value)) return;
1295
1462
  value.registerElement(el);
1463
+ el._syncFromStorage = () => {
1464
+ if (!isRegisterValue(value)) return;
1465
+ setSelected(el, value);
1466
+ el._lastAppliedModel = value.innerRef.value;
1467
+ };
1296
1468
  addTrackedListener(el, "change", () => {
1297
1469
  if (shouldBailListener(el)) return;
1298
1470
  noteInteraction(value);
@@ -1309,7 +1481,7 @@ const vRegisterSelect = {
1309
1481
  el._assigning = false;
1310
1482
  });
1311
1483
  }
1312
- if (isRegisterValue(value) && isDefaultAssigner(el[assignKey])) {
1484
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1313
1485
  setSelected(el, value);
1314
1486
  el._lastAppliedModel = value.innerRef.value;
1315
1487
  }
@@ -1320,7 +1492,13 @@ const vRegisterSelect = {
1320
1492
  // <option>s.
1321
1493
  mounted(el, { value }) {
1322
1494
  setSelected(el, value);
1323
- if (isRegisterValue(value)) el._lastAppliedModel = value.innerRef.value;
1495
+ if (!isRegisterValue(value)) return;
1496
+ el._lastAppliedModel = value.innerRef.value;
1497
+ setupValueSync(el, value.innerRef, () => {
1498
+ if (el._assigning === true) return;
1499
+ setSelected(el, value);
1500
+ el._lastAppliedModel = value.innerRef.value;
1501
+ });
1324
1502
  },
1325
1503
  beforeUpdate(el, binding, vnode) {
1326
1504
  setAssignFunction(el, vnode, binding.value);
@@ -1463,6 +1641,7 @@ const vRegisterDynamic = {
1463
1641
  beforeUnmount(el, { value }) {
1464
1642
  removeTrackedListeners(el);
1465
1643
  teardownAria(el);
1644
+ teardownValueSync(el);
1466
1645
  if (isRegisterValue(value)) {
1467
1646
  value.persistOptIns.removeAllFor(getOrAssignElementId(el));
1468
1647
  value.unmarkNoSync?.();
@@ -1471,6 +1650,7 @@ const vRegisterDynamic = {
1471
1650
  value.deregisterElement(el);
1472
1651
  delete el.composing;
1473
1652
  delete el._assigning;
1653
+ delete el._syncFromStorage;
1474
1654
  delete el[assignKey];
1475
1655
  },
1476
1656
  // The lifecycle hooks above don't run on the server (Vue skips
@@ -1516,7 +1696,7 @@ function installAttaformOnApp(app, options, source) {
1516
1696
  const registry = createRegistry(options);
1517
1697
  attachRegistryToApp(app, registry);
1518
1698
  app.directive("register", vRegister);
1519
- if (options.devtools !== false && !registry.ssr) {
1699
+ if (__DEV__ && options.devtools !== false && !registry.ssr) {
1520
1700
  void (async () => {
1521
1701
  try {
1522
1702
  const { setupAttaformDevtools } = await import('../chunks/devtools.mjs');
@@ -1647,5 +1827,5 @@ function isPathPrefix(prefix, path) {
1647
1827
  return true;
1648
1828
  }
1649
1829
 
1650
- export { AnonPersistError as A, kFormInstanceId as B, parseDottedPath as C, DEFAULT_SENSITIVE_NAMES as D, pathKeyToDotted as E, FORM_ERRORS_PATH as F, segmentsForPathKey as G, useRegister as H, INTERACTIVE_TAG_NAMES as I, useRegistry as J, vRegister as K, OutsideSetupError as O, ROOT_PATH as R, SubmitErrorHandlerError as S, __DEV__ as _, AttaformError as a, FORM_ERRORS_PATH_KEY as b, InvalidPathError as c, InvalidUseFormConfigError as d, ROOT_PATH_KEY as e, RegistryNotInstalledError as f, ReservedFormKeyError as g, allowSensitivePersist as h, assignKey as i, canonicalizePath as j, captureUserCallSite as k, coerceToPathKey as l, createAttaform as m, createIsSensitivePath as n, createPersistOptInRegistry as o, createRegistry as p, ensureAttaformInstalled as q, getOrAssignElementId as r, getRegistryFromApp as s, isPathPrefix as t, isRegisterValue as u, isSensitivePath as v, kAttaformAncestorWizard as w, kAttaformRegistry as x, kAttaformWizardActiveStepResolver as y, kFormContext as z };
1651
- //# sourceMappingURL=attaform.QG5TG8lB.mjs.map
1830
+ export { AnonPersistError as A, kFormInstanceId as B, parseDottedPath as C, DEFAULT_SENSITIVE_NAMES as D, pathKeyToDotted as E, FORM_ERRORS_PATH as F, segmentsForPathKey as G, toError as H, INTERACTIVE_TAG_NAMES as I, useRegister as J, useRegistry as K, vRegister as L, OutsideSetupError as O, ROOT_PATH as R, SubmitErrorHandlerError as S, __DEV__ as _, AttaformError as a, FORM_ERRORS_PATH_KEY as b, InvalidPathError as c, InvalidUseFormConfigError as d, ROOT_PATH_KEY as e, RegistryNotInstalledError as f, ReservedFormKeyError as g, allowSensitivePersist as h, assignKey as i, canonicalizePath as j, captureUserCallSite as k, coerceToPathKey as l, createAttaform as m, createIsSensitivePath as n, createPersistOptInRegistry as o, createRegistry as p, ensureAttaformInstalled as q, getOrAssignElementId as r, getRegistryFromApp as s, isPathPrefix as t, isRegisterValue as u, isSensitivePath as v, kAttaformAncestorWizard as w, kAttaformRegistry as x, kAttaformWizardActiveStepResolver as y, kFormContext as z };
1831
+ //# sourceMappingURL=attaform.pmtahXKy.mjs.map