attaform 0.22.0 → 0.23.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 (101) hide show
  1. package/README.md +7 -10
  2. package/dist/chunks/dev-key-collision-warnings.cjs +0 -33
  3. package/dist/chunks/dev-key-collision-warnings.cjs.map +1 -1
  4. package/dist/chunks/dev-key-collision-warnings.mjs +1 -33
  5. package/dist/chunks/dev-key-collision-warnings.mjs.map +1 -1
  6. package/dist/chunks/devtools.cjs +3 -5
  7. package/dist/chunks/devtools.cjs.map +1 -1
  8. package/dist/chunks/devtools.mjs +3 -5
  9. package/dist/chunks/devtools.mjs.map +1 -1
  10. package/dist/chunks/fingerprint2.cjs +1 -1
  11. package/dist/chunks/fingerprint2.mjs +1 -1
  12. package/dist/index.cjs +3 -5
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +6 -41
  15. package/dist/index.d.mts +6 -41
  16. package/dist/index.d.ts +6 -41
  17. package/dist/index.mjs +5 -5
  18. package/dist/nuxt.d.cts +1 -1
  19. package/dist/nuxt.d.mts +1 -1
  20. package/dist/nuxt.d.ts +1 -1
  21. package/dist/runtime/components/AttaformDevtoolsPanel.vue +3 -11
  22. package/dist/runtime/plugins/attaform.cjs +2 -2
  23. package/dist/runtime/plugins/attaform.mjs +2 -2
  24. package/dist/shared/{attaform.BGwNZ9GV.d.cts → attaform.BGMRvckW.d.ts} +10 -77
  25. package/dist/shared/{attaform.DvUH4a3o.d.ts → attaform.BJnNK75Y.d.cts} +45 -670
  26. package/dist/shared/{attaform.DvUH4a3o.d.mts → attaform.BJnNK75Y.d.mts} +45 -670
  27. package/dist/shared/{attaform.DvUH4a3o.d.cts → attaform.BJnNK75Y.d.ts} +45 -670
  28. package/dist/shared/{attaform.BKFwekY2.mjs → attaform.BhI9Icek.mjs} +3 -287
  29. package/dist/shared/attaform.BhI9Icek.mjs.map +1 -0
  30. package/dist/shared/{attaform.CRzpFCjV.cjs → attaform.BibT5AS_.cjs} +2 -2
  31. package/dist/shared/{attaform.CRzpFCjV.cjs.map → attaform.BibT5AS_.cjs.map} +1 -1
  32. package/dist/shared/{attaform.DkA5J8NW.d.cts → attaform.CO0e7YVY.d.cts} +1 -46
  33. package/dist/shared/{attaform.DkA5J8NW.d.ts → attaform.CO0e7YVY.d.mts} +1 -46
  34. package/dist/shared/{attaform.DkA5J8NW.d.mts → attaform.CO0e7YVY.d.ts} +1 -46
  35. package/dist/shared/{attaform.Q3eAD2wD.cjs → attaform.CaYj3ZfY.cjs} +3 -3
  36. package/dist/shared/{attaform.Q3eAD2wD.cjs.map → attaform.CaYj3ZfY.cjs.map} +1 -1
  37. package/dist/shared/{attaform.AyujQoHp.cjs → attaform.Cmb_LCie.cjs} +4 -4
  38. package/dist/shared/{attaform.DNuiFCXG.mjs.map → attaform.Cmb_LCie.cjs.map} +1 -1
  39. package/dist/shared/{attaform.CsB-iKbU.mjs → attaform.CtJOd7ox.mjs} +81 -591
  40. package/dist/shared/attaform.CtJOd7ox.mjs.map +1 -0
  41. package/dist/shared/{attaform.DgCfLqay.mjs → attaform.CzVta5o2.mjs} +4 -4
  42. package/dist/shared/attaform.CzVta5o2.mjs.map +1 -0
  43. package/dist/shared/{attaform.FN0vaQAg.d.mts → attaform.D52oJiYC.d.cts} +1 -1
  44. package/dist/shared/{attaform.aekT7mMx.d.cts → attaform.DCkSNnPr.d.mts} +1 -1
  45. package/dist/shared/{attaform.01iKS_lz.cjs → attaform.Db4E4IW6.cjs} +2 -294
  46. package/dist/shared/attaform.Db4E4IW6.cjs.map +1 -0
  47. package/dist/shared/{attaform.C-RtnCJM.cjs → attaform.DbyTD8N2.cjs} +4 -4
  48. package/dist/shared/attaform.DbyTD8N2.cjs.map +1 -0
  49. package/dist/shared/{attaform.DCjgGir_.mjs → attaform.Dd1Kmmaj.mjs} +3 -3
  50. package/dist/shared/{attaform.DCjgGir_.mjs.map → attaform.Dd1Kmmaj.mjs.map} +1 -1
  51. package/dist/shared/{attaform.D4XYaasQ.d.ts → attaform.DrY8srOp.d.mts} +10 -77
  52. package/dist/shared/{attaform.CjMcwV7W.cjs → attaform.DsQkXE3o.cjs} +79 -599
  53. package/dist/shared/attaform.DsQkXE3o.cjs.map +1 -0
  54. package/dist/shared/{attaform.CCCeEPwa.d.mts → attaform.DuPneYR0.d.cts} +10 -77
  55. package/dist/shared/{attaform.6xE0Lcfd.mjs → attaform.Dx9-QQE2.mjs} +2 -2
  56. package/dist/shared/{attaform.6xE0Lcfd.mjs.map → attaform.Dx9-QQE2.mjs.map} +1 -1
  57. package/dist/shared/{attaform.DUMWQefY.d.ts → attaform.WEwfXcHq.d.ts} +1 -1
  58. package/dist/shared/{attaform.DNuiFCXG.mjs → attaform.alpG7rT7.mjs} +4 -4
  59. package/dist/shared/{attaform.AyujQoHp.cjs.map → attaform.alpG7rT7.mjs.map} +1 -1
  60. package/dist/zod-v3.cjs +2 -2
  61. package/dist/zod-v3.d.cts +3 -3
  62. package/dist/zod-v3.d.mts +3 -3
  63. package/dist/zod-v3.d.ts +3 -3
  64. package/dist/zod-v3.mjs +2 -2
  65. package/dist/zod-v4.cjs +2 -2
  66. package/dist/zod-v4.d.cts +5 -5
  67. package/dist/zod-v4.d.mts +5 -5
  68. package/dist/zod-v4.d.ts +5 -5
  69. package/dist/zod-v4.mjs +2 -2
  70. package/dist/zod.cjs +5 -5
  71. package/dist/zod.d.cts +5 -5
  72. package/dist/zod.d.mts +5 -5
  73. package/dist/zod.d.ts +5 -5
  74. package/dist/zod.mjs +5 -5
  75. package/package.json +1 -1
  76. package/dist/chunks/indexeddb.cjs +0 -119
  77. package/dist/chunks/indexeddb.cjs.map +0 -1
  78. package/dist/chunks/indexeddb.mjs +0 -117
  79. package/dist/chunks/indexeddb.mjs.map +0 -1
  80. package/dist/chunks/local-storage.cjs +0 -58
  81. package/dist/chunks/local-storage.cjs.map +0 -1
  82. package/dist/chunks/local-storage.mjs +0 -56
  83. package/dist/chunks/local-storage.mjs.map +0 -1
  84. package/dist/chunks/multi-tab-sync.cjs +0 -367
  85. package/dist/chunks/multi-tab-sync.cjs.map +0 -1
  86. package/dist/chunks/multi-tab-sync.mjs +0 -364
  87. package/dist/chunks/multi-tab-sync.mjs.map +0 -1
  88. package/dist/chunks/session-storage.cjs +0 -58
  89. package/dist/chunks/session-storage.cjs.map +0 -1
  90. package/dist/chunks/session-storage.mjs +0 -56
  91. package/dist/chunks/session-storage.mjs.map +0 -1
  92. package/dist/chunks/wire-persistence.cjs +0 -396
  93. package/dist/chunks/wire-persistence.cjs.map +0 -1
  94. package/dist/chunks/wire-persistence.mjs +0 -394
  95. package/dist/chunks/wire-persistence.mjs.map +0 -1
  96. package/dist/shared/attaform.01iKS_lz.cjs.map +0 -1
  97. package/dist/shared/attaform.BKFwekY2.mjs.map +0 -1
  98. package/dist/shared/attaform.C-RtnCJM.cjs.map +0 -1
  99. package/dist/shared/attaform.CjMcwV7W.cjs.map +0 -1
  100. package/dist/shared/attaform.CsB-iKbU.mjs.map +0 -1
  101. package/dist/shared/attaform.DgCfLqay.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const vue = require('vue');
