attaform 0.31.0 → 0.31.2
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 +5 -4
- package/dist/dev/abstract.mjs +5 -4
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +126 -6
- package/dist/dev/index.mjs +6 -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.CtyqGia7.mjs → attaform-dev.BKWPjEB2.mjs} +5 -4
- package/dist/dev/shared/{attaform-dev.DlaT4xGd.mjs → attaform-dev.BnLLxX2l.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.B1q-x9R9.mjs → attaform-dev.Bu6wgrA5.mjs} +1 -1
- package/dist/dev/shared/{attaform-dev.k5X47GMD.mjs → attaform-dev.CKSqs_xQ.mjs} +3 -2
- package/dist/dev/shared/{attaform-dev.DJ3nsWw6.mjs → attaform-dev.Cf_hZfbT.mjs} +18 -9
- package/dist/dev/shared/{attaform-dev.y9x9Vp9F.mjs → attaform-dev.DLk51W7-.mjs} +565 -926
- package/dist/dev/shared/attaform-dev.DoG8mZTq.mjs +127 -0
- package/dist/dev/shared/attaform-dev.G-3XDl9F.mjs +1192 -0
- package/dist/dev/shared/{attaform-dev.Caibt7sb.mjs → attaform-dev.oguHqv1W.mjs} +11 -10
- package/dist/dev/zod-v3.mjs +7 -6
- package/dist/dev/zod-v4.mjs +7 -6
- package/dist/dev/zod.mjs +6 -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 +126 -6
- package/dist/index.d.mts +16 -55
- package/dist/index.mjs +6 -5
- package/dist/runtime/plugins/attaform.mjs +1 -1
- package/dist/shared/{attaform.DL2nl_QR.mjs → attaform.3kV6PqVJ.mjs} +11 -10
- package/dist/shared/{attaform.L011tHgJ.mjs → attaform.BJeiuJE2.mjs} +4 -4
- package/dist/shared/attaform.BNUhW4qC.mjs +103 -0
- package/dist/shared/{attaform.CdZIEf7_.mjs → attaform.BhtAZysa.mjs} +3 -2
- package/dist/shared/{attaform.BWUn8Kjy.mjs → attaform.BlAmZ-WU.mjs} +18 -9
- package/dist/shared/{attaform.LUPC-2Qg.mjs → attaform.CMzc4bPI.mjs} +5 -4
- package/dist/shared/{attaform.C4shmwyJ.mjs → attaform.CdA9bfRv.mjs} +1 -1
- package/dist/shared/attaform.CgyyJVuq.mjs +1187 -0
- package/dist/shared/{attaform.DAo0QBmS.d.mts → attaform.CibLYe9-.d.mts} +214 -173
- package/dist/shared/{attaform.DNPJPOO7.mjs → attaform.DCUJCKyG.mjs} +562 -925
- package/dist/shared/{attaform.D9RqPgGu.d.mts → attaform.DCyZT7u-.d.mts} +1 -1
- package/dist/shared/{attaform.CRVe8s82.d.mts → attaform.DD0Y8krq.d.mts} +43 -19
- package/dist/shared/{attaform.DxKQsqFZ.mjs → attaform.T0YjhjPU.mjs} +3 -2
- package/dist/shared/{attaform.DZnrDrNb.d.mts → attaform.bI_4nKZp.d.mts} +119 -8
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.mjs +7 -6
- package/dist/zod-v4.d.mts +15 -11
- package/dist/zod-v4.mjs +7 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +6 -5
- package/package.json +2 -1
- package/skills/attaform/SKILL.md +1 -0
- package/dist/dev/shared/attaform-dev.CZz4GYZ6.mjs +0 -386
- package/dist/shared/attaform.8mfKZCwH.mjs +0 -358
|
@@ -0,0 +1,1192 @@
|
|
|
1
|
+
import { toRaw } from 'vue';
|
|
2
|
+
import { s as safeAssign, a as safeOwnRead, r as readConsumerIndex, c as consumerKeys, b as readConsumerProp, i as isShadowedKey, d as safeOwnHas, e as consumerHas, f as spreadConsumerRecord, g as copyConsumerArray } from './attaform-dev.DoG8mZTq.mjs';
|
|
3
|
+
import { m as mapSegmentKeys, f as pathsEqual, i as isPathPrefix, s as segmentsForPathKey, e as canonicalizePath, k as keyForSegments } from './attaform-dev.04aupFBW.mjs';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS = 0;
|
|
6
|
+
const DEFAULT_HISTORY_MAX_SNAPSHOTS = 128;
|
|
7
|
+
const RESERVED_KEY_PREFIX = "__atta:";
|
|
8
|
+
const ANONYMOUS_FORM_KEY_PREFIX = `${RESERVED_KEY_PREFIX}anon:`;
|
|
9
|
+
const ANONYMOUS_WIZARD_KEY_PREFIX = `${RESERVED_KEY_PREFIX}anon-wizard:`;
|
|
10
|
+
const DEFAULT_MAX_RECURSION_DEPTH = 64;
|
|
11
|
+
function normalizeNumericOption(config) {
|
|
12
|
+
const { value, source, min, defaultValue } = config;
|
|
13
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
14
|
+
{
|
|
15
|
+
console.warn(
|
|
16
|
+
`[attaform] ${source} must be a non-negative finite integer; got ${String(value)}. Falling back to ${String(defaultValue)}.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return defaultValue;
|
|
20
|
+
}
|
|
21
|
+
return Math.max(min, Math.floor(value));
|
|
22
|
+
}
|
|
23
|
+
function pickDefined(bag) {
|
|
24
|
+
const out = {};
|
|
25
|
+
for (const key of Object.keys(bag)) {
|
|
26
|
+
if (bag[key] !== void 0) out[key] = bag[key];
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isDescendable(value) {
|
|
32
|
+
if (value === null || typeof value !== "object") return false;
|
|
33
|
+
if (Array.isArray(value)) return true;
|
|
34
|
+
if (value instanceof Map) return mapSegmentKeys(value) !== null;
|
|
35
|
+
const proto = Object.getPrototypeOf(value);
|
|
36
|
+
return proto === null || proto === Object.prototype;
|
|
37
|
+
}
|
|
38
|
+
function isBarePatch(patch) {
|
|
39
|
+
return patch.kind === "added" ? isDescendable(patch.newValue) : patch.kind === "removed" && isDescendable(patch.oldValue);
|
|
40
|
+
}
|
|
41
|
+
function appendSegment(prefix, segment) {
|
|
42
|
+
const next = new Array(prefix.length + 1);
|
|
43
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
44
|
+
const s = prefix[i];
|
|
45
|
+
next[i] = s;
|
|
46
|
+
}
|
|
47
|
+
next[prefix.length] = segment;
|
|
48
|
+
return next;
|
|
49
|
+
}
|
|
50
|
+
function diffAndApply(oldValue, newValue, prefix, visit) {
|
|
51
|
+
if (Object.is(oldValue, newValue)) return;
|
|
52
|
+
const oldIsDescendable = isDescendable(oldValue);
|
|
53
|
+
const newIsDescendable = isDescendable(newValue);
|
|
54
|
+
if (oldValue === void 0 && newIsDescendable) {
|
|
55
|
+
walkDescendable(newValue, prefix, visit, true);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (oldIsDescendable && newValue === void 0) {
|
|
59
|
+
walkDescendable(oldValue, prefix, visit, false);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (oldIsDescendable && newIsDescendable) {
|
|
63
|
+
const oldIsMap = oldValue instanceof Map;
|
|
64
|
+
const newIsMap = newValue instanceof Map;
|
|
65
|
+
if (oldIsMap && newIsMap) {
|
|
66
|
+
diffMapsLockstep(oldValue, newValue, prefix, visit);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (oldIsMap !== newIsMap) {
|
|
70
|
+
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const oldIsArray = Array.isArray(oldValue);
|
|
74
|
+
const newIsArray = Array.isArray(newValue);
|
|
75
|
+
if (oldIsArray && newIsArray) {
|
|
76
|
+
diffArraysLockstep(oldValue, newValue, prefix, visit);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!oldIsArray && !newIsArray) {
|
|
80
|
+
diffObjectsLockstep(
|
|
81
|
+
oldValue,
|
|
82
|
+
newValue,
|
|
83
|
+
prefix,
|
|
84
|
+
visit
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (oldIsDescendable && !newIsDescendable) {
|
|
92
|
+
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!oldIsDescendable && newIsDescendable) {
|
|
96
|
+
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (oldValue === void 0) {
|
|
100
|
+
visit({ kind: "added", path: prefix, newValue });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (newValue === void 0) {
|
|
104
|
+
visit({ kind: "removed", path: prefix, oldValue });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
108
|
+
}
|
|
109
|
+
function walkDescendable(value, prefix, visit, arrived) {
|
|
110
|
+
let reported = false;
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
for (let i = 0; i < value.length; i++) {
|
|
113
|
+
diffSlot(readConsumerIndex(value, i), appendSegment(prefix, i), visit, arrived);
|
|
114
|
+
}
|
|
115
|
+
reported = value.length > 0;
|
|
116
|
+
} else if (value instanceof Map) {
|
|
117
|
+
for (const [key, entry] of value) {
|
|
118
|
+
diffSlot(entry, appendSegment(prefix, key), visit, arrived);
|
|
119
|
+
}
|
|
120
|
+
reported = value.size > 0;
|
|
121
|
+
} else {
|
|
122
|
+
const rec = value;
|
|
123
|
+
for (const k of consumerKeys(rec)) {
|
|
124
|
+
const entry = readConsumerProp(rec, k);
|
|
125
|
+
if (entry === void 0) continue;
|
|
126
|
+
reported = true;
|
|
127
|
+
if (arrived) diffAndApply(void 0, entry, appendSegment(prefix, k), visit);
|
|
128
|
+
else diffAndApply(entry, void 0, appendSegment(prefix, k), visit);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!reported) visit(presencePatch(arrived, prefix, value));
|
|
132
|
+
}
|
|
133
|
+
function diffSlot(entry, path, visit, arrived) {
|
|
134
|
+
if (entry === void 0) visit(presencePatch(arrived, path, entry));
|
|
135
|
+
else if (arrived) diffAndApply(void 0, entry, path, visit);
|
|
136
|
+
else diffAndApply(entry, void 0, path, visit);
|
|
137
|
+
}
|
|
138
|
+
function presencePatch(arrived, path, value) {
|
|
139
|
+
return arrived ? { kind: "added", path, newValue: value } : { kind: "removed", path, oldValue: value };
|
|
140
|
+
}
|
|
141
|
+
function diffMapsLockstep(oldMap, newMap, prefix, visit) {
|
|
142
|
+
for (const [key, entry] of newMap) {
|
|
143
|
+
const path = appendSegment(prefix, key);
|
|
144
|
+
if (oldMap.has(key)) diffAndApply(oldMap.get(key), entry, path, visit);
|
|
145
|
+
else diffSlot(entry, path, visit, true);
|
|
146
|
+
}
|
|
147
|
+
for (const [key, entry] of oldMap) {
|
|
148
|
+
if (!newMap.has(key)) diffSlot(entry, appendSegment(prefix, key), visit, false);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function diffArraysLockstep(oldArr, newArr, prefix, visit) {
|
|
152
|
+
const min = Math.min(oldArr.length, newArr.length);
|
|
153
|
+
for (let i = 0; i < min; i++) {
|
|
154
|
+
diffAndApply(
|
|
155
|
+
readConsumerIndex(oldArr, i),
|
|
156
|
+
readConsumerIndex(newArr, i),
|
|
157
|
+
appendSegment(prefix, i),
|
|
158
|
+
visit
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
for (let i = min; i < newArr.length; i++) {
|
|
162
|
+
diffSlot(readConsumerIndex(newArr, i), appendSegment(prefix, i), visit, true);
|
|
163
|
+
}
|
|
164
|
+
for (let i = min; i < oldArr.length; i++) {
|
|
165
|
+
diffSlot(readConsumerIndex(oldArr, i), appendSegment(prefix, i), visit, false);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function diffObjectsLockstep(oldRec, newRec, prefix, visit) {
|
|
169
|
+
const seen = /* @__PURE__ */ new Set();
|
|
170
|
+
for (const k of consumerKeys(oldRec)) {
|
|
171
|
+
seen.add(k);
|
|
172
|
+
diffAndApply(
|
|
173
|
+
readConsumerProp(oldRec, k),
|
|
174
|
+
readConsumerProp(newRec, k),
|
|
175
|
+
appendSegment(prefix, k),
|
|
176
|
+
visit
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
for (const k of consumerKeys(newRec)) {
|
|
180
|
+
if (seen.has(k)) continue;
|
|
181
|
+
diffAndApply(
|
|
182
|
+
readConsumerProp(oldRec, k),
|
|
183
|
+
readConsumerProp(newRec, k),
|
|
184
|
+
appendSegment(prefix, k),
|
|
185
|
+
visit
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function applyChangedKeys(target, source, arrayOpPath, currentPath, patches) {
|
|
190
|
+
if (!isDescendable(target) || !isDescendable(source)) return false;
|
|
191
|
+
if (target instanceof Map || source instanceof Map) return false;
|
|
192
|
+
const targetIsArray = Array.isArray(target);
|
|
193
|
+
const sourceIsArray = Array.isArray(source);
|
|
194
|
+
if (targetIsArray !== sourceIsArray) return false;
|
|
195
|
+
const depth = currentPath.length;
|
|
196
|
+
const changedFirstSegments = /* @__PURE__ */ new Set();
|
|
197
|
+
for (const patch of patches) {
|
|
198
|
+
if (patch.path.length === depth) return false;
|
|
199
|
+
changedFirstSegments.add(patch.path[depth]);
|
|
200
|
+
}
|
|
201
|
+
if (targetIsArray) {
|
|
202
|
+
const t = target;
|
|
203
|
+
const s = source;
|
|
204
|
+
if (arrayOpPath === null || pathsEqual(currentPath, arrayOpPath)) {
|
|
205
|
+
if (t.length > s.length) t.length = s.length;
|
|
206
|
+
for (const idx of changedFirstSegments) {
|
|
207
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
208
|
+
if (i >= s.length) continue;
|
|
209
|
+
t[i] = s[i];
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
for (const idx of changedFirstSegments) {
|
|
213
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
214
|
+
if (i >= s.length) continue;
|
|
215
|
+
const childPath = appendSegment(currentPath, i);
|
|
216
|
+
const curEl = t[i];
|
|
217
|
+
const nextEl = s[i];
|
|
218
|
+
if (isPathPrefix(childPath, arrayOpPath) && isDescendable(curEl) && isDescendable(nextEl) && applyChangedKeys(
|
|
219
|
+
curEl,
|
|
220
|
+
nextEl,
|
|
221
|
+
arrayOpPath,
|
|
222
|
+
childPath,
|
|
223
|
+
patches.filter((p) => isPathPrefix(childPath, p.path))
|
|
224
|
+
)) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
t[i] = nextEl;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
const t = target;
|
|
232
|
+
const s = source;
|
|
233
|
+
const sourceKeys = new Set(Object.keys(s));
|
|
234
|
+
for (const k of Object.keys(t)) {
|
|
235
|
+
if (!sourceKeys.has(k)) delete t[k];
|
|
236
|
+
}
|
|
237
|
+
for (const k of changedFirstSegments) {
|
|
238
|
+
const key = String(k);
|
|
239
|
+
const nextVal = safeOwnRead(s, key);
|
|
240
|
+
if (arrayOpPath !== null) {
|
|
241
|
+
const curVal = safeOwnRead(t, key);
|
|
242
|
+
const childPath = appendSegment(currentPath, key);
|
|
243
|
+
if (isDescendable(curVal) && isDescendable(nextVal) && applyChangedKeys(
|
|
244
|
+
curVal,
|
|
245
|
+
nextVal,
|
|
246
|
+
arrayOpPath,
|
|
247
|
+
childPath,
|
|
248
|
+
patches.filter((p) => isPathPrefix(childPath, p.path))
|
|
249
|
+
)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
safeAssign(t, key, nextVal);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
function structuralSnapshot(value) {
|
|
259
|
+
if (!isDescendable(value)) return value;
|
|
260
|
+
if (value instanceof Map) {
|
|
261
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
262
|
+
for (const [k, v] of value) out2.set(k, structuralSnapshot(v));
|
|
263
|
+
return out2;
|
|
264
|
+
}
|
|
265
|
+
if (Array.isArray(value)) {
|
|
266
|
+
const out2 = new Array(value.length);
|
|
267
|
+
for (let i = 0; i < value.length; i++) {
|
|
268
|
+
out2[i] = structuralSnapshot(value[i]);
|
|
269
|
+
}
|
|
270
|
+
return out2;
|
|
271
|
+
}
|
|
272
|
+
const src = value;
|
|
273
|
+
const out = {};
|
|
274
|
+
for (const k of Object.keys(src)) {
|
|
275
|
+
safeAssign(out, k, structuralSnapshot(safeOwnRead(src, k)));
|
|
276
|
+
}
|
|
277
|
+
return out;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const AttaformErrorCode = {
|
|
281
|
+
/** A required field is in the blank set: no value was supplied. */
|
|
282
|
+
NoValueSupplied: "atta:no-value-supplied",
|
|
283
|
+
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
284
|
+
AdapterThrew: "atta:adapter-threw",
|
|
285
|
+
/**
|
|
286
|
+
* User code inside a `z.preprocess`, `.refine`, or `.transform`
|
|
287
|
+
* threw (sync or async). The adapter caught the throw and surfaced
|
|
288
|
+
* it as a `ValidationError` at the field path so the form's normal
|
|
289
|
+
* error pipeline handles it instead of leaking as an unhandled
|
|
290
|
+
* rejection or routing through `submitError`.
|
|
291
|
+
*/
|
|
292
|
+
ValidatorThrew: "atta:validator-threw",
|
|
293
|
+
/**
|
|
294
|
+
* A function-form `defaultValues` factory threw or its promise
|
|
295
|
+
* rejected. The runtime captures the raw error on `form.hydrateError`
|
|
296
|
+
* and ALSO surfaces a form-level `ValidationError` (path `[]`) so
|
|
297
|
+
* the standard error pipeline carries the signal. Critical for the
|
|
298
|
+
* SSR round-trip: `hydrateError` itself does not ride the wire
|
|
299
|
+
* payload, but `schemaErrors` does, so the client sees the failure
|
|
300
|
+
* after rehydration without an extra channel.
|
|
301
|
+
*/
|
|
302
|
+
HydrationFailed: "atta:hydration-failed",
|
|
303
|
+
/** The supplied path didn't resolve to any node in the schema. */
|
|
304
|
+
PathNotFound: "atta:path-not-found",
|
|
305
|
+
/**
|
|
306
|
+
* A walked form's `activate()` (async `defaultValues` factory) threw
|
|
307
|
+
* during `wizard.handleSubmit`'s path walk. Surfaced as a synthetic
|
|
308
|
+
* `ValidationError` at the form-level path (`[]`) so the wizard's
|
|
309
|
+
* aggregate error pipeline can carry the failure alongside ordinary
|
|
310
|
+
* validation errors. The raw factory error remains on
|
|
311
|
+
* `form.hydrateError` for retry UX.
|
|
312
|
+
*/
|
|
313
|
+
ActivationFailed: "atta:activation-failed",
|
|
314
|
+
/**
|
|
315
|
+
* Default code stamped on a manual error set through `form.setErrors`
|
|
316
|
+
* when the caller omits an explicit `code`. The `setErrors` input is
|
|
317
|
+
* lenient (`code` optional), so this is the fallback that keeps every
|
|
318
|
+
* produced `ValidationError` carrying a stable, branchable identifier.
|
|
319
|
+
* Override it per error by passing your own `code` (`api:…`, `auth:…`).
|
|
320
|
+
*/
|
|
321
|
+
UserError: "atta:user-error",
|
|
322
|
+
/**
|
|
323
|
+
* Stamped on a `ValidationError` synthesized from a throw or rejection
|
|
324
|
+
* out of a `handleSubmit` `onSubmit` callback. The raw error also lands
|
|
325
|
+
* on `form.meta.submitError` (a raw-`Error` inspection channel); this
|
|
326
|
+
* code marks the copy piped into the user-error layer so the failure
|
|
327
|
+
* also surfaces on `form.errors` / `meta.ownErrors` / `firstOwnError`
|
|
328
|
+
* where the UI already reads. A throw carrying its own `path` / `code`
|
|
329
|
+
* keeps them; a bare `Error` or a non-Error throw defaults here at the
|
|
330
|
+
* form-level path `[]`.
|
|
331
|
+
*/
|
|
332
|
+
SubmitError: "atta:submit-error",
|
|
333
|
+
/**
|
|
334
|
+
* Synthesized by `wizard.handleSubmit` when the whole-wizard submit
|
|
335
|
+
* would otherwise succeed but a `gate()` step is still uncleared. A
|
|
336
|
+
* gate clears only on its member form's clean submit (confirmation), so
|
|
337
|
+
* a downstream step that happens to be valid-by-default must not let the
|
|
338
|
+
* wizard finish past an unconfirmed prerequisite. Emitted at the gate
|
|
339
|
+
* form's key (path `[]`) so the aggregate error pipeline routes focus to
|
|
340
|
+
* the gate, and `done` never latches.
|
|
341
|
+
*/
|
|
342
|
+
GateNotCleared: "atta:gate-not-cleared"
|
|
343
|
+
};
|
|
344
|
+
function makeBlankRequiredError(segments) {
|
|
345
|
+
return {
|
|
346
|
+
message: "No value supplied",
|
|
347
|
+
path: [...segments],
|
|
348
|
+
code: AttaformErrorCode.NoValueSupplied
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const NO_ERRORS = Object.freeze([]);
|
|
352
|
+
|
|
353
|
+
const NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
354
|
+
function mapKeyForSegment(map, segment, declared) {
|
|
355
|
+
if (map.has(segment)) return segment;
|
|
356
|
+
if (typeof segment !== "number") return segment;
|
|
357
|
+
const asString = String(segment);
|
|
358
|
+
if (map.has(asString)) return asString;
|
|
359
|
+
return declared === "string" ? asString : segment;
|
|
360
|
+
}
|
|
361
|
+
function isRebuildableContainer(root, segment) {
|
|
362
|
+
if (root === null || root === void 0 || typeof root !== "object") return true;
|
|
363
|
+
return typeof segment === "number" ? Array.isArray(root) : isPlainRecord(root);
|
|
364
|
+
}
|
|
365
|
+
function descendStep(value, segment) {
|
|
366
|
+
if (value === null || value === void 0) return NOT_FOUND;
|
|
367
|
+
if (typeof value !== "object") return NOT_FOUND;
|
|
368
|
+
if (Array.isArray(value)) {
|
|
369
|
+
if (typeof segment !== "number") return NOT_FOUND;
|
|
370
|
+
if (!(segment in value)) return NOT_FOUND;
|
|
371
|
+
return value[segment];
|
|
372
|
+
}
|
|
373
|
+
if (value instanceof Map) {
|
|
374
|
+
const key2 = mapKeyForSegment(value, segment);
|
|
375
|
+
if (!value.has(key2)) return NOT_FOUND;
|
|
376
|
+
return value.get(key2);
|
|
377
|
+
}
|
|
378
|
+
const record = value;
|
|
379
|
+
const key = typeof segment === "number" ? String(segment) : segment;
|
|
380
|
+
if (isShadowedKey(key)) {
|
|
381
|
+
if (!safeOwnHas(record, key)) return NOT_FOUND;
|
|
382
|
+
return safeOwnRead(record, key);
|
|
383
|
+
}
|
|
384
|
+
if (!(key in record)) return NOT_FOUND;
|
|
385
|
+
return record[key];
|
|
386
|
+
}
|
|
387
|
+
function getAtPath(root, path) {
|
|
388
|
+
if (path.length === 0) return root;
|
|
389
|
+
try {
|
|
390
|
+
let current = root;
|
|
391
|
+
for (const segment of path) {
|
|
392
|
+
const next = descendStep(current, segment);
|
|
393
|
+
if (next === NOT_FOUND) return void 0;
|
|
394
|
+
current = next;
|
|
395
|
+
}
|
|
396
|
+
return current;
|
|
397
|
+
} catch {
|
|
398
|
+
return void 0;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function hasAtPath(root, path) {
|
|
402
|
+
if (path.length === 0) return true;
|
|
403
|
+
try {
|
|
404
|
+
return hasAtPathUnguarded(root, path);
|
|
405
|
+
} catch {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function hasAtPathUnguarded(root, path) {
|
|
410
|
+
let current = root;
|
|
411
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
412
|
+
const segment = path[i];
|
|
413
|
+
const next = descendStep(current, segment);
|
|
414
|
+
if (next === NOT_FOUND) return false;
|
|
415
|
+
current = next;
|
|
416
|
+
}
|
|
417
|
+
const last = path[path.length - 1];
|
|
418
|
+
if (current === null || current === void 0) return false;
|
|
419
|
+
if (typeof current !== "object") return false;
|
|
420
|
+
if (Array.isArray(current)) {
|
|
421
|
+
return typeof last === "number" && consumerHas(current, last);
|
|
422
|
+
}
|
|
423
|
+
if (current instanceof Map) {
|
|
424
|
+
return current.has(mapKeyForSegment(current, last));
|
|
425
|
+
}
|
|
426
|
+
const key = typeof last === "number" ? String(last) : last;
|
|
427
|
+
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
428
|
+
return consumerHas(current, key);
|
|
429
|
+
}
|
|
430
|
+
function isPlainRecord(value) {
|
|
431
|
+
if (value === null || typeof value !== "object") return false;
|
|
432
|
+
if (Array.isArray(value)) return false;
|
|
433
|
+
const proto = Object.getPrototypeOf(value);
|
|
434
|
+
return proto === null || proto === Object.prototype;
|
|
435
|
+
}
|
|
436
|
+
const NO_SCHEMA_DEFAULTS = /* @__PURE__ */ new Set();
|
|
437
|
+
const NO_SCHEMA_FILL = {
|
|
438
|
+
getDefaultAtPath: () => void 0,
|
|
439
|
+
arrayShapeAtPath: () => null,
|
|
440
|
+
getSlimPrimitiveTypesAtPath: () => NO_SCHEMA_DEFAULTS,
|
|
441
|
+
entryKeyKindAtPath: () => void 0
|
|
442
|
+
};
|
|
443
|
+
function setAtPath(root, path, value) {
|
|
444
|
+
return setAtPathWithSchemaFill(root, NO_SCHEMA_FILL, path, value);
|
|
445
|
+
}
|
|
446
|
+
const NO_IN_PLACE = { applied: false };
|
|
447
|
+
function tryInPlaceLeafWrite(root, path, value) {
|
|
448
|
+
if (path.length === 0) return NO_IN_PLACE;
|
|
449
|
+
try {
|
|
450
|
+
return descendAndWrite(root, path, value);
|
|
451
|
+
} catch {
|
|
452
|
+
return NO_IN_PLACE;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function descendAndWrite(root, path, value) {
|
|
456
|
+
let node = root;
|
|
457
|
+
for (let i = 0; i < path.length; i++) {
|
|
458
|
+
const seg = path[i];
|
|
459
|
+
if (node instanceof Map) return NO_IN_PLACE;
|
|
460
|
+
if (Array.isArray(node)) {
|
|
461
|
+
if (typeof seg !== "number" || seg < 0 || seg >= node.length) return NO_IN_PLACE;
|
|
462
|
+
} else if (isPlainRecord(node)) {
|
|
463
|
+
if (typeof seg !== "string" || isShadowedKey(seg) || !(seg in node)) return NO_IN_PLACE;
|
|
464
|
+
} else {
|
|
465
|
+
return NO_IN_PLACE;
|
|
466
|
+
}
|
|
467
|
+
const container = node;
|
|
468
|
+
if (i < path.length - 1) {
|
|
469
|
+
node = container[seg];
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
const old = container[seg];
|
|
473
|
+
if (isPlainRecord(old) || Array.isArray(old)) return NO_IN_PLACE;
|
|
474
|
+
container[seg] = value;
|
|
475
|
+
return { applied: true, old };
|
|
476
|
+
}
|
|
477
|
+
return NO_IN_PLACE;
|
|
478
|
+
}
|
|
479
|
+
function mergeStructural(schema, path, consumer, defaultValue = schema.getDefaultAtPath(path)) {
|
|
480
|
+
const scratch = path.slice();
|
|
481
|
+
return mergeStructuralImpl(schema, scratch, consumer, defaultValue);
|
|
482
|
+
}
|
|
483
|
+
function mergeStructuralImpl(schema, scratch, consumer, defaultValue) {
|
|
484
|
+
if (consumer === void 0) {
|
|
485
|
+
if (schema.getSlimPrimitiveTypesAtPath(scratch).has("undefined")) {
|
|
486
|
+
return void 0;
|
|
487
|
+
}
|
|
488
|
+
return defaultValue;
|
|
489
|
+
}
|
|
490
|
+
if (consumer === null) return null;
|
|
491
|
+
if (Array.isArray(consumer)) {
|
|
492
|
+
return mergeStructuralArray(schema, scratch, consumer);
|
|
493
|
+
}
|
|
494
|
+
if (consumer instanceof Map) {
|
|
495
|
+
return mergeStructuralMap(schema, scratch, consumer);
|
|
496
|
+
}
|
|
497
|
+
if (isPlainRecord(consumer)) {
|
|
498
|
+
if (!isPlainRecord(defaultValue)) {
|
|
499
|
+
return consumer;
|
|
500
|
+
}
|
|
501
|
+
const out = spreadConsumerRecord(consumer);
|
|
502
|
+
const filledAny = fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out);
|
|
503
|
+
const recursedAny = recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out);
|
|
504
|
+
return filledAny || recursedAny ? out : consumer;
|
|
505
|
+
}
|
|
506
|
+
return consumer;
|
|
507
|
+
}
|
|
508
|
+
function mergeStructuralMap(schema, scratch, consumer) {
|
|
509
|
+
if (consumer.size === 0) return consumer;
|
|
510
|
+
let entryDefault;
|
|
511
|
+
let entryDefaultRead = false;
|
|
512
|
+
let out = null;
|
|
513
|
+
for (const [key, entry] of consumer) {
|
|
514
|
+
if (typeof key !== "string" && typeof key !== "number") continue;
|
|
515
|
+
scratch.push(key);
|
|
516
|
+
if (!entryDefaultRead) {
|
|
517
|
+
entryDefault = schema.getDefaultAtPath(scratch);
|
|
518
|
+
entryDefaultRead = true;
|
|
519
|
+
}
|
|
520
|
+
const merged = mergeStructuralImpl(schema, scratch, entry, entryDefault);
|
|
521
|
+
scratch.pop();
|
|
522
|
+
if (merged === entry) continue;
|
|
523
|
+
out ?? (out = new Map(consumer));
|
|
524
|
+
out.set(key, merged);
|
|
525
|
+
}
|
|
526
|
+
return out ?? consumer;
|
|
527
|
+
}
|
|
528
|
+
function mergeStructuralArray(schema, scratch, consumer) {
|
|
529
|
+
const shape = schema.arrayShapeAtPath(scratch);
|
|
530
|
+
const isTuple = typeof shape === "number";
|
|
531
|
+
const targetLen = isTuple ? shape : consumer.length;
|
|
532
|
+
let cachedElementDefault;
|
|
533
|
+
let cachedElementDefaultRead = false;
|
|
534
|
+
let mutated = targetLen > consumer.length;
|
|
535
|
+
const out = copyConsumerArray(consumer);
|
|
536
|
+
while (out.length < targetLen) out.push(void 0);
|
|
537
|
+
for (let i = 0; i < targetLen; i++) {
|
|
538
|
+
scratch.push(i);
|
|
539
|
+
let elemDefault;
|
|
540
|
+
if (isTuple) {
|
|
541
|
+
elemDefault = schema.getDefaultAtPath(scratch);
|
|
542
|
+
} else {
|
|
543
|
+
if (!cachedElementDefaultRead) {
|
|
544
|
+
cachedElementDefault = schema.getDefaultAtPath(scratch);
|
|
545
|
+
cachedElementDefaultRead = true;
|
|
546
|
+
}
|
|
547
|
+
elemDefault = cachedElementDefault;
|
|
548
|
+
}
|
|
549
|
+
const consumerElem = i < consumer.length ? readConsumerIndex(consumer, i) : void 0;
|
|
550
|
+
const merged = mergeStructuralImpl(schema, scratch, consumerElem, elemDefault);
|
|
551
|
+
scratch.pop();
|
|
552
|
+
if (merged !== consumerElem) {
|
|
553
|
+
out[i] = merged;
|
|
554
|
+
mutated = true;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return mutated ? out : consumer;
|
|
558
|
+
}
|
|
559
|
+
function fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out) {
|
|
560
|
+
let mutated = false;
|
|
561
|
+
for (const key of Object.keys(defaultValue)) {
|
|
562
|
+
if (!safeOwnHas(consumer, key)) {
|
|
563
|
+
const defAtKey = safeOwnRead(defaultValue, key);
|
|
564
|
+
scratch.push(key);
|
|
565
|
+
const filled = mergeStructuralImpl(schema, scratch, void 0, defAtKey);
|
|
566
|
+
scratch.pop();
|
|
567
|
+
if (filled !== void 0) {
|
|
568
|
+
safeAssign(out, key, filled);
|
|
569
|
+
mutated = true;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return mutated;
|
|
574
|
+
}
|
|
575
|
+
function recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out) {
|
|
576
|
+
let mutated = false;
|
|
577
|
+
for (const key of consumerKeys(consumer)) {
|
|
578
|
+
const cVal = safeOwnRead(consumer, key);
|
|
579
|
+
if (cVal === void 0) continue;
|
|
580
|
+
scratch.push(key);
|
|
581
|
+
const merged = mergeStructuralImpl(schema, scratch, cVal, safeOwnRead(defaultValue, key));
|
|
582
|
+
scratch.pop();
|
|
583
|
+
if (merged !== cVal) {
|
|
584
|
+
safeAssign(out, key, merged);
|
|
585
|
+
mutated = true;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return mutated;
|
|
589
|
+
}
|
|
590
|
+
function setAtPathWithSchemaFill(root, schema, fullPath, value) {
|
|
591
|
+
if (fullPath.length === 0) return value;
|
|
592
|
+
return setAtPathWithSchemaFillImpl(root, schema, fullPath, value, 0);
|
|
593
|
+
}
|
|
594
|
+
function setAtPathWithSchemaFillImpl(root, schema, fullPath, value, startIdx) {
|
|
595
|
+
if (startIdx >= fullPath.length) return value;
|
|
596
|
+
const head = fullPath[startIdx];
|
|
597
|
+
const isLeafStep = startIdx === fullPath.length - 1;
|
|
598
|
+
if (root instanceof Map) {
|
|
599
|
+
const next = new Map(root);
|
|
600
|
+
const key = mapKeyForSegment(root, head, schema.entryKeyKindAtPath(fullPath.slice(0, startIdx)));
|
|
601
|
+
if (isLeafStep) {
|
|
602
|
+
next.set(key, value);
|
|
603
|
+
return next;
|
|
604
|
+
}
|
|
605
|
+
let childRoot2 = next.get(key);
|
|
606
|
+
if (childRoot2 === void 0 || childRoot2 !== null && typeof childRoot2 !== "object") {
|
|
607
|
+
childRoot2 = schema.getDefaultAtPath(fullPath.slice(0, startIdx + 1));
|
|
608
|
+
}
|
|
609
|
+
next.set(key, setAtPathWithSchemaFillImpl(childRoot2, schema, fullPath, value, startIdx + 1));
|
|
610
|
+
return next;
|
|
611
|
+
}
|
|
612
|
+
if (!isRebuildableContainer(root, head)) return root;
|
|
613
|
+
if (typeof head === "number") {
|
|
614
|
+
const arr = Array.isArray(root) ? [...root] : [];
|
|
615
|
+
const prefix = fullPath.slice(0, startIdx);
|
|
616
|
+
if (arr.length < head) {
|
|
617
|
+
const scratch = prefix.slice();
|
|
618
|
+
const shape = schema.arrayShapeAtPath(scratch);
|
|
619
|
+
const tupleLike = typeof shape === "number";
|
|
620
|
+
let cachedArrayDefault;
|
|
621
|
+
if (!tupleLike) {
|
|
622
|
+
scratch.push(0);
|
|
623
|
+
cachedArrayDefault = schema.getDefaultAtPath(scratch);
|
|
624
|
+
scratch.pop();
|
|
625
|
+
}
|
|
626
|
+
while (arr.length < head) {
|
|
627
|
+
const idx = arr.length;
|
|
628
|
+
if (tupleLike) {
|
|
629
|
+
scratch.push(idx);
|
|
630
|
+
arr.push(schema.getDefaultAtPath(scratch));
|
|
631
|
+
scratch.pop();
|
|
632
|
+
} else {
|
|
633
|
+
arr.push(cachedArrayDefault);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (isLeafStep) {
|
|
638
|
+
arr[head] = value;
|
|
639
|
+
return arr;
|
|
640
|
+
}
|
|
641
|
+
let childRoot2 = arr[head];
|
|
642
|
+
if (childRoot2 === void 0 || childRoot2 !== null && typeof childRoot2 !== "object") {
|
|
643
|
+
childRoot2 = schema.getDefaultAtPath([...prefix, head]);
|
|
644
|
+
}
|
|
645
|
+
arr[head] = setAtPathWithSchemaFillImpl(childRoot2, schema, fullPath, value, startIdx + 1);
|
|
646
|
+
return arr;
|
|
647
|
+
}
|
|
648
|
+
const rec = isPlainRecord(root) ? { ...root } : {};
|
|
649
|
+
if (isLeafStep) {
|
|
650
|
+
safeAssign(rec, head, value);
|
|
651
|
+
return rec;
|
|
652
|
+
}
|
|
653
|
+
const existing = safeOwnRead(rec, head);
|
|
654
|
+
let childRoot;
|
|
655
|
+
if (existing === void 0 || existing !== null && typeof existing !== "object") {
|
|
656
|
+
const intermPath = [...fullPath.slice(0, startIdx + 1)];
|
|
657
|
+
const intermDefault = schema.getDefaultAtPath(intermPath);
|
|
658
|
+
childRoot = intermDefault;
|
|
659
|
+
} else {
|
|
660
|
+
childRoot = existing;
|
|
661
|
+
}
|
|
662
|
+
safeAssign(
|
|
663
|
+
rec,
|
|
664
|
+
head,
|
|
665
|
+
setAtPathWithSchemaFillImpl(childRoot, schema, fullPath, value, startIdx + 1)
|
|
666
|
+
);
|
|
667
|
+
return rec;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function remapForOp(op, oldLen) {
|
|
671
|
+
const moved = /* @__PURE__ */ new Map();
|
|
672
|
+
const vacated = /* @__PURE__ */ new Set();
|
|
673
|
+
const fresh = /* @__PURE__ */ new Set();
|
|
674
|
+
let newLen = oldLen;
|
|
675
|
+
switch (op.kind) {
|
|
676
|
+
case "insert":
|
|
677
|
+
for (let i = op.index; i < oldLen; i++) moved.set(i, i + 1);
|
|
678
|
+
fresh.add(op.index);
|
|
679
|
+
newLen = oldLen + 1;
|
|
680
|
+
break;
|
|
681
|
+
case "remove":
|
|
682
|
+
vacated.add(op.index);
|
|
683
|
+
for (let i = op.index + 1; i < oldLen; i++) moved.set(i, i - 1);
|
|
684
|
+
newLen = Math.max(0, oldLen - 1);
|
|
685
|
+
break;
|
|
686
|
+
case "move":
|
|
687
|
+
if (op.from !== op.to) {
|
|
688
|
+
moved.set(op.from, op.to);
|
|
689
|
+
if (op.from < op.to) {
|
|
690
|
+
for (let i = op.from + 1; i <= op.to; i++) moved.set(i, i - 1);
|
|
691
|
+
} else {
|
|
692
|
+
for (let i = op.to; i < op.from; i++) moved.set(i, i + 1);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
break;
|
|
696
|
+
case "swap":
|
|
697
|
+
if (op.a !== op.b) {
|
|
698
|
+
moved.set(op.a, op.b);
|
|
699
|
+
moved.set(op.b, op.a);
|
|
700
|
+
}
|
|
701
|
+
break;
|
|
702
|
+
case "replace-at":
|
|
703
|
+
vacated.add(op.index);
|
|
704
|
+
fresh.add(op.index);
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
return { moved, vacated, fresh, oldLen, newLen };
|
|
708
|
+
}
|
|
709
|
+
function changedIndices(remap) {
|
|
710
|
+
const changed = new Set(remap.vacated);
|
|
711
|
+
for (const [from, to] of remap.moved) {
|
|
712
|
+
changed.add(from);
|
|
713
|
+
changed.add(to);
|
|
714
|
+
}
|
|
715
|
+
for (const index of remap.fresh) changed.add(index);
|
|
716
|
+
return changed;
|
|
717
|
+
}
|
|
718
|
+
function permuteList(list, remap, fill) {
|
|
719
|
+
const claimed = new Array(remap.newLen);
|
|
720
|
+
for (let i = 0; i < remap.oldLen; i++) {
|
|
721
|
+
if (remap.vacated.has(i)) continue;
|
|
722
|
+
const to = remap.moved.get(i) ?? i;
|
|
723
|
+
if (to < remap.newLen) claimed[to] = list[i];
|
|
724
|
+
}
|
|
725
|
+
const next = [];
|
|
726
|
+
for (let i = 0; i < remap.newLen; i++) {
|
|
727
|
+
next.push(claimed[i] ?? fill());
|
|
728
|
+
}
|
|
729
|
+
return next;
|
|
730
|
+
}
|
|
731
|
+
function elementIndexAfter(key, head) {
|
|
732
|
+
if (!key.startsWith(head)) return null;
|
|
733
|
+
let index = 0;
|
|
734
|
+
let at = head.length;
|
|
735
|
+
for (let code = key.charCodeAt(at); code >= 48 && code <= 57; code = key.charCodeAt(++at)) {
|
|
736
|
+
index = index * 10 + code - 48;
|
|
737
|
+
}
|
|
738
|
+
return at > head.length ? index : null;
|
|
739
|
+
}
|
|
740
|
+
function collectKeysAtIndices(keys, arrayPath, member) {
|
|
741
|
+
const { key: arrayKey } = keyForSegments(arrayPath);
|
|
742
|
+
const head = arrayPath.length === 0 ? "[" : `${arrayKey.slice(0, -1)},`;
|
|
743
|
+
const hits = [];
|
|
744
|
+
for (const key of keys) {
|
|
745
|
+
const index = elementIndexAfter(key, head);
|
|
746
|
+
if (index === null || !member(index)) continue;
|
|
747
|
+
const segments = segmentsForPathKey(key);
|
|
748
|
+
if (segments === null) continue;
|
|
749
|
+
hits.push({ key, segments: [...segments], index });
|
|
750
|
+
}
|
|
751
|
+
return hits;
|
|
752
|
+
}
|
|
753
|
+
function remapAffects(remap) {
|
|
754
|
+
return (index) => remap.moved.has(index) || remap.vacated.has(index) || remap.fresh.has(index);
|
|
755
|
+
}
|
|
756
|
+
function migrateMapSubtree(map, arrayPath, remap, rewriteValue) {
|
|
757
|
+
relocateHits(
|
|
758
|
+
map,
|
|
759
|
+
collectKeysAtIndices(toRaw(map).keys(), arrayPath, remapAffects(remap)),
|
|
760
|
+
arrayPath,
|
|
761
|
+
remap,
|
|
762
|
+
rewriteValue
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
function relocateHits(map, hits, arrayPath, remap, rewriteValue) {
|
|
766
|
+
if (hits.length === 0) return;
|
|
767
|
+
const idxPos = arrayPath.length;
|
|
768
|
+
const snapshots = [];
|
|
769
|
+
const raw = toRaw(map);
|
|
770
|
+
for (const hit of hits) {
|
|
771
|
+
const value = raw.get(hit.key);
|
|
772
|
+
if (value !== void 0) snapshots.push({ ...hit, value });
|
|
773
|
+
}
|
|
774
|
+
for (const snap of snapshots) map.delete(snap.key);
|
|
775
|
+
for (const snap of snapshots) {
|
|
776
|
+
const target = remap.moved.get(snap.index);
|
|
777
|
+
if (target === void 0) continue;
|
|
778
|
+
const relocated = snap.segments.slice();
|
|
779
|
+
relocated[idxPos] = target;
|
|
780
|
+
map.set(canonicalizePath(relocated).key, rewriteValue(snap.value, relocated));
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
function migrateSetSubtree(set, arrayPath, remap) {
|
|
784
|
+
const hits = collectKeysAtIndices(toRaw(set), arrayPath, remapAffects(remap));
|
|
785
|
+
if (hits.length === 0) return;
|
|
786
|
+
const idxPos = arrayPath.length;
|
|
787
|
+
for (const hit of hits) set.delete(hit.key);
|
|
788
|
+
for (const hit of hits) {
|
|
789
|
+
const target = remap.moved.get(hit.index);
|
|
790
|
+
if (target === void 0) continue;
|
|
791
|
+
const relocated = hit.segments.slice();
|
|
792
|
+
relocated[idxPos] = target;
|
|
793
|
+
set.add(canonicalizePath(relocated).key);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function evictSchemaVerdictsAtIndices(errorCells, arrayPath, indices) {
|
|
797
|
+
const raw = toRaw(errorCells);
|
|
798
|
+
for (const hit of collectKeysAtIndices(raw.keys(), arrayPath, (index) => indices.has(index))) {
|
|
799
|
+
const cell = raw.get(hit.key);
|
|
800
|
+
if (cell === void 0) continue;
|
|
801
|
+
if (cell.user.length === 0) errorCells.delete(hit.key);
|
|
802
|
+
else if (cell.schema.length > 0) errorCells.set(hit.key, { schema: NO_ERRORS, user: cell.user });
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
function deleteKeysAtIndices(keys, del, arrayPath, indices) {
|
|
806
|
+
for (const hit of collectKeysAtIndices(keys, arrayPath, (index) => indices.has(index))) {
|
|
807
|
+
del(hit.key);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function createArrayIdentity(getArrayLength, onChange) {
|
|
811
|
+
const tokens = /* @__PURE__ */ new Map();
|
|
812
|
+
const baselines = /* @__PURE__ */ new Map();
|
|
813
|
+
const baselineSlots = /* @__PURE__ */ new WeakMap();
|
|
814
|
+
let counter = 0;
|
|
815
|
+
const allocate = () => `k${(counter++).toString(36)}`;
|
|
816
|
+
function ensure(arrayKey, expectedLen) {
|
|
817
|
+
let ids = tokens.get(arrayKey);
|
|
818
|
+
const firstTrack = ids === void 0;
|
|
819
|
+
if (ids === void 0) {
|
|
820
|
+
ids = [];
|
|
821
|
+
tokens.set(arrayKey, ids);
|
|
822
|
+
}
|
|
823
|
+
if (ids.length < expectedLen) {
|
|
824
|
+
const baseline = baselines.get(arrayKey);
|
|
825
|
+
while (ids.length < expectedLen) {
|
|
826
|
+
const anchored = baseline?.[ids.length];
|
|
827
|
+
ids.push(anchored !== void 0 && !ids.includes(anchored) ? anchored : allocate());
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if (ids.length > expectedLen) ids.length = expectedLen;
|
|
831
|
+
if (firstTrack) baselines.set(arrayKey, [...ids]);
|
|
832
|
+
return ids;
|
|
833
|
+
}
|
|
834
|
+
function orderPristineForKey(arrayKey) {
|
|
835
|
+
const baseline = baselines.get(arrayKey);
|
|
836
|
+
const current = tokens.get(arrayKey);
|
|
837
|
+
if (baseline === void 0 || current === void 0) return true;
|
|
838
|
+
if (baseline.length !== current.length) return false;
|
|
839
|
+
for (let i = 0; i < current.length; i++) {
|
|
840
|
+
if (current[i] !== baseline[i]) return false;
|
|
841
|
+
}
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
tokenAt(arraySegs, index) {
|
|
846
|
+
const len = getArrayLength(arraySegs);
|
|
847
|
+
if (index < 0 || index >= len) return "";
|
|
848
|
+
const ids = ensure(canonicalizePath(arraySegs).key, len);
|
|
849
|
+
return ids[index] ?? "";
|
|
850
|
+
},
|
|
851
|
+
baselineIndexOf(arraySegs, index) {
|
|
852
|
+
const len = getArrayLength(arraySegs);
|
|
853
|
+
if (index < 0 || index >= len) return -1;
|
|
854
|
+
const arrayKey = canonicalizePath(arraySegs).key;
|
|
855
|
+
const token = ensure(arrayKey, len)[index];
|
|
856
|
+
const baseline = baselines.get(arrayKey);
|
|
857
|
+
if (token === void 0 || baseline === void 0) return -1;
|
|
858
|
+
let slots = baselineSlots.get(baseline);
|
|
859
|
+
if (slots === void 0) {
|
|
860
|
+
slots = new Map(baseline.map((id, i) => [id, i]));
|
|
861
|
+
baselineSlots.set(baseline, slots);
|
|
862
|
+
}
|
|
863
|
+
return slots.get(token) ?? -1;
|
|
864
|
+
},
|
|
865
|
+
applyOp(arraySegs, remap) {
|
|
866
|
+
const arrayKey = canonicalizePath(arraySegs).key;
|
|
867
|
+
const ids = ensure(arrayKey, remap.oldLen);
|
|
868
|
+
tokens.set(arrayKey, permuteList(ids, remap, allocate));
|
|
869
|
+
onChange([arraySegs]);
|
|
870
|
+
},
|
|
871
|
+
applyRemap(arrayPath, remap) {
|
|
872
|
+
if (remap.moved.size === 0 && remap.vacated.size === 0 && remap.fresh.size === 0) return;
|
|
873
|
+
const moved = [];
|
|
874
|
+
for (const hit of collectKeysAtIndices(tokens.keys(), arrayPath, remapAffects(remap))) {
|
|
875
|
+
moved.push(hit.segments);
|
|
876
|
+
}
|
|
877
|
+
migrateMapSubtree(tokens, arrayPath, remap, (value, segments) => {
|
|
878
|
+
moved.push(segments);
|
|
879
|
+
return value;
|
|
880
|
+
});
|
|
881
|
+
migrateMapSubtree(baselines, arrayPath, remap, (value) => value);
|
|
882
|
+
if (moved.length > 0) onChange(moved);
|
|
883
|
+
},
|
|
884
|
+
realign(arraySegs) {
|
|
885
|
+
ensure(canonicalizePath(arraySegs).key, getArrayLength(arraySegs));
|
|
886
|
+
},
|
|
887
|
+
realignContaining(paths) {
|
|
888
|
+
if (tokens.size === 0 || paths.length === 0) return;
|
|
889
|
+
const resized = [];
|
|
890
|
+
for (const [arrayKey, ids] of tokens) {
|
|
891
|
+
const segs = segmentsForPathKey(arrayKey);
|
|
892
|
+
if (segs === null || !paths.some((path) => isPathPrefix(segs, path) || isPathPrefix(path, segs))) {
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
const len = getArrayLength(segs);
|
|
896
|
+
if (ids.length === len) continue;
|
|
897
|
+
ensure(arrayKey, len);
|
|
898
|
+
resized.push(segs);
|
|
899
|
+
}
|
|
900
|
+
if (resized.length > 0) onChange(resized);
|
|
901
|
+
},
|
|
902
|
+
hasStructuralChangeUnder(prefix) {
|
|
903
|
+
for (const arrayKey of tokens.keys()) {
|
|
904
|
+
if (orderPristineForKey(arrayKey)) continue;
|
|
905
|
+
const segs = segmentsForPathKey(arrayKey);
|
|
906
|
+
if (segs === null) continue;
|
|
907
|
+
if (isPathPrefix(prefix, segs)) return true;
|
|
908
|
+
}
|
|
909
|
+
return false;
|
|
910
|
+
},
|
|
911
|
+
rebaseline(covers) {
|
|
912
|
+
const rebased = [];
|
|
913
|
+
for (const arrayKey of [...tokens.keys()]) {
|
|
914
|
+
const segs = segmentsForPathKey(arrayKey);
|
|
915
|
+
if (segs === null || !covers(segs)) continue;
|
|
916
|
+
const ids = ensure(arrayKey, getArrayLength(segs));
|
|
917
|
+
baselines.set(arrayKey, [...ids]);
|
|
918
|
+
rebased.push(segs);
|
|
919
|
+
}
|
|
920
|
+
if (rebased.length > 0) onChange(rebased);
|
|
921
|
+
},
|
|
922
|
+
snapshot() {
|
|
923
|
+
return { tokens: copyLists(tokens), baselines: copyLists(baselines) };
|
|
924
|
+
},
|
|
925
|
+
restore(orders) {
|
|
926
|
+
const keys = /* @__PURE__ */ new Set([...tokens.keys(), ...orders.tokens.keys()]);
|
|
927
|
+
tokens.clear();
|
|
928
|
+
for (const [key, ids] of orders.tokens) tokens.set(key, [...ids]);
|
|
929
|
+
baselines.clear();
|
|
930
|
+
for (const [key, ids] of orders.baselines) baselines.set(key, [...ids]);
|
|
931
|
+
const restored = [];
|
|
932
|
+
for (const key of keys) {
|
|
933
|
+
const segs = segmentsForPathKey(key);
|
|
934
|
+
if (segs !== null) restored.push(segs);
|
|
935
|
+
}
|
|
936
|
+
if (restored.length > 0) onChange(restored);
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
function migrateFieldRecords(fields, arrayPath, remap, release) {
|
|
941
|
+
const raw = toRaw(fields);
|
|
942
|
+
const hits = collectKeysAtIndices(raw.keys(), arrayPath, remapAffects(remap));
|
|
943
|
+
if (remap.vacated.size > 0) {
|
|
944
|
+
const released = [];
|
|
945
|
+
for (const { key, index } of hits) {
|
|
946
|
+
const record = remap.vacated.has(index) ? raw.get(key) : void 0;
|
|
947
|
+
if (record !== void 0) released.push(record);
|
|
948
|
+
}
|
|
949
|
+
release(arrayPath, released);
|
|
950
|
+
}
|
|
951
|
+
relocateHits(fields, hits, arrayPath, remap, (record, segments) => ({
|
|
952
|
+
...record,
|
|
953
|
+
path: segments
|
|
954
|
+
}));
|
|
955
|
+
}
|
|
956
|
+
function copyLists(lists) {
|
|
957
|
+
const out = /* @__PURE__ */ new Map();
|
|
958
|
+
for (const [key, ids] of lists) out.set(key, [...ids]);
|
|
959
|
+
return out;
|
|
960
|
+
}
|
|
961
|
+
function createVariantMemory() {
|
|
962
|
+
const memory = /* @__PURE__ */ new Map();
|
|
963
|
+
return {
|
|
964
|
+
clear() {
|
|
965
|
+
memory.clear();
|
|
966
|
+
},
|
|
967
|
+
clearUnderPath(parentPath) {
|
|
968
|
+
for (const memKey of [...memory.keys()]) {
|
|
969
|
+
const segs = segmentsForPathKey(memKey);
|
|
970
|
+
if (segs === null) continue;
|
|
971
|
+
if (isPathPrefix(parentPath, segs)) memory.delete(memKey);
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
dropAtIndices(arrayPath, indices) {
|
|
975
|
+
deleteKeysAtIndices([...memory.keys()], (key) => memory.delete(key), arrayPath, indices);
|
|
976
|
+
},
|
|
977
|
+
recordOutgoing(unionKey, discValue, snapshot) {
|
|
978
|
+
let perUnion = memory.get(unionKey);
|
|
979
|
+
if (perUnion === void 0) {
|
|
980
|
+
perUnion = /* @__PURE__ */ new Map();
|
|
981
|
+
memory.set(unionKey, perUnion);
|
|
982
|
+
}
|
|
983
|
+
perUnion.set(discValue, snapshot);
|
|
984
|
+
},
|
|
985
|
+
lookupIncoming(unionKey, discValue) {
|
|
986
|
+
return memory.get(unionKey)?.get(discValue);
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
function cloneVariantSnapshot(value) {
|
|
991
|
+
if (value === null || typeof value !== "object") return value;
|
|
992
|
+
const raw = toRaw(value);
|
|
993
|
+
if (raw instanceof Date) return new Date(raw.getTime());
|
|
994
|
+
if (raw instanceof Map) {
|
|
995
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
996
|
+
for (const [k, v] of raw.entries()) out2.set(cloneVariantSnapshot(k), cloneVariantSnapshot(v));
|
|
997
|
+
return out2;
|
|
998
|
+
}
|
|
999
|
+
if (raw instanceof Set) {
|
|
1000
|
+
const out2 = /* @__PURE__ */ new Set();
|
|
1001
|
+
for (const v of raw) out2.add(cloneVariantSnapshot(v));
|
|
1002
|
+
return out2;
|
|
1003
|
+
}
|
|
1004
|
+
if (raw instanceof RegExp) return new RegExp(raw.source, raw.flags);
|
|
1005
|
+
if (Array.isArray(raw)) {
|
|
1006
|
+
const out2 = new Array(raw.length);
|
|
1007
|
+
for (let i = 0; i < raw.length; i++) out2[i] = cloneVariantSnapshot(raw[i]);
|
|
1008
|
+
return out2;
|
|
1009
|
+
}
|
|
1010
|
+
if (!isPlainRecord(raw)) return raw;
|
|
1011
|
+
const src = raw;
|
|
1012
|
+
const out = {};
|
|
1013
|
+
for (const k of consumerKeys(src)) {
|
|
1014
|
+
safeAssign(out, k, cloneVariantSnapshot(readConsumerProp(src, k)));
|
|
1015
|
+
}
|
|
1016
|
+
return out;
|
|
1017
|
+
}
|
|
1018
|
+
function createArrayBookkeeping(deps) {
|
|
1019
|
+
const {
|
|
1020
|
+
form,
|
|
1021
|
+
fields,
|
|
1022
|
+
errorCells,
|
|
1023
|
+
originals,
|
|
1024
|
+
blankPaths,
|
|
1025
|
+
originalBlankPaths,
|
|
1026
|
+
authoredPaths,
|
|
1027
|
+
removedPaths,
|
|
1028
|
+
notifyStructure,
|
|
1029
|
+
fieldValidationCounts,
|
|
1030
|
+
fieldValidatingSince,
|
|
1031
|
+
fieldValidationState,
|
|
1032
|
+
activeValidations,
|
|
1033
|
+
arrayIdentity,
|
|
1034
|
+
variantMemory,
|
|
1035
|
+
touchFieldRecord,
|
|
1036
|
+
stampContainers,
|
|
1037
|
+
stampBareContainers,
|
|
1038
|
+
foldInteractionHistory,
|
|
1039
|
+
decFieldValidation
|
|
1040
|
+
} = deps;
|
|
1041
|
+
function migrateElementState(arrayPath, remap) {
|
|
1042
|
+
if (remap.moved.size === 0 && remap.vacated.size === 0) return;
|
|
1043
|
+
migrateSetSubtree(originalBlankPaths, arrayPath, remap);
|
|
1044
|
+
migrateSetSubtree(authoredPaths, arrayPath, remap);
|
|
1045
|
+
const removedMoved = [];
|
|
1046
|
+
for (const hit of collectKeysAtIndices(removedPaths.keys(), arrayPath, remapAffects(remap))) {
|
|
1047
|
+
removedMoved.push(hit.segments);
|
|
1048
|
+
}
|
|
1049
|
+
migrateMapSubtree(removedPaths, arrayPath, remap, (_, segments) => {
|
|
1050
|
+
removedMoved.push(segments);
|
|
1051
|
+
return segments;
|
|
1052
|
+
});
|
|
1053
|
+
migrateFieldRecords(fields, arrayPath, remap, foldInteractionHistory);
|
|
1054
|
+
migrateMapSubtree(errorCells(), arrayPath, remap, (cell, segments) => ({
|
|
1055
|
+
schema: NO_ERRORS,
|
|
1056
|
+
user: cell.user.map((error) => ({ ...error, path: [...segments] }))
|
|
1057
|
+
}));
|
|
1058
|
+
migrateMapSubtree(originals, arrayPath, remap, (record, segments) => ({
|
|
1059
|
+
segments,
|
|
1060
|
+
value: record.value
|
|
1061
|
+
}));
|
|
1062
|
+
migrateSetSubtree(blankPaths, arrayPath, remap);
|
|
1063
|
+
migrateMapSubtree(fieldValidatingSince, arrayPath, remap, (since) => since);
|
|
1064
|
+
migrateMapSubtree(fieldValidationCounts, arrayPath, remap, (count) => count);
|
|
1065
|
+
migrateMapSubtree(fieldValidationState, arrayPath, remap, (entry, segments) => {
|
|
1066
|
+
entry.key = keyForSegments(segments).key;
|
|
1067
|
+
entry.path = segments;
|
|
1068
|
+
return entry;
|
|
1069
|
+
});
|
|
1070
|
+
arrayIdentity.applyRemap(arrayPath, remap);
|
|
1071
|
+
if (removedMoved.length > 0) notifyStructure(removedMoved);
|
|
1072
|
+
}
|
|
1073
|
+
function seedFreshElement(arrayPath, freshIndex, now) {
|
|
1074
|
+
const elementPath = [...arrayPath, freshIndex];
|
|
1075
|
+
const patches = [];
|
|
1076
|
+
diffAndApply(void 0, getAtPath(form.value, elementPath), elementPath, (patch) => {
|
|
1077
|
+
patches.push(patch);
|
|
1078
|
+
});
|
|
1079
|
+
const bare = [];
|
|
1080
|
+
patches.forEach((patch, index) => {
|
|
1081
|
+
if (patch.kind !== "added") return;
|
|
1082
|
+
if (isBarePatch(patch)) {
|
|
1083
|
+
bare.push(index);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const { key, segments } = canonicalizePath(patch.path);
|
|
1087
|
+
if (!originals.has(key)) originals.set(key, { segments: patch.path, value: void 0 });
|
|
1088
|
+
touchFieldRecord(key, segments, { updatedAt: now });
|
|
1089
|
+
});
|
|
1090
|
+
if (bare.length > 0) stampBareContainers(patches, bare, now);
|
|
1091
|
+
else if (patches.length === 0 && hasAtPath(form.value, elementPath)) {
|
|
1092
|
+
stampContainers([elementPath], now);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
function abortValidationAtVacatedIndices(arrayPath, remap) {
|
|
1096
|
+
if (remap.vacated.size === 0) return;
|
|
1097
|
+
const hits = collectKeysAtIndices(
|
|
1098
|
+
[...fieldValidationState.keys()],
|
|
1099
|
+
arrayPath,
|
|
1100
|
+
(index) => remap.vacated.has(index)
|
|
1101
|
+
);
|
|
1102
|
+
for (const hit of hits) {
|
|
1103
|
+
const entry = fieldValidationState.get(hit.key);
|
|
1104
|
+
if (entry === void 0) continue;
|
|
1105
|
+
if (entry.timer !== null) {
|
|
1106
|
+
clearTimeout(entry.timer);
|
|
1107
|
+
} else if (!entry.settled && !entry.released) {
|
|
1108
|
+
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
1109
|
+
decFieldValidation(hit.key);
|
|
1110
|
+
entry.released = true;
|
|
1111
|
+
}
|
|
1112
|
+
entry.aborted = true;
|
|
1113
|
+
fieldValidationState.delete(hit.key);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
return {
|
|
1117
|
+
applyStructuralOp(arrayPath, remap, now) {
|
|
1118
|
+
abortValidationAtVacatedIndices(arrayPath, remap);
|
|
1119
|
+
migrateElementState(arrayPath, remap);
|
|
1120
|
+
for (const freshIndex of remap.fresh) seedFreshElement(arrayPath, freshIndex, now);
|
|
1121
|
+
const changed = changedIndices(remap);
|
|
1122
|
+
evictSchemaVerdictsAtIndices(errorCells(), arrayPath, changed);
|
|
1123
|
+
variantMemory.dropAtIndices(arrayPath, changed);
|
|
1124
|
+
arrayIdentity.applyOp(arrayPath, remap);
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
function buildFieldArrayApi(state) {
|
|
1129
|
+
function readArray(path) {
|
|
1130
|
+
const segments = canonicalizePath(path).segments;
|
|
1131
|
+
const current = state.getValueAtPath(segments);
|
|
1132
|
+
return Array.isArray(current) ? current.slice() : [];
|
|
1133
|
+
}
|
|
1134
|
+
function writeArray(path, next, arrayOp) {
|
|
1135
|
+
const { segments } = canonicalizePath(path);
|
|
1136
|
+
const meta = {
|
|
1137
|
+
...arrayOp !== void 0 ? { arrayOp } : {}
|
|
1138
|
+
};
|
|
1139
|
+
return state.setValueAtPath(segments, next, meta);
|
|
1140
|
+
}
|
|
1141
|
+
return {
|
|
1142
|
+
append(path, value) {
|
|
1143
|
+
const next = readArray(path);
|
|
1144
|
+
next.push(value);
|
|
1145
|
+
return writeArray(path, next, { kind: "insert", index: next.length - 1 });
|
|
1146
|
+
},
|
|
1147
|
+
prepend(path, value) {
|
|
1148
|
+
const next = readArray(path);
|
|
1149
|
+
next.unshift(value);
|
|
1150
|
+
return writeArray(path, next, { kind: "insert", index: 0 });
|
|
1151
|
+
},
|
|
1152
|
+
insert(path, index, value) {
|
|
1153
|
+
const next = readArray(path);
|
|
1154
|
+
const preLen = next.length;
|
|
1155
|
+
const insertIndex = index < 0 ? Math.max(0, preLen + index) : Math.min(index, preLen);
|
|
1156
|
+
next.splice(insertIndex, 0, value);
|
|
1157
|
+
return writeArray(path, next, { kind: "insert", index: insertIndex });
|
|
1158
|
+
},
|
|
1159
|
+
remove(path, index) {
|
|
1160
|
+
const next = readArray(path);
|
|
1161
|
+
if (index < 0 || index >= next.length) return false;
|
|
1162
|
+
next.splice(index, 1);
|
|
1163
|
+
return writeArray(path, next, { kind: "remove", index });
|
|
1164
|
+
},
|
|
1165
|
+
swap(path, a, b) {
|
|
1166
|
+
const next = readArray(path);
|
|
1167
|
+
if (a < 0 || a >= next.length) return false;
|
|
1168
|
+
if (b < 0 || b >= next.length) return false;
|
|
1169
|
+
if (a === b) return false;
|
|
1170
|
+
const tmp = next[a];
|
|
1171
|
+
next[a] = next[b];
|
|
1172
|
+
next[b] = tmp;
|
|
1173
|
+
return writeArray(path, next, { kind: "swap", a, b });
|
|
1174
|
+
},
|
|
1175
|
+
move(path, from, to) {
|
|
1176
|
+
const next = readArray(path);
|
|
1177
|
+
if (from < 0 || from >= next.length) return false;
|
|
1178
|
+
const [item] = next.splice(from, 1);
|
|
1179
|
+
const clampedTo = Math.max(0, Math.min(to, next.length));
|
|
1180
|
+
next.splice(clampedTo, 0, item);
|
|
1181
|
+
return writeArray(path, next, { kind: "move", from, to: clampedTo });
|
|
1182
|
+
},
|
|
1183
|
+
replace(path, index, value) {
|
|
1184
|
+
const next = readArray(path);
|
|
1185
|
+
if (index < 0 || index >= next.length) return false;
|
|
1186
|
+
next[index] = value;
|
|
1187
|
+
return writeArray(path, next, { kind: "replace-at", index });
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
export { AttaformErrorCode as A, ANONYMOUS_WIZARD_KEY_PREFIX as B, DEFAULT_HISTORY_MAX_SNAPSHOTS as D, NO_ERRORS as N, RESERVED_KEY_PREFIX as R, ANONYMOUS_FORM_KEY_PREFIX as a, makeBlankRequiredError as b, buildFieldArrayApi as c, DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS as d, diffAndApply as e, mergeStructural as f, getAtPath as g, hasAtPath as h, isPlainRecord as i, createArrayBookkeeping as j, createVariantMemory as k, createArrayIdentity as l, migrateMapSubtree as m, normalizeNumericOption as n, isDescendable as o, pickDefined as p, migrateFieldRecords as q, setAtPath as r, structuralSnapshot as s, remapForOp as t, isBarePatch as u, applyChangedKeys as v, cloneVariantSnapshot as w, setAtPathWithSchemaFill as x, tryInPlaceLeafWrite as y, DEFAULT_MAX_RECURSION_DEPTH as z };
|