attaform 0.27.6 → 0.28.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 (184) hide show
  1. package/dist/abstract.d.mts +5 -4
  2. package/dist/abstract.mjs +4 -3
  3. package/dist/chunks/fingerprint.mjs +0 -1
  4. package/dist/chunks/fingerprint2.mjs +1 -2
  5. package/dist/dev/abstract.mjs +4 -0
  6. package/dist/{chunks → dev/chunks}/dev-key-collision-warnings.mjs +0 -1
  7. package/dist/{chunks → dev/chunks}/devtools.mjs +5 -6
  8. package/dist/{chunks/fingerprint.cjs → dev/chunks/fingerprint.mjs} +7 -10
  9. package/dist/{chunks/fingerprint2.cjs → dev/chunks/fingerprint2.mjs} +32 -35
  10. package/dist/dev/directive.mjs +1 -0
  11. package/dist/dev/history.mjs +89 -0
  12. package/dist/dev/index.mjs +5 -0
  13. package/dist/dev/runtime/plugins/attaform.mjs +40 -0
  14. package/dist/{shared/attaform.D6tk90Rc.cjs → dev/shared/attaform-dev.6qxD-Yqo.mjs} +187 -43
  15. package/dist/{shared/attaform.CQN9R62B.cjs → dev/shared/attaform-dev.BJGA_UOS.mjs} +1 -4
  16. package/dist/{shared/attaform.DYEr28Pt.mjs → dev/shared/attaform-dev.BR8u0YOZ.mjs} +6 -7
  17. package/dist/dev/shared/attaform-dev.BXE2cr0L.mjs +220 -0
  18. package/dist/dev/shared/attaform-dev.By4PRjt0.mjs +248 -0
  19. package/dist/{shared/attaform.B1ZYt2Li.mjs → dev/shared/attaform-dev.D2I8e_Mm.mjs} +132 -568
  20. package/dist/dev/shared/attaform-dev.Dr2YzS5B.mjs +197 -0
  21. package/dist/{shared/attaform.nMaz2C5P.mjs → dev/shared/attaform-dev.P7cseiEG.mjs} +178 -397
  22. package/dist/{shared/attaform.CKH2lGdL.mjs → dev/shared/attaform-dev.WmuhD_CZ.mjs} +3944 -5056
  23. package/dist/{shared/attaform.DMxM2kol.mjs → dev/shared/attaform-dev.oYrkP9dj.mjs} +160 -508
  24. package/dist/dev/zod-v3.mjs +17 -0
  25. package/dist/dev/zod-v4.mjs +16 -0
  26. package/dist/dev/zod.mjs +5 -0
  27. package/dist/directive.d.mts +20 -0
  28. package/dist/directive.mjs +1 -0
  29. package/dist/esbuild.mjs +0 -1
  30. package/dist/history.d.mts +59 -0
  31. package/dist/history.mjs +89 -0
  32. package/dist/index.d.mts +11 -5
  33. package/dist/index.mjs +5 -4
  34. package/dist/nuxt.d.mts +1 -1
  35. package/dist/nuxt.mjs +5 -2
  36. package/dist/rollup.mjs +0 -1
  37. package/dist/rspack.d.mts +6 -1
  38. package/dist/rspack.mjs +0 -1
  39. package/dist/runtime/components/AttaformDevtoolsPanel.vue +9 -8
  40. package/dist/runtime/plugins/attaform.mjs +1 -2
  41. package/dist/shared/{attaform.Fp3sCrVs.d.ts → attaform.B4VkS43-.d.mts} +2 -2
  42. package/dist/shared/{attaform.DrvMscNX.cjs → attaform.B8k8JrmK.mjs} +4073 -5630
  43. package/dist/shared/attaform.BJGA_UOS.mjs +0 -1
  44. package/dist/shared/{attaform.CoR4mWfv.mjs → attaform.C09fpdLS.mjs} +172 -16
  45. package/dist/shared/{attaform.D8kliaKw.cjs → attaform.CJP3RkGa.mjs} +141 -590
  46. package/dist/shared/{attaform.DniawQLP.d.cts → attaform.Cgu-hdSb.d.mts} +268 -68
  47. package/dist/shared/attaform.Cs2Rbdlo.mjs +0 -1
  48. package/dist/shared/{attaform.CHlJLAiv.d.mts → attaform.D5V4tZWq.d.mts} +69 -179
  49. package/dist/shared/{attaform.B9Wyhfro.cjs → attaform.D6DCnnQu.mjs} +11 -16
  50. package/dist/shared/attaform.DhnPb6nK.mjs +0 -1
  51. package/dist/shared/attaform.Dq4vWxuG.mjs +197 -0
  52. package/dist/shared/attaform.JfSWdEcb.d.mts +44 -0
  53. package/dist/shared/attaform.KvlEedlF.mjs +0 -1
  54. package/dist/shared/{attaform.DdQN7sgN.cjs → attaform.NLmerepI.mjs} +175 -557
  55. package/dist/shared/attaform.h0i6LijT.mjs +242 -0
  56. package/dist/shared/{attaform.Biytrv0-.cjs → attaform.uLbun31C.mjs} +204 -544
  57. package/dist/shared/attaform.v0fQtWyA.mjs +0 -1
  58. package/dist/shared/attaform.wfY8XFvm.mjs +197 -0
  59. package/dist/transforms.mjs +0 -1
  60. package/dist/vite.d.mts +17 -5
  61. package/dist/vite.mjs +24 -2
  62. package/dist/webpack.d.mts +6 -1
  63. package/dist/webpack.mjs +0 -1
  64. package/dist/zod-v3.d.mts +11 -6
  65. package/dist/zod-v3.mjs +17 -4
  66. package/dist/zod-v4.d.mts +12 -6
  67. package/dist/zod-v4.mjs +16 -4
  68. package/dist/zod.d.mts +4 -3
  69. package/dist/zod.mjs +5 -4
  70. package/package.json +23 -8
  71. package/skills/attaform/SKILL.md +2 -1
  72. package/dist/abstract.cjs +0 -48
  73. package/dist/abstract.cjs.map +0 -1
  74. package/dist/abstract.d.cts +0 -42
  75. package/dist/abstract.d.ts +0 -42
  76. package/dist/abstract.mjs.map +0 -1
  77. package/dist/chunks/dev-key-collision-warnings.cjs +0 -25
  78. package/dist/chunks/dev-key-collision-warnings.cjs.map +0 -1
  79. package/dist/chunks/dev-key-collision-warnings.mjs.map +0 -1
  80. package/dist/chunks/devtools.cjs +0 -157
  81. package/dist/chunks/devtools.cjs.map +0 -1
  82. package/dist/chunks/devtools.mjs.map +0 -1
  83. package/dist/chunks/fingerprint.cjs.map +0 -1
  84. package/dist/chunks/fingerprint.mjs.map +0 -1
  85. package/dist/chunks/fingerprint2.cjs.map +0 -1
  86. package/dist/chunks/fingerprint2.mjs.map +0 -1
  87. package/dist/esbuild.cjs +0 -28
  88. package/dist/esbuild.cjs.map +0 -1
  89. package/dist/esbuild.d.cts +0 -56
  90. package/dist/esbuild.d.ts +0 -56
  91. package/dist/esbuild.mjs.map +0 -1
  92. package/dist/index.cjs +0 -51
  93. package/dist/index.cjs.map +0 -1
  94. package/dist/index.d.cts +0 -249
  95. package/dist/index.d.ts +0 -249
  96. package/dist/index.mjs.map +0 -1
  97. package/dist/nuxt.cjs +0 -84
  98. package/dist/nuxt.cjs.map +0 -1
  99. package/dist/nuxt.d.cts +0 -66
  100. package/dist/nuxt.d.ts +0 -66
  101. package/dist/nuxt.mjs.map +0 -1
  102. package/dist/rollup.cjs +0 -24
  103. package/dist/rollup.cjs.map +0 -1
  104. package/dist/rollup.d.cts +0 -35
  105. package/dist/rollup.d.ts +0 -35
  106. package/dist/rollup.mjs.map +0 -1
  107. package/dist/rspack.cjs +0 -10
  108. package/dist/rspack.cjs.map +0 -1
  109. package/dist/rspack.d.cts +0 -40
  110. package/dist/rspack.d.ts +0 -40
  111. package/dist/rspack.mjs.map +0 -1
  112. package/dist/runtime/components/AttaformDevtoolsPanel.vue.d.ts +0 -7
  113. package/dist/runtime/components/DevtoolsValueTree.vue.d.ts +0 -35
  114. package/dist/runtime/plugins/attaform.cjs +0 -43
  115. package/dist/runtime/plugins/attaform.cjs.map +0 -1
  116. package/dist/runtime/plugins/attaform.d.cts +0 -5
  117. package/dist/runtime/plugins/attaform.d.ts +0 -5
  118. package/dist/runtime/plugins/attaform.mjs.map +0 -1
  119. package/dist/shared/attaform.B1ZYt2Li.mjs.map +0 -1
  120. package/dist/shared/attaform.B9Wyhfro.cjs.map +0 -1
  121. package/dist/shared/attaform.BGDV42hI.d.cts +0 -232
  122. package/dist/shared/attaform.BJGA_UOS.mjs.map +0 -1
  123. package/dist/shared/attaform.Biytrv0-.cjs.map +0 -1
  124. package/dist/shared/attaform.Bn0IzhD_.cjs +0 -800
  125. package/dist/shared/attaform.Bn0IzhD_.cjs.map +0 -1
  126. package/dist/shared/attaform.C9fPTxjB.d.cts +0 -41
  127. package/dist/shared/attaform.C9fPTxjB.d.ts +0 -41
  128. package/dist/shared/attaform.CKH2lGdL.mjs.map +0 -1
  129. package/dist/shared/attaform.CQN9R62B.cjs.map +0 -1
  130. package/dist/shared/attaform.CoR4mWfv.mjs.map +0 -1
  131. package/dist/shared/attaform.Cs2Rbdlo.mjs.map +0 -1
  132. package/dist/shared/attaform.D6tk90Rc.cjs.map +0 -1
  133. package/dist/shared/attaform.D8kliaKw.cjs.map +0 -1
  134. package/dist/shared/attaform.DLknk9nF.d.mts +0 -232
  135. package/dist/shared/attaform.DMxM2kol.mjs.map +0 -1
  136. package/dist/shared/attaform.DRUT703x.d.cts +0 -56
  137. package/dist/shared/attaform.DRUT703x.d.ts +0 -56
  138. package/dist/shared/attaform.DYEr28Pt.mjs.map +0 -1
  139. package/dist/shared/attaform.DdQN7sgN.cjs.map +0 -1
  140. package/dist/shared/attaform.DhnPb6nK.mjs.map +0 -1
  141. package/dist/shared/attaform.DniawQLP.d.mts +0 -4763
  142. package/dist/shared/attaform.DniawQLP.d.ts +0 -4763
  143. package/dist/shared/attaform.DoQm_Vkd.cjs +0 -58
  144. package/dist/shared/attaform.DoQm_Vkd.cjs.map +0 -1
  145. package/dist/shared/attaform.DrvMscNX.cjs.map +0 -1
  146. package/dist/shared/attaform.F2Q8iv38.d.ts +0 -2494
  147. package/dist/shared/attaform.FmqKO1Ex.d.cts +0 -2494
  148. package/dist/shared/attaform.KvlEedlF.mjs.map +0 -1
  149. package/dist/shared/attaform.RaTzp1WF.cjs +0 -26
  150. package/dist/shared/attaform.RaTzp1WF.cjs.map +0 -1
  151. package/dist/shared/attaform.nMaz2C5P.mjs.map +0 -1
  152. package/dist/shared/attaform.v0fQtWyA.mjs.map +0 -1
  153. package/dist/shared/attaform.yUrz7C2z.cjs +0 -29
  154. package/dist/shared/attaform.yUrz7C2z.cjs.map +0 -1
  155. package/dist/transforms.cjs +0 -12
  156. package/dist/transforms.cjs.map +0 -1
  157. package/dist/transforms.d.cts +0 -73
  158. package/dist/transforms.d.ts +0 -73
  159. package/dist/transforms.mjs.map +0 -1
  160. package/dist/vite.cjs +0 -363
  161. package/dist/vite.cjs.map +0 -1
  162. package/dist/vite.d.cts +0 -133
  163. package/dist/vite.d.ts +0 -133
  164. package/dist/vite.mjs.map +0 -1
  165. package/dist/webpack.cjs +0 -10
  166. package/dist/webpack.cjs.map +0 -1
  167. package/dist/webpack.d.cts +0 -37
  168. package/dist/webpack.d.ts +0 -37
  169. package/dist/webpack.mjs.map +0 -1
  170. package/dist/zod-v3.cjs +0 -53
  171. package/dist/zod-v3.cjs.map +0 -1
  172. package/dist/zod-v3.d.cts +0 -246
  173. package/dist/zod-v3.d.ts +0 -246
  174. package/dist/zod-v3.mjs.map +0 -1
  175. package/dist/zod-v4.cjs +0 -55
  176. package/dist/zod-v4.cjs.map +0 -1
  177. package/dist/zod-v4.d.cts +0 -172
  178. package/dist/zod-v4.d.ts +0 -172
  179. package/dist/zod-v4.mjs.map +0 -1
  180. package/dist/zod.cjs +0 -51
  181. package/dist/zod.cjs.map +0 -1
  182. package/dist/zod.d.cts +0 -7
  183. package/dist/zod.d.ts +0 -7
  184. package/dist/zod.mjs.map +0 -1
