attaform 0.30.1 → 0.31.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 (49) hide show
  1. package/dist/abstract.d.mts +5 -5
  2. package/dist/abstract.mjs +3 -3
  3. package/dist/dev/abstract.mjs +3 -3
  4. package/dist/dev/chunks/devtools.mjs +2 -2
  5. package/dist/dev/directive.mjs +1 -1
  6. package/dist/dev/history.mjs +1 -1
  7. package/dist/dev/index.mjs +4 -4
  8. package/dist/dev/runtime/plugins/attaform.mjs +1 -1
  9. package/dist/dev/shared/{attaform-dev.Chm4D6SJ.mjs → attaform-dev.B1q-x9R9.mjs} +2 -2
  10. package/dist/dev/shared/{attaform-dev.BUIFcTYf.mjs → attaform-dev.Caibt7sb.mjs} +11 -10
  11. package/dist/dev/shared/{attaform-dev.CT7MDjPy.mjs → attaform-dev.CtyqGia7.mjs} +152 -227
  12. package/dist/dev/shared/{attaform-dev.BJK1kqHY.mjs → attaform-dev.DJ3nsWw6.mjs} +74 -110
  13. package/dist/dev/shared/{attaform-dev.DuEE4GU1.mjs → attaform-dev.DlaT4xGd.mjs} +3 -3
  14. package/dist/dev/shared/{attaform-dev.BMQ3GcgD.mjs → attaform-dev.k5X47GMD.mjs} +474 -336
  15. package/dist/dev/shared/{attaform-dev.DxHdkkPG.mjs → attaform-dev.y9x9Vp9F.mjs} +206 -127
  16. package/dist/dev/zod-v3.mjs +5 -5
  17. package/dist/dev/zod-v4.mjs +5 -5
  18. package/dist/dev/zod.mjs +4 -4
  19. package/dist/directive.d.mts +2 -2
  20. package/dist/directive.mjs +1 -1
  21. package/dist/history.d.mts +1 -1
  22. package/dist/history.mjs +1 -1
  23. package/dist/index.d.mts +6 -6
  24. package/dist/index.mjs +4 -4
  25. package/dist/runtime/components/AttaformDevtoolsPanel.vue +3 -3
  26. package/dist/runtime/plugins/attaform.mjs +1 -1
  27. package/dist/shared/{attaform.CO918TdU.mjs → attaform.BWUn8Kjy.mjs} +74 -110
  28. package/dist/shared/{attaform.WiGdIqgx.mjs → attaform.C4shmwyJ.mjs} +2 -2
  29. package/dist/shared/{attaform.2FslhB9R.d.mts → attaform.CRVe8s82.d.mts} +1 -1
  30. package/dist/shared/{attaform.L0kUn3vL.d.mts → attaform.D9RqPgGu.d.mts} +1 -1
  31. package/dist/shared/{attaform.BcQwgWaq.d.mts → attaform.DAo0QBmS.d.mts} +28 -8
  32. package/dist/shared/{attaform.ZYn2ahzJ.mjs → attaform.DBCbxlyk.mjs} +59 -1
  33. package/dist/shared/{attaform.DRsANMok.mjs → attaform.DL2nl_QR.mjs} +11 -10
  34. package/dist/shared/{attaform.BIWicztt.mjs → attaform.DNPJPOO7.mjs} +204 -125
  35. package/dist/shared/{attaform.Br8EBn5B.d.mts → attaform.DZnrDrNb.d.mts} +136 -32
  36. package/dist/shared/{attaform.D_f1WgYf.mjs → attaform.DxKQsqFZ.mjs} +456 -318
  37. package/dist/shared/{attaform.B2iebkPA.mjs → attaform.L011tHgJ.mjs} +3 -3
  38. package/dist/shared/{attaform.D_pt1gOj.mjs → attaform.LUPC-2Qg.mjs} +152 -227
  39. package/dist/transforms.mjs +1 -1
  40. package/dist/vite.mjs +1 -1
  41. package/dist/zod-v3.d.mts +4 -4
  42. package/dist/zod-v3.mjs +5 -5
  43. package/dist/zod-v4.d.mts +13 -11
  44. package/dist/zod-v4.mjs +5 -5
  45. package/dist/zod.d.mts +4 -4
  46. package/dist/zod.mjs +4 -4
  47. package/package.json +1 -1
  48. package/skills/attaform/SKILL.md +1 -1
  49. package/skills/attaform/references/custom-components.md +4 -0
@@ -1,6 +1,6 @@
1
- import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, reactive, shallowReactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope, nextTick } from 'vue';
2
- import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.WiGdIqgx.mjs';
3
- import { c as armDomBinding } from './attaform.D_f1WgYf.mjs';
1
+ import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, reactive, shallowReactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, effectScope, onBeforeMount, onBeforeUpdate, onMounted, nextTick } from 'vue';
2
+ import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.C4shmwyJ.mjs';
3
+ import { c as armDomBinding, r as recordInheritedModifiers, w as withInheritedModifiers } from './attaform.DxKQsqFZ.mjs';
4
4
  import { R as REGISTER_OWNER_MARKER, b as V_REGISTER_MARKER } from './attaform.KvlEedlF.mjs';
5
5
  import { A as ANONYMOUS_FORM_KEY_PREFIX, i as isShadowedKey, d as safeOwnHas, a as safeOwnRead, e as consumerHas, f as spreadConsumerRecord, g as copyConsumerArray, r as readConsumerIndex, b as safeAssign, h as consumerKeys, j as readConsumerProp, k as diffAndApply, p as pickDefined, s as structuralSnapshot, n as normalizeNumericOption, l as DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS, m as consumerSymbolKeys, o as applyChangedKeys, R as RESERVED_KEY_PREFIX, q as DEFAULT_MAX_RECURSION_DEPTH, c as callConsumerFn, t as ANONYMOUS_WIZARD_KEY_PREFIX } from './attaform.8mfKZCwH.mjs';
