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,334 +1,153 @@
1
- 'use strict';
1
+ import { reactive, markRaw, effectScope, watch, nextTick } from 'vue';
2
+ import { i as isRegisterValue, a as isTransforming, S as SSR_COMPONENT_HOST_MODIFIER, R as REGISTER_OWNER_MARKER, b as V_REGISTER_MARKER } from './attaform.KvlEedlF.mjs';
3
+ import { e as canonicalizePath } from './attaform.wfY8XFvm.mjs';
2
4
 
3
- const vue = require('vue');
4
- const registerProtocol = require('./attaform.yUrz7C2z.cjs');
5
-
6
- class AttaformError extends Error {
7
- constructor(message, options) {
8
- super(message, options);
9
- this.name = new.target.name;
10
- }
11
- }
12
- class InvalidPathError extends AttaformError {
13
- }
14
- class InvalidUseFormConfigError extends AttaformError {
15
- constructor() {
16
- super(
17
- "[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."
18
- );
19
- }
20
- }
21
- class SubmitErrorHandlerError extends AttaformError {
22
- }
23
- function toError(value) {
24
- if (value instanceof Error) return value;
25
- const message = typeof value === "string" && value.length > 0 ? value : `Submit callback threw a non-Error value (${typeof value})`;
26
- return new Error(message, { cause: value });
27
- }
28
- function normalizeErrorInput(item, scope, formKey, defaultCode) {
29
- if (item instanceof Error) {
30
- return {
31
- message: item.message.length > 0 ? item.message : "Unknown error",
32
- path: scope !== void 0 ? [...scope] : [],
33
- formKey,
34
- code: defaultCode
35
- };
36
- }
37
- const entry = {
38
- message: typeof item.message === "string" && item.message.length > 0 ? item.message : "Unknown error",
39
- path: scope !== void 0 ? [...scope] : Array.isArray(item.path) ? [...item.path] : [],
40
- formKey,
41
- code: typeof item.code === "string" && item.code.length > 0 ? item.code : defaultCode
42
- };
43
- if (item.data !== void 0) entry.data = item.data;
44
- return entry;
45
- }
46
- function normalizeErrorInputs(input, scope, formKey, defaultCode) {
47
- const items = Array.isArray(input) ? input : [input];
48
- return items.map((item) => normalizeErrorInput(item, scope, formKey, defaultCode));
49
- }
50
- class RegistryNotInstalledError extends AttaformError {
51
- constructor() {
52
- super(
53
- "[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`."
54
- );
55
- }
56
- }
57
- class OutsideSetupError extends AttaformError {
58
- constructor() {
59
- super(
60
- "[attaform] useForm / injectForm called outside Vue setup(). Move into setup or mount a child component to trigger from an event."
61
- );
62
- }
63
- }
64
- class ReservedFormKeyError extends AttaformError {
65
- constructor(key) {
66
- super(
67
- `[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).`
68
- );
69
- }
70
- }
5
+ const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
71
6
 