@@ -1,332 +1,170 @@
1
- import { shallowReactive, getCurrentInstance, inject, effectScope, watch, warn, nextTick } from 'vue';
2
- import { i as isRegisterValue, a as isTransforming, S as SSR_COMPONENT_HOST_MODIFIER, R as REGISTER_OWNER_MARKER, V as V_REGISTER_COMPILED_MODIFIER, b as V_REGISTER_MARKER } from './attaform.KvlEedlF.mjs';
1
+ import { reactive, markRaw, isRef, effectScope, watch, warn, nextTick } from 'vue';
2
+ import { e as canonicalizePath } from './attaform-dev.Dr2YzS5B.mjs';
3
3
 
4
- class AttaformError extends Error {
5
- constructor(message, options) {
6
- super(message, options);
7
- this.name = new.target.name;
8
- }
9
- }
10
- class InvalidPathError extends AttaformError {
11
- }
12
- class InvalidUseFormConfigError extends AttaformError {
13
- constructor() {
14
- super(
15
- "[attaform] useForm received an invalid configuration (a schema directly, no argument, or no `schema` field). Pass it as `useForm({ schema })` \u2014 the schema is one of several configuration options. See https://attaform.dev/docs/reading-the-form/the-form for the full configuration shape."
16
- );
17
- }
18
- }
19
- class SubmitErrorHandlerError extends AttaformError {
20
- }
21
- function toError(value) {
22
- if (value instanceof Error) return value;
23
- const message = typeof value === "string" && value.length > 0 ? value : `Submit callback threw a non-Error value (${typeof value})`;
24
- return new Error(message, { cause: value });
25
- }
26
- function normalizeErrorInput(item, scope, formKey, defaultCode) {
27
- if (item instanceof Error) {
28
- return {
29
- message: item.message.length > 0 ? item.message : "Unknown error",
30
- path: scope !== void 0 ? [...scope] : [],
31
- formKey,
32
- code: defaultCode
33
- };
34
- }
35
- const entry = {
36
- message: typeof item.message === "string" && item.message.length > 0 ? item.message : "Unknown error",
37
- path: scope !== void 0 ? [...scope] : Array.isArray(item.path) ? [...item.path] : [],
38
- formKey,
39
- code: typeof item.code === "string" && item.code.length > 0 ? item.code : defaultCode
40
- };
41
- if (item.data !== void 0) entry.data = item.data;
42
- return entry;
43
- }
44
- function normalizeErrorInputs(input, scope, formKey, defaultCode) {
45
- const items = Array.isArray(input) ? input : [input];
46
- return items.map((item) => normalizeErrorInput(item, scope, formKey, defaultCode));
47
- }
48
- class RegistryNotInstalledError extends AttaformError {
49
- constructor() {
50
- super(
51
- "[attaform] No registry attached to this Vue app. Component-level useForm / injectForm / useRegister auto-install the registry, but SSR helpers (renderAttaformState, hydrateAttaformState) run outside setup and require an explicit `app.use(createAttaform())` at server-render time. Add it to your SSR entry, before `renderToString`."
52
- );
53
- }
54
- }
55
- class OutsideSetupError extends AttaformError {
56
- constructor() {
57
- super(
58
- "[attaform] useForm / injectForm called outside Vue setup(). Move into setup or mount a child component to trigger from an event."
59
- );
60
- }
61
- }
62
- class ReservedFormKeyError extends AttaformError {
63
- constructor(key) {
64
- super(
65
- `[attaform] Form key "${key}" uses the reserved "__atta:" namespace. Use a different prefix \u2014 "__atta:" is for library-internal synthetic keys (anonymous useForm() calls without an explicit key).`
66
- );
67
- }
68
- }
4
+ const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
69
5
 