6
6
  import { i as isPathPrefix, e as canonicalizePath, k as keyForSegments, m as mapSegmentKeys, b as ROOT_PATH_KEY, s as segmentsForPathKey, S as SubmitErrorHandlerError, t as toError, j as groupErrorsByKey, n as normalizeErrorInput, h as SET_MEMBER_SEGMENT, R as ROOT_PATH, l as normalizeErrorInputs, a as InvalidUseFormConfigError, d as ReservedFormKeyError } from './attaform.CdZIEf7_.mjs';
@@ -532,7 +532,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
532
532
  const value = state.getValueAtPath(segments);
533
533
  const original = state.originals.get(key)?.value;
534
534
  const pristine = state.isPristineAtPathByKey(key, segments);
535
- const cell = state.errorCells.get(key);
535
+ const cell = state.errorCells().get(key);
536
536
  const schemaForKey = cell !== void 0 && cell.schema.length > 0 ? cell.schema : void 0;
537
537
  const blankForKey = state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments) ? [makeBlankRequiredError(segments)] : void 0;
538
538
  const userForKey = cell !== void 0 && cell.user.length > 0 ? cell.user : void 0;
@@ -821,7 +821,7 @@ function aggregateErrorsAt(state, prefix, prefixKey) {
821
821
  const candidates = state.errorWindowAt(prefix, prefixKey);
822
822
  if (candidates.length === 0) return [];
823
823
  const formValue = state.form.value;
824
- const cells = state.errorCells;
824
+ const cells = state.errorCells();
825
825
  const buckets = /* @__PURE__ */ new Map();
826
826
  for (const { key, segments } of candidates) {
827
827
  if (!isPathPrefix(prefix, segments)) continue;
@@ -1100,7 +1100,7 @@ function buildErrorsSurface(state, sweep) {
1100
1100
  });
1101
1101
  }
1102
1102
  function collectErrorsAt(state, key, segments, active, into) {
1103
- const cell = state.errorCells.get(key);
1103
+ const cell = state.errorCells().get(key);
1104
1104
  if (active) {
1105
1105
  if (cell !== void 0) into.push(...cell.schema);
1106
1106
  if (state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments)) {
@@ -1681,7 +1681,7 @@ function createArrayBookkeeping(deps) {
1681
1681
  ...record,
1682
1682
  path: segments
1683
1683
  }));
