attaform 0.30.1 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abstract.d.mts +5 -5
- package/dist/abstract.mjs +4 -4
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/devtools.mjs +3 -3
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +15 -2
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +1 -1
- package/dist/dev/shared/{attaform-dev.zlvDr0WB.mjs → attaform-dev.04aupFBW.mjs} +3 -2
- package/dist/dev/shared/{attaform-dev.DxHdkkPG.mjs → attaform-dev.3uTCYwy8.mjs} +770 -254
- package/dist/dev/shared/{attaform-dev.BJK1kqHY.mjs → attaform-dev.BpVGFSFa.mjs} +88 -115
- package/dist/dev/shared/{attaform-dev.Chm4D6SJ.mjs → attaform-dev.Bu6wgrA5.mjs} +3 -3
- package/dist/dev/shared/{attaform-dev.BMQ3GcgD.mjs → attaform-dev.Cbx0AiQF.mjs} +476 -337
- package/dist/dev/shared/attaform-dev.CwYTWyPX.mjs +120 -0
- package/dist/dev/shared/{attaform-dev.DuEE4GU1.mjs → attaform-dev.D7lKyM_7.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.CT7MDjPy.mjs → attaform-dev.OceE0X3v.mjs} +154 -229
- package/dist/{shared/attaform.DRsANMok.mjs → dev/shared/attaform-dev.PTGM9KE1.mjs} +16 -15
- package/dist/{shared/attaform.8mfKZCwH.mjs → dev/shared/attaform-dev.n6n00owJ.mjs} +49 -128
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +2 -2
- package/dist/directive.mjs +1 -1
- package/dist/history.d.mts +1 -1
- package/dist/history.mjs +15 -2
- package/dist/index.d.mts +16 -55
- package/dist/index.mjs +5 -5
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +3 -3
- package/dist/runtime/plugins/attaform.mjs +1 -1
- package/dist/shared/{attaform.CO918TdU.mjs → attaform.B5b-HmhH.mjs} +88 -115
- package/dist/shared/{attaform.2FslhB9R.d.mts → attaform.B9PYKlhB.d.mts} +43 -19
- package/dist/shared/{attaform.D_f1WgYf.mjs → attaform.BPMOl562.mjs} +458 -319
- package/dist/{dev/shared/attaform-dev.CZz4GYZ6.mjs → shared/attaform.BPSqtU7a.mjs} +44 -156
- package/dist/shared/{attaform.CdZIEf7_.mjs → attaform.BhtAZysa.mjs} +3 -2
- package/dist/shared/{attaform.BcQwgWaq.d.mts → attaform.CYlF4P6X.d.mts} +58 -17
- package/dist/shared/{attaform.WiGdIqgx.mjs → attaform.CdA9bfRv.mjs} +3 -3
- package/dist/shared/{attaform.BIWicztt.mjs → attaform.DAf4ehIe.mjs} +765 -251
- package/dist/shared/{attaform.ZYn2ahzJ.mjs → attaform.DBCbxlyk.mjs} +59 -1
- package/dist/shared/{attaform.L0kUn3vL.d.mts → attaform.DZOynI6c.d.mts} +1 -1
- package/dist/shared/{attaform.B2iebkPA.mjs → attaform.KEfNRDot.mjs} +4 -4
- package/dist/shared/attaform._1Zp3mDG.mjs +96 -0
- package/dist/shared/{attaform.Br8EBn5B.d.mts → attaform.i13OEHJF.d.mts} +195 -38
- package/dist/{dev/shared/attaform-dev.BUIFcTYf.mjs → shared/attaform.j9xI_ObC.mjs} +16 -15
- package/dist/shared/{attaform.D_pt1gOj.mjs → attaform.u6jfHoed.mjs} +154 -229
- package/dist/transforms.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +22 -16
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +2 -1
- package/skills/attaform/SKILL.md +2 -1
- package/skills/attaform/references/custom-components.md +4 -0
|
@@ -1,8 +1,374 @@
|
|
|
1
|
-
import { reactive, markRaw,
|
|
2
|
-
import { e as canonicalizePath } from './attaform-dev.
|
|
1
|
+
import { isRef, warn, toRaw, reactive, markRaw, effectScope, watch, nextTick } from 'vue';
|
|
2
|
+
import { e as canonicalizePath } from './attaform-dev.04aupFBW.mjs';
|
|
3
|
+
import { e as safeOwnHas } from './attaform-dev.CwYTWyPX.mjs';
|
|
4
|
+
|
|
5
|
+
function activeElementOf(node) {
|
|
6
|
+
const rootNode = node.getRootNode();
|
|
7
|
+
return rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
|
|
8
|
+
}
|
|
3
9
|
|
|
4
10
|
const INTERACTIVE_TAG_NAMES = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]);
|
|
5
11
|
|
|
12
|
+
const isArray = Array.isArray;
|
|
13
|
+
function isFunction(value) {
|
|
14
|
+
return typeof value === "function";
|
|
15
|
+
}
|
|
16
|
+
function toTypeString(value) {
|
|
17
|
+
return Object.prototype.toString.call(value);
|
|
18
|
+
}
|
|
19
|
+
function isSet(value) {
|
|
20
|
+
return toTypeString(value) === "[object Set]";
|
|
21
|
+
}
|
|
22
|
+
function isDate(value) {
|
|
23
|
+
return toTypeString(value) === "[object Date]";
|
|
24
|
+
}
|
|
25
|
+
function isSymbol(value) {
|
|
26
|
+
return typeof value === "symbol";
|
|
27
|
+
}
|
|
28
|
+
function isObject(value) {
|
|
29
|
+
return value !== null && typeof value === "object";
|
|
30
|
+
}
|
|
31
|
+
function looseToNumber(val) {
|
|
32
|
+
const n = parseFloat(val);
|
|
33
|
+
return isNaN(n) ? val : n;
|
|
34
|
+
}
|
|
35
|
+
function looseCompareArrays(a, b) {
|
|
36
|
+
if (a.length !== b.length) return false;
|
|
37
|
+
let equal = true;
|
|
38
|
+
for (let i = 0; equal && i < a.length; i++) {
|
|
39
|
+
equal = looseEqual(a[i], b[i]);
|
|
40
|
+
}
|
|
41
|
+
return equal;
|
|
42
|
+
}
|
|
43
|
+
function looseEqual(a, b) {
|
|
44
|
+
if (a === b) return true;
|
|
45
|
+
const aValidType = isDate(a);
|
|
46
|
+
const bValidType = isDate(b);
|
|
47
|
+
if (aValidType || bValidType) {
|
|
48
|
+
return aValidType && bValidType ? a.getTime() === b.getTime() : false;
|
|
49
|
+
}
|
|
50
|
+
const aSymbol = isSymbol(a);
|
|
51
|
+
const bSymbol = isSymbol(b);
|
|
52
|
+
if (aSymbol || bSymbol) return a === b;
|
|
53
|
+
const aIsArray = isArray(a);
|
|
54
|
+
const bIsArray = isArray(b);
|
|
55
|
+
if (aIsArray || bIsArray) {
|
|
56
|
+
return aIsArray && bIsArray ? looseCompareArrays(a, b) : false;
|
|
57
|
+
}
|
|
58
|
+
const aIsObject = isObject(a);
|
|
59
|
+
const bIsObject = isObject(b);
|
|
60
|
+
if (aIsObject !== bIsObject) return false;
|
|
61
|
+
if (aIsObject && bIsObject) {
|
|
62
|
+
const keysA = Object.keys(a);
|
|
63
|
+
if (keysA.length !== Object.keys(b).length) return false;
|
|
64
|
+
for (const key of keysA) {
|
|
65
|
+
const hasA = Object.prototype.hasOwnProperty.call(a, key);
|
|
66
|
+
const hasB = Object.prototype.hasOwnProperty.call(b, key);
|
|
67
|
+
if (!hasA || !hasB || !looseEqual(a[key], b[key])) return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return String(a) === String(b);
|
|
72
|
+
}
|
|
73
|
+
function looseIndexOf(arr, val) {
|
|
74
|
+
return arr.findIndex((item) => looseEqual(item, val));
|
|
75
|
+
}
|
|
76
|
+
function invokeArrayFns(fns, ...args) {
|
|
77
|
+
for (let i = 0; i < fns.length; i++) {
|
|
78
|
+
const fn = fns[i];
|
|
79
|
+
if (fn) fn(...args);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const V_REGISTER_MARKER = /* @__PURE__ */ Symbol.for("attaform:v-register-directive");
|
|
84
|
+
const REGISTER_OWNER_MARKER = /* @__PURE__ */ Symbol.for("attaform:register-owner-marker");
|
|
85
|
+
const SSR_COMPONENT_HOST_MODIFIER = "attaformComponentHost";
|
|
86
|
+
const V_REGISTER_COMPILED_MODIFIER = "attaformCompiled";
|
|
87
|
+
function isRegisterValue(val) {
|
|
88
|
+
if (typeof val !== "object" || val === null) return false;
|
|
89
|
+
if (!("innerRef" in val)) return false;
|
|
90
|
+
if (!isRef(val.innerRef)) return false;
|
|
91
|
+
if (!("registerElement" in val)) return false;
|
|
92
|
+
if (typeof val.registerElement !== "function") return false;
|
|
93
|
+
if (!("setValueWithInternalPath" in val)) return false;
|
|
94
|
+
if (typeof val.setValueWithInternalPath !== "function") return false;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
function isTransforming(value) {
|
|
98
|
+
return isRegisterValue(value) && value.transforming;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const assignKey = /* @__PURE__ */ Symbol.for("attaform:assign-key");
|
|
102
|
+
const DEFAULT_ASSIGNER_TAG = /* @__PURE__ */ Symbol.for("attaform:default-assigner-tag");
|
|
103
|
+
function isDefaultAssigner(fn) {
|
|
104
|
+
return typeof fn === "function" && fn[DEFAULT_ASSIGNER_TAG] === true;
|
|
105
|
+
}
|
|
106
|
+
const CONSUMER_WRAPPED_TAG = /* @__PURE__ */ Symbol.for("attaform:consumer-wrapped-assigner");
|
|
107
|
+
function isConsumerWrapped(fn) {
|
|
108
|
+
return typeof fn === "function" && fn[CONSUMER_WRAPPED_TAG] === true;
|
|
109
|
+
}
|
|
110
|
+
function fireAssigner(el, registerValue, value) {
|
|
111
|
+
const fn = el[assignKey];
|
|
112
|
+
if (fn === void 0) return void 0;
|
|
113
|
+
if (isDefaultAssigner(fn) || isConsumerWrapped(fn)) {
|
|
114
|
+
return fn(value);
|
|
115
|
+
}
|
|
116
|
+
if (!isRegisterValue(registerValue)) {
|
|
117
|
+
return fn(value, void 0);
|
|
118
|
+
}
|
|
119
|
+
return wrapWithTransforms(
|
|
120
|
+
value,
|
|
121
|
+
registerValue,
|
|
122
|
+
(coerced) => fn(coerced, registerValue),
|
|
123
|
+
void 0
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function isThenable(x) {
|
|
127
|
+
return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
|
|
128
|
+
}
|
|
129
|
+
function makeTransformContext() {
|
|
130
|
+
const holder = { controller: null, aborted: false };
|
|
131
|
+
const ctx = {
|
|
132
|
+
get signal() {
|
|
133
|
+
if (holder.controller === null) {
|
|
134
|
+
holder.controller = new AbortController();
|
|
135
|
+
if (holder.aborted) holder.controller.abort();
|
|
136
|
+
}
|
|
137
|
+
return holder.controller.signal;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
return { ctx, holder };
|
|
141
|
+
}
|
|
142
|
+
function runTransforms(initial, registerValue) {
|
|
143
|
+
const transforms = registerValue.transforms;
|
|
144
|
+
if (transforms === void 0 || transforms.length === 0) {
|
|
145
|
+
return { kind: "sync", ok: true, value: initial };
|
|
146
|
+
}
|
|
147
|
+
const { ctx, holder } = makeTransformContext();
|
|
148
|
+
let v = initial;
|
|
149
|
+
for (let i = 0; i < transforms.length; i++) {
|
|
150
|
+
const fn = transforms[i];
|
|
151
|
+
let out;
|
|
152
|
+
try {
|
|
153
|
+
out = fn(v, ctx);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
logTransformFailure(registerValue.path, i, fn, err);
|
|
156
|
+
return { kind: "sync", ok: false };
|
|
157
|
+
}
|
|
158
|
+
if (isThenable(out)) {
|
|
159
|
+
const rest = transforms.slice(i + 1);
|
|
160
|
+
const seed = out;
|
|
161
|
+
const run = () => rest.reduce(
|
|
162
|
+
(acc, next) => acc.then((value) => next(value, ctx)),
|
|
163
|
+
Promise.resolve(seed)
|
|
164
|
+
);
|
|
165
|
+
return { kind: "async", run, holder };
|
|
166
|
+
}
|
|
167
|
+
v = out;
|
|
168
|
+
}
|
|
169
|
+
return { kind: "sync", ok: true, value: v };
|
|
170
|
+
}
|
|
171
|
+
function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
|
|
172
|
+
const token = rv.beginTransform(holder);
|
|
173
|
+
void run().then(
|
|
174
|
+
(value) => {
|
|
175
|
+
const live = rv.isCurrentTransform(token);
|
|
176
|
+
rv.endTransform(token);
|
|
177
|
+
if (!live) return;
|
|
178
|
+
const coerced = applyCoerce(value, rv);
|
|
179
|
+
const wrote = commit(coerced);
|
|
180
|
+
if (wrote === false) rv.setTransformError(transformGateRejectedError(rv.path));
|
|
181
|
+
else syncDom?.();
|
|
182
|
+
},
|
|
183
|
+
(err) => {
|
|
184
|
+
if (rv.isCurrentTransform(token)) rv.setTransformError(toTransformError(err));
|
|
185
|
+
rv.endTransform(token);
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
function logTransformFailure(path, index, fn, err) {
|
|
190
|
+
{
|
|
191
|
+
const namePart = fn.name !== "" ? `, '${fn.name}'` : "";
|
|
192
|
+
console.error(
|
|
193
|
+
`[attaform] transform threw for path '${path}' (index ${index}${namePart}). Write aborted. Transforms must not throw; wrap your own try/catch if the throw is recoverable. Original error:`,
|
|
194
|
+
err
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function applyCoerce(value, registerValue) {
|
|
199
|
+
return registerValue.coerce !== void 0 ? registerValue.coerce(value) : value;
|
|
200
|
+
}
|
|
201
|
+
function wrapWithTransforms(value, registerValue, commit, syncDom) {
|
|
202
|
+
const r = runTransforms(value, registerValue);
|
|
203
|
+
if (r.kind === "async") {
|
|
204
|
+
kickoffAsyncTransform(registerValue, r.holder, r.run, commit, syncDom);
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (!r.ok) return false;
|
|
208
|
+
const coerced = applyCoerce(r.value, registerValue);
|
|
209
|
+
return commit(coerced);
|
|
210
|
+
}
|
|
211
|
+
function toTransformError(value) {
|
|
212
|
+
if (value instanceof Error) return value;
|
|
213
|
+
const message = typeof value === "string" && value.length > 0 ? value : `Transform rejected with a non-Error value (${typeof value})`;
|
|
214
|
+
return new Error(message, { cause: value });
|
|
215
|
+
}
|
|
216
|
+
function transformGateRejectedError(path) {
|
|
217
|
+
return new Error(
|
|
218
|
+
`[attaform] transform result for path '${path}' was rejected by the field's type gate (the resolved value did not fit the schema slot).`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const getModelAssigner = (el, vnode, registerValue) => {
|
|
222
|
+
const fn = vnode.props?.["onUpdate:registerValue"] ?? vnode.props?.["on:update:registerValue"];
|
|
223
|
+
if (isArray(fn)) {
|
|
224
|
+
const fnArr = fn.filter((x) => isFunction(x));
|
|
225
|
+
const wrapped = (value) => {
|
|
226
|
+
return wrapWithTransforms(
|
|
227
|
+
value,
|
|
228
|
+
registerValue,
|
|
229
|
+
(coerced) => {
|
|
230
|
+
invokeArrayFns(fnArr, coerced, registerValue);
|
|
231
|
+
return void 0;
|
|
232
|
+
},
|
|
233
|
+
void 0
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
wrapped[CONSUMER_WRAPPED_TAG] = true;
|
|
237
|
+
return wrapped;
|
|
238
|
+
}
|
|
239
|
+
if (isFunction(fn)) {
|
|
240
|
+
const handler = fn;
|
|
241
|
+
const wrapped = (value) => {
|
|
242
|
+
return wrapWithTransforms(
|
|
243
|
+
value,
|
|
244
|
+
registerValue,
|
|
245
|
+
(coerced) => handler(coerced, registerValue),
|
|
246
|
+
void 0
|
|
247
|
+
);
|
|
248
|
+
};
|
|
249
|
+
wrapped[CONSUMER_WRAPPED_TAG] = true;
|
|
250
|
+
return wrapped;
|
|
251
|
+
}
|
|
252
|
+
const defaultAssigner = (value) => {
|
|
253
|
+
if (value === void 0 && registerValue.acceptsUndefined) {
|
|
254
|
+
return registerValue.setValueWithInternalPath(void 0);
|
|
255
|
+
}
|
|
256
|
+
return wrapWithTransforms(
|
|
257
|
+
value,
|
|
258
|
+
registerValue,
|
|
259
|
+
(coerced) => registerValue.setValueWithInternalPath(coerced),
|
|
260
|
+
el._syncFromStorage
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
defaultAssigner[DEFAULT_ASSIGNER_TAG] = true;
|
|
264
|
+
return defaultAssigner;
|
|
265
|
+
};
|
|
266
|
+
function makeNoopAssigner() {
|
|
267
|
+
const noop = (_) => void 0;
|
|
268
|
+
noop[DEFAULT_ASSIGNER_TAG] = true;
|
|
269
|
+
return noop;
|
|
270
|
+
}
|
|
271
|
+
function setAssignFunction(el, vnode, value) {
|
|
272
|
+
const current = el[assignKey];
|
|
273
|
+
if (current !== void 0 && !isDefaultAssigner(current) && !isConsumerWrapped(current)) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (value === void 0) {
|
|
277
|
+
el[assignKey] = makeNoopAssigner();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (!isRegisterValue(value)) {
|
|
281
|
+
{
|
|
282
|
+
warn(
|
|
283
|
+
`v-register expected a RegisterValue, got '${typeof value}'. Bind to form.register('field'), not the field's ref, value, or path string.`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
el[assignKey] = makeNoopAssigner();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
el[assignKey] = getModelAssigner(el, vnode, value);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const inherited = /* @__PURE__ */ new WeakMap();
|
|
293
|
+
function recordInheritedModifiers(rv, modifiers) {
|
|
294
|
+
const lazy = modifiers.lazy === true;
|
|
295
|
+
const trim = modifiers.trim === true;
|
|
296
|
+
const number = modifiers.number === true;
|
|
297
|
+
if ((lazy || trim || number) && typeof rv === "object" && rv !== null) {
|
|
298
|
+
inherited.set(toRaw(rv), { lazy, trim, number });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function withInheritedModifiers(rv, own) {
|
|
302
|
+
const found = typeof rv === "object" && rv !== null ? inherited.get(toRaw(rv)) : void 0;
|
|
303
|
+
return found === void 0 ? own : { ...found, ...own };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function commit(rv, raw, modifiers) {
|
|
307
|
+
let value = raw;
|
|
308
|
+
if (modifiers.number === true && typeof value === "string") {
|
|
309
|
+
const cast = looseToNumber(value);
|
|
310
|
+
if (typeof cast !== "number") return rv.markBlank();
|
|
311
|
+
if (!Number.isFinite(cast)) return false;
|
|
312
|
+
value = cast;
|
|
313
|
+
}
|
|
314
|
+
if (value == null || value === "" && !rv.acceptsString) return rv.commitFromHost(value);
|
|
315
|
+
return wrapWithTransforms(value, rv, (coerced) => rv.commitFromHost(coerced), void 0) !== false;
|
|
316
|
+
}
|
|
317
|
+
function createHostChannel() {
|
|
318
|
+
const editing = /* @__PURE__ */ new Set();
|
|
319
|
+
const pending = /* @__PURE__ */ new Map();
|
|
320
|
+
const heldDraft = (rv) => {
|
|
321
|
+
const draft = pending.get(rv.path);
|
|
322
|
+
return draft?.basis === rv.innerRef.value ? draft : void 0;
|
|
323
|
+
};
|
|
324
|
+
return {
|
|
325
|
+
write(rv, value, ownModifiers) {
|
|
326
|
+
const modifiers = withInheritedModifiers(rv, ownModifiers);
|
|
327
|
+
if (modifiers.lazy === true && editing.has(rv.path)) {
|
|
328
|
+
pending.set(rv.path, { value, basis: rv.innerRef.value });
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
return commit(rv, value, modifiers);
|
|
332
|
+
},
|
|
333
|
+
writeInput(rv, payload, modifiers) {
|
|
334
|
+
if (typeof payload !== "object" || payload === null || payload instanceof Event || !("value" in payload) || !safeOwnHas(payload, "value")) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
return rv.setValueFromHost(payload.value, modifiers);
|
|
338
|
+
},
|
|
339
|
+
markEditing(rv, isEditing, modifiers) {
|
|
340
|
+
if (isEditing) {
|
|
341
|
+
editing.add(rv.path);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
editing.delete(rv.path);
|
|
345
|
+
const draft = heldDraft(rv);
|
|
346
|
+
if (pending.delete(rv.path)) {
|
|
347
|
+
if (draft !== void 0) {
|
|
348
|
+
const buffered = draft.value;
|
|
349
|
+
commit(
|
|
350
|
+
rv,
|
|
351
|
+
modifiers.trim === true && typeof buffered === "string" ? buffered.trim() : buffered,
|
|
352
|
+
modifiers
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (modifiers.trim === true) {
|
|
358
|
+
const current = rv.innerRef.value;
|
|
359
|
+
if (typeof current === "string" && current !== current.trim()) {
|
|
360
|
+
commit(rv, current.trim(), modifiers);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
holdsDraft: (rv) => heldDraft(rv) !== void 0,
|
|
365
|
+
release(rv) {
|
|
366
|
+
editing.delete(rv.path);
|
|
367
|
+
pending.delete(rv.path);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
6
372
|
const attaformListenersSymbol = /* @__PURE__ */ Symbol.for("attaform:focus-listeners");
|
|
7
373
|
const HOST_FOCUS_TARGET_SELECTOR = [
|
|
8
374
|
'input:not([type="hidden"])',
|
|
@@ -32,9 +398,7 @@ function attachFocusListeners(kernel, segments, element, instanceMeta) {
|
|
|
32
398
|
element.addEventListener("focus", handleFocus);
|
|
33
399
|
element.addEventListener("blur", handleBlur);
|
|
34
400
|
target[attaformListenersSymbol] = { handleFocus, handleBlur };
|
|
35
|
-
|
|
36
|
-
const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
|
|
37
|
-
if (activeElement === element) {
|
|
401
|
+
if (activeElementOf(element) === element) {
|
|
38
402
|
kernel.markFocused(segments, true, focusMeta);
|
|
39
403
|
}
|
|
40
404
|
}
|
|
@@ -109,133 +473,45 @@ function createDomBinding(kernel) {
|
|
|
109
473
|
host: false,
|
|
110
474
|
formInstanceId: elementToFormInstance.get(el) ?? ""
|
|
111
475
|
});
|
|
112
|
-
}
|
|
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
|
|
121
|
-
});
|
|
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;
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
elements,
|
|
142
|
-
attach,
|
|
143
|
-
detach,
|
|
144
|
-
markHostConnected,
|
|
145
|
-
getFirstErrorElement
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
function armDomBinding(value) {
|
|
149
|
-
value.ensureDomBinding?.(createDomBinding);
|
|
150
|
-
}
|
|
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;
|
|
165
|
-
}
|
|
166
|
-
function isTransforming(value) {
|
|
167
|
-
return isRegisterValue(value) && value.transforming;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const isArray = Array.isArray;
|
|
171
|
-
function isFunction(value) {
|
|
172
|
-
return typeof value === "function";
|
|
173
|
-
}
|
|
174
|
-
function toTypeString(value) {
|
|
175
|
-
return Object.prototype.toString.call(value);
|
|
176
|
-
}
|
|
177
|
-
function isSet(value) {
|
|
178
|
-
return toTypeString(value) === "[object Set]";
|
|
179
|
-
}
|
|
180
|
-
function isDate(value) {
|
|
181
|
-
return toTypeString(value) === "[object Date]";
|
|
182
|
-
}
|
|
183
|
-
function isSymbol(value) {
|
|
184
|
-
return typeof value === "symbol";
|
|
185
|
-
}
|
|
186
|
-
function isObject(value) {
|
|
187
|
-
return value !== null && typeof value === "object";
|
|
188
|
-
}
|
|
189
|
-
function looseToNumber(val) {
|
|
190
|
-
const n = parseFloat(val);
|
|
191
|
-
return isNaN(n) ? val : n;
|
|
192
|
-
}
|
|
193
|
-
function looseCompareArrays(a, b) {
|
|
194
|
-
if (a.length !== b.length) return false;
|
|
195
|
-
let equal = true;
|
|
196
|
-
for (let i = 0; equal && i < a.length; i++) {
|
|
197
|
-
equal = looseEqual(a[i], b[i]);
|
|
198
|
-
}
|
|
199
|
-
return equal;
|
|
200
|
-
}
|
|
201
|
-
function looseEqual(a, b) {
|
|
202
|
-
if (a === b) return true;
|
|
203
|
-
const aValidType = isDate(a);
|
|
204
|
-
const bValidType = isDate(b);
|
|
205
|
-
if (aValidType || bValidType) {
|
|
206
|
-
return aValidType && bValidType ? a.getTime() === b.getTime() : false;
|
|
207
|
-
}
|
|
208
|
-
const aSymbol = isSymbol(a);
|
|
209
|
-
const bSymbol = isSymbol(b);
|
|
210
|
-
if (aSymbol || bSymbol) return a === b;
|
|
211
|
-
const aIsArray = isArray(a);
|
|
212
|
-
const bIsArray = isArray(b);
|
|
213
|
-
if (aIsArray || bIsArray) {
|
|
214
|
-
return aIsArray && bIsArray ? looseCompareArrays(a, b) : false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
for (const [key, target] of hostTargets) {
|
|
479
|
+
if (elements.has(key)) continue;
|
|
480
|
+
flat.push({
|
|
481
|
+
path: target.path,
|
|
482
|
+
element: target.hostRoot,
|
|
483
|
+
host: true,
|
|
484
|
+
formInstanceId: target.formInstanceId
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
flat.sort(
|
|
488
|
+
(a, b) => a.element.compareDocumentPosition(b.element) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
|
|
489
|
+
);
|
|
490
|
+
return flat;
|
|
215
491
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
if (!hasA || !hasB || !looseEqual(a[key], b[key])) return false;
|
|
492
|
+
function getFirstErrorElement(formInstanceId) {
|
|
493
|
+
sortedRegistrationsCache ?? (sortedRegistrationsCache = rebuildSortedRegistrations());
|
|
494
|
+
for (const entry of sortedRegistrationsCache) {
|
|
495
|
+
if (entry.formInstanceId !== formInstanceId) continue;
|
|
496
|
+
if (!entry.element.isConnected) continue;
|
|
497
|
+
if (entry.element.offsetParent === null) continue;
|
|
498
|
+
if (kernel.getErrorsForPath(entry.path).length === 0) continue;
|
|
499
|
+
const element = entry.host ? resolveHostFocusTarget(entry.element) : entry.element;
|
|
500
|
+
return { path: entry.path, element };
|
|
226
501
|
}
|
|
227
|
-
return
|
|
502
|
+
return null;
|
|
228
503
|
}
|
|
229
|
-
return
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
504
|
+
return {
|
|
505
|
+
elements,
|
|
506
|
+
attach,
|
|
507
|
+
detach,
|
|
508
|
+
markHostConnected,
|
|
509
|
+
getFirstErrorElement,
|
|
510
|
+
hostChannel: createHostChannel()
|
|
511
|
+
};
|
|
233
512
|
}
|
|
234
|
-
function
|
|
235
|
-
|
|
236
|
-
const fn = fns[i];
|
|
237
|
-
if (fn) fn(...args);
|
|
238
|
-
}
|
|
513
|
+
function armDomBinding(value) {
|
|
514
|
+
return value.ensureDomBinding?.(createDomBinding);
|
|
239
515
|
}
|
|
240
516
|
|
|
241
517
|
const MANAGED_ARIA_ATTRS = [
|
|
@@ -386,197 +662,6 @@ function isRegisterValueLike(val) {
|
|
|
386
662
|
return typeof val === "object" && val !== null && "markInteracted" in val && typeof val.markInteracted === "function";
|
|
387
663
|
}
|
|
388
664
|
|
|
389
|
-
const assignKey = /* @__PURE__ */ Symbol.for("attaform:assign-key");
|
|
390
|
-
const DEFAULT_ASSIGNER_TAG = /* @__PURE__ */ Symbol.for("attaform:default-assigner-tag");
|
|
391
|
-
function isDefaultAssigner(fn) {
|
|
392
|
-
return typeof fn === "function" && fn[DEFAULT_ASSIGNER_TAG] === true;
|
|
393
|
-
}
|
|
394
|
-
const CONSUMER_WRAPPED_TAG = /* @__PURE__ */ Symbol.for("attaform:consumer-wrapped-assigner");
|
|
395
|
-
function isConsumerWrapped(fn) {
|
|
396
|
-
return typeof fn === "function" && fn[CONSUMER_WRAPPED_TAG] === true;
|
|
397
|
-
}
|
|
398
|
-
function fireAssigner(el, registerValue, value) {
|
|
399
|
-
const fn = el[assignKey];
|
|
400
|
-
if (fn === void 0) return void 0;
|
|
401
|
-
if (isDefaultAssigner(fn) || isConsumerWrapped(fn)) {
|
|
402
|
-
return fn(value);
|
|
403
|
-
}
|
|
404
|
-
if (!isRegisterValue(registerValue)) {
|
|
405
|
-
return fn(value, void 0);
|
|
406
|
-
}
|
|
407
|
-
return wrapWithTransforms(
|
|
408
|
-
value,
|
|
409
|
-
registerValue,
|
|
410
|
-
(coerced) => fn(coerced, registerValue),
|
|
411
|
-
void 0
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
function isThenable(x) {
|
|
415
|
-
return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
|
|
416
|
-
}
|
|
417
|
-
function makeTransformContext() {
|
|
418
|
-
const holder = { controller: null, aborted: false };
|
|
419
|
-
const ctx = {
|
|
420
|
-
get signal() {
|
|
421
|
-
if (holder.controller === null) {
|
|
422
|
-
holder.controller = new AbortController();
|
|
423
|
-
if (holder.aborted) holder.controller.abort();
|
|
424
|
-
}
|
|
425
|
-
return holder.controller.signal;
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
return { ctx, holder };
|
|
429
|
-
}
|
|
430
|
-
function runTransforms(initial, registerValue) {
|
|
431
|
-
const transforms = registerValue.transforms;
|
|
432
|
-
if (transforms === void 0 || transforms.length === 0) {
|
|
433
|
-
return { kind: "sync", ok: true, value: initial };
|
|
434
|
-
}
|
|
435
|
-
const { ctx, holder } = makeTransformContext();
|
|
436
|
-
let v = initial;
|
|
437
|
-
for (let i = 0; i < transforms.length; i++) {
|
|
438
|
-
const fn = transforms[i];
|
|
439
|
-
let out;
|
|
440
|
-
try {
|
|
441
|
-
out = fn(v, ctx);
|
|
442
|
-
} catch (err) {
|
|
443
|
-
logTransformFailure(registerValue.path, i, fn, err);
|
|
444
|
-
return { kind: "sync", ok: false };
|
|
445
|
-
}
|
|
446
|
-
if (isThenable(out)) {
|
|
447
|
-
const rest = transforms.slice(i + 1);
|
|
448
|
-
const seed = out;
|
|
449
|
-
const run = () => rest.reduce(
|
|
450
|
-
(acc, next) => acc.then((value) => next(value, ctx)),
|
|
451
|
-
Promise.resolve(seed)
|
|
452
|
-
);
|
|
453
|
-
return { kind: "async", run, holder };
|
|
454
|
-
}
|
|
455
|
-
v = out;
|
|
456
|
-
}
|
|
457
|
-
return { kind: "sync", ok: true, value: v };
|
|
458
|
-
}
|
|
459
|
-
function kickoffAsyncTransform(rv, holder, run, commit, syncDom) {
|
|
460
|
-
const token = rv.beginTransform(holder);
|
|
461
|
-
void run().then(
|
|
462
|
-
(value) => {
|
|
463
|
-
const live = rv.isCurrentTransform(token);
|
|
464
|
-
rv.endTransform(token);
|
|
465
|
-
if (!live) return;
|
|
466
|
-
const coerced = applyCoerce(value, rv);
|
|
467
|
-
const wrote = commit(coerced);
|
|
468
|
-
if (wrote === false) rv.setTransformError(transformGateRejectedError(rv.path));
|
|
469
|
-
else syncDom?.();
|
|
470
|
-
},
|
|
471
|
-
(err) => {
|
|
472
|
-
if (rv.isCurrentTransform(token)) rv.setTransformError(toTransformError(err));
|
|
473
|
-
rv.endTransform(token);
|
|
474
|
-
}
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
function logTransformFailure(path, index, fn, err) {
|
|
478
|
-
{
|
|
479
|
-
const namePart = fn.name !== "" ? `, '${fn.name}'` : "";
|
|
480
|
-
console.error(
|
|
481
|
-
`[attaform] transform threw for path '${path}' (index ${index}${namePart}). Write aborted. Transforms must not throw; wrap your own try/catch if the throw is recoverable. Original error:`,
|
|
482
|
-
err
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
function applyCoerce(value, registerValue) {
|
|
487
|
-
return registerValue.coerce !== void 0 ? registerValue.coerce(value) : value;
|
|
488
|
-
}
|
|
489
|
-
function wrapWithTransforms(value, registerValue, commit, syncDom) {
|
|
490
|
-
const r = runTransforms(value, registerValue);
|
|
491
|
-
if (r.kind === "async") {
|
|
492
|
-
kickoffAsyncTransform(registerValue, r.holder, r.run, commit, syncDom);
|
|
493
|
-
return true;
|
|
494
|
-
}
|
|
495
|
-
if (!r.ok) return false;
|
|
496
|
-
const coerced = applyCoerce(r.value, registerValue);
|
|
497
|
-
return commit(coerced);
|
|
498
|
-
}
|
|
499
|
-
function toTransformError(value) {
|
|
500
|
-
if (value instanceof Error) return value;
|
|
501
|
-
const message = typeof value === "string" && value.length > 0 ? value : `Transform rejected with a non-Error value (${typeof value})`;
|
|
502
|
-
return new Error(message, { cause: value });
|
|
503
|
-
}
|
|
504
|
-
function transformGateRejectedError(path) {
|
|
505
|
-
return new Error(
|
|
506
|
-
`[attaform] transform result for path '${path}' was rejected by the field's type gate (the resolved value did not fit the schema slot).`
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
const getModelAssigner = (el, vnode, registerValue) => {
|
|
510
|
-
const fn = vnode.props?.["onUpdate:registerValue"] ?? vnode.props?.["on:update:registerValue"];
|
|
511
|
-
if (isArray(fn)) {
|
|
512
|
-
const fnArr = fn.filter((x) => isFunction(x));
|
|
513
|
-
const wrapped = (value) => {
|
|
514
|
-
return wrapWithTransforms(
|
|
515
|
-
value,
|
|
516
|
-
registerValue,
|
|
517
|
-
(coerced) => {
|
|
518
|
-
invokeArrayFns(fnArr, coerced, registerValue);
|
|
519
|
-
return void 0;
|
|
520
|
-
},
|
|
521
|
-
void 0
|
|
522
|
-
);
|
|
523
|
-
};
|
|
524
|
-
wrapped[CONSUMER_WRAPPED_TAG] = true;
|
|
525
|
-
return wrapped;
|
|
526
|
-
}
|
|
527
|
-
if (isFunction(fn)) {
|
|
528
|
-
const handler = fn;
|
|
529
|
-
const wrapped = (value) => {
|
|
530
|
-
return wrapWithTransforms(
|
|
531
|
-
value,
|
|
532
|
-
registerValue,
|
|
533
|
-
(coerced) => handler(coerced, registerValue),
|
|
534
|
-
void 0
|
|
535
|
-
);
|
|
536
|
-
};
|
|
537
|
-
wrapped[CONSUMER_WRAPPED_TAG] = true;
|
|
538
|
-
return wrapped;
|
|
539
|
-
}
|
|
540
|
-
const defaultAssigner = (value) => {
|
|
541
|
-
if (value === void 0 && registerValue.acceptsUndefined) {
|
|
542
|
-
return registerValue.setValueWithInternalPath(void 0);
|
|
543
|
-
}
|
|
544
|
-
return wrapWithTransforms(
|
|
545
|
-
value,
|
|
546
|
-
registerValue,
|
|
547
|
-
(coerced) => registerValue.setValueWithInternalPath(coerced),
|
|
548
|
-
el._syncFromStorage
|
|
549
|
-
);
|
|
550
|
-
};
|
|
551
|
-
defaultAssigner[DEFAULT_ASSIGNER_TAG] = true;
|
|
552
|
-
return defaultAssigner;
|
|
553
|
-
};
|
|
554
|
-
function makeNoopAssigner() {
|
|
555
|
-
const noop = (_) => void 0;
|
|
556
|
-
noop[DEFAULT_ASSIGNER_TAG] = true;
|
|
557
|
-
return noop;
|
|
558
|
-
}
|
|
559
|
-
function setAssignFunction(el, vnode, value) {
|
|
560
|
-
const current = el[assignKey];
|
|
561
|
-
if (current !== void 0 && !isDefaultAssigner(current) && !isConsumerWrapped(current)) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
if (value === void 0) {
|
|
565
|
-
el[assignKey] = makeNoopAssigner();
|
|
566
|
-
return;
|
|
567
|
-
}
|
|
568
|
-
if (!isRegisterValue(value)) {
|
|
569
|
-
{
|
|
570
|
-
warn(
|
|
571
|
-
`v-register expected a RegisterValue, got '${typeof value}'. Bind to form.register('field'), not the field's ref, value, or path string.`
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
el[assignKey] = makeNoopAssigner();
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
el[assignKey] = getModelAssigner(el, vnode, value);
|
|
578
|
-
}
|
|
579
|
-
|
|
580
665
|
function isBlankFileValue(value) {
|
|
581
666
|
if (value === null || value === void 0) return true;
|
|
582
667
|
if (Array.isArray(value) && value.length === 0) return true;
|
|
@@ -668,11 +753,6 @@ function syncElementRegistration(el, value, oldValue) {
|
|
|
668
753
|
}
|
|
669
754
|
|
|
670
755
|
const valueSyncScopeKey = /* @__PURE__ */ Symbol.for("attaform:value-sync-scope");
|
|
671
|
-
function isElementFocused(el) {
|
|
672
|
-
const rootNode = el.getRootNode();
|
|
673
|
-
const activeElement = rootNode instanceof Document || rootNode instanceof ShadowRoot ? rootNode.activeElement : null;
|
|
674
|
-
return activeElement === el;
|
|
675
|
-
}
|
|
676
756
|
function setupValueSync(el, source, apply, options = {}) {
|
|
677
757
|
const skipWhileFocused = options.skipWhileFocused === true;
|
|
678
758
|
const scope = effectScope(true);
|
|
@@ -681,7 +761,7 @@ function setupValueSync(el, source, apply, options = {}) {
|
|
|
681
761
|
source,
|
|
682
762
|
() => {
|
|
683
763
|
if (el.composing === true) return;
|
|
684
|
-
if (skipWhileFocused &&
|
|
764
|
+
if (skipWhileFocused && activeElementOf(el) === el) return;
|
|
685
765
|
apply();
|
|
686
766
|
},
|
|
687
767
|
{ flush: "post" }
|
|
@@ -740,6 +820,28 @@ function onCompositionEnd(e) {
|
|
|
740
820
|
target.dispatchEvent(new Event("input"));
|
|
741
821
|
}
|
|
742
822
|
}
|
|
823
|
+
const heldDrafts = /* @__PURE__ */ new WeakMap();
|
|
824
|
+
function holdDraft(owner, control, stale) {
|
|
825
|
+
heldDrafts.set(owner, {
|
|
826
|
+
control,
|
|
827
|
+
text: control.value,
|
|
828
|
+
stale,
|
|
829
|
+
start: control.selectionStart,
|
|
830
|
+
end: control.selectionEnd
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
function restoreDraft(owner) {
|
|
834
|
+
const held = heldDrafts.get(owner);
|
|
835
|
+
if (held === void 0) return;
|
|
836
|
+
heldDrafts.delete(owner);
|
|
837
|
+
const { control, text, stale, start, end } = held;
|
|
838
|
+
if (control.value !== stale || stale === text) return;
|
|
839
|
+
control.value = text;
|
|
840
|
+
if (start !== null && end !== null) control.setSelectionRange(start, end);
|
|
841
|
+
}
|
|
842
|
+
function textControl(node) {
|
|
843
|
+
return node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement ? node : null;
|
|
844
|
+
}
|
|
743
845
|
const vRegisterText = {
|
|
744
846
|
created(el, { value, modifiers: { lazy, trim, number } }, vnode) {
|
|
745
847
|
const castToNumberAtCreated = number === true || vnode.props?.["type"] === "number";
|
|
@@ -862,12 +964,14 @@ const vRegisterText = {
|
|
|
862
964
|
mounted(el, { value }) {
|
|
863
965
|
if (!isRegisterValue(value)) return;
|
|
864
966
|
el.value = value.displayValue.value;
|
|
967
|
+
el._lastAppliedModel = value.innerRef.value;
|
|
865
968
|
setupValueSync(
|
|
866
969
|
el,
|
|
867
970
|
value.displayValue,
|
|
868
971
|
() => {
|
|
869
972
|
const next = value.displayValue.value;
|
|
870
973
|
if (el.value !== next) el.value = next;
|
|
974
|
+
el._lastAppliedModel = value.innerRef.value;
|
|
871
975
|
},
|
|
872
976
|
{ skipWhileFocused: true }
|
|
873
977
|
);
|
|
@@ -876,17 +980,16 @@ const vRegisterText = {
|
|
|
876
980
|
setAssignFunction(el, vnode, value);
|
|
877
981
|
if (el.composing === true) return;
|
|
878
982
|
if (!isRegisterValue(value)) return;
|
|
983
|
+
const model = value.innerRef.value;
|
|
984
|
+
const modelMoved = model !== el._lastAppliedModel || !isRegisterValue(oldValue) || oldValue.path !== value.path;
|
|
985
|
+
el._lastAppliedModel = model;
|
|
879
986
|
const target = value.displayValue.value;
|
|
880
987
|
if (el.value === target) {
|
|
881
988
|
return;
|
|
882
989
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
if (lazy === true && value.innerRef.value === oldValue) {
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
if (trim === true && el.value.trim() === target) {
|
|
990
|
+
if (activeElementOf(el) === el && el.type !== "range") {
|
|
991
|
+
if (lazy === true && !modelMoved || trim === true && el.value.trim() === target) {
|
|
992
|
+
holdDraft(el, el, target);
|
|
890
993
|
return;
|
|
891
994
|
}
|
|
892
995
|
}
|
|
@@ -1265,6 +1368,29 @@ function observeForLateHostControl(el, rv) {
|
|
|
1265
1368
|
observer.observe(el, { childList: true, subtree: true });
|
|
1266
1369
|
hostHealObservers.set(el, observer);
|
|
1267
1370
|
}
|
|
1371
|
+
const hostEdits = /* @__PURE__ */ new WeakMap();
|
|
1372
|
+
function trackHostEdits(el, rv, modifiers) {
|
|
1373
|
+
if (modifiers.lazy !== true && modifiers.trim !== true) return;
|
|
1374
|
+
if (!INTERACTIVE_TAG_NAMES.has(el.tagName) && rv.hasRegisteredDescendant(el)) return;
|
|
1375
|
+
const channel = armDomBinding(rv)?.hostChannel;
|
|
1376
|
+
if (channel === void 0) return;
|
|
1377
|
+
const edits = { channel, rv, base: void 0 };
|
|
1378
|
+
const edge = (editing) => (event) => {
|
|
1379
|
+
if (editing && !channel.holdsDraft(rv)) edits.base = textControl(event.target)?.value;
|
|
1380
|
+
const other = event.relatedTarget;
|
|
1381
|
+
if (other instanceof Node && el.contains(other)) return;
|
|
1382
|
+
channel.markEditing(rv, editing, modifiers);
|
|
1383
|
+
};
|
|
1384
|
+
addTrackedListener(el, "focus", edge(true), { capture: true });
|
|
1385
|
+
addTrackedListener(el, "blur", edge(false), { capture: true });
|
|
1386
|
+
hostEdits.set(el, edits);
|
|
1387
|
+
}
|
|
1388
|
+
function holdHostDraft(el) {
|
|
1389
|
+
const edits = hostEdits.get(el);
|
|
1390
|
+
if (edits?.base === void 0 || !edits.channel.holdsDraft(edits.rv)) return;
|
|
1391
|
+
const control = textControl(activeElementOf(el));
|
|
1392
|
+
if (control !== null && el.contains(control)) holdDraft(el, control, edits.base);
|
|
1393
|
+
}
|
|
1268
1394
|
function activateComponentHost(el, rv) {
|
|
1269
1395
|
if (rv.hasRegisteredDescendant(el)) return;
|
|
1270
1396
|
el[REGISTER_OWNER_MARKER] = true;
|
|
@@ -1279,19 +1405,26 @@ function activateComponentHost(el, rv) {
|
|
|
1279
1405
|
setupNoLatchHost(el, rv);
|
|
1280
1406
|
scheduleHostSelfHeal(el, rv);
|
|
1281
1407
|
}
|
|
1408
|
+
function inheritModifiers(binding) {
|
|
1409
|
+
const modifiers = withInheritedModifiers(binding.value, binding.modifiers);
|
|
1410
|
+
return modifiers === binding.modifiers ? binding : { ...binding, modifiers };
|
|
1411
|
+
}
|
|
1282
1412
|
const vRegisterDynamic = {
|
|
1283
|
-
created(el,
|
|
1413
|
+
created(el, ownBinding, vnode) {
|
|
1414
|
+
const binding = inheritModifiers(ownBinding);
|
|
1284
1415
|
if (isRegisterValue(binding.value)) armDomBinding(binding.value);
|
|
1285
1416
|
callModelHook(el, binding, vnode, null, "created");
|
|
1286
1417
|
if (isRegisterValue(binding.value)) setupAria(el, binding.value, vnode);
|
|
1287
1418
|
warnRedundantStateBinding(el, binding, vnode);
|
|
1288
1419
|
},
|
|
1289
|
-
mounted(el,
|
|
1420
|
+
mounted(el, ownBinding, vnode) {
|
|
1421
|
+
const binding = inheritModifiers(ownBinding);
|
|
1290
1422
|
callModelHook(el, binding, vnode, null, "mounted");
|
|
1291
1423
|
if (isRegisterValue(binding.value) && INTERACTIVE_TAG_NAMES.has(el.tagName) && binding.modifiers[SSR_COMPONENT_HOST_MODIFIER] !== true && vnode.props?.["disabled"] === void 0) {
|
|
1292
1424
|
setupDisabledSync(el, binding.value.disabled);
|
|
1293
1425
|
}
|
|
1294
1426
|
if (binding.modifiers[SSR_COMPONENT_HOST_MODIFIER] === true && isRegisterValue(binding.value)) {
|
|
1427
|
+
trackHostEdits(el, binding.value, binding.modifiers);
|
|
1295
1428
|
activateComponentHost(el, binding.value);
|
|
1296
1429
|
}
|
|
1297
1430
|
if (warnedUnsupportedElements !== null && !INTERACTIVE_TAG_NAMES.has(el.tagName) && !warnedUnsupportedElements.has(el)) {
|
|
@@ -1309,10 +1442,12 @@ const vRegisterDynamic = {
|
|
|
1309
1442
|
});
|
|
1310
1443
|
}
|
|
1311
1444
|
},
|
|
1312
|
-
beforeUpdate(el,
|
|
1445
|
+
beforeUpdate(el, ownBinding, vnode, prevVNode) {
|
|
1446
|
+
const binding = inheritModifiers(ownBinding);
|
|
1313
1447
|
if (isRegisterValue(binding.value)) armDomBinding(binding.value);
|
|
1314
1448
|
syncElementRegistration(el, binding.value, binding.oldValue);
|
|
1315
1449
|
callModelHook(el, binding, vnode, prevVNode, "beforeUpdate");
|
|
1450
|
+
holdHostDraft(el);
|
|
1316
1451
|
const ariaEl = el;
|
|
1317
1452
|
const value = binding.value;
|
|
1318
1453
|
if (!isRegisterValue(value) || value.ariaDisplayState === void 0) {
|
|
@@ -1330,13 +1465,17 @@ const vRegisterDynamic = {
|
|
|
1330
1465
|
}
|
|
1331
1466
|
},
|
|
1332
1467
|
updated(el, binding, vnode, prevVNode) {
|
|
1333
|
-
callModelHook(el, binding, vnode, prevVNode, "updated");
|
|
1468
|
+
callModelHook(el, inheritModifiers(binding), vnode, prevVNode, "updated");
|
|
1469
|
+
restoreDraft(el);
|
|
1334
1470
|
},
|
|
1335
1471
|
beforeUnmount(el, { value }) {
|
|
1336
1472
|
removeTrackedListeners(el);
|
|
1337
1473
|
teardownAria(el);
|
|
1338
1474
|
teardownValueSync(el);
|
|
1339
1475
|
teardownDisabledSync(el);
|
|
1476
|
+
const edits = hostEdits.get(el);
|
|
1477
|
+
edits?.channel.release(edits.rv);
|
|
1478
|
+
hostEdits.delete(el);
|
|
1340
1479
|
if (!isRegisterValue(value)) return;
|
|
1341
1480
|
value.deregisterElement(el);
|
|
1342
1481
|
if (componentHostLatch.has(el)) {
|
|
@@ -1449,4 +1588,4 @@ function installVRegister(app) {
|
|
|
1449
1588
|
}
|
|
1450
1589
|
}
|
|
1451
1590
|
|
|
1452
|
-
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 };
|
|
1591
|
+
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, recordInheritedModifiers as r, vRegister as v, withInheritedModifiers as w };
|