70
- const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
71
- function normalizeSegment(raw) {
72
- if (typeof raw === "number") {
73
- if (!Number.isInteger(raw) || raw < 0) {
74
- throw new InvalidPathError(
75
- `Path segments must be non-negative integers when numeric; got ${String(raw)}`
76
- );
6
+ const attaformListenersSymbol = /* @__PURE__ */ Symbol.for("attaform:focus-listeners");
7
+ const HOST_FOCUS_TARGET_SELECTOR = [
8
+ 'input:not([type="hidden"])',
9
+ "select",
10
+ "textarea",
11
+ "button",
12
+ "a[href]",
13
+ '[tabindex]:not([tabindex="-1"])',
14
+ '[contenteditable="true"]'
15
+ ].join(", ");
16
+ function resolveHostFocusTarget(hostRoot) {
17
+ const candidates = hostRoot.querySelectorAll(HOST_FOCUS_TARGET_SELECTOR);
18
+ for (const el of candidates) {
19
+ if (!el.isConnected) continue;
20
+ if (el.offsetParent === null) continue;
21
+ if (el.matches(":disabled")) continue;
22
+ return el;
23
+ }
24
+ return hostRoot;
25
+ }
26
+ function attachFocusListeners(kernel, segments, element, instanceMeta) {
27
+ const target = element;
28
+ if (target[attaformListenersSymbol] !== void 0) return;
29
+ const focusMeta = instanceMeta !== void 0 ? { instance: instanceMeta } : void 0;
30
+ const handleFocus = () => kernel.markFocused(segments, true, focusMeta);
31
+ const handleBlur = () => kernel.markFocused(segments, false, focusMeta);
32
+ element.addEventListener("focus", handleFocus);
33
+ element.addEventListener("blur", handleBlur);
34
+ target[attaformListenersSymbol] = { handleFocus, handleBlur };
35
+ const rootNode = element.getRootNode();
36
+ const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
37
+ if (activeElement === element) {
38
+ kernel.markFocused(segments, true, focusMeta);
39
+ }
40
+ }
41
+ function detachFocusListeners(element) {
42
+ const target = element;
43
+ const listeners = target[attaformListenersSymbol];
44
+ if (listeners === void 0) return;
45
+ element.removeEventListener("focus", listeners.handleFocus);
46
+ element.removeEventListener("blur", listeners.handleBlur);
47
+ delete target[attaformListenersSymbol];
48
+ }
49
+ function createDomBinding(kernel) {
50
+ const elements = reactive(/* @__PURE__ */ new Map());
51
+ const elementToFormInstance = /* @__PURE__ */ new WeakMap();
52
+ const hostTargets = /* @__PURE__ */ new Map();
53
+ let sortedRegistrationsCache = null;
54
+ function attach(segments, element, formInstanceId, instanceMeta) {
55
+ if (!INTERACTIVE_TAG_NAMES.has(element.tagName)) return;
56
+ const { key } = canonicalizePath(segments);
57
+ const record = elements.get(key);
58
+ const raw = markRaw(element);
59
+ if (record === void 0) {
60
+ elements.set(key, { path: segments, elements: reactive(/* @__PURE__ */ new Set([raw])) });
61
+ } else {
62
+ if (record.elements.has(raw)) return;
63
+ record.elements.add(raw);
77
64
  }
78
- return raw;
79
- }
80
- if (INTEGER_SEGMENT.test(raw)) return Number(raw);
81
- return raw;
82
- }
83
- function parseDottedPath(path) {
84
- if (path.length === 0) return [""];
85
- const rawSegments = path.split(".");
86
- const segments = [];
87
- for (const raw of rawSegments) {
88
- if (raw.length === 0) {
89
- throw new InvalidPathError(
90
- `Path '${path}' has an empty segment; use the array form for empty keys.`
91
- );
65
+ elementToFormInstance.set(element, formInstanceId);
66
+ hostTargets.delete(key);
67
+ sortedRegistrationsCache = null;
68
+ kernel.noteDomConnected(segments);
69
+ attachFocusListeners(kernel, segments, element, instanceMeta);
70
+ }
71
+ function detach(segments, element) {
72
+ detachFocusListeners(element);
73
+ const { key } = canonicalizePath(segments);
74
+ const record = elements.get(key);
75
+ if (record === void 0) return;
76
+ const removed = record.elements.delete(element);
77
+ if (removed) {
78
+ elementToFormInstance.delete(element);
79
+ sortedRegistrationsCache = null;
92
80
  }
93
- segments.push(normalizeSegment(raw));
94
- }
95
- return segments;
96
- }
97
- const CANONICAL_STRING_CACHE_MAX = 128;
98
- const canonicalStringCache = /* @__PURE__ */ new Map();
99
- const PATHKEY_TO_SEGMENTS_MAX = 4096;
100
- const pathKeyToSegments = /* @__PURE__ */ new Map();
101
- function rememberSegmentsForPathKey(key, segments) {
102
- if (!pathKeyToSegments.has(key) && pathKeyToSegments.size >= PATHKEY_TO_SEGMENTS_MAX) {
103
- const oldest = pathKeyToSegments.keys().next().value;
104
- if (oldest !== void 0) pathKeyToSegments.delete(oldest);
105
- }
106
- pathKeyToSegments.set(key, segments);
107
- }
108
- function segmentsForPathKey(key) {
109
- const cached = pathKeyToSegments.get(key);
110
- if (cached !== void 0) return cached;
111
- let parsed;
112
- try {
113
- parsed = JSON.parse(key);
114
- } catch {
115
- return null;
116
- }
117
- if (!Array.isArray(parsed)) return null;
118
- const segments = [];
119
- for (const raw of parsed) {
120
- if (typeof raw !== "string" && typeof raw !== "number") return null;
121
- segments.push(normalizeSegment(raw));
122
- }
123
- rememberSegmentsForPathKey(key, segments);
124
- return segments;
125
- }
126
- function canonicalizePath(input) {
127
- if (typeof input === "string") {
128
- const cached = canonicalStringCache.get(input);
129
- if (cached !== void 0) return cached;
130
- const segments = parseDottedPath(input);
131
- const key = JSON.stringify(segments);
132
- const entry = { segments, key };
133
- if (canonicalStringCache.size >= CANONICAL_STRING_CACHE_MAX) {
134
- const oldest = canonicalStringCache.keys().next().value;
135
- if (oldest !== void 0) canonicalStringCache.delete(oldest);
81
+ if (record.elements.size === 0) {
82
+ elements.delete(key);
83
+ kernel.noteDomDisconnected(segments);
84
+ kernel.cancelTransformsUnder(segments);
136
85
  }
137
- canonicalStringCache.set(input, entry);
138
- rememberSegmentsForPathKey(key, segments);
139
- return entry;
140
86
  }
141
- return keyForSegments(input);
142
- }
143
- function keyForSegments(input) {
144
- const segments = Array.from(input).map(normalizeSegment);
145
- const key = JSON.stringify(segments);
146
- rememberSegmentsForPathKey(key, segments);
147
- return { segments, key };
148
- }
149
- function segmentsToDotted(segments) {
150
- return segments.join(".");
151
- }
152
- function pathKeyToDotted(key) {
153
- const segments = segmentsForPathKey(key);
154
- if (segments === null) return null;
155
- return segmentsToDotted(segments);
156
- }
157
- function coerceToPathKey(input) {
158
- if (input.length > 0 && input.charCodeAt(0) === 91) {
159
- try {
160
- const parsed = JSON.parse(input);
161
- if (Array.isArray(parsed) && parsed.every((s) => typeof s === "string" || typeof s === "number")) {
162
- return input;
87
+ function markHostConnected(segments, connected, hostEl, formInstanceId) {
88
+ const { key } = canonicalizePath(segments);
89
+ if (connected) {
90
+ if (!elements.has(key)) {
91
+ hostTargets.set(key, { path: segments, hostRoot: hostEl, formInstanceId });
92
+ sortedRegistrationsCache = null;
163
93
  }
164
- } catch {
94
+ if (kernel.getFieldRecord(segments)?.connected === true) return;
95
+ kernel.noteDomConnected(segments);
96
+ } else {
97
+ if (hostTargets.delete(key)) sortedRegistrationsCache = null;
98
+ if (kernel.getFieldRecord(segments)?.connected !== true) return;
99
+ kernel.noteDomDisconnected(segments);
165
100
  }
166
101
  }
167
- return canonicalizePath(input).key;
168
- }
169
- const ROOT_PATH = Object.freeze([]);
170
- const ROOT_PATH_KEY = "[]";
171
- function isPathPrefix(prefix, path) {
172
- if (path.length < prefix.length) return false;
173
- for (let i = 0; i < prefix.length; i++) {
174
- if (path[i] !== prefix[i]) return false;
175
- }
176
- return true;
177
- }
178
- function pathsEqual(a, b) {
179
- if (a.length !== b.length) return false;
180
- for (let i = 0; i < a.length; i++) {
181
- if (a[i] !== b[i]) return false;
182
- }
183
- return true;
184
- }
185
-
186
- const __DEV__ = (typeof process !== "undefined" ? process.env.NODE_ENV : "production") !== "production";
187
-
188
- const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
189
-
190
- function detectSSR(options = {}) {
191
- if (options.ssr !== void 0) return options.ssr;
192
- return typeof window === "undefined" && typeof document === "undefined";
193
- }
194
-
195
- const kAttaformRegistry = /* @__PURE__ */ Symbol.for("attaform:registry");
196
- const kAttaformAncestorWizard = /* @__PURE__ */ Symbol.for(
197
- "attaform:ancestor-wizard"
198
- );
199
- const kAttaformWizardActiveStepResolver = /* @__PURE__ */ Symbol.for(
200
- "attaform:wizard-active-step-resolver"
201
- );
202
- const kFormContext = /* @__PURE__ */ Symbol.for("attaform:form-context");
203
- const kFormInstanceId = /* @__PURE__ */ Symbol.for("attaform:form-instance-id");
204
- function createRegistry(options = {}) {
205
- const ssr = detectSSR(options);
206
- const defaults = Object.freeze({ ...options.defaults ?? {} });
207
- const forms = shallowReactive(/* @__PURE__ */ new Map());
208
- const wizards = shallowReactive(/* @__PURE__ */ new Map());
209
- const pendingHydration = shallowReactive(/* @__PURE__ */ new Map());
210
- const consumers = /* @__PURE__ */ new Map();
211
- const evicting = /* @__PURE__ */ new Set();
212
- const pendingEvictions = /* @__PURE__ */ new Map();
213
- function cancelPendingEviction(key) {
214
- const pending = pendingEvictions.get(key);
215
- if (pending === void 0) return;
216
- pending.cancelled = true;
217
- pendingEvictions.delete(key);
218
- }
219
- function trackConsumer(key) {
220
- cancelPendingEviction(key);
221
- consumers.set(key, (consumers.get(key) ?? 0) + 1);
222
- let disposed = false;
223
- return () => {
224
- if (disposed) return;
225
- disposed = true;
226
- const remaining = (consumers.get(key) ?? 1) - 1;
227
- if (remaining > 0) {
228
- consumers.set(key, remaining);
229
- return;
230
- }
231
- consumers.delete(key);
232
- const token = { cancelled: false };
233
- pendingEvictions.set(key, token);
234
- queueMicrotask(() => {
235
- if (token.cancelled) return;
236
- if (pendingEvictions.get(key) !== token) return;
237
- pendingEvictions.delete(key);
238
- const state = forms.get(key);
239
- forms.delete(key);
240
- if (state === void 0) return;
241
- evicting.add(state);
242
- void state.awaitPendingWrites().catch(() => void 0).finally(() => {
243
- evicting.delete(state);
244
- state.dispose();
102
+ function rebuildSortedRegistrations() {
103
+ const flat = [];
104
+ for (const [, record] of elements) {
105
+ for (const el of record.elements) {
106
+ flat.push({
107
+ path: record.path,
108
+ element: el,
109
+ host: false,
110
+ formInstanceId: elementToFormInstance.get(el) ?? ""
245
111
  });
246
- });
247
- };
248
- }
249
- const wizardConsumers = /* @__PURE__ */ new Map();
250
- const pendingWizardEvictions = /* @__PURE__ */ new Map();
251
- function cancelPendingWizardEviction(key) {
252
- const pending = pendingWizardEvictions.get(key);
253
- if (pending === void 0) return;
254
- pending.cancelled = true;
255
- pendingWizardEvictions.delete(key);
256
- }
257
- function trackWizardConsumer(key) {
258
- cancelPendingWizardEviction(key);
259
- wizardConsumers.set(key, (wizardConsumers.get(key) ?? 0) + 1);
260
- let disposed = false;
261
- return () => {
262
- if (disposed) return;
263
- disposed = true;
264
- const remaining = (wizardConsumers.get(key) ?? 1) - 1;
265
- if (remaining > 0) {
266
- wizardConsumers.set(key, remaining);
267
- return;
268
112
  }
269
- wizardConsumers.delete(key);
270
- const token = { cancelled: false };
271
- pendingWizardEvictions.set(key, token);
272
- queueMicrotask(() => {
273
- if (token.cancelled) return;
274
- if (pendingWizardEvictions.get(key) !== token) return;
275
- pendingWizardEvictions.delete(key);
276
- wizards.delete(key);
113
+ }
114
+ for (const [key, target] of hostTargets) {
115
+ if (elements.has(key)) continue;
116
+ flat.push({
117
+ path: target.path,
118
+ element: target.hostRoot,
119
+ host: true,
120
+ formInstanceId: target.formInstanceId
277
121
  });
278
- };
279
- }
280
- async function shutdown() {
281
- const states = [...forms.values(), ...evicting];
282
- await Promise.allSettled(states.map((state) => state.awaitPendingWrites()));
283
- }
284
- const prefetchEnqueued = /* @__PURE__ */ new Set();
285
- const prefetchSkipped = /* @__PURE__ */ new Set();
286
- function enqueuePrefetch(key) {
287
- prefetchEnqueued.add(key);
288
- }
289
- function skipPrefetch(key) {
290
- prefetchSkipped.add(key);
291
- }
292
- function shouldPrefetch(key) {
293
- return prefetchEnqueued.has(key) && !prefetchSkipped.has(key);
122
+ }
123
+ flat.sort(
124
+ (a, b) => a.element.compareDocumentPosition(b.element) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
125
+ );
126
+ return flat;
127
+ }
128
+ function getFirstErrorElement(formInstanceId) {
129
+ sortedRegistrationsCache ?? (sortedRegistrationsCache = rebuildSortedRegistrations());
130
+ for (const entry of sortedRegistrationsCache) {
131
+ if (entry.formInstanceId !== formInstanceId) continue;
132
+ if (!entry.element.isConnected) continue;
133
+ if (entry.element.offsetParent === null) continue;
134
+ if (kernel.getErrorsForPath(entry.path).length === 0) continue;
135
+ const element = entry.host ? resolveHostFocusTarget(entry.element) : entry.element;
136
+ return { path: entry.path, element };
137
+ }
138
+ return null;
294
139
  }
295
140
  return {
296
- forms,
297
- wizards,
298
- pendingHydration,
299
- ssr,
300
- defaults,
301
- trackConsumer,
302
- trackWizardConsumer,
303
- enqueuePrefetch,
304
- skipPrefetch,
305
- shouldPrefetch,
306
- shutdown
141
+ elements,
142
+ attach,
143
+ detach,
144
+ markHostConnected,
145
+ getFirstErrorElement
307
146
  };
308
147
  }
309
- function useRegistry() {
310
- const instance = getCurrentInstance();
311
- if (instance === null) {
312
- throw new OutsideSetupError();
313
- }
314
- const registry = inject(kAttaformRegistry, null);
315
- if (registry === null) {
316
- throw new RegistryNotInstalledError();
317
- }
318
- return registry;
148
+ function armDomBinding(value) {
149
+ value.ensureDomBinding?.(createDomBinding);
319
150
  }
320
- function getRegistryFromApp(app) {
321
- const registry = app._attaform;
322
- if (registry === void 0) {
323
- throw new RegistryNotInstalledError();
324
- }
325
- return registry;
151
+
152
+ const V_REGISTER_MARKER = /* @__PURE__ */ Symbol.for("attaform:v-register-directive");
153
+ const REGISTER_OWNER_MARKER = /* @__PURE__ */ Symbol.for("attaform:register-owner-marker");
154
+ const SSR_COMPONENT_HOST_MODIFIER = "attaformComponentHost";
155
+ const V_REGISTER_COMPILED_MODIFIER = "attaformCompiled";
156
+ function isRegisterValue(val) {
157
+ if (typeof val !== "object" || val === null) return false;
158
+ if (!("innerRef" in val)) return false;
159
+ if (!isRef(val.innerRef)) return false;
160
+ if (!("registerElement" in val)) return false;
161
+ if (typeof val.registerElement !== "function") return false;
162
+ if (!("setValueWithInternalPath" in val)) return false;
163
+ if (typeof val.setValueWithInternalPath !== "function") return false;
164
+ return true;
326
165
  }
327
- function attachRegistryToApp(app, registry) {
328
- app.provide(kAttaformRegistry, registry);
329
- app._attaform = registry;
166
+ function isTransforming(value) {
167
+ return isRegisterValue(value) && value.transforming;
330
168
  }
331
169
 
332
170
  const isArray = Array.isArray;
@@ -637,16 +475,12 @@ function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
637
475
  );
638
476
  }
639
477
  function logTransformFailure(path, index, fn, err) {
640
- if (__DEV__) {
478
+ {
641
479
  const namePart = fn.name !== "" ? `, '${fn.name}'` : "";
642
480
  console.error(
643
481
  `[attaform] transform threw for path '${path}' (index ${index}${namePart}) \u2014 write aborted. Transforms must not throw; wrap your own try/catch if the throw is recoverable. Original error:`,
644
482
  err
645
483
  );
646
- } else {
647
- console.error(
648
- `[attaform] transform error \u2014 write aborted (set NODE_ENV=development for details).`
649
- );
650
484
  }
651
485
  }
652
486
  function applyCoerce(value, registerValue) {
@@ -732,9 +566,11 @@ function setAssignFunction(el, vnode, value) {
732
566
  return;
733
567
  }
734
568
  if (!isRegisterValue(value)) {
735
- warn(
736
- `v-register expected a RegisterValue, got '${typeof value}'. Bind to form.register('field') \u2014 not the field's ref, value, or path string.`
737
- );
569
+ {
570
+ warn(
571
+ `v-register expected a RegisterValue, got '${typeof value}'. Bind to form.register('field') \u2014 not the field's ref, value, or path string.`
572
+ );
573
+ }
738
574
  el[assignKey] = makeNoopAssigner();
739
575
  return;
740
576
  }
@@ -766,6 +602,7 @@ const vRegisterFile = {
766
602
  created(el, { value }, vnode) {
767
603
  if (!isRegisterValue(value)) return;
768
604
  const input = el;
605
+ armDomBinding(value);
769
606
  value.registerElement(input);
770
607
  setAssignFunction(input, vnode, value);
771
608
  const currentRaw = value.innerRef.value;
@@ -1077,9 +914,11 @@ const vRegisterCheckbox = {
1077
914
  const checked = el.checked;
1078
915
  if (isArray(modelValue)) {
1079
916
  if (rawElementValue === void 0) {
1080
- warn(
1081
- 'Checkbox bound to an array model is missing a `value` attribute \u2014 cannot determine which item to add or remove. Add value="..." to each <input type="checkbox">.'
1082
- );
917
+ {
918
+ warn(
919
+ 'Checkbox bound to an array model is missing a `value` attribute \u2014 cannot determine which item to add or remove. Add value="..." to each <input type="checkbox">.'
920
+ );
921
+ }
1083
922
  return;
1084
923
  }
1085
924
  const elementValue = applyElementCoerce(rawElementValue, value);
@@ -1094,9 +933,11 @@ const vRegisterCheckbox = {
1094
933
  }
1095
934
  } else if (isSet(modelValue)) {
1096
935
  if (rawElementValue === void 0) {
1097
- warn(
1098
- 'Checkbox bound to a Set model is missing a `value` attribute \u2014 cannot determine which item to add or remove. Add value="..." to each <input type="checkbox">.'
1099
- );
936
+ {
937
+ warn(
938
+ 'Checkbox bound to a Set model is missing a `value` attribute \u2014 cannot determine which item to add or remove. Add value="..." to each <input type="checkbox">.'
939
+ );
940
+ }
1100
941
  return;
1101
942
  }
1102
943
  const elementValue = applyElementCoerce(rawElementValue, value);
@@ -1303,7 +1144,7 @@ function setSelected(el, value) {
1303
1144
  const isMultiple = el.multiple;
1304
1145
  const isArrayValue = isArray(externalValue);
1305
1146
  if (isMultiple && !isArrayValue && !isSet(externalValue)) {
1306
- if (__DEV__) {
1147
+ {
1307
1148
  warn(
1308
1149
  `<select multiple v-register> expected an Array or Set, got ${Object.prototype.toString.call(externalValue).slice(8, -1)}. Bind to a list-typed schema (e.g. z.array(z.string()) or z.set(z.string())).`
1309
1150
  );
@@ -1311,7 +1152,7 @@ function setSelected(el, value) {
1311
1152
  return;
1312
1153
  }
1313
1154
  if (!isMultiple && (isArrayValue || isSet(externalValue))) {
1314
- if (__DEV__) {
1155
+ {
1315
1156
  warn(
1316
1157
  `<select v-register> (no \`multiple\` attribute) expected a scalar value for its binding, but got ${Object.prototype.toString.call(externalValue).slice(8, -1)}. Add the \`multiple\` attribute to bind to a list, or use a scalar schema (e.g. \`z.string()\`) for a single-select binding.`
1317
1158
  );
@@ -1358,8 +1199,8 @@ function getCheckboxValue(el, checked) {
1358
1199
  const key = checked ? "_trueValue" : "_falseValue";
1359
1200
  return key in el ? el[key] : checked;
1360
1201
  }
1361
- const warnedUnsupportedElements = __DEV__ ? /* @__PURE__ */ new WeakSet() : null;
1362
- const warnedRedundantBindings = __DEV__ ? /* @__PURE__ */ new Set() : null;
1202
+ const warnedUnsupportedElements = /* @__PURE__ */ new WeakSet() ;
1203
+ const warnedRedundantBindings = /* @__PURE__ */ new Set() ;
1363
1204
  const componentHostLatch = /* @__PURE__ */ new WeakMap();
1364
1205
  const hostFocusListeners = /* @__PURE__ */ new WeakMap();
1365
1206
  const hostHealObservers = /* @__PURE__ */ new WeakMap();
@@ -1444,9 +1285,10 @@ function activateComponentHost(el, rv) {
1444
1285
  }
1445
1286
  const vRegisterDynamic = {
1446
1287
  created(el, binding, vnode) {
1288
+ if (isRegisterValue(binding.value)) armDomBinding(binding.value);
1447
1289
  callModelHook(el, binding, vnode, null, "created");
1448
1290
  if (isRegisterValue(binding.value)) setupAria(el, binding.value, vnode);
1449
- if (__DEV__) warnRedundantStateBinding(el, binding, vnode);
1291
+ warnRedundantStateBinding(el, binding, vnode);
1450
1292
  },
1451
1293
  mounted(el, binding, vnode) {
1452
1294
  callModelHook(el, binding, vnode, null, "mounted");
@@ -1456,7 +1298,7 @@ const vRegisterDynamic = {
1456
1298
  if (binding.modifiers[SSR_COMPONENT_HOST_MODIFIER] === true && isRegisterValue(binding.value)) {
1457
1299
  activateComponentHost(el, binding.value);
1458
1300
  }
1459
- if (__DEV__ && warnedUnsupportedElements !== null && !INTERACTIVE_TAG_NAMES.has(el.tagName) && !warnedUnsupportedElements.has(el)) {
1301
+ if (warnedUnsupportedElements !== null && !INTERACTIVE_TAG_NAMES.has(el.tagName) && !warnedUnsupportedElements.has(el)) {
1460
1302
  void nextTick(() => {
1461
1303
  if (warnedUnsupportedElements.has(el)) return;
1462
1304
  const hasMarker = el[REGISTER_OWNER_MARKER] === true;
@@ -1472,6 +1314,7 @@ const vRegisterDynamic = {
1472
1314
  }
1473
1315
  },
1474
1316
  beforeUpdate(el, binding, vnode, prevVNode) {
1317
+ if (isRegisterValue(binding.value)) armDomBinding(binding.value);
1475
1318
  syncElementRegistration(el, binding.value, binding.oldValue);
1476
1319
  callModelHook(el, binding, vnode, prevVNode, "beforeUpdate");
1477
1320
  const ariaEl = el;
@@ -1604,72 +1447,10 @@ function callModelHook(el, binding, vnode, prevVNode, hook) {
1604
1447
  }
1605
1448
  const vRegister = vRegisterDynamic;
1606
1449
  vRegisterDynamic[V_REGISTER_MARKER] = true;
1607
-
1608
- function installAttaformOnApp(app, options, source) {
1609
- if (app._attaform !== void 0) {
1610
- if (__DEV__ && source === "explicit") {
1611
- console.warn(
1612
- "[attaform] createAttaform() install was called twice on the same app; the second call is a no-op. Likely cause: registering the plugin via both the Nuxt module AND a manual `app.use(...)`."
1613
- );
1614
- }
1615
- return app._attaform;
1616
- }
1617
- const registry = createRegistry(options);
1618
- attachRegistryToApp(app, registry);
1619
- app.directive("register", vRegister);
1620
- if (__DEV__ && options.devtools !== false && !registry.ssr) {
1621
- void (async () => {
1622
- try {
1623
- const { setupAttaformDevtools } = await import('../chunks/devtools.mjs');
1624
- await setupAttaformDevtools(app, registry);
1625
- } catch {
1626
- }
1627
- })();
1450
+ function installVRegister(app) {
1451
+ if (app.directive("register") === void 0) {
1452
+ app.directive("register", vRegister);
1628
1453
  }
1629
- return registry;
1630
1454
  }
1631
- function ensureAttaformInstalled(app) {
1632
- return installAttaformOnApp(app, {}, "lazy");
1633
- }
1634
- function createAttaform(options = {}) {
1635
- const plugin = {
1636
- install(app) {
1637
- installAttaformOnApp(app, options, "explicit");
1638
- }
1639
- };
1640
- return plugin;
1641
- }
1642
-
1643
- function renderAttaformState(app) {
1644
- const registry = getRegistryFromApp(app);
1645
- const forms = [];
1646
- for (const [key, state] of registry.forms) {
1647
- const transientList = [];
1648
- for (const pk of state.blankPaths) {
1649
- const d = pathKeyToDotted(pk);
1650
- if (d !== null) transientList.push(d);
1651
- }
1652
- forms.push([
1653
- key,
1654
- {
1655
- form: state.form.value,
1656
- schemaErrors: Array.from(state.schemaErrors.entries()),
1657
- userErrors: Array.from(state.userErrors.entries()),
1658
- fields: Array.from(state.fields.entries()),
1659
- ...transientList.length > 0 ? { blankPaths: transientList } : {}
1660
- }
1661
- ]);
1662
- }
1663
- return { forms };
1664
- }
1665
- function hydrateAttaformState(app, payload) {
1666
- const registry = getRegistryFromApp(app);
1667
- for (const [key, data] of payload.forms) {
1668
- registry.pendingHydration.set(key, data);
1669
- }
1670
- }
1671
-
1672
- const DEVTOOLS_WINDOW_KEY = "__attaform_devtools__";
1673
1455
 
1674
- export { AttaformError as A, kFormContext as B, kFormInstanceId as C, DEVTOOLS_WINDOW_KEY as D, kAttaformAncestorWizard as E, InvalidPathError as I, OutsideSetupError as O, ROOT_PATH as R, SubmitErrorHandlerError as S, __DEV__ as _, InvalidUseFormConfigError as a, ROOT_PATH_KEY as b, RegistryNotInstalledError as c, ReservedFormKeyError as d, assignKey as e, canonicalizePath as f, createAttaform as g, createRegistry as h, getRegistryFromApp as i, hydrateAttaformState as j, isPathPrefix as k, kAttaformRegistry as l, kAttaformWizardActiveStepResolver as m, pathsEqual as n, keyForSegments as o, parseDottedPath as p, normalizeErrorInput as q, renderAttaformState as r, segmentsForPathKey as s, toError as t, useRegistry as u, vRegister as v, INTERACTIVE_TAG_NAMES as w, normalizeErrorInputs as x, coerceToPathKey as y, ensureAttaformInstalled as z };
1675
- //# sourceMappingURL=attaform.nMaz2C5P.mjs.map
1456
+ export { REGISTER_OWNER_MARKER as R, V_REGISTER_MARKER as V, assignKey as a, installVRegister as b, vRegisterFile as c, armDomBinding as d, isRegisterValue as i, vRegister as v };