1684
- migrateMapSubtree(errorCells, arrayPath, remap, (cell, segments) => ({
1684
+ migrateMapSubtree(errorCells(), arrayPath, remap, (cell, segments) => ({
1685
1685
  schema: NO_ERRORS,
1686
1686
  user: cell.user.map((error) => ({ ...error, path: [...segments] }))
1687
1687
  }));
@@ -1731,7 +1731,7 @@ function createArrayBookkeeping(deps) {
1731
1731
  migrateElementState(arrayPath, remap);
1732
1732
  for (const freshIndex of remap.fresh) seedFreshElement(arrayPath, freshIndex);
1733
1733
  const changed = changedIndices(remap);
1734
- evictSchemaVerdictsAtIndices(errorCells, arrayPath, changed);
1734
+ evictSchemaVerdictsAtIndices(errorCells(), arrayPath, changed);
1735
1735
  abortValidationAtVacatedIndices(arrayPath, remap);
1736
1736
  variantMemory.dropAtIndices(arrayPath, changed);
1737
1737
  arrayIdentity.applyOp(arrayPath, remap);
@@ -2036,7 +2036,7 @@ function adapterThrowMessage(err) {
2036
2036
  return "Adapter validateAtPath threw a non-Error value";
2037
2037
  }
2038
2038
  function hasUserErrorEntries(state) {
2039
- for (const cell of state.errorCells.values()) {
2039
+ for (const cell of state.errorCells().values()) {
2040
2040
  if (cell.user.length > 0) return true;
2041
2041
  }
2042
2042
  return false;
@@ -2256,6 +2256,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2256
2256
  const isRequired = state.schema.isRequiredAtPath(segments);
2257
2257
  const ariaDisplayState = getDisplayStateAt !== void 0 ? computed(() => getDisplayStateAt(segments)) : void 0;
2258
2258
  const markBlank = () => state.setValueAtPath(segments, slimDefault, withInstanceMeta({ blank: true }));
2259
+ const commitFromHost = (value) => value === "" && !acceptsString || value === null && !slimTypes.has("null") || value === void 0 && !acceptsUndefined ? markBlank() : state.setValueAtPath(segments, value, withInstanceMeta(void 0));
2259
2260
  const internalRv = {
2260
2261
  innerRef,
2261
2262
  displayValue,
@@ -2272,7 +2273,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2272
2273
  },
2273
2274
  ensureDomBinding: (factory) => {
2274
2275
  var _a;
2275
- (_a = state.domBinding).value ?? (_a.value = factory(state));
2276
+ return (_a = state.domBinding).value ?? (_a.value = factory(state));
2276
2277
  },
2277
2278
  registerElement: (element) => {
2278
2279
  const dom = state.domBinding.value;
@@ -2287,12 +2288,13 @@ function buildRegister(state, formInstanceId, instanceConfig) {
2287
2288
  setValueWithInternalPath: (value, meta) => {
2288
2289
  return state.setValueAtPath(segments, value, withInstanceMeta(meta));
2289
2290
  },
2290
- setValueFromHost: (value) => {
2291
+ commitFromHost,
2292
+ setValueFromHost: (value, modifiers) => {
2291
2293
  state.markInteracted(segments);
2292
- const isBlankSignal = value === "" && !acceptsString || value === null && !slimTypes.has("null") || value === void 0 && !acceptsUndefined;
2293
- const accepted = isBlankSignal ? markBlank() : state.setValueAtPath(segments, value, withInstanceMeta(void 0));
2294
+ const accepted = state.domBinding.value?.hostChannel.write(internalRv, value, modifiers) ?? commitFromHost(value);
2294
2295
  return accepted;
2295
2296
  },
2297
+ setValueFromHostInput: (payload, modifiers) => state.domBinding.value?.hostChannel.writeInput(internalRv, payload, modifiers) ?? false,
2296
2298
  // Called by the `vRegisterHintTransform` compile-time transform's wrapping
2297
2299
  // IIFE on every server-side render of `<element v-register="…">`.
2298
2300
  // Without it, every SSR'd FieldState serialises `connected: false`
@@ -2366,25 +2368,24 @@ function isUnset(value) {
2366
2368
  return value === unset;
2367
2369
  }
2368
2370
 
2369
- function walkUnsetSentinels(values, schema) {
2371
+ function walkUnsetSentinels(values, schema, rootDefault) {
2370
2372
  const paths = [];
2371
2373
  if (values === void 0) {
2372
- const rootSlim = schema.getDefaultAtPath([]);
2373
- walkUnspecified(rootSlim, [], paths);
2374
+ walkUnspecified(rootDefault, [], paths);
2374
2375
  return { cleanedValues: void 0, paths };
2375
2376
  }
2376
- const cleaned = walkCore(values, [], schema, paths, true);
2377
+ const cleaned = walkCore(values, [], schema, paths, { rootDefault });
2377
2378
  return { cleanedValues: cleaned, paths };
2378
2379
  }
2379
2380
  function isRecursable(value) {
2380
2381
  return Array.isArray(value) || isPlainRecord(value);
2381
2382
  }
2382
- function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
2383
+ function walkCore(input, segments, schema, paths, synthesis) {
2383
2384
  if (isUnset(input)) {
2384
2385
  return expandUnsetAt(segments, schema, paths);
2385
2386
  }
2386
2387
  if (input === void 0) {
2387
- if (synthesizeSchemaKeys) {
2388
+ if (synthesis !== null) {
2388
2389
  const slim = schema.getDefaultAtPath(segments);
2389
2390
  return walkUnspecified(slim, segments, paths);
2390
2391
  }
@@ -2397,7 +2398,7 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
2397
2398
  let mutated = false;
2398
2399
  for (let i = 0; i < input.length; i++) {
2399
2400
  const original = readConsumerIndex(input, i);
2400
- const walked = walkCore(original, [...segments, i], schema, paths, synthesizeSchemaKeys);
2401
+ const walked = walkCore(original, [...segments, i], schema, paths, synthesis);
2401
2402
  out[i] = walked;
2402
2403
  if (walked !== original) mutated = true;
2403
2404
  }
@@ -2409,10 +2410,10 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
2409
2410
  let keys = inputKeys;
2410
2411
  let mutated = false;
2411
2412
  let inputKeysSet = null;
2412
- if (synthesizeSchemaKeys) {
2413
+ if (synthesis !== null) {
2413
2414
  inputKeysSet = new Set(inputKeys);
2414
2415
  const allKeys = new Set(inputKeys);
2415
- const slim = schema.getDefaultAtPath(segments);
2416
+ const slim = segments.length === 0 ? synthesis.rootDefault : schema.getDefaultAtPath(segments);
2416
2417
  if (isPlainRecord(slim)) {
2417
2418
  for (const k of Object.keys(slim)) allKeys.add(k);
2418
2419
  }
@@ -2422,12 +2423,12 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
2422
2423
  const out = {};
2423
2424
  for (const key of keys) {
2424
2425
  const orig = readConsumerProp(obj, key);
2425
- if (synthesizeSchemaKeys && orig === void 0 && inputKeysSet?.has(key) === true) {
2426
+ if (synthesis !== null && orig === void 0 && inputKeysSet?.has(key) === true) {
2426
2427
  safeAssign(out, key, void 0);
2427
2428
  mutated = true;
2428
2429
  continue;
2429
2430
  }
2430
- const walked = walkCore(orig, [...segments, key], schema, paths, synthesizeSchemaKeys);
2431
+ const walked = walkCore(orig, [...segments, key], schema, paths, synthesis);
2431
2432
  safeAssign(out, key, walked);
2432
2433
  if (walked !== orig) mutated = true;
2433
2434
  }
@@ -2451,7 +2452,7 @@ function walkUnspecified(slim, segments, paths) {
2451
2452
  }
2452
2453
  function substituteUnsetSentinels(value, prefix, schema) {
2453
2454
  const paths = [];
2454
- const cleaned = walkCore(value, [...prefix], schema, paths, false);
2455
+ const cleaned = walkCore(value, [...prefix], schema, paths, null);
2455
2456
  return { cleanedValues: cleaned, paths };
2456
2457
  }
2457
2458
  function isPrimitiveOrEmpty(value) {
@@ -2616,7 +2617,18 @@ function buildFormApi(state, formInstanceId, options = {}) {
2616
2617
  void state.submitted.value;
2617
2618
  return metaBase;
2618
2619
  };
2619
- const pathSweep = state.pathSweep;
2620
+ const releases = [];
2621
+ const lease = (release) => {
2622
+ releases.push(release);
2623
+ return release;
2624
+ };
2625
+ onScopeDispose(() => {
2626
+ for (const release of releases) release();
2627
+ }, true);
2628
+ const pathSweep = {
2629
+ track: state.pathSweep.track,
2630
+ onEvict: (evict) => lease(state.pathSweep.onEvict(evict))
2631
+ };
2620
2632
  const getRootFieldStateAt = buildFieldStateAccessor(
2621
2633
  state,
2622
2634
  formInstanceId,
@@ -2674,7 +2686,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
2674
2686
  const next = typeof pathOrValue === "function" ? pathOrValue(structuralSnapshot(state.form.value)) : pathOrValue;
2675
2687
  const walked2 = walkUnsetSentinels(
2676
2688
  next,
2677
- state.schema
2689
+ state.schema,
2690
+ state.schema.getDefaultAtPath([])
2678
2691
  );
2679
2692
  const ok2 = state.setValueAtPath([], walked2.cleanedValues, writeMeta());
2680
2693
  if (!ok2) return false;
@@ -2739,7 +2752,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2739
2752
  const errorsProxy = buildErrorsSurface(state, pathSweep);
2740
2753
  function flattenUserErrors() {
2741
2754
  const all = [];
2742
- for (const cell of state.errorCells.values()) all.push(...cell.user);
2755
+ for (const cell of state.errorCells().values()) all.push(...cell.user);
2743
2756
  return all;
2744
2757
  }
2745
2758
  function setErrors(arg1, arg2) {
@@ -2747,7 +2760,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2747
2760
  if (isScoped) {
2748
2761
  const { segments, key } = canonicalizePath(arg1);
2749
2762
  const input2 = arg2;
2750
- const resolved2 = typeof input2 === "function" ? input2([...state.errorCells.get(key)?.user ?? []]) : input2;
2763
+ const resolved2 = typeof input2 === "function" ? input2([...state.errorCells().get(key)?.user ?? []]) : input2;
2751
2764
  state.setUserErrorsForPath(
2752
2765
  segments,
2753
2766
  normalizeErrorInputs(resolved2, segments, AttaformErrorCode.UserError)
@@ -2775,7 +2788,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
2775
2788
  const departAttempts = computed(() => state.departAttempts.value);
2776
2789
  const validating = computed(() => state.activeValidations.value > 0);
2777
2790
  const valid = computed(
2778
- () => state.firstValidationDone.value && state.errorCells.size === 0 && state.derivedBlankErrors.value.size === 0 && !validating.value
2791
+ () => state.firstValidationDone.value && state.errorCells().size === 0 && state.derivedBlankErrors.value.size === 0 && !validating.value
2779
2792
  );
2780
2793
  const history = options.history;
2781
2794
  const formHistory = history === void 0 ? inertHistory() : readonly(
@@ -2891,7 +2904,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
2891
2904
  };
2892
2905
  return Object.freeze(view);
2893
2906
  });
2894
- const valuesProxy = buildValuesSurface(state.form, state.onFormChange);
2907
+ const valuesProxy = buildValuesSurface(
2908
+ state.form,
2909
+ (listener) => lease(state.onFormChange(listener))
2910
+ );
2895
2911
  const fieldStateProxy = buildFieldsSurface(state, getRootFieldStateAt, pathSweep);
2896
2912
  const needsLazyGate = state.defaultValuesFactory.value !== void 0 || state.hasSsrPrefetch;
2897
2913
  function gated(fn) {
@@ -3012,7 +3028,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
3012
3028
  const SWEEP_SLICE = 8;
3013
3029
  function createDynamicPathSweep(deps) {
3014
3030
  const dynamicKeys = /* @__PURE__ */ new Set();
3015
- const evictors = [];
3031
+ const evictors = /* @__PURE__ */ new Set();
3016
3032
  const isDynamicPath = (segments) => {
3017
3033
  for (let i = 0; i < segments.length; i++) {
3018
3034
  if (typeof segments[i] === "number") return true;
@@ -3043,7 +3059,10 @@ function createDynamicPathSweep(deps) {
3043
3059
  if (isDynamicPath(segments)) dynamicKeys.add(key);
3044
3060
  },
3045
3061
  onEvict(evict) {
3046
- evictors.push(evict);
3062
+ evictors.add(evict);
3063
+ return () => {
3064
+ evictors.delete(evict);
3065
+ };
3047
3066
  }
3048
3067
  };
3049
3068
  }
@@ -3242,7 +3261,7 @@ function mergeObjectKeys(target, source, path, schema) {
3242
3261
  async function runFactoryAndApply(st, factory) {
3243
3262
  try {
3244
3263
  const value = await factory();
3245
- walkAuthoredFromConstraints(value, [], st.authoredPaths);
3264
+ if (st.hasPreprocessOrCoerce) walkAuthoredFromConstraints(value, [], st.authoredPaths);
3246
3265
  const full = mergeSparseHydration(
3247
3266
  toRaw(st.form.value),
3248
3267
  value,
@@ -3266,7 +3285,7 @@ async function runFactoryAndApply(st, factory) {
3266
3285
  }
3267
3286
  }
3268
3287
  function clearHydrationFailedEntry(st) {
3269
- const existing = st.errorCells.get(ROOT_PATH_KEY)?.schema;
3288
+ const existing = st.errorCells().get(ROOT_PATH_KEY)?.schema;
3270
3289
  if (existing === void 0 || existing.length === 0) return;
3271
3290
  const filtered = existing.filter((e) => e.code !== AttaformErrorCode.HydrationFailed);
3272
3291
  if (filtered.length !== existing.length) {
@@ -3280,7 +3299,7 @@ function appendHydrationFailedEntry(st, error) {
3280
3299
  path: [...ROOT_PATH],
3281
3300
  code: AttaformErrorCode.HydrationFailed
3282
3301
  };
3283
- const existing = st.errorCells.get(ROOT_PATH_KEY)?.schema ?? [];
3302
+ const existing = st.errorCells().get(ROOT_PATH_KEY)?.schema ?? [];
3284
3303
  st.setSchemaErrorsForPath([...ROOT_PATH], [...existing, entry]);
3285
3304
  return entry;
3286
3305
  }
@@ -3398,23 +3417,24 @@ function walkAuthoredFromSchemaDiff(withDefaults, withoutDefaults, prefix, out)
3398
3417
  out.add(canonicalizePath(prefix).key);
3399
3418
  }
3400
3419
  }
3401
- function computeBaselineResponse(schema, source) {
3402
- const completed = source === void 0 ? void 0 : mergeStructural(schema, [], source);
3420
+ function computeBaseline(schema, source, schemaDefaults) {
3421
+ if (source === void 0) return schemaDefaults;
3403
3422
  return schema.getDefaultValues({
3404
3423
  useDefaultSchemaValues: true,
3405
- constraints: completed
3424
+ constraints: mergeStructural(schema, [], source, schemaDefaults)
3406
3425
  });
3407
3426
  }
3408
3427
  function initialFirstValidationGate(schema) {
3409
3428
  return schema.needsAsyncValidation?.() !== true;
3410
3429
  }
3411
- function seedOriginalsFromBaseline(st, baseline, ensureOrdinals) {
3430
+ function seedOriginalsFromBaseline(st, baseline) {
3412
3431
  st.originals.clear();
3413
3432
  diffAndApply({}, baseline, [], (patch) => {
3414
3433
  if (patch.kind !== "added") return;
3415
- const { key } = canonicalizePath(patch.path);
3416
- st.originals.set(key, { segments: patch.path, value: patch.newValue });
3417
- if (ensureOrdinals) ensurePathOrdinal(st, key);
3434
+ st.originals.set(canonicalizePath(patch.path).key, {
3435
+ segments: patch.path,
3436
+ value: patch.newValue
3437
+ });
3418
3438
  });
3419
3439
  }
3420
3440
  function queueInitialAsyncValidation(st) {
@@ -3428,6 +3448,7 @@ function queueInitialAsyncValidation(st) {
3428
3448
  }
3429
3449
  }
3430
3450
  function rebuildAuthoredPaths(st, constraints, schemaWithDefaultsData) {
3451
+ if (!st.hasPreprocessOrCoerce) return;
3431
3452
  st.authoredPaths.clear();
3432
3453
  if (constraints !== void 0) {
3433
3454
  walkAuthoredFromConstraints(constraints, [], st.authoredPaths);
@@ -3461,6 +3482,7 @@ function ensurePathOrdinal(st, key) {
3461
3482
  return ordinal;
3462
3483
  }
3463
3484
  function pathHasAsyncValidationByKey(st, key, segments) {
3485
+ if (st.schema.needsAsyncValidation?.() === false) return false;
3464
3486
  const cached = st.pathAsyncCache.get(key);
3465
3487
  if (cached !== void 0) return cached;
3466
3488
  const candidates = st.schema.getSchemasAtPath(segments);
@@ -3789,16 +3811,19 @@ function setValueAtPath(st, path, value, meta) {
3789
3811
  }
3790
3812
  }
3791
3813
  }
3792
- const wasAuthoredBefore = st.authoredPaths.has(pathKey);
3793
- if (arrayOpRemap !== null && Array.isArray(value)) {
3794
- if (path.length > 0) st.authoredPaths.add(pathKey);
3795
- for (const idx of arrayOpRemap.fresh) {
3796
- walkAuthoredFromConstraints(value[idx], [...path, idx], st.authoredPaths);
3814
+ let newlyAuthored = false;
3815
+ if (st.hasPreprocessOrCoerce) {
3816
+ const wasAuthoredBefore = st.authoredPaths.has(pathKey);
3817
+ if (arrayOpRemap !== null && Array.isArray(value)) {
3818
+ if (path.length > 0) st.authoredPaths.add(pathKey);
3819
+ for (const idx of arrayOpRemap.fresh) {
3820
+ walkAuthoredFromConstraints(value[idx], [...path, idx], st.authoredPaths);
3821
+ }
3822
+ } else {
3823
+ walkAuthoredFromConstraints(value, path, st.authoredPaths);
3797
3824
  }
3798
- } else {
3799
- walkAuthoredFromConstraints(value, path, st.authoredPaths);
3825
+ newlyAuthored = !wasAuthoredBefore && st.authoredPaths.has(pathKey);
3800
3826
  }
3801
- const newlyAuthored = !wasAuthoredBefore && st.authoredPaths.has(pathKey);
3802
3827
  let completedValue;
3803
3828
  if (arrayOpRemap !== null && Array.isArray(value)) {
3804
3829
  for (const idx of arrayOpRemap.fresh) {
@@ -4055,22 +4080,38 @@ function getValueAtPath(st, path) {
4055
4080
  return getAtPath(st.form.value, path);
4056
4081
  }
4057
4082
  const ERROR_SOURCES = ["schema", "user"];
4083
+ function createErrorCells(schema, pristine) {
4084
+ const raw = /* @__PURE__ */ new Map();
4085
+ const cells = shallowReactive(raw);
4086
+ return (seed) => {
4087
+ const data = pristine;
4088
+ if (data !== void 0) {
4089
+ pristine = void 0;
4090
+ if (seed) {
4091
+ for (const [key, list] of groupErrorsByKey(schema.validateSync(data))) {
4092
+ raw.set(key, { schema: list, user: NO_ERRORS });
4093
+ }
4094
+ }
4095
+ }
4096
+ return cells;
4097
+ };
4098
+ }
4058
4099
  function setErrorChannelForKey(st, key, src, entries) {
4059
- const current = st.errorCells.get(key);
4100
+ const current = st.errorCells().get(key);
4060
4101
  const schema = src === "schema" ? entries : current?.schema ?? NO_ERRORS;
4061
4102
  const user = src === "user" ? entries : current?.user ?? NO_ERRORS;
4062
4103
  if (schema.length === 0 && user.length === 0) {
4063
- if (current !== void 0) st.errorCells.delete(key);
4104
+ if (current !== void 0) st.errorCells().delete(key);
4064
4105
  return;
4065
4106
  }
4066
- st.errorCells.set(key, { schema, user });
4107
+ st.errorCells().set(key, { schema, user });
4067
4108
  }
4068
4109
  function replaceErrorChannel(st, src, entries) {
4069
4110
  const other = src === "schema" ? "user" : "schema";
4070
4111
  const grouped = groupErrorsByKey(entries);
4071
- for (const [key, cell] of st.errorCells) {
4112
+ for (const [key, cell] of st.errorCells()) {
4072
4113
  if (cell[other].length === 0) {
4073
- st.errorCells.delete(key);
4114
+ st.errorCells().delete(key);
4074
4115
  continue;
4075
4116
  }
4076
4117
  const fresh = grouped.get(key);
@@ -4095,8 +4136,9 @@ function clearErrorChannel(st, src, path) {
4095
4136
  function applySchemaErrorsForSubtree(st, path, entries) {
4096
4137
  const parentKey = canonicalizePath(path).key;
4097
4138
  const grouped = groupErrorsByKey(entries);
4139
+ if (path.length === 0) st.skipErrorSeed();
4098
4140
  if (!grouped.has(parentKey)) setErrorChannelForKey(st, parentKey, "schema", NO_ERRORS);
4099
- for (const [existingKey, cell] of st.errorCells) {
4141
+ for (const [existingKey, cell] of st.errorCells()) {
4100
4142
  if (existingKey === parentKey) continue;
4101
4143
  if (cell.schema.length === 0) continue;
4102
4144
  if (isPathKeyUnder(existingKey, path) && !grouped.has(existingKey)) {
@@ -4108,15 +4150,15 @@ function applySchemaErrorsForSubtree(st, path, entries) {
4108
4150
  }
4109
4151
  }
4110
4152
  function restoreErrorCells(st, entries) {
4111
- st.errorCells.clear();
4153
+ st.skipErrorSeed().clear();
4112
4154
  for (const [key, cell] of entries) {
4113
4155
  if (cell.schema.length === 0 && cell.user.length === 0) continue;
4114
- st.errorCells.set(key, { schema: [...cell.schema], user: [...cell.user] });
4156
+ st.errorCells().set(key, { schema: [...cell.schema], user: [...cell.user] });
4115
4157
  }
4116
4158
  }
4117
4159
  function getErrorsForPath(st, path) {
4118
4160
  const { key } = canonicalizePath(path);
4119
- const cell = st.errorCells.get(key);
4161
+ const cell = st.errorCells().get(key);
4120
4162
  const blankForKey = st.derivedBlankErrors.value.get(key);
4121
4163
  if (cell === void 0 && blankForKey === void 0) {
4122
4164
  return [];
@@ -4266,7 +4308,14 @@ function adoptResolvedDefaults(st, value) {
4266
4308
  st.schema
4267
4309
  )
4268
4310
  );
4269
- seedOriginalsFromBaseline(st, computeBaselineResponse(st.schema, st.defaultValues).data, false);
4311
+ seedOriginalsFromBaseline(
4312
+ st,
4313
+ computeBaseline(
4314
+ st.schema,
4315
+ st.defaultValues,
4316
+ st.schema.getDefaultValues({ useDefaultSchemaValues: true })
4317
+ )
4318
+ );
4270
4319
  }
4271
4320
  function reset(st, nextDefaultValues) {
4272
4321
  const resetSource = nextDefaultValues === void 0 ? st.defaultValues : mergeSparseHydration(
@@ -4275,13 +4324,16 @@ function reset(st, nextDefaultValues) {
4275
4324
  st.schema
4276
4325
  );
4277
4326
  st.defaultValues = structuralSnapshot(resetSource);
4278
- const resetResponse = computeBaselineResponse(st.schema, resetSource);
4279
- const next = resetResponse.data;
4327
+ const next = computeBaseline(
4328
+ st.schema,
4329
+ resetSource,
4330
+ st.schema.getDefaultValues({ useDefaultSchemaValues: true })
4331
+ );
4280
4332
  rebuildAuthoredPaths(st, resetSource, next);
4281
4333
  applyFormReplacement(st, next);
4282
4334
  st.arrayIdentity.rebaselineAll();
4283
4335
  st.removedSubtrees.clear();
4284
- seedOriginalsFromBaseline(st, next, false);
4336
+ seedOriginalsFromBaseline(st, next);
4285
4337
  if (nextDefaultValues !== void 0) {
4286
4338
  const mentioned = /* @__PURE__ */ new Set();
4287
4339
  walkAuthoredFromConstraints(nextDefaultValues, [], mentioned);
@@ -4291,14 +4343,8 @@ function reset(st, nextDefaultValues) {
4291
4343
  for (const key of st.originalBlankPaths) {
4292
4344
  st.blankPaths.add(key);
4293
4345
  }
4294
- st.errorCells.clear();
4295
- if (!resetResponse.success) {
4296
- replaceErrorChannel(st, "schema", resetResponse.errors);
4297
- }
4298
- const syncResult = st.schema.validateAtPath(st.form.value, void 0, { sync: true });
4299
- if (!(syncResult instanceof Promise) && !syncResult.success) {
4300
- applySchemaErrorsForSubtree(st, [], syncResult.errors);
4301
- }
4346
+ st.skipErrorSeed().clear();
4347
+ replaceErrorChannel(st, "schema", st.schema.validateSync(next));
4302
4348
  st.firstValidationDone.value = initialFirstValidationGate(st.schema);
4303
4349
  queueInitialAsyncValidation(st);
4304
4350
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -4375,7 +4421,7 @@ function resetField(st, path) {
4375
4421
  }
4376
4422
  }
4377
4423
  function deleteErrorCellsUnderPrefix(st, prefix) {
4378
- for (const [errorKey, cell] of st.errorCells) {
4424
+ for (const [errorKey, cell] of st.errorCells()) {
4379
4425
  for (const src of ERROR_SOURCES) {
4380
4426
  const first = cell[src][0];
4381
4427
  if (first !== void 0 && isPathPrefix(prefix, first.path)) {
@@ -4440,8 +4486,8 @@ function createFormStore(options) {
4440
4486
  const fieldValidatingSince = reactive(/* @__PURE__ */ new Map());
4441
4487
  const displayEngine = createDisplayEngine(ssr);
4442
4488
  cleanupHooks.push(() => displayEngine.dispose());
4443
- const schemaResponse = computeBaselineResponse(schema, defaultValues);
4444
- const schemaInitialData = schemaResponse.data;
4489
+ const ownDefaultValues = structuralSnapshot(defaultValues);
4490
+ const schemaInitialData = computeBaseline(schema, ownDefaultValues, options.schemaDefaults);
4445
4491
  const authoredPaths = /* @__PURE__ */ new Set();
4446
4492
  const initialData = hydration !== void 0 ? hydration.form : structuralSnapshot(schemaInitialData);
4447
4493
  const hasDU = schema.hasDiscriminatedUnions?.() !== false;
@@ -4455,7 +4501,11 @@ function createFormStore(options) {
4455
4501
  });
4456
4502
  const fields = shallowReactive(/* @__PURE__ */ new Map());
4457
4503
  const domBinding = shallowRef(null);
4458
- const errorCells = shallowReactive(/* @__PURE__ */ new Map());
4504
+ const errorStore = createErrorCells(
4505
+ schema,
4506
+ hydration === void 0 ? schemaInitialData : void 0
4507
+ );
4508
+ const errorCells = () => errorStore(true);
4459
4509
  const originals = shallowReactive(/* @__PURE__ */ new Map());
4460
4510
  const removedSubtrees = /* @__PURE__ */ new Set();
4461
4511
  const blankPaths = reactive(/* @__PURE__ */ new Set());
@@ -4479,7 +4529,7 @@ function createFormStore(options) {
4479
4529
  return result;
4480
4530
  });
4481
4531
  const errorPathIndex = computed(
4482
- () => buildErrorPathIndex(errorCells, derivedBlankErrors.value)
4532
+ () => buildErrorPathIndex(errorCells(), derivedBlankErrors.value)
4483
4533
  );
4484
4534
  const submitting = ref(false);
4485
4535
  const activeSubmissions = ref(0);
@@ -4611,18 +4661,16 @@ function createFormStore(options) {
4611
4661
  blankPaths,
4612
4662
  originalBlankPaths,
4613
4663
  // --- kernel-internal state ---
4614
- // A defensive copy. `getDefaultValues` building a fresh tree is an adapter
4615
- // implementation detail, not a contract, and this field is durable state
4616
- // that every `reset()` reads, so it must not depend on one. The copy also
4617
- // stops a consumer holding a reference to the literal they passed from
4618
- // mutating the form's defaults from outside. `reset()` snapshots for a
4619
- // harder reason, where an alias IS reachable.
4620
- defaultValues: structuralSnapshot(defaultValues),
4664
+ // The copy taken above, which also stops a consumer holding a reference to
4665
+ // the literal they passed from mutating the form's defaults from outside.
4666
+ // `reset()` snapshots for a harder reason, where an alias IS reachable.
4667
+ defaultValues: ownDefaultValues,
4621
4668
  ssrPrefetch,
4622
4669
  rememberVariants,
4623
4670
  fieldValidationMode,
4624
4671
  fieldValidationDebounceMs,
4625
4672
  hasDU,
4673
+ hasPreprocessOrCoerce: schema.hasPreprocessOrCoerce?.() !== false,
4626
4674
  fieldValidationState,
4627
4675
  formChangeListeners,
4628
4676
  submitSuccessListeners,
@@ -4638,6 +4686,7 @@ function createFormStore(options) {
4638
4686
  transformRuns,
4639
4687
  transformWaiters,
4640
4688
  arrayBookkeeping,
4689
+ skipErrorSeed: () => errorStore(false),
4641
4690
  nextOrdinal: 0,
4642
4691
  scheduleEpoch: 0,
4643
4692
  lastCommittedEpoch: 0,
@@ -4705,7 +4754,25 @@ function createFormStore(options) {
4705
4754
  dispose: bind(dispose)
4706
4755
  };
4707
4756
  rebuildAuthoredPaths(st, defaultValues, schemaInitialData);
4708
- seedOriginalsFromBaseline(st, schemaInitialData, true);
4757
+ const initStamp = (/* @__PURE__ */ new Date()).toISOString();
4758
+ diffAndApply({}, schemaInitialData, [], (patch) => {
4759
+ if (patch.kind !== "added") return;
4760
+ const { key } = canonicalizePath(patch.path);
4761
+ originals.set(key, { segments: patch.path, value: patch.newValue });
4762
+ ensurePathOrdinal(st, key);
4763
+ if (hydration === void 0) {
4764
+ fields.set(key, {
4765
+ path: patch.path,
4766
+ updatedAt: initStamp,
4767
+ connected: false,
4768
+ focused: null,
4769
+ blurred: null,
4770
+ touched: false,
4771
+ interacted: false,
4772
+ blurredAfterInteraction: false
4773
+ });
4774
+ }
4775
+ });
4709
4776
  if (hydration !== void 0) {
4710
4777
  for (const [rawKey, record] of hydration.fields) {
4711
4778
  if (typeof rawKey !== "string" || !isHydratedFieldRecord(record)) {
@@ -4725,25 +4792,6 @@ function createFormStore(options) {
4725
4792
  }
4726
4793
  setErrorChannelForKey(st, rawKey, "user", errs);
4727
4794
  }
4728
- } else {
4729
- const initStamp = (/* @__PURE__ */ new Date()).toISOString();
4730
- diffAndApply({}, initialData, [], (patch) => {
4731
- if (patch.kind !== "added") return;
4732
- const { key } = canonicalizePath(patch.path);
4733
- fields.set(key, {
4734
- path: patch.path,
4735
- updatedAt: initStamp,
4736
- connected: false,
4737
- focused: null,
4738
- blurred: null,
4739
- touched: false,
4740
- interacted: false,
4741
- blurredAfterInteraction: false
4742
- });
4743
- });
4744
- if (!schemaResponse.success) {
4745
- replaceErrorChannel(st, "schema", schemaResponse.errors);
4746
- }
4747
4795
  }
4748
4796
  queueInitialAsyncValidation(st);
4749
4797
  return st;
@@ -4836,9 +4884,11 @@ const HISTORY_MODULE_KEY = "history";
4836
4884
  function buildFreshState(key, schema, configuration, registry) {
4837
4885
  const pending = registry.pendingHydration.get(key);
4838
4886
  if (pending !== void 0) registry.pendingHydration.delete(key);
4887
+ const schemaDefaults = schema.getDefaultValues({ useDefaultSchemaValues: true });
4839
4888
  const walked = walkUnsetSentinels(
4840
4889
  configuration.defaultValues,
4841
- schema
4890
+ schema,
4891
+ schemaDefaults
4842
4892
  );
4843
4893
  let initialBlankPaths;
4844
4894
  if (pending === void 0) {
@@ -4848,6 +4898,7 @@ function buildFreshState(key, schema, configuration, registry) {
4848
4898
  formKey: key,
4849
4899
  schema,
4850
4900
  defaultValues: walked.cleanedValues,
4901
+ schemaDefaults,
4851
4902
  hydration: pending,
4852
4903
  ssr: registry.ssr,
4853
4904
  ...pickDefined({
@@ -4898,6 +4949,7 @@ function resolveFormKey(key) {
4898
4949
  }
4899
4950
 
4900
4951
  let injectedInstanceCounter = 0;
4952
+ const sharedApis = /* @__PURE__ */ new WeakMap();
4901
4953
  function injectForm(input) {
4902
4954
  const key = typeof input === "string" ? input : input?.key;
4903
4955
  const ssrAccessed = typeof input === "object" && input !== null ? input.__ssrAccessed === true : false;
@@ -4920,12 +4972,37 @@ function injectForm(input) {
4920
4972
  apiOptions.history = history;
4921
4973
  }
4922
4974
  const ambientInstanceId = getCurrentInstance() !== null ? inject(kFormInstanceId, null) : null;
4923
- const formInstanceId = ambientInstanceId ?? (getCurrentInstance() !== null ? useId() : `atta:form-instance-injected:${injectedInstanceCounter++}`);
4924
- return buildFormApi(
4975
+ const api = ambientInstanceId !== null ? shareApi(state, ambientInstanceId, apiOptions) : buildFormApi(
4925
4976
  state,
4926
- formInstanceId,
4977
+ getCurrentInstance() !== null ? useId() : `atta:form-instance-injected:${injectedInstanceCounter++}`,
4927
4978
  apiOptions
4928
4979
  );
4980
+ return api;
4981
+ }
4982
+ function shareApi(state, formInstanceId, options) {
4983
+ let instances = sharedApis.get(state);
4984
+ if (instances === void 0) {
4985
+ instances = /* @__PURE__ */ new Map();
4986
+ sharedApis.set(state, instances);
4987
+ }
4988
+ const byInstance = instances;
4989
+ let shared = byInstance.get(formInstanceId);
4990
+ if (shared === void 0) {
4991
+ const scope = effectScope(true);
4992
+ const api = scope.run(() => buildFormApi(state, formInstanceId, options));
4993
+ if (api === void 0) return buildFormApi(state, formInstanceId, options);
4994
+ shared = { api, scope, users: 0 };
4995
+ byInstance.set(formInstanceId, shared);
4996
+ }
4997
+ const entry = shared;
4998
+ entry.users += 1;
4999
+ onScopeDispose(() => {
5000
+ entry.users -= 1;
5001
+ if (entry.users > 0) return;
5002
+ entry.scope.stop();
5003
+ byInstance.delete(formInstanceId);
5004
+ });
5005
+ return entry.api;
4929
5006
  }
4930
5007
  function resolveState(key, registry) {
4931
5008
  if (key !== void 0) {
@@ -4985,22 +5062,23 @@ function useRegister(options) {
4985
5062
  const capturedRegisterValue = shallowRef(void 0);
4986
5063
  const refreshAndStripBridgeAttrs = () => {
4987
5064
  const rawAttrs = instance.attrs;
5065
+ const parentBinding = instance.vnode.dirs?.find(
5066
+ (dir) => dir.dir?.[V_REGISTER_MARKER] === true
5067
+ );
4988
5068
  if ("registerValue" in rawAttrs) {
4989
5069
  capturedRegisterValue.value = rawAttrs["registerValue"];
4990
5070
  delete rawAttrs["registerValue"];
4991
- if (capturedRegisterValue.value !== void 0) armDomBinding(capturedRegisterValue.value);
4992
- } else {
4993
- const dirs = instance.vnode.dirs;
4994
- if (dirs !== null && dirs !== void 0) {
4995
- for (const dir of dirs) {
4996
- const marked = dir.dir?.[V_REGISTER_MARKER];
4997
- if (marked === true) {
4998
- capturedRegisterValue.value = dir.value;
4999
- if (capturedRegisterValue.value !== void 0)
5000
- armDomBinding(capturedRegisterValue.value);
5001
- break;
5002
- }
5003
- }
5071
+ } else if (parentBinding !== void 0) {
5072
+ capturedRegisterValue.value = parentBinding.value;
5073
+ }
5074
+ const captured = capturedRegisterValue.value;
5075
+ if (captured !== void 0) {
5076
+ armDomBinding(captured);
5077
+ if (parentBinding !== void 0) {
5078
+ recordInheritedModifiers(
5079
+ captured,
5080
+ withInheritedModifiers(parentBinding.value, parentBinding.modifiers)
5081
+ );
5004
5082
  }
5005
5083
  }
5006
5084
  if ("value" in rawAttrs) delete rawAttrs["value"];
@@ -5107,11 +5185,11 @@ const NOOP_SUCCESS = {
5107
5185
  data: EMPTY_VALUE,
5108
5186
  errors: void 0
5109
5187
  };
5110
- const NOOP_DEFAULTS = NOOP_SUCCESS;
5111
5188
  let NOOP_SCHEMA;
5112
5189
  function buildNoopWizardSchema() {
5113
5190
  NOOP_SCHEMA ?? (NOOP_SCHEMA = {
5114
- getDefaultValues: () => NOOP_DEFAULTS,
5191
+ getDefaultValues: () => EMPTY_VALUE,
5192
+ validateSync: () => [],
5115
5193
  getDefaultAtPath: () => void 0,
5116
5194
  getEmptyValueAtPath: () => void 0,
5117
5195
  isPreprocessOrCoerceLeaf: () => false,
@@ -5127,7 +5205,8 @@ function buildNoopWizardSchema() {
5127
5205
  isLeafAtPath: () => false,
5128
5206
  isRequiredAtPath: () => false,
5129
5207
  getUnionDiscriminatorAtPath: () => void 0,
5130
- hasDiscriminatedUnions: () => false
5208
+ hasDiscriminatedUnions: () => false,
5209
+ hasPreprocessOrCoerce: () => false
5131
5210
  });
5132
5211
  return NOOP_SCHEMA;
5133
5212
  }
@@ -6040,7 +6119,7 @@ function useWizard(options) {
6040
6119
  for (const key of keys) {
6041
6120
  const store = registry.forms.get(key);
6042
6121
  if (store === void 0) continue;
6043
- for (const cell of store.errorCells.values()) {
6122
+ for (const cell of store.errorCells().values()) {
6044
6123
  for (const err of cell.user) out.push(toWizardAggregateError(err, key));
6045
6124
  }
6046
6125
  }