4
- const paths = require('./attaform.01iKS_lz.cjs');
4
+ const paths = require('./attaform.Db4E4IW6.cjs');
5
5
 
6
6
  function safeAssign(target, key, value) {
7
7
  if (key === "__proto__") {
@@ -642,9 +642,7 @@ function makeBlankRequiredError(segments, formKey) {
642
642
  }
643
643
 
644
644
  const DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS = 0;
645
- const DEFAULT_PERSISTENCE_DEBOUNCE_MS = 300;
646
645
  const DEFAULT_HISTORY_MAX_SNAPSHOTS = 128;
647
- const PERSISTENCE_KEY_PREFIX = "attaform:";
648
646
  const RESERVED_KEY_PREFIX = "__atta:";
649
647
  const ANONYMOUS_FORM_KEY_PREFIX = `${RESERVED_KEY_PREFIX}anon:`;
650
648
  const ANONYMOUS_WIZARD_KEY_PREFIX = `${RESERVED_KEY_PREFIX}anon-wizard:`;
@@ -1515,9 +1513,8 @@ function buildFieldArrayApi(state) {
1515
1513
  return Array.isArray(current) ? current.slice() : [];
1516
1514
  }
1517
1515
  function writeArray(path, next, arrayOp) {
1518
- const { segments, key } = paths.canonicalizePath(path);
1516
+ const { segments } = paths.canonicalizePath(path);
1519
1517
  const meta = {
1520
- persist: state.persistOptIns.hasAnyOptInForPath(key),
1521
1518
  ...arrayOp !== void 0 ? { arrayOp } : {}
1522
1519
  };
1523
1520
  return state.setValueAtPath(segments, next, meta);
@@ -1739,121 +1736,6 @@ function walk$1(value, basePath, schema, snapshotFieldStateAt) {
1739
1736
  return result;
1740
1737
  }
1741
1738
 
1742
- const PERSISTENCE_MODULE_KEY = "persistence";
1743
- async function getStorageAdapter(storage) {
1744
- if (typeof storage === "object") return storage;
1745
- switch (storage) {
1746
- case "local": {
1747
- const { createLocalStorageAdapter } = await import('../chunks/local-storage.cjs');
1748
- return createLocalStorageAdapter();
1749
- }
1750
- case "session": {
1751
- const { createSessionStorageAdapter } = await import('../chunks/session-storage.cjs');
1752
- return createSessionStorageAdapter();
1753
- }
1754
- case "indexeddb": {
1755
- const { createIndexedDbAdapter } = await import('../chunks/indexeddb.cjs');
1756
- return createIndexedDbAdapter();
1757
- }
1758
- }
1759
- }
1760
- function resolveStorageKeyBase(config, formKey) {
1761
- return config.key ?? `${PERSISTENCE_KEY_PREFIX}${formKey}`;
1762
- }
1763
- async function removeMatchingKeys(adapter, base, keepKey) {
1764
- let keys;
1765
- try {
1766
- keys = await adapter.listKeys(base);
1767
- } catch {
1768
- return;
1769
- }
1770
- for (const key of keys) {
1771
- if (key === keepKey) continue;
1772
- if (key === base || key.startsWith(`${base}:`)) {
1773
- void adapter.removeItem(key).catch(() => void 0);
1774
- }
1775
- }
1776
- }
1777
- async function cleanupOrphanKeys(adapter, base, currentKey) {
1778
- await removeMatchingKeys(adapter, base, currentKey);
1779
- }
1780
- const STANDARD_STORAGE_KINDS = ["local", "session", "indexeddb"];
1781
- function normalizePersistConfig(input) {
1782
- if (typeof input === "string") return { storage: input };
1783
- if ("storage" in input) return input;
1784
- return { storage: input };
1785
- }
1786
- async function sweepAllOrphansAcrossStandardStores(base) {
1787
- for (const kind of STANDARD_STORAGE_KINDS) {
1788
- try {
1789
- const adapter = await getStorageAdapter(kind);
1790
- await removeMatchingKeys(adapter, base);
1791
- } catch {
1792
- }
1793
- }
1794
- }
1795
- async function sweepNonConfiguredStandardStoresForOrphans(configured, base) {
1796
- const configuredKind = typeof configured === "string" ? configured : null;
1797
- for (const kind of STANDARD_STORAGE_KINDS) {
1798
- if (kind === configuredKind) continue;
1799
- try {
1800
- const adapter = await getStorageAdapter(kind);
1801
- await removeMatchingKeys(adapter, base);
1802
- } catch {
1803
- }
1804
- }
1805
- }
1806
- function mergeSparseHydration(schemaDefaults, sparse, schema) {
1807
- return mergeDeep(schemaDefaults, sparse, [], schema);
1808
- }
1809
- function mergeDeep(target, source, path, schema) {
1810
- if (source === void 0) return target;
1811
- if (source === null || typeof source !== "object") return source;
1812
- if (Array.isArray(source)) return source;
1813
- if (!isPlainRecord(source)) return source;
1814
- if (schema !== void 0) {
1815
- const du = schema.getUnionDiscriminatorAtPath(path);
1816
- if (du !== void 0) return mergeDuAwareKeys(source, path, schema, du);
1817
- }
1818
- return mergeObjectKeys(target, source, path, schema);
1819
- }
1820
- function mergeDuAwareKeys(source, path, schema, du) {
1821
- const sourceDisc = source[du.discriminatorKey];
1822
- if (sourceDisc !== void 0 && !du.isVariantSelected(sourceDisc)) {
1823
- return { [du.discriminatorKey]: sourceDisc };
1824
- }
1825
- if (sourceDisc !== void 0) {
1826
- const variantDefault = du.getVariantDefault(sourceDisc);
1827
- if (isPlainRecord(variantDefault)) {
1828
- return mergeVariantKeys(source, variantDefault, path, schema, du);
1829
- }
1830
- }
1831
- return {};
1832
- }
1833
- function mergeVariantKeys(source, variantDefault, path, schema, du) {
1834
- const out = { ...variantDefault };
1835
- for (const key of Object.keys(source)) {
1836
- if (!safeOwnHas(variantDefault, key) && key !== du.discriminatorKey) continue;
1837
- safeAssign(
1838
- out,
1839
- key,
1840
- mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
1841
- );
1842
- }
1843
- return out;
1844
- }
1845
- function mergeObjectKeys(target, source, path, schema) {
1846
- const out = isPlainRecord(target) ? { ...target } : {};
1847
- for (const key of Object.keys(source)) {
1848
- safeAssign(
1849
- out,
1850
- key,
1851
- mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
1852
- );
1853
- }
1854
- return out;
1855
- }
1856
-
1857
1739
  const warnedNoScopeStores = paths.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
1858
1740
  function buildProcessForm(state, formInstanceId, options = {}) {
1859
1741
  const invalidPolicy = options.onInvalidSubmit ?? "focus-first-error";
@@ -2111,44 +1993,6 @@ function applyInvalidSubmitPolicy(state, formInstanceId, policy) {
2111
1993
  target.element.focus({ preventScroll: true });
2112
1994
  }
2113
1995
 
2114
- function captureUserCallSite() {
2115
- const raw = new Error().stack;
2116
- if (typeof raw !== "string") return void 0;
2117
- const lines = raw.split("\n");
2118
- for (let i = 1; i < lines.length; i++) {
2119
- const frame = lines[i];
2120
- if (frame === void 0) continue;
2121
- if (/attaform[/-]forms?/i.test(frame)) continue;
2122
- if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
2123
- const trimmed = frame.trim();
2124
- if (trimmed.length === 0) continue;
2125
- return shortenSourceFrame(trimmed);
2126
- }
2127
- return void 0;
2128
- }
2129
- function shortenSourceFrame(frame) {
2130
- const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
2131
- if (match === null) return frame;
2132
- const [, urlOrPath, line] = match;
2133
- if (urlOrPath === void 0 || line === void 0) return frame;
2134
- let path = urlOrPath;
2135
- path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
2136
- path = path.replace(/^_nuxt\//, "");
2137
- path = path.replace(/^\//, "");
2138
- return `(${path}:${line})`;
2139
- }
2140
-
2141
- function extractSchemaFields(schema) {
2142
- try {
2143
- const root = schema.getDefaultAtPath([]);
2144
- if (root !== null && typeof root === "object" && !Array.isArray(root)) {
2145
- return Object.keys(root);
2146
- }
2147
- } catch {
2148
- }
2149
- return [];
2150
- }
2151
-
2152
1996
  const warnedRejections = paths.__DEV__ ? /* @__PURE__ */ new WeakMap() : null;
2153
1997
  function shouldWarnOnce$1(store, key) {
2154
1998
  if (warnedRejections === null) return false;
@@ -2478,16 +2322,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2478
2322
  const slimTypes = state.schema.getSlimPrimitiveTypesAtPath(segments);
2479
2323
  const acceptsUndefined = slimTypes.has("undefined");
2480
2324
  const acceptsString = slimTypes.has("string");
2481
- const persist = options?.persist === true;
2482
- const acknowledgeSensitive = options?.acknowledgeSensitive === true;
2483
- const multiTab = options?.multiTab !== false;
2484
2325
  const transforms = options?.transforms ?? EMPTY_TRANSFORMS;
2485
- const markNoSync = !multiTab ? () => {
2486
- state.incrementNoSyncOptOut(pathKey);
2487
- } : void 0;
2488
- const unmarkNoSync = !multiTab ? () => {
2489
- state.decrementNoSyncOptOut(pathKey);
2490
- } : void 0;
2491
2326
  const coerce = buildCoerceFn(
2492
2327
  state.schema,
2493
2328
  segments,
@@ -2498,18 +2333,10 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2498
2333
  segments,
2499
2334
  coerceIndex
2500
2335
  );
2501
- if (persist && !state.ssr && !state.modules.has(PERSISTENCE_MODULE_KEY)) {
2502
- throw new paths.AnonPersistError({
2503
- cause: "register-without-config",
2504
- schemaFields: extractSchemaFields(state.schema),
2505
- callSite: captureUserCallSite()
2506
- });
2507
- }
2508
2336
  const { aria } = computeFieldIdentity(formInstanceId, state.formKey, pathKey);
2509
2337
  const isRequired = state.schema.isRequiredAtPath(segments);
2510
2338
  const ariaEnabled = options?.autoAria ?? formAutoAria;
2511
2339
  const ariaDisplayState = getDisplayStateAt !== void 0 ? vue.computed(() => getDisplayStateAt(segments)) : void 0;
2512
- let boundElement = null;
2513
2340
  const internalRv = {
2514
2341
  innerRef,
2515
2342
  displayValue,
@@ -2519,8 +2346,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2519
2346
  segments,
2520
2347
  slimDefault,
2521
2348
  withInstanceMeta({
2522
- blank: true,
2523
- persist
2349
+ blank: true
2524
2350
  })
2525
2351
  );
2526
2352
  },
@@ -2528,7 +2354,6 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2528
2354
  state.markInteracted(segments);
2529
2355
  },
2530
2356
  registerElement: (element) => {
2531
- boundElement = element;
2532
2357
  if (!paths.INTERACTIVE_TAG_NAMES.has(element.tagName)) return;
2533
2358
  const added = state.registerElement(segments, element, formInstanceId);
2534
2359
  if (added) attachFocusListeners(state, segments, element, instanceMeta);
@@ -2536,11 +2361,9 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2536
2361
  deregisterElement: (element) => {
2537
2362
  detachFocusListeners(element);
2538
2363
  state.deregisterElement(segments, element);
2539
- if (boundElement === element) boundElement = null;
2540
2364
  },
2541
2365
  setValueWithInternalPath: (value, meta) => {
2542
- const resolvedMeta = meta === void 0 && boundElement !== null ? { persist: state.persistOptIns.hasOptIn(paths.getOrAssignElementId(boundElement), pathKey) } : meta;
2543
- return state.setValueAtPath(segments, value, withInstanceMeta(resolvedMeta));
2366
+ return state.setValueAtPath(segments, value, withInstanceMeta(meta));
2544
2367
  },
2545
2368
  // Called by the `vRegisterHint` compile-time transform's wrapping
2546
2369
  // IIFE on every server-side render of `<element v-register="…">`.
@@ -2578,15 +2401,6 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2578
2401
  segments: Object.freeze(segments.slice()),
2579
2402
  formKey: state.formKey,
2580
2403
  formInstanceId,
2581
- // --- Persistence opt-in (internal; the directive is the only
2582
- // legitimate consumer) ---
2583
- persist,
2584
- acknowledgeSensitive,
2585
- persistOptIns: state.persistOptIns,
2586
- isSensitivePath: state.isSensitivePath,
2587
- multiTab,
2588
- ...markNoSync !== void 0 ? { markNoSync } : {},
2589
- ...unmarkNoSync !== void 0 ? { unmarkNoSync } : {},
2590
2404
  transforms,
2591
2405
  coerce,
2592
2406
  ...coerceElement !== void 0 ? { coerceElement } : {},
@@ -3023,12 +2837,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
3023
2837
  const segments = paths.canonicalizePath(pathInput).segments;
3024
2838
  return vue.computed(() => getAtPath(state.form.value, segments));
3025
2839
  }
3026
- function setValueImpl(pathOrValue, maybeValue, maybeOptions) {
2840
+ function setValueImpl(pathOrValue, maybeValue) {
3027
2841
  const argc = arguments.length;
3028
2842
  const isPathForm = argc >= 2 && (typeof pathOrValue === "string" || Array.isArray(pathOrValue));
3029
- const options2 = isPathForm ? maybeOptions : argc >= 2 ? maybeValue : void 0;
3030
- const silent = options2?.silent === true;
3031
- const writeMeta = (extra) => withInstanceMeta(silent ? { ...extra, silent: true } : extra);
2843
+ const writeMeta = (extra) => withInstanceMeta(extra);
3032
2844
  if (!isPathForm) {
3033
2845
  const next = typeof pathOrValue === "function" ? pathOrValue(structuralSnapshot(state.form.value)) : pathOrValue;
3034
2846
  const walked2 = walkUnsetSentinels(
@@ -3320,7 +3132,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
3320
3132
  instanceId: formInstanceId
3321
3133
  })
3322
3134
  );
3323
- const persistenceHandle = state.modules.get(PERSISTENCE_MODULE_KEY);
3324
3135
  const reset = (nextDefaultValues) => {
3325
3136
  if (nextDefaultValues === void 0) {
3326
3137
  state.reset();
@@ -3335,16 +3146,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
3335
3146
  state.originalBlankPaths.add(pathKey);
3336
3147
  }
3337
3148
  }
3338
- if (persistenceHandle !== void 0) {
3339
- void persistenceHandle.ready.then((m) => m?.clearPersistedDraft()).catch(() => void 0);
3340
- }
3341
3149
  };
3342
3150
  const resetField = (pathInput) => {
3343
3151
  const segments = paths.canonicalizePath(pathInput).segments;
3344
3152
  state.resetField(segments);
3345
- if (persistenceHandle !== void 0) {
3346
- void persistenceHandle.ready.then((m) => m?.clearPersistedDraft(segments)).catch(() => void 0);
3347
- }
3348
3153
  };
3349
3154
  function clear(pathInput) {
3350
3155
  if (pathInput === void 0) {
@@ -3352,31 +3157,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
3352
3157
  }
3353
3158
  return setValueImpl(pathInput, unset);
3354
3159
  }
3355
- const persist = async (pathInput, options2) => {
3356
- const segments = paths.canonicalizePath(pathInput).segments;
3357
- if (!paths.allowSensitivePersist(
3358
- segments,
3359
- options2?.acknowledgeSensitive === true,
3360
- state.isSensitivePath
3361
- )) {
3362
- return;
3363
- }
3364
- if (persistenceHandle === void 0) return;
3365
- const persistence = await persistenceHandle.ready;
3366
- if (persistence === void 0) return;
3367
- await persistence.writePathImmediately(segments);
3368
- };
3369
- const clearPersistedDraft = async (pathInput) => {
3370
- if (persistenceHandle === void 0) return;
3371
- const persistence = await persistenceHandle.ready;
3372
- if (persistence === void 0) return;
3373
- if (pathInput === void 0) {
3374
- await persistence.clearPersistedDraft();
3375
- return;
3376
- }
3377
- const segments = paths.canonicalizePath(pathInput).segments;
3378
- await persistence.clearPersistedDraft(segments);
3379
- };
3380
3160
  function touch(pathInput) {
3381
3161
  const segments = pathInput === void 0 ? paths.ROOT_PATH : paths.canonicalizePath(pathInput).segments;
3382
3162
  state.touchAtPath(segments);
@@ -3461,18 +3241,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
3461
3241
  }
3462
3242
  return Object.freeze(out);
3463
3243
  }
3464
- const formHandle = {
3465
- current: void 0
3466
- };
3467
- function onChangeImpl(a, b, c) {
3468
- const sourced = typeof b === "function";
3469
- const source = sourced ? a : void 0;
3470
- const handler = sourced ? b : a;
3471
- const options2 = sourced ? c : b;
3472
- const stop = state.registerOnChange(source, handler, options2, () => formHandle.current);
3473
- if (vue.getCurrentScope() !== void 0) vue.onScopeDispose(stop);
3474
- return stop;
3475
- }
3476
3244
  const api = {
3477
3245
  handleSubmit: gated(handleSubmit),
3478
3246
  // Callable readonly Proxies (`values`, `fields`, `errors`) and the
@@ -3538,8 +3306,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
3538
3306
  reset: gated(reset),
3539
3307
  resetField: gated(resetField),
3540
3308
  clear: gated(clear),
3541
- persist: gated(persist),
3542
- clearPersistedDraft: gated(clearPersistedDraft),
3543
3309
  focusFirstError: gated(focusFirstError),
3544
3310
  scrollToFirstError: gated(scrollToFirstError),
3545
3311
  applyInvalidSubmitPolicy: gated(applyInvalidSubmitPolicyPublic),
@@ -3560,10 +3326,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
3560
3326
  get blankPaths() {
3561
3327
  void state.activate();
3562
3328
  return blankPathsView;
3563
- },
3564
- onChange: onChangeImpl
3329
+ }
3565
3330
  };
3566
- formHandle.current = api;
3567
3331
  return api;
3568
3332
  }
3569
3333
 
@@ -4075,168 +3839,55 @@ function createArrayBookkeeping(deps) {
4075
3839
  };
4076
3840
  }
4077
3841
 
4078
- const NOOP_STOP = () => {
4079
- };
4080
- function isThenable(value) {
4081
- return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
4082
- }
4083
- function isSuppressed(meta) {
4084
- return meta?.hydration === true || meta?.crossTab === true || meta?.silent === true;
4085
- }
4086
- function canonicalizeSourceList(raw) {
4087
- const list = typeof raw === "string" ? [raw] : raw;
4088
- const out = [];
4089
- const seen = /* @__PURE__ */ new Set();
4090
- for (const entry of list) {
4091
- const { segments, key } = paths.canonicalizePath(entry);
4092
- if (seen.has(key)) continue;
4093
- seen.add(key);
4094
- out.push({ segments, key, dotted: paths.segmentsToDotted(segments) });
4095
- }
4096
- return out;
3842
+ function mergeSparseHydration(schemaDefaults, sparse, schema) {
3843
+ return mergeDeep(schemaDefaults, sparse, [], schema);
4097
3844
  }
4098
- function makeResolver(source) {
4099
- if (source === void 0) {
4100
- const root = [{ segments: paths.ROOT_PATH, key: paths.ROOT_PATH_KEY, dotted: "" }];
4101
- return () => root;
4102
- }
4103
- if (typeof source !== "function" && !vue.isRef(source)) {
4104
- const fixed = canonicalizeSourceList(source);
4105
- return () => fixed;
3845
+ function mergeDeep(target, source, path, schema) {
3846
+ if (source === void 0) return target;
3847
+ if (source === null || typeof source !== "object") return source;
3848
+ if (Array.isArray(source)) return source;
3849
+ if (!isPlainRecord(source)) return source;
3850
+ if (schema !== void 0) {
3851
+ const du = schema.getUnionDiscriminatorAtPath(path);
3852
+ if (du !== void 0) return mergeDuAwareKeys(source, path, schema, du);
4106
3853
  }
4107
- return () => canonicalizeSourceList(vue.toValue(source));
3854
+ return mergeObjectKeys(target, source, path, schema);
4108
3855
  }
4109
- function createOnChangeRegistry(deps) {
4110
- const handlers = /* @__PURE__ */ new Set();
4111
- function isCurrent(reg, key, token) {
4112
- return reg.runs.get(key)?.token === token;
4113
- }
4114
- function routeError(reg, error, source, changed, value, previous, attempt, token) {
4115
- if (reg.onError === void 0) {
4116
- if (paths.__DEV__) {
4117
- console.error(
4118
- `[attaform] onChange handler threw for path '${source.dotted}' \u2014 error swallowed. Pass { onError } to handle it. Original error:`,
4119
- error
4120
- );
4121
- }
4122
- return;
4123
- }
4124
- const retry = () => {
4125
- if (!isCurrent(reg, source.key, token)) return;
4126
- runHandler(reg, source, changed, value, previous, attempt + 1);
4127
- };
4128
- const errCtx = {
4129
- path: source.dotted,
4130
- value,
4131
- attempt,
4132
- retry,
4133
- form: reg.getForm()
4134
- };
4135
- try {
4136
- reg.onError(error, errCtx);
4137
- } catch (err) {
4138
- if (paths.__DEV__) console.error("[attaform] onChange onError threw:", err);
4139
- }
4140
- }
4141
- function runHandler(reg, source, changed, value, previous, attempt) {
4142
- const prior = reg.runs.get(source.key);
4143
- if (prior) prior.controller.abort();
4144
- const controller = new AbortController();
4145
- const token = ++reg.seq;
4146
- reg.runs.set(source.key, { token, controller });
4147
- const ctx = {
4148
- path: source.dotted,
4149
- previous,
4150
- signal: controller.signal,
4151
- attempt,
4152
- form: reg.getForm(),
4153
- changed
4154
- };
4155
- let result;
4156
- try {
4157
- result = reg.handler(value, ctx);
4158
- } catch (error) {
4159
- routeError(reg, error, source, changed, value, previous, attempt, token);
4160
- return;
4161
- }
4162
- if (isThenable(result)) {
4163
- result.then(void 0, (error) => {
4164
- if (isCurrent(reg, source.key, token)) {
4165
- routeError(reg, error, source, changed, value, previous, attempt, token);
4166
- }
4167
- });
4168
- }
3856
+ function mergeDuAwareKeys(source, path, schema, du) {
3857
+ const sourceDisc = source[du.discriminatorKey];
3858
+ if (sourceDisc !== void 0 && !du.isVariantSelected(sourceDisc)) {
3859
+ return { [du.discriminatorKey]: sourceDisc };
4169
3860
  }
4170
- function dispatch(patches, meta) {
4171
- if (handlers.size === 0 || isSuppressed(meta)) return;
4172
- for (const reg of handlers) {
4173
- let sources;
4174
- try {
4175
- sources = reg.resolve();
4176
- } catch (error) {
4177
- if (paths.__DEV__) console.error("[attaform] onChange source getter threw:", error);
4178
- continue;
4179
- }
4180
- for (const source of sources) {
4181
- let changed;
4182
- for (const patch of patches) {
4183
- if (paths.isPathPrefix(source.segments, patch.path) || paths.isPathPrefix(patch.path, source.segments)) {
4184
- (changed ?? (changed = [])).push(paths.segmentsToDotted(patch.path));
4185
- }
4186
- }
4187
- if (changed === void 0) continue;
4188
- const value = deps.getValueAtPath(source.segments);
4189
- const previous = reg.previous.has(source.key) ? reg.previous.get(source.key) : value;
4190
- reg.previous.set(source.key, value);
4191
- runHandler(reg, source, changed, value, previous, 0);
4192
- }
3861
+ if (sourceDisc !== void 0) {
3862
+ const variantDefault = du.getVariantDefault(sourceDisc);
3863
+ if (isPlainRecord(variantDefault)) {
3864
+ return mergeVariantKeys(source, variantDefault, path, schema, du);
4193
3865
  }
4194
3866
  }
4195
- function register(source, handler, options, getForm) {
4196
- if (deps.ssr) return NOOP_STOP;
4197
- const reg = {
4198
- handler,
4199
- onError: options?.onError,
4200
- getForm,
4201
- resolve: makeResolver(source),
4202
- previous: /* @__PURE__ */ new Map(),
4203
- runs: /* @__PURE__ */ new Map(),
4204
- seq: 0
4205
- };
4206
- try {
4207
- for (const { key, segments } of reg.resolve()) {
4208
- reg.previous.set(key, deps.getValueAtPath(segments));
4209
- }
4210
- } catch (error) {
4211
- if (paths.__DEV__) console.error("[attaform] onChange source getter threw at registration:", error);
4212
- }
4213
- handlers.add(reg);
4214
- let stopped = false;
4215
- return () => {
4216
- if (stopped) return;
4217
- stopped = true;
4218
- handlers.delete(reg);
4219
- for (const run of reg.runs.values()) run.controller.abort();
4220
- reg.runs.clear();
4221
- reg.previous.clear();
4222
- };
3867
+ return {};
3868
+ }
3869
+ function mergeVariantKeys(source, variantDefault, path, schema, du) {
3870
+ const out = { ...variantDefault };
3871
+ for (const key of Object.keys(source)) {
3872
+ if (!safeOwnHas(variantDefault, key) && key !== du.discriminatorKey) continue;
3873
+ safeAssign(
3874
+ out,
3875
+ key,
3876
+ mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
3877
+ );
4223
3878
  }
4224
- function dispose() {
4225
- for (const reg of handlers) {
4226
- for (const run of reg.runs.values()) run.controller.abort();
4227
- reg.runs.clear();
4228
- reg.previous.clear();
4229
- }
4230
- handlers.clear();
3879
+ return out;
3880
+ }
3881
+ function mergeObjectKeys(target, source, path, schema) {
3882
+ const out = isPlainRecord(target) ? { ...target } : {};
3883
+ for (const key of Object.keys(source)) {
3884
+ safeAssign(
3885
+ out,
3886
+ key,
3887
+ mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
3888
+ );
4231
3889
  }
4232
- return {
4233
- get active() {
4234
- return handlers.size > 0;
4235
- },
4236
- register,
4237
- dispatch,
4238
- dispose
4239
- };
3890
+ return out;
4240
3891
  }
4241
3892
 
4242
3893
  function isHydratedFieldRecord(value) {
@@ -4372,27 +4023,8 @@ function createFormStore(options) {
4372
4023
  const formChangeListeners = /* @__PURE__ */ new Set();
4373
4024
  const submitSuccessListeners = /* @__PURE__ */ new Set();
4374
4025
  const resetListeners = /* @__PURE__ */ new Set();
4375
- const onChangeRegistry = createOnChangeRegistry({ getValueAtPath, ssr });
4376
- const persistOptIns = paths.createPersistOptInRegistry();
4377
- const noSyncPaths = /* @__PURE__ */ new Set();
4378
- const noSyncPathCounts = /* @__PURE__ */ new Map();
4379
- function incrementNoSyncOptOut(path) {
4380
- const next = (noSyncPathCounts.get(path) ?? 0) + 1;
4381
- noSyncPathCounts.set(path, next);
4382
- if (next === 1) noSyncPaths.add(path);
4383
- }
4384
- function decrementNoSyncOptOut(path) {
4385
- const current = noSyncPathCounts.get(path) ?? 0;
4386
- if (current <= 1) {
4387
- noSyncPathCounts.delete(path);
4388
- noSyncPaths.delete(path);
4389
- return;
4390
- }
4391
- noSyncPathCounts.set(path, current - 1);
4392
- }
4393
4026
  const coerceIndex = resolveCoercionIndex(options.coerce);
4394
4027
  const resolvedGetDisplayState = resolveGetDisplayState(options.getDisplayState);
4395
- const resolvedIsSensitivePath = options.isSensitivePath ?? paths.isSensitivePath;
4396
4028
  const cleanupHooks = [];
4397
4029
  const modules = /* @__PURE__ */ new Map();
4398
4030
  const fieldValidatingSince = vue.reactive(/* @__PURE__ */ new Map());
@@ -4740,7 +4372,6 @@ function createFormStore(options) {
4740
4372
  console.error("[attaform] onFormChange threw:", err);
4741
4373
  }
4742
4374
  }
4743
- if (onChangeRegistry.active) onChangeRegistry.dispatch(patches, meta);
4744
4375
  }
4745
4376
  function applyFormReplacementWithPath(next, meta, arrayOpPath) {
4746
4377
  const prev = form.value;
@@ -5181,10 +4812,6 @@ function createFormStore(options) {
5181
4812
  formChangeListeners.clear();
5182
4813
  submitSuccessListeners.clear();
5183
4814
  resetListeners.clear();
5184
- onChangeRegistry.dispose();
5185
- persistOptIns.clear();
5186
- noSyncPaths.clear();
5187
- noSyncPathCounts.clear();
5188
4815
  }
5189
4816
  function getValueAtPath(path) {
5190
4817
  return getAtPath(form.value, path);
@@ -5487,7 +5114,7 @@ function createFormStore(options) {
5487
5114
  });
5488
5115
  const next = resetResponse.data;
5489
5116
  rebuildAuthoredPaths(resetSource, next);
5490
- applyFormReplacement(next, { silent: true });
5117
+ applyFormReplacement(next);
5491
5118
  arrayIdentity.rebaselineAll();
5492
5119
  originals.clear();
5493
5120
  diffAndApply({}, next, [], (patch) => {
@@ -5733,7 +5360,6 @@ function createFormStore(options) {
5733
5360
  settleTransforms,
5734
5361
  scheduleFieldValidation,
5735
5362
  onFormChange,
5736
- registerOnChange: onChangeRegistry.register,
5737
5363
  onSubmitSuccess,
5738
5364
  onReset,
5739
5365
  emitSubmitSuccess,
@@ -5741,11 +5367,6 @@ function createFormStore(options) {
5741
5367
  registerDrain,
5742
5368
  awaitPendingWrites,
5743
5369
  modules,
5744
- persistOptIns,
5745
- isSensitivePath: resolvedIsSensitivePath,
5746
- noSyncPaths,
5747
- incrementNoSyncOptOut,
5748
- decrementNoSyncOptOut,
5749
5370
  coerceIndex,
5750
5371
  blankPaths,
5751
5372
  originalBlankPaths,
@@ -5753,6 +5374,33 @@ function createFormStore(options) {
5753
5374
  };
5754
5375
  }
5755
5376
 
5377
+ function captureUserCallSite() {
5378
+ const raw = new Error().stack;
5379
+ if (typeof raw !== "string") return void 0;
5380
+ const lines = raw.split("\n");
5381
+ for (let i = 1; i < lines.length; i++) {
5382
+ const frame = lines[i];
5383
+ if (frame === void 0) continue;
5384
+ if (/attaform[/-]forms?/i.test(frame)) continue;
5385
+ if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
5386
+ const trimmed = frame.trim();
5387
+ if (trimmed.length === 0) continue;
5388
+ return shortenSourceFrame(trimmed);
5389
+ }
5390
+ return void 0;
5391
+ }
5392
+ function shortenSourceFrame(frame) {
5393
+ const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
5394
+ if (match === null) return frame;
5395
+ const [, urlOrPath, line] = match;
5396
+ if (urlOrPath === void 0 || line === void 0) return frame;
5397
+ let path = urlOrPath;
5398
+ path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
5399
+ path = path.replace(/^_nuxt\//, "");
5400
+ path = path.replace(/^\//, "");
5401
+ return `(${path}:${line})`;
5402
+ }
5403
+
5756
5404
  function getComputedSchema(formKey, schemaOrCallback, options) {
5757
5405
  if (typeof schemaOrCallback === "function") return schemaOrCallback(formKey, options);
5758
5406
  return schemaOrCallback;
@@ -5862,10 +5510,6 @@ function createHistoryModule(state, config) {
5862
5510
  clear();
5863
5511
  return;
5864
5512
  }
5865
- if (meta?.crossTab === true) {
5866
- currentSnapshot.value = captureSnapshot();
5867
- return;
5868
- }
5869
5513
  const newSnap = captureSnapshot();
5870
5514
  const prevSnap = currentSnapshot.value;
5871
5515
  const formPatches = [];
@@ -5886,9 +5530,7 @@ function createHistoryModule(state, config) {
5886
5530
  suppressNext = true;
5887
5531
  state.blankPaths.clear();
5888
5532
  for (const key of snap.blankPaths) state.blankPaths.add(key);
5889
- state.applyFormReplacement(snap.form, {
5890
- persist: !state.persistOptIns.isEmpty()
5891
- });
5533
+ state.applyFormReplacement(snap.form);
5892
5534
  const schemaFlat = snap.schemaErrors.flatMap(([, errs]) => errs);
5893
5535
  const userFlat = snap.userErrors.flatMap(([, errs]) => errs);
5894
5536
  state.setAllSchemaErrors(schemaFlat);
@@ -5939,28 +5581,6 @@ function createHistoryModule(state, config) {
5939
5581
  };
5940
5582
  }
5941
5583
 
5942
- const warned = /* @__PURE__ */ new Set();
5943
- function warnOnceInsecureContext(feature) {
5944
- if (!paths.__DEV__) return;
5945
- if (warned.has(feature)) return;
5946
- warned.add(feature);
5947
- const message = featureMessage(feature);
5948
- console.warn(`[attaform] ${message}`);
5949
- }
5950
- function featureMessage(feature) {
5951
- switch (feature) {
5952
- case "multiTab":
5953
- return "Multi-tab sync requires a secure context (HTTPS or localhost). Plain HTTP on a real hostname is interceptable by network observers, so the sync module is disabled. Serve over HTTPS in production (or develop on `localhost`) to enable cross-tab synchronisation. Use `multiTab: false` on `useForm` to silence this warning.";
5954
- case "persist:local":
5955
- return "Built-in `persist: 'local'` storage requires a secure context (HTTPS or localhost). Plain HTTP on a real hostname is MITM-interceptable, so the persistence layer is disabled. Serve over HTTPS to enable localStorage persistence, or pass a custom storage adapter to opt out of the secure-context gate.";
5956
- case "persist:session":
5957
- return "Built-in `persist: 'session'` storage requires a secure context (HTTPS or localhost). Plain HTTP on a real hostname is MITM-interceptable, so the persistence layer is disabled. Serve over HTTPS to enable sessionStorage persistence, or pass a custom storage adapter to opt out of the secure-context gate.";
5958
- }
5959
- }
5960
- function isSecureContext() {
5961
- return typeof window !== "undefined" && window.isSecureContext === true;
5962
- }
5963
-
5964
5584
  function resolveTrichotomy(input) {
5965
5585
  if (typeof input === "function") {
5966
5586
  return { kind: "async", factory: input };
@@ -5989,18 +5609,10 @@ function useAbstractForm(configuration, options) {
5989
5609
  defaultValue: DEFAULT_MAX_RECURSION_DEPTH
5990
5610
  });
5991
5611
  const resolvedSchema = getComputedSchema(key, configuration.schema, { maxRecursionDepth });
5992
- if (configuration.persist !== void 0 && configuration.key === void 0) {
5993
- throw new paths.AnonPersistError({
5994
- cause: "no-key",
5995
- schemaFields: extractSchemaFields(resolvedSchema),
5996
- callSite: captureUserCallSite()
5997
- });
5998
- }
5999
5612
  const existing = registry.forms.get(key);
6000
5613
  if (paths.__DEV__ && existing !== void 0) {
6001
5614
  void import('../chunks/dev-key-collision-warnings.cjs').then((m) => {
6002
5615
  void m.warnOnSchemaFingerprintMismatch(key, existing.schema, resolvedSchema);
6003
- m.warnOnPersistDivergence(key, existing, configuration.persist);
6004
5616
  });
6005
5617
  }
6006
5618
  const hadPendingHydration = registry.pendingHydration.has(key);
@@ -6028,85 +5640,6 @@ function useAbstractForm(configuration, options) {
6028
5640
  const releaseConsumer = registry.trackConsumer(key);
6029
5641
  vue.onScopeDispose(releaseConsumer);
6030
5642
  }
6031
- const persistDisabledByAnonRule = merged.persist !== void 0 && enforceAnonPersistRule(state.formKey, registry.ssr);
6032
- if (existing === void 0 && !registry.ssr) {
6033
- if (merged.persist !== void 0 && !persistDisabledByAnonRule) {
6034
- const resolvedPersist = normalizePersistConfig(merged.persist);
6035
- const storageKind = resolvedPersist.storage;
6036
- const isBuiltinStorage = typeof storageKind === "string";
6037
- const secureContextOk = !isBuiltinStorage || isSecureContext();
6038
- if (!secureContextOk) {
6039
- const feature = storageKind === "session" ? "persist:session" : "persist:local";
6040
- warnOnceInsecureContext(feature);
6041
- void sweepAllOrphansAcrossStandardStores(`${PERSISTENCE_KEY_PREFIX}${state.formKey}`);
6042
- } else {
6043
- const persistenceBase = resolveStorageKeyBase(resolvedPersist, state.formKey);
6044
- void sweepNonConfiguredStandardStoresForOrphans(resolvedPersist.storage, persistenceBase);
6045
- const adapterPromise = getStorageAdapter(resolvedPersist.storage);
6046
- let persistDisposed = false;
6047
- state.registerCleanup(() => {
6048
- persistDisposed = true;
6049
- });
6050
- const ready = (async () => {
6051
- try {
6052
- const [{ wirePersistence }, fingerprintToken] = await Promise.all([
6053
- import('../chunks/wire-persistence.cjs'),
6054
- resolvePersistFingerprintToken(state)
6055
- ]);
6056
- if (persistDisposed) return void 0;
6057
- const persistenceModule = wirePersistence(
6058
- state,
6059
- resolvedPersist,
6060
- adapterPromise,
6061
- fingerprintToken
6062
- );
6063
- state.registerDrain(() => persistenceModule.awaitPendingWrites());
6064
- state.registerCleanup(() => persistenceModule.dispose());
6065
- return persistenceModule;
6066
- } catch {
6067
- return void 0;
6068
- }
6069
- })();
6070
- const persistenceHandle = { config: resolvedPersist, ready };
6071
- state.modules.set(PERSISTENCE_MODULE_KEY, persistenceHandle);
6072
- }
6073
- } else {
6074
- void sweepAllOrphansAcrossStandardStores(`${PERSISTENCE_KEY_PREFIX}${state.formKey}`);
6075
- }
6076
- }
6077
- if (existing === void 0 && merged.multiTab === true && configuration.key !== void 0 && !registry.ssr) {
6078
- const hasBroadcastChannel = typeof BroadcastChannel !== "undefined";
6079
- const secureContext = isSecureContext();
6080
- if (hasBroadcastChannel && secureContext) {
6081
- let formDisposed = false;
6082
- state.registerCleanup(() => {
6083
- formDisposed = true;
6084
- });
6085
- void (async () => {
6086
- try {
6087
- const [{ createMultiTabSyncModule, MULTI_TAB_SYNC_MODULE_KEY }, fingerprint] = await Promise.all([import('../chunks/multi-tab-sync.cjs'), state.schema.fingerprint()]);
6088
- if (formDisposed) return;
6089
- const channelName = `attaform:sync:${state.formKey}:${hashStableString(fingerprint)}`;
6090
- const syncModule = createMultiTabSyncModule(state, channelName, {
6091
- isSensitivePath: state.isSensitivePath,
6092
- noSyncPaths: state.noSyncPaths,
6093
- validateForm: (form) => {
6094
- const result = state.schema.validateAtPath(form, void 0, { sync: true });
6095
- if (result instanceof Promise) return;
6096
- if (!result.success) {
6097
- throw new Error("attaform multi-tab sync: post-apply schema validation failed");
6098
- }
6099
- }
6100
- });
6101
- state.modules.set(MULTI_TAB_SYNC_MODULE_KEY, syncModule);
6102
- state.registerCleanup(() => syncModule.dispose());
6103
- } catch {
6104
- }
6105
- })();
6106
- } else if (hasBroadcastChannel && !secureContext) {
6107
- warnOnceInsecureContext("multiTab");
6108
- }
6109
- }
6110
5643
  if (existing === void 0 && merged.history !== void 0) {
6111
5644
  const historyModule = createHistoryModule(state, merged.history);
6112
5645
  state.modules.set(HISTORY_MODULE_KEY, historyModule);
@@ -6148,14 +5681,6 @@ function useAbstractForm(configuration, options) {
6148
5681
  apiOptions.autoAria = merged.autoAria;
6149
5682
  }
6150
5683
  const api = buildFormApi(state, formInstanceId, apiOptions);
6151
- const onChangeConfig = configuration.onChange;
6152
- if (onChangeConfig !== void 0) {
6153
- const handler = typeof onChangeConfig === "function" ? onChangeConfig : onChangeConfig.handler;
6154
- const onError = typeof onChangeConfig === "function" ? void 0 : onChangeConfig.onError;
6155
- const options2 = onError === void 0 ? void 0 : { onError };
6156
- const stop = state.registerOnChange(void 0, handler, options2, () => api);
6157
- if (vue.getCurrentScope() !== void 0) vue.onScopeDispose(stop);
6158
- }
6159
5684
  return api;
6160
5685
  }
6161
5686
  function mergeWithDefaults(defaults, configuration) {
@@ -6168,8 +5693,6 @@ function mergeWithDefaults(defaults, configuration) {
6168
5693
  const debounceMs = configuration.debounceMs ?? defaults.debounceMs;
6169
5694
  const getDisplayState = configuration.getDisplayState ?? defaults.getDisplayState;
6170
5695
  const maxRecursionDepth = configuration.maxRecursionDepth ?? defaults.maxRecursionDepth;
6171
- const sensitiveNames = configuration.sensitiveNames ?? defaults.sensitiveNames;
6172
- const multiTab = configuration.multiTab ?? defaults.multiTab;
6173
5696
  const autoAria = configuration.autoAria ?? defaults.autoAria;
6174
5697
  return {
6175
5698
  ...configuration,
@@ -6182,8 +5705,6 @@ function mergeWithDefaults(defaults, configuration) {
6182
5705
  ...debounceMs === void 0 ? {} : { debounceMs },
6183
5706
  ...getDisplayState === void 0 ? {} : { getDisplayState },
6184
5707
  ...maxRecursionDepth === void 0 ? {} : { maxRecursionDepth },
6185
- ...sensitiveNames === void 0 ? {} : { sensitiveNames },
6186
- ...multiTab === void 0 ? {} : { multiTab },
6187
5708
  ...autoAria === void 0 ? {} : { autoAria }
6188
5709
  };
6189
5710
  }
@@ -6199,8 +5720,6 @@ function buildFreshState(key, schema, configuration, registry) {
6199
5720
  if (pending === void 0) {
6200
5721
  initialBlankPaths = walked.paths;
6201
5722
  }
6202
- const resolvedSensitiveNames = configuration.sensitiveNames;
6203
- const resolvedIsSensitivePath = resolvedSensitiveNames === void 0 ? void 0 : paths.createIsSensitivePath(resolvedSensitiveNames);
6204
5723
  const createOptions = {
6205
5724
  formKey: key,
6206
5725
  schema,
@@ -6228,8 +5747,7 @@ function buildFreshState(key, schema, configuration, registry) {
6228
5747
  ...configuration.rememberVariants !== void 0 ? { rememberVariants: configuration.rememberVariants } : {},
6229
5748
  ...configuration.coerce !== void 0 ? { coerce: configuration.coerce } : {},
6230
5749
  ...configuration.getDisplayState !== void 0 ? { getDisplayState: configuration.getDisplayState } : {},
6231
- ...initialBlankPaths !== void 0 ? { initialBlankPaths } : {},
6232
- ...resolvedIsSensitivePath !== void 0 ? { isSensitivePath: resolvedIsSensitivePath } : {}
5750
+ ...initialBlankPaths !== void 0 ? { initialBlankPaths } : {}
6233
5751
  };
6234
5752
  const state = createFormStore(createOptions);
6235
5753
  registry.forms.set(
@@ -6268,34 +5786,6 @@ function resolveFormKey(key) {
6268
5786
  }
6269
5787
  return `${ANONYMOUS_FORM_KEY_PREFIX}${anonCounter++}`;
6270
5788
  }
6271
- async function resolvePersistFingerprintToken(state) {
6272
- try {
6273
- return hashStableString(await state.schema.fingerprint());
6274
- } catch (err) {
6275
- if (paths.__DEV__) {
6276
- console.warn(
6277
- `[attaform] Could not fingerprint the schema for form '${state.formKey}': ${err instanceof Error ? err.message : String(err)}. Persistence falls back to a fingerprint-free key, so a schema change won't auto-invalidate a saved draft.`
6278
- );
6279
- }
6280
- return "unfingerprinted";
6281
- }
6282
- }
6283
- const warnedAnonPersistKeys = /* @__PURE__ */ new Set();
6284
- function enforceAnonPersistRule(formKey, ssr) {
6285
- if (!formKey.startsWith(ANONYMOUS_FORM_KEY_PREFIX)) return false;
6286
- if (paths.__DEV__)
6287
- throw new paths.AnonPersistError({
6288
- cause: "no-key",
6289
- callSite: captureUserCallSite()
6290
- });
6291
- if (!ssr && !warnedAnonPersistKeys.has(formKey)) {
6292
- warnedAnonPersistKeys.add(formKey);
6293
- console.warn(
6294
- "[attaform] persist: ignored \u2014 anonymous useForm() can't safely persist (key drift + cross-form collision risk).\n Persistence is disabled for this form; the app keeps working.\n Fix: useForm({ schema, key: 'login', persist: '...' })"
6295
- );
6296
- }
6297
- return true;
6298
- }
6299
5789
 
6300
5790
  let injectedInstanceCounter = 0;
6301
5791
  function injectForm(input) {
@@ -7523,16 +7013,10 @@ function warnIfAmbientWizardProviderHadDuplicates() {
7523
7013
  }
7524
7014
 
7525
7015
  exports.AttaformErrorCode = AttaformErrorCode;
7526
- exports.DEFAULT_PERSISTENCE_DEBOUNCE_MS = DEFAULT_PERSISTENCE_DEBOUNCE_MS;
7527
7016
  exports.DEFAULT_TIMINGS = DEFAULT_TIMINGS;
7528
- exports.PERSISTENCE_MODULE_KEY = PERSISTENCE_MODULE_KEY;
7529
- exports.applyPatchesForward = applyPatchesForward;
7530
- exports.cleanupOrphanKeys = cleanupOrphanKeys;
7531
7017
  exports.defaultCoercionRules = defaultCoercionRules;
7532
7018
  exports.defaultDisplayState = defaultDisplayState;
7533
7019
  exports.defineCoercion = defineCoercion;
7534
- exports.deleteAtPath = deleteAtPath;
7535
- exports.diffAndApply = diffAndApply;
7536
7020
  exports.getAtPath = getAtPath;
7537
7021
  exports.humanize = humanize;
7538
7022
  exports.injectForm = injectForm;
@@ -7541,17 +7025,13 @@ exports.isPlainRecord = isPlainRecord;
7541
7025
  exports.isUnset = isUnset;
7542
7026
  exports.lazy = lazy;
7543
7027
  exports.makeDefaultDisplayState = makeDefaultDisplayState;
7544
- exports.mergeSparseHydration = mergeSparseHydration;
7545
7028
  exports.normalizeNumericOption = normalizeNumericOption;
7546
- exports.normalizePersistConfig = normalizePersistConfig;
7547
- exports.resolveStorageKeyBase = resolveStorageKeyBase;
7548
7029
  exports.safeAssign = safeAssign;
7549
7030
  exports.safeOwnRead = safeOwnRead;
7550
7031
  exports.setAtPath = setAtPath;
7551
7032
  exports.slimKindOf = slimKindOf;
7552
- exports.structuralSnapshot = structuralSnapshot;
7553
7033
  exports.unset = unset;
7554
7034
  exports.useAbstractForm = useAbstractForm;
7555
7035
  exports.useRegister = useRegister;
7556
7036
  exports.useWizard = useWizard;
7557
- //# sourceMappingURL=attaform.CjMcwV7W.cjs.map
7037
+ //# sourceMappingURL=attaform.DsQkXE3o.cjs.map