72
- const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
73
- function normalizeSegment(raw) {
74
- if (typeof raw === "number") {
75
- if (!Number.isInteger(raw) || raw < 0) {
76
- throw new InvalidPathError(
77
- `Path segments must be non-negative integers when numeric; got ${String(raw)}`
78
- );
7
+ const attaformListenersSymbol = /* @__PURE__ */ Symbol.for("attaform:focus-listeners");
8
+ const HOST_FOCUS_TARGET_SELECTOR = [
9
+ 'input:not([type="hidden"])',
10
+ "select",
11
+ "textarea",
12
+ "button",
13
+ "a[href]",
14
+ '[tabindex]:not([tabindex="-1"])',
15
+ '[contenteditable="true"]'
16
+ ].join(", ");
17
+ function resolveHostFocusTarget(hostRoot) {
18
+ const candidates = hostRoot.querySelectorAll(HOST_FOCUS_TARGET_SELECTOR);
19
+ for (const el of candidates) {
20
+ if (!el.isConnected) continue;
21
+ if (el.offsetParent === null) continue;
22
+ if (el.matches(":disabled")) continue;
23
+ return el;
24
+ }
25
+ return hostRoot;
26
+ }
27
+ function attachFocusListeners(kernel, segments, element, instanceMeta) {
28
+ const target = element;
29
+ if (target[attaformListenersSymbol] !== void 0) return;
30
+ const focusMeta = instanceMeta !== void 0 ? { instance: instanceMeta } : void 0;
31
+ const handleFocus = () => kernel.markFocused(segments, true, focusMeta);
32
+ const handleBlur = () => kernel.markFocused(segments, false, focusMeta);
33
+ element.addEventListener("focus", handleFocus);
34
+ element.addEventListener("blur", handleBlur);
35
+ target[attaformListenersSymbol] = { handleFocus, handleBlur };
36
+ const rootNode = element.getRootNode();
37
+ const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
38
+ if (activeElement === element) {
39
+ kernel.markFocused(segments, true, focusMeta);
40
+ }
41
+ }
42
+ function detachFocusListeners(element) {
43
+ const target = element;
44
+ const listeners = target[attaformListenersSymbol];
45
+ if (listeners === void 0) return;
46
+ element.removeEventListener("focus", listeners.handleFocus);
47
+ element.removeEventListener("blur", listeners.handleBlur);
48
+ delete target[attaformListenersSymbol];
49
+ }
50
+ function createDomBinding(kernel) {
51
+ const elements = reactive(/* @__PURE__ */ new Map());
52
+ const elementToFormInstance = /* @__PURE__ */ new WeakMap();
53
+ const hostTargets = /* @__PURE__ */ new Map();
54
+ let sortedRegistrationsCache = null;
55
+ function attach(segments, element, formInstanceId, instanceMeta) {
56
+ if (!INTERACTIVE_TAG_NAMES.has(element.tagName)) return;
57
+ const { key } = canonicalizePath(segments);
58
+ const record = elements.get(key);
59
+ const raw = markRaw(element);
60
+ if (record === void 0) {
61
+ elements.set(key, { path: segments, elements: reactive(/* @__PURE__ */ new Set([raw])) });
62
+ } else {
63
+ if (record.elements.has(raw)) return;
64
+ record.elements.add(raw);
79
65
  }
80
- return raw;
81
- }
82
- if (INTEGER_SEGMENT.test(raw)) return Number(raw);
83
- return raw;
84
- }
85
- function parseDottedPath(path) {
86
- if (path.length === 0) return [""];
87
- const rawSegments = path.split(".");
88
- const segments = [];
89
- for (const raw of rawSegments) {
90
- if (raw.length === 0) {
91
- throw new InvalidPathError(
92
- `Path '${path}' has an empty segment; use the array form for empty keys.`
93
- );
66
+ elementToFormInstance.set(element, formInstanceId);
67
+ hostTargets.delete(key);
68
+ sortedRegistrationsCache = null;
69
+ kernel.noteDomConnected(segments);
70
+ attachFocusListeners(kernel, segments, element, instanceMeta);
71
+ }
72
+ function detach(segments, element) {
73
+ detachFocusListeners(element);
74
+ const { key } = canonicalizePath(segments);
75
+ const record = elements.get(key);
76
+ if (record === void 0) return;
77
+ const removed = record.elements.delete(element);
78
+ if (removed) {
79
+ elementToFormInstance.delete(element);
80
+ sortedRegistrationsCache = null;
94
81
  }
95
- segments.push(normalizeSegment(raw));
96
- }
97
- return segments;
98
- }
99
- const CANONICAL_STRING_CACHE_MAX = 128;
100
- const canonicalStringCache = /* @__PURE__ */ new Map();
101
- const PATHKEY_TO_SEGMENTS_MAX = 4096;
102
- const pathKeyToSegments = /* @__PURE__ */ new Map();
103
- function rememberSegmentsForPathKey(key, segments) {
104
- if (!pathKeyToSegments.has(key) && pathKeyToSegments.size >= PATHKEY_TO_SEGMENTS_MAX) {
105
- const oldest = pathKeyToSegments.keys().next().value;
106
- if (oldest !== void 0) pathKeyToSegments.delete(oldest);
107
- }
108
- pathKeyToSegments.set(key, segments);
109
- }
110
- function segmentsForPathKey(key) {
111
- const cached = pathKeyToSegments.get(key);
112
- if (cached !== void 0) return cached;
113
- let parsed;
114
- try {
115
- parsed = JSON.parse(key);
116
- } catch {
117
- return null;
118
- }
119
- if (!Array.isArray(parsed)) return null;
120
- const segments = [];
121
- for (const raw of parsed) {
122
- if (typeof raw !== "string" && typeof raw !== "number") return null;
123
- segments.push(normalizeSegment(raw));
124
- }
125
- rememberSegmentsForPathKey(key, segments);
126
- return segments;
127
- }
128
- function canonicalizePath(input) {
129
- if (typeof input === "string") {
130
- const cached = canonicalStringCache.get(input);
131
- if (cached !== void 0) return cached;
132
- const segments = parseDottedPath(input);
133
- const key = JSON.stringify(segments);
134
- const entry = { segments, key };
135
- if (canonicalStringCache.size >= CANONICAL_STRING_CACHE_MAX) {
136
- const oldest = canonicalStringCache.keys().next().value;
137
- if (oldest !== void 0) canonicalStringCache.delete(oldest);
82
+ if (record.elements.size === 0) {
83
+ elements.delete(key);
84
+ kernel.noteDomDisconnected(segments);
85
+ kernel.cancelTransformsUnder(segments);
138
86
  }
139
- canonicalStringCache.set(input, entry);
140
- rememberSegmentsForPathKey(key, segments);
141
- return entry;
142
87
  }
143
- return keyForSegments(input);
144
- }
145
- function keyForSegments(input) {
146
- const segments = Array.from(input).map(normalizeSegment);
147
- const key = JSON.stringify(segments);
148
- rememberSegmentsForPathKey(key, segments);
149
- return { segments, key };
150
- }
151
- function segmentsToDotted(segments) {
152
- return segments.join(".");
153
- }
154
- function pathKeyToDotted(key) {
155
- const segments = segmentsForPathKey(key);
156
- if (segments === null) return null;
157
- return segmentsToDotted(segments);
158
- }
159
- function coerceToPathKey(input) {
160
- if (input.length > 0 && input.charCodeAt(0) === 91) {
161
- try {
162
- const parsed = JSON.parse(input);
163
- if (Array.isArray(parsed) && parsed.every((s) => typeof s === "string" || typeof s === "number")) {
164
- return input;
88
+ function markHostConnected(segments, connected, hostEl, formInstanceId) {
89
+ const { key } = canonicalizePath(segments);
90
+ if (connected) {
91
+ if (!elements.has(key)) {
92
+ hostTargets.set(key, { path: segments, hostRoot: hostEl, formInstanceId });
93
+ sortedRegistrationsCache = null;
165
94
  }
166
- } catch {
95
+ if (kernel.getFieldRecord(segments)?.connected === true) return;
96
+ kernel.noteDomConnected(segments);
97
+ } else {
98
+ if (hostTargets.delete(key)) sortedRegistrationsCache = null;
99
+ if (kernel.getFieldRecord(segments)?.connected !== true) return;
100
+ kernel.noteDomDisconnected(segments);
167
101
  }
168
102
  }
169
- return canonicalizePath(input).key;
170
- }
171
- const ROOT_PATH = Object.freeze([]);
172
- const ROOT_PATH_KEY = "[]";
173
- function isPathPrefix(prefix, path) {
174
- if (path.length < prefix.length) return false;
175
- for (let i = 0; i < prefix.length; i++) {
176
- if (path[i] !== prefix[i]) return false;
177
- }
178
- return true;
179
- }
180
- function pathsEqual(a, b) {
181
- if (a.length !== b.length) return false;
182
- for (let i = 0; i < a.length; i++) {
183
- if (a[i] !== b[i]) return false;
184
- }
185
- return true;
186
- }
187
-
188
- const __DEV__ = (typeof process !== "undefined" ? process.env.NODE_ENV : "production") !== "production";
189
-
190
- const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
191
-
192
- function detectSSR(options = {}) {
193
- if (options.ssr !== void 0) return options.ssr;
194
- return typeof window === "undefined" && typeof document === "undefined";
195
- }
196
-
197
- const kAttaformRegistry = /* @__PURE__ */ Symbol.for("attaform:registry");
198
- const kAttaformAncestorWizard = /* @__PURE__ */ Symbol.for(
199
- "attaform:ancestor-wizard"
200
- );
201
- const kAttaformWizardActiveStepResolver = /* @__PURE__ */ Symbol.for(
202
- "attaform:wizard-active-step-resolver"
203
- );
204
- const kFormContext = /* @__PURE__ */ Symbol.for("attaform:form-context");
205
- const kFormInstanceId = /* @__PURE__ */ Symbol.for("attaform:form-instance-id");
206
- function createRegistry(options = {}) {
207
- const ssr = detectSSR(options);
208
- const defaults = Object.freeze({ ...options.defaults ?? {} });
209
- const forms = vue.shallowReactive(/* @__PURE__ */ new Map());
210
- const wizards = vue.shallowReactive(/* @__PURE__ */ new Map());
211
- const pendingHydration = vue.shallowReactive(/* @__PURE__ */ new Map());
212
- const consumers = /* @__PURE__ */ new Map();
213
- const evicting = /* @__PURE__ */ new Set();
214
- const pendingEvictions = /* @__PURE__ */ new Map();
215
- function cancelPendingEviction(key) {
216
- const pending = pendingEvictions.get(key);
217
- if (pending === void 0) return;
218
- pending.cancelled = true;
219
- pendingEvictions.delete(key);
220
- }
221
- function trackConsumer(key) {
222
- cancelPendingEviction(key);
223
- consumers.set(key, (consumers.get(key) ?? 0) + 1);
224
- let disposed = false;
225
- return () => {
226
- if (disposed) return;
227
- disposed = true;
228
- const remaining = (consumers.get(key) ?? 1) - 1;
229
- if (remaining > 0) {
230
- consumers.set(key, remaining);
231
- return;
232
- }
233
- consumers.delete(key);
234
- const token = { cancelled: false };
235
- pendingEvictions.set(key, token);
236
- queueMicrotask(() => {
237
- if (token.cancelled) return;
238
- if (pendingEvictions.get(key) !== token) return;
239
- pendingEvictions.delete(key);
240
- const state = forms.get(key);
241
- forms.delete(key);
242
- if (state === void 0) return;
243
- evicting.add(state);
244
- void state.awaitPendingWrites().catch(() => void 0).finally(() => {
245
- evicting.delete(state);
246
- state.dispose();
103
+ function rebuildSortedRegistrations() {
104
+ const flat = [];
105
+ for (const [, record] of elements) {
106
+ for (const el of record.elements) {
107
+ flat.push({
108
+ path: record.path,
109
+ element: el,
110
+ host: false,
111
+ formInstanceId: elementToFormInstance.get(el) ?? ""
247
112
  });
248
- });
249
- };
250
- }
251
- const wizardConsumers = /* @__PURE__ */ new Map();
252
- const pendingWizardEvictions = /* @__PURE__ */ new Map();
253
- function cancelPendingWizardEviction(key) {
254
- const pending = pendingWizardEvictions.get(key);
255
- if (pending === void 0) return;
256
- pending.cancelled = true;
257
- pendingWizardEvictions.delete(key);
258
- }
259
- function trackWizardConsumer(key) {
260
- cancelPendingWizardEviction(key);
261
- wizardConsumers.set(key, (wizardConsumers.get(key) ?? 0) + 1);
262
- let disposed = false;
263
- return () => {
264
- if (disposed) return;
265
- disposed = true;
266
- const remaining = (wizardConsumers.get(key) ?? 1) - 1;
267
- if (remaining > 0) {
268
- wizardConsumers.set(key, remaining);
269
- return;
270
113
  }
271
- wizardConsumers.delete(key);
272
- const token = { cancelled: false };
273
- pendingWizardEvictions.set(key, token);
274
- queueMicrotask(() => {
275
- if (token.cancelled) return;
276
- if (pendingWizardEvictions.get(key) !== token) return;
277
- pendingWizardEvictions.delete(key);
278
- wizards.delete(key);
114
+ }
115
+ for (const [key, target] of hostTargets) {
116
+ if (elements.has(key)) continue;
117
+ flat.push({
118
+ path: target.path,
119
+ element: target.hostRoot,
120
+ host: true,
121
+ formInstanceId: target.formInstanceId
279
122
  });
280
- };
281
- }
282
- async function shutdown() {
283
- const states = [...forms.values(), ...evicting];
284
- await Promise.allSettled(states.map((state) => state.awaitPendingWrites()));
285
- }
286
- const prefetchEnqueued = /* @__PURE__ */ new Set();
287
- const prefetchSkipped = /* @__PURE__ */ new Set();
288
- function enqueuePrefetch(key) {
289
- prefetchEnqueued.add(key);
290
- }
291
- function skipPrefetch(key) {
292
- prefetchSkipped.add(key);
293
- }
294
- function shouldPrefetch(key) {
295
- return prefetchEnqueued.has(key) && !prefetchSkipped.has(key);
123
+ }
124
+ flat.sort(
125
+ (a, b) => a.element.compareDocumentPosition(b.element) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
126
+ );
127
+ return flat;
128
+ }
129
+ function getFirstErrorElement(formInstanceId) {
130
+ sortedRegistrationsCache ?? (sortedRegistrationsCache = rebuildSortedRegistrations());
131
+ for (const entry of sortedRegistrationsCache) {
132
+ if (entry.formInstanceId !== formInstanceId) continue;
133
+ if (!entry.element.isConnected) continue;
134
+ if (entry.element.offsetParent === null) continue;
135
+ if (kernel.getErrorsForPath(entry.path).length === 0) continue;
136
+ const element = entry.host ? resolveHostFocusTarget(entry.element) : entry.element;
137
+ return { path: entry.path, element };
138
+ }
139
+ return null;
296
140
  }
297
141
  return {
298
- forms,
299
- wizards,
300
- pendingHydration,
301
- ssr,
302
- defaults,
303
- trackConsumer,
304
- trackWizardConsumer,
305
- enqueuePrefetch,
306
- skipPrefetch,
307
- shouldPrefetch,
308
- shutdown
142
+ elements,
143
+ attach,
144
+ detach,
145
+ markHostConnected,
146
+ getFirstErrorElement
309
147
  };
310
148
  }
311
- function useRegistry() {
312
- const instance = vue.getCurrentInstance();
313
- if (instance === null) {
314
- throw new OutsideSetupError();
315
- }
316
- const registry = vue.inject(kAttaformRegistry, null);
317
- if (registry === null) {
318
- throw new RegistryNotInstalledError();
319
- }
320
- return registry;
321
- }
322
- function getRegistryFromApp(app) {
323
- const registry = app._attaform;
324
- if (registry === void 0) {
325
- throw new RegistryNotInstalledError();
326
- }
327
- return registry;
328
- }
329
- function attachRegistryToApp(app, registry) {
330
- app.provide(kAttaformRegistry, registry);
331
- app._attaform = registry;
149
+ function armDomBinding(value) {
150
+ value.ensureDomBinding?.(createDomBinding);
332
151
  }
333
152
 
334
153
  const isArray = Array.isArray;
@@ -472,9 +291,9 @@ function setupAria(el, rv, vnode) {
472
291
  mergeAriaLocks(el, vnode);
473
292
  applyAria(el, rv, vnode);
474
293
  const displayState = rv.ariaDisplayState;
475
- const scope = vue.effectScope(true);
294
+ const scope = effectScope(true);
476
295
  scope.run(() => {
477
- vue.watch(displayState, () => applyAria(el, rv, vnode), { flush: "post" });
296
+ watch(displayState, () => applyAria(el, rv, vnode), { flush: "post" });
478
297
  });
479
298
  el[ariaScopeKey] = () => scope.stop();
480
299
  }
@@ -494,9 +313,9 @@ function setupAriaLive(el, rv) {
494
313
  seedLocksFromDom(el);
495
314
  applyAria(el, rv, null);
496
315
  const displayState = rv.ariaDisplayState;
497
- const scope = vue.effectScope(true);
316
+ const scope = effectScope(true);
498
317
  scope.run(() => {
499
- vue.watch(displayState, () => applyAria(el, rv, null), { flush: "post" });
318
+ watch(displayState, () => applyAria(el, rv, null), { flush: "post" });
500
319
  });
501
320
  el[ariaScopeKey] = () => scope.stop();
502
321
  }
@@ -565,7 +384,7 @@ function fireAssigner(el, registerValue, value) {
565
384
  if (isDefaultAssigner(fn) || isConsumerWrapped(fn)) {
566
385
  return fn(value);
567
386
  }
568
- if (!registerProtocol.isRegisterValue(registerValue)) {
387
+ if (!isRegisterValue(registerValue)) {
569
388
  return fn(value, void 0);
570
389
  }
571
390
  return wrapWithTransforms(
@@ -604,7 +423,7 @@ function runTransforms(initial, registerValue) {
604
423
  try {
605
424
  out = fn(v, ctx);
606
425
  } catch (err) {
607
- logTransformFailure(registerValue.path, i, fn, err);
426
+ logTransformFailure(registerValue.path);
608
427
  return { kind: "sync", ok: false };
609
428
  }
610
429
  if (isThenable(out)) {
@@ -639,16 +458,8 @@ function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
639
458
  );
640
459
  }
641
460
  function logTransformFailure(path, index, fn, err) {
642
- if (__DEV__) {
643
- const namePart = fn.name !== "" ? `, '${fn.name}'` : "";
644
- console.error(
645
- `[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:`,
646
- err
647
- );
648
- } else {
649
- console.error(
650
- `[attaform] transform error \u2014 write aborted (set NODE_ENV=development for details).`
651
- );
461
+ {
462
+ console.error("[attaform] AF14 attaform.dev/e/af14");
652
463
  }
653
464
  }
654
465
  function applyCoerce(value, registerValue) {
@@ -733,10 +544,7 @@ function setAssignFunction(el, vnode, value) {
733
544
  el[assignKey] = makeNoopAssigner();
734
545
  return;
735
546
  }
736
- if (!registerProtocol.isRegisterValue(value)) {
737
- vue.warn(
738
- `v-register expected a RegisterValue, got '${typeof value}'. Bind to form.register('field') \u2014 not the field's ref, value, or path string.`
739
- );
547
+ if (!isRegisterValue(value)) {
740
548
  el[assignKey] = makeNoopAssigner();
741
549
  return;
742
550
  }
@@ -766,8 +574,9 @@ function readFilesFromInput(el) {
766
574
  const fileScopeKey = /* @__PURE__ */ Symbol.for("attaform:file-scope");
767
575
  const vRegisterFile = {
768
576
  created(el, { value }, vnode) {
769
- if (!registerProtocol.isRegisterValue(value)) return;
577
+ if (!isRegisterValue(value)) return;
770
578
  const input = el;
579
+ armDomBinding(value);
771
580
  value.registerElement(input);
772
581
  setAssignFunction(input, vnode, value);
773
582
  const currentRaw = value.innerRef.value;
@@ -784,9 +593,9 @@ const vRegisterFile = {
784
593
  }
785
594
  fireAssigner(input, value, next);
786
595
  });
787
- const scope = vue.effectScope(true);
596
+ const scope = effectScope(true);
788
597
  scope.run(() => {
789
- vue.watch(
598
+ watch(
790
599
  value.innerRef,
791
600
  (next) => {
792
601
  if (!isBlankFileValue(next)) return;
@@ -799,10 +608,10 @@ const vRegisterFile = {
799
608
  input[fileScopeKey] = () => scope.stop();
800
609
  },
801
610
  beforeUpdate(el, { value }) {
802
- if (!registerProtocol.isRegisterValue(value)) return;
611
+ if (!isRegisterValue(value)) return;
803
612
  const input = el;
804
613
  const currentRaw = value.innerRef.value;
805
- if (isBlankFileValue(currentRaw) && !registerProtocol.isTransforming(value)) {
614
+ if (isBlankFileValue(currentRaw) && !isTransforming(value)) {
806
615
  value.setValueWithInternalPath(currentRaw, { blank: true });
807
616
  if (input.value !== "") input.value = "";
808
617
  }
@@ -814,14 +623,14 @@ const vRegisterFile = {
814
623
  stop();
815
624
  delete el[fileScopeKey];
816
625
  }
817
- if (!registerProtocol.isRegisterValue(value)) return;
626
+ if (!isRegisterValue(value)) return;
818
627
  value.deregisterElement(el);
819
628
  }
820
629
  };
821
630
 
822
631
  function syncElementRegistration(el, value, oldValue) {
823
- const wasRegistered = registerProtocol.isRegisterValue(oldValue);
824
- const isRegistered = registerProtocol.isRegisterValue(value);
632
+ const wasRegistered = isRegisterValue(oldValue);
633
+ const isRegistered = isRegisterValue(value);
825
634
  if (!wasRegistered && !isRegistered) return;
826
635
  const samePathAndStore = wasRegistered && isRegistered && oldValue.path === value.path && oldValue.formKey === value.formKey;
827
636
  if (wasRegistered && !samePathAndStore) {
@@ -840,9 +649,9 @@ function isElementFocused(el) {
840
649
  }
841
650
  function setupValueSync(el, source, apply, options = {}) {
842
651
  const skipWhileFocused = options.skipWhileFocused === true;
843
- const scope = vue.effectScope(true);
652
+ const scope = effectScope(true);
844
653
  scope.run(() => {
845
- vue.watch(
654
+ watch(
846
655
  source,
847
656
  () => {
848
657
  if (el.composing === true) return;
@@ -869,9 +678,9 @@ function setupDisabledSync(el, source) {
869
678
  if (control.disabled !== next) control.disabled = next;
870
679
  };
871
680
  apply();
872
- const scope = vue.effectScope(true);
681
+ const scope = effectScope(true);
873
682
  scope.run(() => {
874
- vue.watch(source, apply, { flush: "post" });
683
+ watch(source, apply, { flush: "post" });
875
684
  });
876
685
  el[disabledSyncScopeKey] = () => scope.stop();
877
686
  }
@@ -909,12 +718,12 @@ const vRegisterText = {
909
718
  created(el, { value, modifiers: { lazy, trim, number } }, vnode) {
910
719
  const castToNumberAtCreated = number === true || vnode.props?.["type"] === "number";
911
720
  const liveCastToNumber = () => number === true || el.getAttribute("type") === "number";
912
- if (registerProtocol.isRegisterValue(value)) {
721
+ if (isRegisterValue(value)) {
913
722
  value.registerElement(el);
914
723
  setAssignFunction(el, vnode, value);
915
724
  }
916
725
  el._syncFromStorage = () => {
917
- if (!registerProtocol.isRegisterValue(value)) return;
726
+ if (!isRegisterValue(value)) return;
918
727
  const storage = value.innerRef.value;
919
728
  const display = storage == null ? "" : String(storage);
920
729
  if (el.value !== display) el.value = display;
@@ -936,7 +745,7 @@ const vRegisterText = {
936
745
  if (validity?.badInput === true) {
937
746
  return;
938
747
  }
939
- if (registerProtocol.isRegisterValue(value)) {
748
+ if (isRegisterValue(value)) {
940
749
  writeLastTypedForm(value, null);
941
750
  value.markBlank();
942
751
  }
@@ -945,29 +754,29 @@ const vRegisterText = {
945
754
  const typedString = domValue;
946
755
  domValue = looseToNumber(domValue);
947
756
  if (typeof domValue !== "number") {
948
- if (registerProtocol.isRegisterValue(value)) {
757
+ if (isRegisterValue(value)) {
949
758
  writeLastTypedForm(value, null);
950
759
  value.markBlank();
951
760
  }
952
761
  return;
953
762
  }
954
763
  if (!Number.isFinite(domValue)) {
955
- if (registerProtocol.isRegisterValue(value)) {
764
+ if (isRegisterValue(value)) {
956
765
  const target2 = value.displayValue.value;
957
766
  if (el.value !== target2) el.value = target2;
958
767
  }
959
768
  return;
960
769
  }
961
- if (registerProtocol.isRegisterValue(value)) writeLastTypedForm(value, typedString);
770
+ if (isRegisterValue(value)) writeLastTypedForm(value, typedString);
962
771
  }
963
- if (domValue === "" && registerProtocol.isRegisterValue(value) && !value.acceptsString && !value.acceptsUndefined) {
772
+ if (domValue === "" && isRegisterValue(value) && !value.acceptsString && !value.acceptsUndefined) {
964
773
  writeLastTypedForm(value, null);
965
774
  value.markBlank();
966
775
  return;
967
776
  }
968
- const commit = domValue === "" && registerProtocol.isRegisterValue(value) && value.acceptsUndefined ? void 0 : domValue;
777
+ const commit = domValue === "" && isRegisterValue(value) && value.acceptsUndefined ? void 0 : domValue;
969
778
  fireAssigner(el, value, commit);
970
- if (registerProtocol.isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !registerProtocol.isTransforming(value)) {
779
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
971
780
  const storage = value.innerRef.value;
972
781
  if (storage !== domValue) {
973
782
  const display = storage == null ? "" : String(storage);
@@ -985,11 +794,11 @@ const vRegisterText = {
985
794
  if (castToNumber) {
986
795
  const cast = looseToNumber(normalized);
987
796
  if (typeof cast === "number" && Number.isFinite(cast)) {
988
- if (registerProtocol.isRegisterValue(value)) writeLastTypedForm(value, null);
797
+ if (isRegisterValue(value)) writeLastTypedForm(value, null);
989
798
  el.value = String(cast);
990
799
  if (lazy !== true) fireAssigner(el, value, cast);
991
800
  } else {
992
- if (registerProtocol.isRegisterValue(value)) {
801
+ if (isRegisterValue(value)) {
993
802
  writeLastTypedForm(value, null);
994
803
  value.markBlank();
995
804
  }
@@ -1025,7 +834,7 @@ const vRegisterText = {
1025
834
  },
1026
835
  // set value on mounted so it's after min/max for type="range"
1027
836
  mounted(el, { value }) {
1028
- if (!registerProtocol.isRegisterValue(value)) return;
837
+ if (!isRegisterValue(value)) return;
1029
838
  el.value = value.displayValue.value;
1030
839
  setupValueSync(
1031
840
  el,
@@ -1040,7 +849,7 @@ const vRegisterText = {
1040
849
  beforeUpdate(el, { value, oldValue, modifiers: { lazy, trim } }, vnode) {
1041
850
  setAssignFunction(el, vnode, value);
1042
851
  if (el.composing === true) return;
1043
- if (!registerProtocol.isRegisterValue(value)) return;
852
+ if (!isRegisterValue(value)) return;
1044
853
  const target = value.displayValue.value;
1045
854
  if (el.value === target) {
1046
855
  return;
@@ -1062,11 +871,11 @@ const vRegisterCheckbox = {
1062
871
  // #4096 array checkboxes need to be deep traversed
1063
872
  deep: true,
1064
873
  created(el, { value }, vnode) {
1065
- if (!registerProtocol.isRegisterValue(value)) return;
874
+ if (!isRegisterValue(value)) return;
1066
875
  value.registerElement(el);
1067
876
  setAssignFunction(el, vnode, value);
1068
877
  el._syncFromStorage = () => {
1069
- if (!registerProtocol.isRegisterValue(value)) return;
878
+ if (!isRegisterValue(value)) return;
1070
879
  setChecked(el, value);
1071
880
  el._lastAppliedModel = value.innerRef.value;
1072
881
  };
@@ -1079,9 +888,6 @@ const vRegisterCheckbox = {
1079
888
  const checked = el.checked;
1080
889
  if (isArray(modelValue)) {
1081
890
  if (rawElementValue === void 0) {
1082
- vue.warn(
1083
- '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">.'
1084
- );
1085
891
  return;
1086
892
  }
1087
893
  const elementValue = applyElementCoerce(rawElementValue, value);
@@ -1096,9 +902,6 @@ const vRegisterCheckbox = {
1096
902
  }
1097
903
  } else if (isSet(modelValue)) {
1098
904
  if (rawElementValue === void 0) {
1099
- vue.warn(
1100
- '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">.'
1101
- );
1102
905
  return;
1103
906
  }
1104
907
  const elementValue = applyElementCoerce(rawElementValue, value);
@@ -1112,7 +915,7 @@ const vRegisterCheckbox = {
1112
915
  } else {
1113
916
  fireAssigner(el, value, getCheckboxValue(el, checked));
1114
917
  }
1115
- if (registerProtocol.isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !registerProtocol.isTransforming(value)) {
918
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1116
919
  setChecked(el, value);
1117
920
  el._lastAppliedModel = value.innerRef.value;
1118
921
  }
@@ -1121,7 +924,7 @@ const vRegisterCheckbox = {
1121
924
  // set initial checked on mount to wait for true-value/false-value
1122
925
  mounted(el, { value }) {
1123
926
  setChecked(el, value);
1124
- if (!registerProtocol.isRegisterValue(value)) return;
927
+ if (!isRegisterValue(value)) return;
1125
928
  el._lastAppliedModel = value.innerRef.value;
1126
929
  setupValueSync(el, value.innerRef, () => {
1127
930
  setChecked(el, value);
@@ -1144,7 +947,7 @@ const vRegisterCheckbox = {
1144
947
  // reference equality tracks "did the model move" exactly.
1145
948
  beforeUpdate(el, binding, vnode) {
1146
949
  setAssignFunction(el, vnode, binding.value);
1147
- if (!registerProtocol.isRegisterValue(binding.value)) return;
950
+ if (!isRegisterValue(binding.value)) return;
1148
951
  const currentModel = binding.value.innerRef.value;
1149
952
  if (el._lastAppliedModel === currentModel) return;
1150
953
  setChecked(el, binding.value);
@@ -1152,7 +955,7 @@ const vRegisterCheckbox = {
1152
955
  }
1153
956
  };
1154
957
  function setChecked(el, value) {
1155
- if (!registerProtocol.isRegisterValue(value)) return;
958
+ if (!isRegisterValue(value)) return;
1156
959
  const originalValue = value.innerRef.value;
1157
960
  let checked;
1158
961
  if (isArray(originalValue)) {
@@ -1169,11 +972,11 @@ function setChecked(el, value) {
1169
972
  }
1170
973
  const vRegisterRadio = {
1171
974
  created(el, { value }, vnode) {
1172
- if (!registerProtocol.isRegisterValue(value)) return;
975
+ if (!isRegisterValue(value)) return;
1173
976
  value.registerElement(el);
1174
977
  setAssignFunction(el, vnode, value);
1175
978
  el._syncFromStorage = () => {
1176
- if (!registerProtocol.isRegisterValue(value)) return;
979
+ if (!isRegisterValue(value)) return;
1177
980
  const currentModel = value.innerRef.value;
1178
981
  const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1179
982
  if (el.checked !== target) el.checked = target;
@@ -1183,7 +986,7 @@ const vRegisterRadio = {
1183
986
  if (shouldBailListener(el)) return;
1184
987
  noteInteraction(value);
1185
988
  fireAssigner(el, value, getValue(el));
1186
- if (registerProtocol.isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !registerProtocol.isTransforming(value)) {
989
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1187
990
  const currentModel = value.innerRef.value;
1188
991
  const target = looseEqual(currentModel, applyCoerce(getValue(el), value));
1189
992
  if (el.checked !== target) el.checked = target;
@@ -1199,7 +1002,7 @@ const vRegisterRadio = {
1199
1002
  // model. Checkbox already uses `mounted: setChecked` for the same
1200
1003
  // reason.
1201
1004
  mounted(el, { value }) {
1202
- if (!registerProtocol.isRegisterValue(value)) return;
1005
+ if (!isRegisterValue(value)) return;
1203
1006
  el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
1204
1007
  el._lastAppliedModel = value.innerRef.value;
1205
1008
  setupValueSync(el, value.innerRef, () => {
@@ -1217,7 +1020,7 @@ const vRegisterRadio = {
1217
1020
  // write triggers `beforeUpdate` mid-click and writes back the
1218
1021
  // prior model state, clobbering the in-flight selection.
1219
1022
  beforeUpdate(el, { value }, vnode) {
1220
- if (!registerProtocol.isRegisterValue(value)) return;
1023
+ if (!isRegisterValue(value)) return;
1221
1024
  setAssignFunction(el, vnode, value);
1222
1025
  const currentModel = value.innerRef.value;
1223
1026
  if (el._lastAppliedModel === currentModel) return;
@@ -1229,10 +1032,10 @@ const vRegisterSelect = {
1229
1032
  // <select multiple> value need to be deep traversed
1230
1033
  deep: true,
1231
1034
  created(el, { value, modifiers: { number } }, vnode) {
1232
- if (!registerProtocol.isRegisterValue(value)) return;
1035
+ if (!isRegisterValue(value)) return;
1233
1036
  value.registerElement(el);
1234
1037
  el._syncFromStorage = () => {
1235
- if (!registerProtocol.isRegisterValue(value)) return;
1038
+ if (!isRegisterValue(value)) return;
1236
1039
  setSelected(el, value);
1237
1040
  el._lastAppliedModel = value.innerRef.value;
1238
1041
  };
@@ -1248,11 +1051,11 @@ const vRegisterSelect = {
1248
1051
  );
1249
1052
  if (wrote !== false) {
1250
1053
  el._assigning = true;
1251
- void vue.nextTick(() => {
1054
+ void nextTick(() => {
1252
1055
  el._assigning = false;
1253
1056
  });
1254
1057
  }
1255
- if (registerProtocol.isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !registerProtocol.isTransforming(value)) {
1058
+ if (isRegisterValue(value) && isDefaultAssigner(el[assignKey]) && !isTransforming(value)) {
1256
1059
  setSelected(el, value);
1257
1060
  el._lastAppliedModel = value.innerRef.value;
1258
1061
  }
@@ -1263,7 +1066,7 @@ const vRegisterSelect = {
1263
1066
  // <option>s.
1264
1067
  mounted(el, { value }) {
1265
1068
  setSelected(el, value);
1266
- if (!registerProtocol.isRegisterValue(value)) return;
1069
+ if (!isRegisterValue(value)) return;
1267
1070
  el._lastAppliedModel = value.innerRef.value;
1268
1071
  setupValueSync(el, value.innerRef, () => {
1269
1072
  if (el._assigning === true) return;
@@ -1292,7 +1095,7 @@ const vRegisterSelect = {
1292
1095
  // DOM is already in sync from the user's click.
1293
1096
  updated(el, { value }) {
1294
1097
  if (el._assigning === true) return;
1295
- if (!registerProtocol.isRegisterValue(value)) return;
1098
+ if (!isRegisterValue(value)) return;
1296
1099
  const currentModel = value.innerRef.value;
1297
1100
  if (el._lastAppliedModel === currentModel) return;
1298
1101
  setSelected(el, value);
@@ -1300,24 +1103,14 @@ const vRegisterSelect = {
1300
1103
  }
1301
1104
  };
1302
1105
  function setSelected(el, value) {
1303
- if (!registerProtocol.isRegisterValue(value)) return;
1106
+ if (!isRegisterValue(value)) return;
1304
1107
  const externalValue = value.innerRef.value;
1305
1108
  const isMultiple = el.multiple;
1306
1109
  const isArrayValue = isArray(externalValue);
1307
1110
  if (isMultiple && !isArrayValue && !isSet(externalValue)) {
1308
- if (__DEV__) {
1309
- vue.warn(
1310
- `<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())).`
1311
- );
1312
- }
1313
1111
  return;
1314
1112
  }
1315
1113
  if (!isMultiple && (isArrayValue || isSet(externalValue))) {
1316
- if (__DEV__) {
1317
- vue.warn(
1318
- `<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.`
1319
- );
1320
- }
1321
1114
  return;
1322
1115
  }
1323
1116
  if (isMultiple) {
@@ -1360,8 +1153,6 @@ function getCheckboxValue(el, checked) {
1360
1153
  const key = checked ? "_trueValue" : "_falseValue";
1361
1154
  return key in el ? el[key] : checked;
1362
1155
  }
1363
- const warnedUnsupportedElements = __DEV__ ? /* @__PURE__ */ new WeakSet() : null;
1364
- const warnedRedundantBindings = __DEV__ ? /* @__PURE__ */ new Set() : null;
1365
1156
  const componentHostLatch = /* @__PURE__ */ new WeakMap();
1366
1157
  const hostFocusListeners = /* @__PURE__ */ new WeakMap();
1367
1158
  const hostHealObservers = /* @__PURE__ */ new WeakMap();
@@ -1411,7 +1202,7 @@ function trySupersedeHostLatch(el, rv) {
1411
1202
  return true;
1412
1203
  }
1413
1204
  function scheduleHostSelfHeal(el, rv) {
1414
- void vue.nextTick(() => {
1205
+ void nextTick(() => {
1415
1206
  if (componentHostLatch.get(el) !== null || !el.isConnected) return;
1416
1207
  if (trySupersedeHostLatch(el, rv)) return;
1417
1208
  observeForLateHostControl(el, rv);
@@ -1432,7 +1223,7 @@ function observeForLateHostControl(el, rv) {
1432
1223
  function activateComponentHost(el, rv) {
1433
1224
  if (rv.hasRegisteredDescendant(el))
1434
1225
  return;
1435
- el[registerProtocol.REGISTER_OWNER_MARKER] = true;
1226
+ el[REGISTER_OWNER_MARKER] = true;
1436
1227
  if (!el.tagName.includes("-")) {
1437
1228
  el.removeAttribute("registerValue");
1438
1229
  }
@@ -1446,43 +1237,30 @@ function activateComponentHost(el, rv) {
1446
1237
  }
1447
1238
  const vRegisterDynamic = {
1448
1239
  created(el, binding, vnode) {
1240
+ if (isRegisterValue(binding.value)) armDomBinding(binding.value);
1449
1241
  callModelHook(el, binding, vnode, null, "created");
1450
- if (registerProtocol.isRegisterValue(binding.value)) setupAria(el, binding.value, vnode);
1451
- if (__DEV__) warnRedundantStateBinding(el, binding, vnode);
1242
+ if (isRegisterValue(binding.value)) setupAria(el, binding.value, vnode);
1452
1243
  },
1453
1244
  mounted(el, binding, vnode) {
1454
1245
  callModelHook(el, binding, vnode, null, "mounted");
1455
- if (registerProtocol.isRegisterValue(binding.value) && INTERACTIVE_TAG_NAMES.has(el.tagName) && binding.modifiers[registerProtocol.SSR_COMPONENT_HOST_MODIFIER] !== true && vnode.props?.["disabled"] === void 0) {
1246
+ if (isRegisterValue(binding.value) && INTERACTIVE_TAG_NAMES.has(el.tagName) && binding.modifiers[SSR_COMPONENT_HOST_MODIFIER] !== true && vnode.props?.["disabled"] === void 0) {
1456
1247
  setupDisabledSync(el, binding.value.disabled);
1457
1248
  }
1458
- if (binding.modifiers[registerProtocol.SSR_COMPONENT_HOST_MODIFIER] === true && registerProtocol.isRegisterValue(binding.value)) {
1249
+ if (binding.modifiers[SSR_COMPONENT_HOST_MODIFIER] === true && isRegisterValue(binding.value)) {
1459
1250
  activateComponentHost(el, binding.value);
1460
1251
  }
1461
- if (__DEV__ && warnedUnsupportedElements !== null && !INTERACTIVE_TAG_NAMES.has(el.tagName) && !warnedUnsupportedElements.has(el)) {
1462
- void vue.nextTick(() => {
1463
- if (warnedUnsupportedElements.has(el)) return;
1464
- const hasMarker = el[registerProtocol.REGISTER_OWNER_MARKER] === true;
1465
- const hasUserAssigner = !isDefaultAssigner(
1466
- el[assignKey]
1467
- );
1468
- if (hasMarker || hasUserAssigner) return;
1469
- warnedUnsupportedElements.add(el);
1470
- vue.warn(
1471
- `[attaform] v-register on <${el.tagName.toLowerCase()}> is a no-op \u2014 non-input roots aren't bound to text-input semantics. For custom components: call \`useRegister()\` in the child's setup and re-bind v-register to an inner native element. Lower-level: install a custom assigner via the \`assignKey\` symbol on the element.`
1472
- );
1473
- });
1474
- }
1475
1252
  },
1476
1253
  beforeUpdate(el, binding, vnode, prevVNode) {
1254
+ if (isRegisterValue(binding.value)) armDomBinding(binding.value);
1477
1255
  syncElementRegistration(el, binding.value, binding.oldValue);
1478
1256
  callModelHook(el, binding, vnode, prevVNode, "beforeUpdate");
1479
1257
  const ariaEl = el;
1480
1258
  const value = binding.value;
1481
- if (!registerProtocol.isRegisterValue(value) || value.ariaEnabled !== true || value.ariaDisplayState === void 0) {
1259
+ if (!isRegisterValue(value) || value.ariaEnabled !== true || value.ariaDisplayState === void 0) {
1482
1260
  teardownAria(ariaEl);
1483
1261
  } else {
1484
1262
  const old = binding.oldValue;
1485
- const pathChanged = !registerProtocol.isRegisterValue(old) || old.path !== value.path;
1263
+ const pathChanged = !isRegisterValue(old) || old.path !== value.path;
1486
1264
  if (pathChanged) {
1487
1265
  teardownAria(ariaEl);
1488
1266
  setupAria(ariaEl, value, vnode);
@@ -1500,7 +1278,7 @@ const vRegisterDynamic = {
1500
1278
  teardownAria(el);
1501
1279
  teardownValueSync(el);
1502
1280
  teardownDisabledSync(el);
1503
- if (!registerProtocol.isRegisterValue(value)) return;
1281
+ if (!isRegisterValue(value)) return;
1504
1282
  value.deregisterElement(el);
1505
1283
  if (componentHostLatch.has(el)) {
1506
1284
  const healObserver = hostHealObservers.get(el);
@@ -1529,11 +1307,11 @@ const vRegisterDynamic = {
1529
1307
  // describedby matches the client after hydration.
1530
1308
  getSSRProps(binding, vnode) {
1531
1309
  const rv = binding.value;
1532
- if (!registerProtocol.isRegisterValue(rv)) return void 0;
1310
+ if (!isRegisterValue(rv)) return void 0;
1533
1311
  const realVnode = vnode ?? null;
1534
1312
  const isInteractiveElementVnode = realVnode !== null && typeof realVnode.type === "string" && INTERACTIVE_TAG_NAMES.has(realVnode.type.toUpperCase());
1535
1313
  const modifiers = binding.modifiers;
1536
- const isComponentHostModifier = modifiers?.[registerProtocol.SSR_COMPONENT_HOST_MODIFIER] === true;
1314
+ const isComponentHostModifier = modifiers?.[SSR_COMPONENT_HOST_MODIFIER] === true;
1537
1315
  const suppressHostAria = isComponentHostModifier || realVnode !== null && !isInteractiveElementVnode;
1538
1316
  const ariaProps = suppressHostAria ? void 0 : getSSRAriaProps(rv, realVnode);
1539
1317
  const formStateProps = realVnode !== null && !isComponentHostModifier ? getSSRFormStateProps(rv, realVnode) : void 0;
@@ -1550,27 +1328,6 @@ function resolveDynamicModel(tagName, type) {
1550
1328
  if (type === "radio") return vRegisterRadio;
1551
1329
  return vRegisterText;
1552
1330
  }
1553
- function warnRedundantStateBinding(el, binding, vnode) {
1554
- if (warnedRedundantBindings === null) return;
1555
- if (!INTERACTIVE_TAG_NAMES.has(el.tagName)) return;
1556
- if (binding.modifiers[registerProtocol.V_REGISTER_COMPILED_MODIFIER] === true) return;
1557
- const props = vnode.props;
1558
- if (props == null) return;
1559
- const variant = resolveDynamicModel(el.tagName, props["type"]);
1560
- if (variant === vRegisterFile) return;
1561
- const hasVModel = "onUpdate:modelValue" in props;
1562
- const stateAttr = variant === vRegisterCheckbox || variant === vRegisterRadio ? "checked" : "value";
1563
- const hasStateAttr = stateAttr in props;
1564
- if (!hasVModel && !hasStateAttr) return;
1565
- const tag = el.tagName.toLowerCase();
1566
- const redundant = hasVModel ? "v-model" : `:${stateAttr}`;
1567
- const signature = `${tag}:${String(props["type"] ?? "")}:${redundant}`;
1568
- if (warnedRedundantBindings.has(signature)) return;
1569
- warnedRedundantBindings.add(signature);
1570
- vue.warn(
1571
- `[attaform] \`${redundant}\` is redundant beside v-register on <${tag}>. v-register already drives this field's value, so keep v-register alone and drop \`${redundant}\`. (An identity \`:value\` on a radio or <option> is expected and stays silent.)`
1572
- );
1573
- }
1574
1331
  function ssrCheckboxProps(rv, props) {
1575
1332
  const model = rv.innerRef.value;
1576
1333
  const optionValue = props?.["value"];
@@ -1605,108 +1362,11 @@ function callModelHook(el, binding, vnode, prevVNode, hook) {
1605
1362
  fn?.(el, binding, vnode, prevVNode);
1606
1363
  }
1607
1364
  const vRegister = vRegisterDynamic;
1608
- vRegisterDynamic[registerProtocol.V_REGISTER_MARKER] = true;
1609
-
1610
- function installAttaformOnApp(app, options, source) {
1611
- if (app._attaform !== void 0) {
1612
- if (__DEV__ && source === "explicit") {
1613
- console.warn(
1614
- "[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(...)`."
1615
- );
1616
- }
1617
- return app._attaform;
1365
+ vRegisterDynamic[V_REGISTER_MARKER] = true;
1366
+ function installVRegister(app) {
1367
+ if (app.directive("register") === void 0) {
1368
+ app.directive("register", vRegister);
1618
1369
  }
1619
- const registry = createRegistry(options);
1620
- attachRegistryToApp(app, registry);
1621
- app.directive("register", vRegister);
1622
- if (__DEV__ && options.devtools !== false && !registry.ssr) {
1623
- void (async () => {
1624
- try {
1625
- const { setupAttaformDevtools } = await import('../chunks/devtools.cjs');
1626
- await setupAttaformDevtools(app, registry);
1627
- } catch {
1628
- }
1629
- })();
1630
- }
1631
- return registry;
1632
- }
1633
- function ensureAttaformInstalled(app) {
1634
- return installAttaformOnApp(app, {}, "lazy");
1635
1370
  }
1636
- function createAttaform(options = {}) {
1637
- const plugin = {
1638
- install(app) {
1639
- installAttaformOnApp(app, options, "explicit");
1640
- }
1641
- };
1642
- return plugin;
1643
- }
1644
-
1645
- function renderAttaformState(app) {
1646
- const registry = getRegistryFromApp(app);
1647
- const forms = [];
1648
- for (const [key, state] of registry.forms) {
1649
- const transientList = [];
1650
- for (const pk of state.blankPaths) {
1651
- const d = pathKeyToDotted(pk);
1652
- if (d !== null) transientList.push(d);
1653
- }
1654
- forms.push([
1655
- key,
1656
- {
1657
- form: state.form.value,
1658
- schemaErrors: Array.from(state.schemaErrors.entries()),
1659
- userErrors: Array.from(state.userErrors.entries()),
1660
- fields: Array.from(state.fields.entries()),
1661
- ...transientList.length > 0 ? { blankPaths: transientList } : {}
1662
- }
1663
- ]);
1664
- }
1665
- return { forms };
1666
- }
1667
- function hydrateAttaformState(app, payload) {
1668
- const registry = getRegistryFromApp(app);
1669
- for (const [key, data] of payload.forms) {
1670
- registry.pendingHydration.set(key, data);
1671
- }
1672
- }
1673
-
1674
- const DEVTOOLS_WINDOW_KEY = "__attaform_devtools__";
1675
1371
 
1676
- exports.AttaformError = AttaformError;
1677
- exports.DEVTOOLS_WINDOW_KEY = DEVTOOLS_WINDOW_KEY;
1678
- exports.INTERACTIVE_TAG_NAMES = INTERACTIVE_TAG_NAMES;
1679
- exports.InvalidPathError = InvalidPathError;
1680
- exports.InvalidUseFormConfigError = InvalidUseFormConfigError;
1681
- exports.OutsideSetupError = OutsideSetupError;
1682
- exports.ROOT_PATH = ROOT_PATH;
1683
- exports.ROOT_PATH_KEY = ROOT_PATH_KEY;
1684
- exports.RegistryNotInstalledError = RegistryNotInstalledError;
1685
- exports.ReservedFormKeyError = ReservedFormKeyError;
1686
- exports.SubmitErrorHandlerError = SubmitErrorHandlerError;
1687
- exports.__DEV__ = __DEV__;
1688
- exports.assignKey = assignKey;
1689
- exports.canonicalizePath = canonicalizePath;
1690
- exports.coerceToPathKey = coerceToPathKey;
1691
- exports.createAttaform = createAttaform;
1692
- exports.createRegistry = createRegistry;
1693
- exports.ensureAttaformInstalled = ensureAttaformInstalled;
1694
- exports.getRegistryFromApp = getRegistryFromApp;
1695
- exports.hydrateAttaformState = hydrateAttaformState;
1696
- exports.isPathPrefix = isPathPrefix;
1697
- exports.kAttaformAncestorWizard = kAttaformAncestorWizard;
1698
- exports.kAttaformRegistry = kAttaformRegistry;
1699
- exports.kAttaformWizardActiveStepResolver = kAttaformWizardActiveStepResolver;
1700
- exports.kFormContext = kFormContext;
1701
- exports.kFormInstanceId = kFormInstanceId;
1702
- exports.keyForSegments = keyForSegments;
1703
- exports.normalizeErrorInput = normalizeErrorInput;
1704
- exports.normalizeErrorInputs = normalizeErrorInputs;
1705
- exports.parseDottedPath = parseDottedPath;
1706
- exports.pathsEqual = pathsEqual;
1707
- exports.renderAttaformState = renderAttaformState;
1708
- exports.segmentsForPathKey = segmentsForPathKey;
1709
- exports.toError = toError;
1710
- exports.useRegistry = useRegistry;
1711
- exports.vRegister = vRegister;
1712
- //# sourceMappingURL=attaform.Biytrv0-.cjs.map
1372
+ export { assignKey as a, vRegisterFile as b, armDomBinding as c, installVRegister as i, vRegister as v };