@samline/forms 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -1
- package/README.md +43 -31
- package/dist/browser/global.d.ts +49 -3
- package/dist/browser/global.global.js +20 -12
- package/dist/browser/global.global.js.map +1 -1
- package/dist/browser/index.cjs +253 -37
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/{chunk-23VZAYA3.js → chunk-JAEFD56I.js} +254 -38
- package/dist/chunk-JAEFD56I.js.map +1 -0
- package/dist/index.cjs +253 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{registry-GzopYPCR.d.cts → registry-CPe_lf8-.d.cts} +50 -4
- package/dist/{registry-GzopYPCR.d.ts → registry-CPe_lf8-.d.ts} +50 -4
- package/package.json +11 -8
- package/dist/chunk-23VZAYA3.js.map +0 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -240,12 +240,37 @@ var restoreCursor = (field, position) => {
|
|
|
240
240
|
var state = null;
|
|
241
241
|
var MISSING_MESSAGE = "[samline/forms] The `format()` and `formatAll()` methods require the @samline/formatter package. Install it with: npm i @samline/formatter (or pnpm/bun/yarn equivalent).";
|
|
242
242
|
var warned = false;
|
|
243
|
+
var phonePromise = null;
|
|
244
|
+
var PHONE_MESSAGE = "[samline/forms] Phone formatting needs `@samline/formatter/phone` (@samline/formatter >= 3.0.0 makes phones opt-in) and it could not be loaded.";
|
|
243
245
|
var warnOnce = () => {
|
|
244
246
|
if (warned) return;
|
|
245
247
|
warned = true;
|
|
246
248
|
console.error(MISSING_MESSAGE);
|
|
247
249
|
};
|
|
248
|
-
var
|
|
250
|
+
var ensurePhone = (formatter) => {
|
|
251
|
+
if (typeof formatter.isPhoneRegistered !== "function") return Promise.resolve(true);
|
|
252
|
+
if (formatter.isPhoneRegistered()) return Promise.resolve(true);
|
|
253
|
+
if (!phonePromise) {
|
|
254
|
+
phonePromise = (async () => {
|
|
255
|
+
try {
|
|
256
|
+
const mod = await import("@samline/formatter/phone");
|
|
257
|
+
mod.registerPhone();
|
|
258
|
+
return true;
|
|
259
|
+
} catch {
|
|
260
|
+
console.error(PHONE_MESSAGE);
|
|
261
|
+
phonePromise = null;
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
})();
|
|
265
|
+
}
|
|
266
|
+
return phonePromise;
|
|
267
|
+
};
|
|
268
|
+
var loadFormatter = async (options = {}) => {
|
|
269
|
+
const formatter = await loadFormatterModule();
|
|
270
|
+
if (!formatter || !options.phone) return formatter;
|
|
271
|
+
return await ensurePhone(formatter) ? formatter : null;
|
|
272
|
+
};
|
|
273
|
+
var loadFormatterModule = () => {
|
|
249
274
|
if (state && state.status === "resolved") {
|
|
250
275
|
if (!state.module) warnOnce();
|
|
251
276
|
return Promise.resolve(state.module);
|
|
@@ -380,7 +405,7 @@ var applyFormat = async (state2, helpers, config) => {
|
|
|
380
405
|
phase1Entries.push(entry);
|
|
381
406
|
}
|
|
382
407
|
}
|
|
383
|
-
const formatter = await loadFormatter();
|
|
408
|
+
const formatter = await loadFormatter({ phone: formatType === "phone" });
|
|
384
409
|
if (state2.isDestroyed) {
|
|
385
410
|
rollbackPhase1(phase1Entries, bucket, state2.formattedFields);
|
|
386
411
|
return;
|
|
@@ -519,6 +544,7 @@ var createDestroy = (state2, _helpers) => () => {
|
|
|
519
544
|
}
|
|
520
545
|
}
|
|
521
546
|
state2.watchedFields.clear();
|
|
547
|
+
state2.groupWatchers.clear();
|
|
522
548
|
state2.subscribers.clear();
|
|
523
549
|
state2.submitHandlers.clear();
|
|
524
550
|
state2.fieldCache.clear();
|
|
@@ -746,9 +772,9 @@ var writeFieldValue = (fields, value) => {
|
|
|
746
772
|
continue;
|
|
747
773
|
}
|
|
748
774
|
if (field instanceof HTMLSelectElement && field.multiple) {
|
|
749
|
-
const
|
|
775
|
+
const selectedValues2 = normalizedArray ?? [normalizedValue];
|
|
750
776
|
for (const option of field.options) {
|
|
751
|
-
option.selected =
|
|
777
|
+
option.selected = selectedValues2.includes(option.value);
|
|
752
778
|
}
|
|
753
779
|
continue;
|
|
754
780
|
}
|
|
@@ -783,8 +809,7 @@ var submitForm = (form3) => {
|
|
|
783
809
|
var createGetValue = (state2, helpers) => (name) => readFieldValue(helpers.getFieldsByName(name));
|
|
784
810
|
|
|
785
811
|
// src/api/observe.ts
|
|
786
|
-
var
|
|
787
|
-
if (state2.isDestroyed) return () => void 0;
|
|
812
|
+
var observeField = (state2, field, callback) => {
|
|
788
813
|
const callbacks = state2.watchedFields.get(field) ?? /* @__PURE__ */ new Set();
|
|
789
814
|
callbacks.add(callback);
|
|
790
815
|
state2.watchedFields.set(field, callbacks);
|
|
@@ -799,6 +824,26 @@ var createObserve = (state2, helpers) => (field, callback) => {
|
|
|
799
824
|
}
|
|
800
825
|
};
|
|
801
826
|
};
|
|
827
|
+
var observeFields = (state2, fields, callback) => {
|
|
828
|
+
const names = Array.from(new Set(fields));
|
|
829
|
+
if (names.length === 0) return () => void 0;
|
|
830
|
+
const entry = { fields: names, callback };
|
|
831
|
+
state2.groupWatchers.add(entry);
|
|
832
|
+
if (state2.element) {
|
|
833
|
+
const values = Object.fromEntries(names.map((name) => [name, state2.api.getValue(name)]));
|
|
834
|
+
callback(values, null, state2.element, state2.api.getState());
|
|
835
|
+
}
|
|
836
|
+
return () => {
|
|
837
|
+
state2.groupWatchers.delete(entry);
|
|
838
|
+
};
|
|
839
|
+
};
|
|
840
|
+
var createObserve = (state2, _helpers) => {
|
|
841
|
+
function observe(field, callback) {
|
|
842
|
+
if (state2.isDestroyed) return () => void 0;
|
|
843
|
+
return Array.isArray(field) ? observeFields(state2, field, callback) : observeField(state2, field, callback);
|
|
844
|
+
}
|
|
845
|
+
return observe;
|
|
846
|
+
};
|
|
802
847
|
|
|
803
848
|
// src/api/on-submit.ts
|
|
804
849
|
var createOnSubmit = (state2, _helpers) => (callback, preventDefault = true) => {
|
|
@@ -870,6 +915,75 @@ var createSetErrors = (state2, helpers) => (fields) => {
|
|
|
870
915
|
return state2.api;
|
|
871
916
|
};
|
|
872
917
|
|
|
918
|
+
// src/api/set-options.ts
|
|
919
|
+
var isGroup = (entry) => typeof entry === "object" && entry !== null && Array.isArray(entry.options);
|
|
920
|
+
var createOption = (entry) => {
|
|
921
|
+
const option = document.createElement("option");
|
|
922
|
+
if (typeof entry === "object") {
|
|
923
|
+
option.value = String(entry.value);
|
|
924
|
+
option.textContent = entry.label ?? String(entry.value);
|
|
925
|
+
option.disabled = Boolean(entry.disabled);
|
|
926
|
+
if (entry.selected) option.defaultSelected = true;
|
|
927
|
+
} else {
|
|
928
|
+
option.value = String(entry);
|
|
929
|
+
option.textContent = String(entry);
|
|
930
|
+
}
|
|
931
|
+
return option;
|
|
932
|
+
};
|
|
933
|
+
var buildNodes = (options) => {
|
|
934
|
+
const nodes = [];
|
|
935
|
+
let hasExplicitSelection = false;
|
|
936
|
+
const track = (option) => {
|
|
937
|
+
if (option.defaultSelected) hasExplicitSelection = true;
|
|
938
|
+
return option;
|
|
939
|
+
};
|
|
940
|
+
for (const entry of options) {
|
|
941
|
+
if (entry === null || entry === void 0) continue;
|
|
942
|
+
if (isGroup(entry)) {
|
|
943
|
+
const group = document.createElement("optgroup");
|
|
944
|
+
group.label = entry.label;
|
|
945
|
+
group.disabled = Boolean(entry.disabled);
|
|
946
|
+
for (const child of entry.options) {
|
|
947
|
+
if (child === null || child === void 0) continue;
|
|
948
|
+
group.appendChild(track(createOption(child)));
|
|
949
|
+
}
|
|
950
|
+
nodes.push(group);
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
nodes.push(track(createOption(entry)));
|
|
954
|
+
}
|
|
955
|
+
return { nodes, hasExplicitSelection };
|
|
956
|
+
};
|
|
957
|
+
var selectedValues = (select) => Array.from(select.selectedOptions, (option) => option.value);
|
|
958
|
+
var restoreSelection = (select, previous) => {
|
|
959
|
+
if (previous.length === 0) return;
|
|
960
|
+
const options = Array.from(select.options);
|
|
961
|
+
if (select.multiple) {
|
|
962
|
+
for (const option of options) option.selected = previous.includes(option.value);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const match = options.find((option) => option.value === previous[0]);
|
|
966
|
+
if (match) match.selected = true;
|
|
967
|
+
};
|
|
968
|
+
var sameValues = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
969
|
+
var createSetOptions = (state2, helpers) => (name, options, config = {}) => {
|
|
970
|
+
if (!state2.element || state2.isDestroyed) return state2.api;
|
|
971
|
+
const selects = helpers.getFieldsByName(name).filter((field) => field instanceof HTMLSelectElement);
|
|
972
|
+
if (selects.length === 0) return state2.api;
|
|
973
|
+
const keepValue = config.keepValue ?? true;
|
|
974
|
+
const changed = [];
|
|
975
|
+
for (const select of selects) {
|
|
976
|
+
const previous = selectedValues(select);
|
|
977
|
+
const { nodes, hasExplicitSelection } = buildNodes(options);
|
|
978
|
+
select.replaceChildren(...nodes);
|
|
979
|
+
if (keepValue && !hasExplicitSelection) restoreSelection(select, previous);
|
|
980
|
+
if (!sameValues(previous, selectedValues(select))) changed.push(select);
|
|
981
|
+
}
|
|
982
|
+
helpers.commitOwnMutations(selects);
|
|
983
|
+
changed[0]?.dispatchEvent(new Event("input", { bubbles: true }));
|
|
984
|
+
return state2.api;
|
|
985
|
+
};
|
|
986
|
+
|
|
873
987
|
// src/api/set-value.ts
|
|
874
988
|
var createSetValue = (state2, helpers) => (name, value) => {
|
|
875
989
|
if (state2.isDestroyed) return state2.api;
|
|
@@ -893,28 +1007,46 @@ var createSubscribe = (state2, _helpers) => (listener) => {
|
|
|
893
1007
|
};
|
|
894
1008
|
|
|
895
1009
|
// src/api/unwatch.ts
|
|
896
|
-
var
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1010
|
+
var sameFields = (left, right) => left.length === right.size && left.every((name) => right.has(name));
|
|
1011
|
+
var createUnwatch = (state2, _helpers) => {
|
|
1012
|
+
function unwatch(field, callback) {
|
|
1013
|
+
if (field === void 0 || field === "") {
|
|
1014
|
+
state2.watchedFields.clear();
|
|
1015
|
+
state2.groupWatchers.clear();
|
|
1016
|
+
return state2.api;
|
|
1017
|
+
}
|
|
1018
|
+
if (Array.isArray(field)) {
|
|
1019
|
+
const names = new Set(field);
|
|
1020
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
1021
|
+
if (!sameFields(entry.fields, names)) continue;
|
|
1022
|
+
if (callback && entry.callback !== callback) continue;
|
|
1023
|
+
state2.groupWatchers.delete(entry);
|
|
1024
|
+
}
|
|
1025
|
+
return state2.api;
|
|
1026
|
+
}
|
|
1027
|
+
if (!callback) {
|
|
1028
|
+
state2.watchedFields.delete(field);
|
|
1029
|
+
return state2.api;
|
|
1030
|
+
}
|
|
1031
|
+
const callbacks = state2.watchedFields.get(field);
|
|
1032
|
+
callbacks?.delete(callback);
|
|
1033
|
+
if (callbacks && callbacks.size === 0) {
|
|
1034
|
+
state2.watchedFields.delete(field);
|
|
1035
|
+
}
|
|
903
1036
|
return state2.api;
|
|
904
1037
|
}
|
|
905
|
-
|
|
906
|
-
callbacks?.delete(callback);
|
|
907
|
-
if (callbacks && callbacks.size === 0) {
|
|
908
|
-
state2.watchedFields.delete(field);
|
|
909
|
-
}
|
|
910
|
-
return state2.api;
|
|
1038
|
+
return unwatch;
|
|
911
1039
|
};
|
|
912
1040
|
|
|
913
1041
|
// src/api/watch.ts
|
|
914
|
-
var createWatch = (state2, helpers) =>
|
|
1042
|
+
var createWatch = (state2, helpers) => {
|
|
915
1043
|
const observe = createObserve(state2, helpers);
|
|
916
|
-
|
|
917
|
-
|
|
1044
|
+
function watch(field, callback) {
|
|
1045
|
+
if (Array.isArray(field)) observe(field, callback);
|
|
1046
|
+
else observe(field, callback);
|
|
1047
|
+
return state2.api;
|
|
1048
|
+
}
|
|
1049
|
+
return watch;
|
|
918
1050
|
};
|
|
919
1051
|
|
|
920
1052
|
// src/core/validation.ts
|
|
@@ -1067,6 +1199,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1067
1199
|
attributes,
|
|
1068
1200
|
validators: normalizedOptions.validators ?? {},
|
|
1069
1201
|
watchedFields: /* @__PURE__ */ new Map(),
|
|
1202
|
+
groupWatchers: /* @__PURE__ */ new Set(),
|
|
1070
1203
|
subscribers: /* @__PURE__ */ new Set(),
|
|
1071
1204
|
submitHandlers: /* @__PURE__ */ new Set(),
|
|
1072
1205
|
fieldCache: /* @__PURE__ */ new Map(),
|
|
@@ -1237,7 +1370,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1237
1370
|
}
|
|
1238
1371
|
return affected;
|
|
1239
1372
|
};
|
|
1240
|
-
const
|
|
1373
|
+
const emitSingleWatchers = (name) => {
|
|
1241
1374
|
if (!state2.element || !state2.api) return;
|
|
1242
1375
|
const callbacks = state2.watchedFields.get(name);
|
|
1243
1376
|
if (!callbacks || callbacks.size === 0) return;
|
|
@@ -1246,6 +1379,23 @@ var createFormController = (target, options = {}) => {
|
|
|
1246
1379
|
const snapshot = state2.api.getState();
|
|
1247
1380
|
callbacks.forEach((callback) => callback(value, fieldElement, state2.element, snapshot));
|
|
1248
1381
|
};
|
|
1382
|
+
const emitGroupWatchers = (names) => {
|
|
1383
|
+
if (!state2.element || !state2.api || state2.groupWatchers.size === 0) return;
|
|
1384
|
+
let snapshot;
|
|
1385
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
1386
|
+
const changed = names ? names.find((name) => entry.fields.includes(name)) : null;
|
|
1387
|
+
if (changed === void 0) continue;
|
|
1388
|
+
snapshot ?? (snapshot = state2.api.getState());
|
|
1389
|
+
const values = Object.fromEntries(
|
|
1390
|
+
entry.fields.map((field) => [field, state2.api.getValue(field)])
|
|
1391
|
+
);
|
|
1392
|
+
entry.callback(values, changed, state2.element, snapshot);
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
const emitFieldWatchers = (name) => {
|
|
1396
|
+
emitSingleWatchers(name);
|
|
1397
|
+
emitGroupWatchers([name]);
|
|
1398
|
+
};
|
|
1249
1399
|
const runAutoSubmit = () => {
|
|
1250
1400
|
state2.autoSubmitTimer = null;
|
|
1251
1401
|
if (!state2.element || state2.isDestroyed || !state2.autoSubmitEnabled) return;
|
|
@@ -1266,8 +1416,20 @@ var createFormController = (target, options = {}) => {
|
|
|
1266
1416
|
}
|
|
1267
1417
|
runAutoSubmit();
|
|
1268
1418
|
};
|
|
1419
|
+
const selectSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1420
|
+
const readSelectSnapshot = (select) => Array.from(select.selectedOptions, (option) => option.value).join("\0");
|
|
1421
|
+
const snapshotSelect = (select) => {
|
|
1422
|
+
selectSnapshots.set(select, readSelectSnapshot(select));
|
|
1423
|
+
};
|
|
1424
|
+
const snapshotAllSelects = () => {
|
|
1425
|
+
if (!state2.element) return;
|
|
1426
|
+
for (const field of getNamedFields(state2.element)) {
|
|
1427
|
+
if (field instanceof HTMLSelectElement) snapshotSelect(field);
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1269
1430
|
const emitAllFieldWatchers = () => {
|
|
1270
|
-
for (const name of Array.from(state2.watchedFields.keys()))
|
|
1431
|
+
for (const name of Array.from(state2.watchedFields.keys())) emitSingleWatchers(name);
|
|
1432
|
+
emitGroupWatchers(null);
|
|
1271
1433
|
};
|
|
1272
1434
|
const applyReset = () => {
|
|
1273
1435
|
if (!state2.element || state2.isDestroyed) return;
|
|
@@ -1279,6 +1441,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1279
1441
|
state2.validationElementErrors.clear();
|
|
1280
1442
|
clearAttributes(state2.element, [attributes.error, attributes.filled, "aria-invalid"]);
|
|
1281
1443
|
syncVisualState();
|
|
1444
|
+
snapshotAllSelects();
|
|
1282
1445
|
emitAllFieldWatchers();
|
|
1283
1446
|
notifySubscribers();
|
|
1284
1447
|
};
|
|
@@ -1293,7 +1456,8 @@ var createFormController = (target, options = {}) => {
|
|
|
1293
1456
|
validateNames,
|
|
1294
1457
|
emitFieldWatchers,
|
|
1295
1458
|
scheduleAutoSubmit,
|
|
1296
|
-
applyReset
|
|
1459
|
+
applyReset,
|
|
1460
|
+
commitOwnMutations: (selects) => commitOwnMutations(selects)
|
|
1297
1461
|
};
|
|
1298
1462
|
const handleDelegatedEvent = (event) => {
|
|
1299
1463
|
const target2 = event.target;
|
|
@@ -1301,6 +1465,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1301
1465
|
const name = target2.name;
|
|
1302
1466
|
if (!name) return;
|
|
1303
1467
|
clearFieldCache();
|
|
1468
|
+
if (target2 instanceof HTMLSelectElement) snapshotSelect(target2);
|
|
1304
1469
|
const canonical = resolveCanonicalForName(state2, name) ?? name;
|
|
1305
1470
|
const displayName = resolveDisplayNameForName(state2, name);
|
|
1306
1471
|
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
@@ -1311,8 +1476,9 @@ var createFormController = (target, options = {}) => {
|
|
|
1311
1476
|
if (state2.isValidated && affectedValidationNames.some((field) => state2.validators[field] !== void 0)) {
|
|
1312
1477
|
validateNames(affectedValidationNames);
|
|
1313
1478
|
}
|
|
1314
|
-
|
|
1315
|
-
if (canonical !== name)
|
|
1479
|
+
emitSingleWatchers(canonical);
|
|
1480
|
+
if (canonical !== name) emitSingleWatchers(name);
|
|
1481
|
+
emitGroupWatchers(canonical !== name ? [canonical, name] : [canonical]);
|
|
1316
1482
|
notifySubscribers();
|
|
1317
1483
|
scheduleAutoSubmit();
|
|
1318
1484
|
};
|
|
@@ -1341,6 +1507,10 @@ var createFormController = (target, options = {}) => {
|
|
|
1341
1507
|
};
|
|
1342
1508
|
const handleSubmitEvent = (event) => {
|
|
1343
1509
|
if (!state2.element || state2.isDestroyed || !state2.api) return;
|
|
1510
|
+
if (!state2.isAutoSubmitting && state2.autoSubmitTimer) {
|
|
1511
|
+
clearTimeout(state2.autoSubmitTimer);
|
|
1512
|
+
state2.autoSubmitTimer = null;
|
|
1513
|
+
}
|
|
1344
1514
|
if (normalizedOptions.clearErrorsOnSubmit) state2.manualErrors = {};
|
|
1345
1515
|
const validation = state2.api.validate();
|
|
1346
1516
|
const handlers = Array.from(state2.submitHandlers);
|
|
@@ -1393,18 +1563,62 @@ var createFormController = (target, options = {}) => {
|
|
|
1393
1563
|
const cancel = () => clearTimeout(timer);
|
|
1394
1564
|
state2.cleanups.add(cancel);
|
|
1395
1565
|
};
|
|
1566
|
+
const touchesFields = (node) => node instanceof Element && (isFieldElement(node) || node.querySelector("input, select, textarea") !== null);
|
|
1567
|
+
const isStructural = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1568
|
+
const isOptionNode = (node) => node instanceof HTMLOptionElement || node instanceof HTMLOptGroupElement;
|
|
1569
|
+
const optionListOwner = (record) => {
|
|
1570
|
+
if (record.type !== "childList") return null;
|
|
1571
|
+
const touchesOptions = Array.from(record.addedNodes).some(isOptionNode) || Array.from(record.removedNodes).some(isOptionNode);
|
|
1572
|
+
if (!touchesOptions) return null;
|
|
1573
|
+
const target2 = record.target;
|
|
1574
|
+
if (target2 instanceof HTMLSelectElement) return target2;
|
|
1575
|
+
if (target2 instanceof HTMLOptGroupElement && target2.parentElement instanceof HTMLSelectElement) {
|
|
1576
|
+
return target2.parentElement;
|
|
1577
|
+
}
|
|
1578
|
+
return null;
|
|
1579
|
+
};
|
|
1580
|
+
const handleMutations = (records) => {
|
|
1581
|
+
if (state2.isDestroyed) return;
|
|
1582
|
+
const structural = records.some(isStructural);
|
|
1583
|
+
const changedNames = /* @__PURE__ */ new Set();
|
|
1584
|
+
for (const record of records) {
|
|
1585
|
+
const select = optionListOwner(record);
|
|
1586
|
+
if (!select || !select.name) continue;
|
|
1587
|
+
const next = readSelectSnapshot(select);
|
|
1588
|
+
if (selectSnapshots.get(select) !== next) changedNames.add(select.name);
|
|
1589
|
+
selectSnapshots.set(select, next);
|
|
1590
|
+
}
|
|
1591
|
+
if (!structural && changedNames.size === 0) return;
|
|
1592
|
+
clearFieldCache();
|
|
1593
|
+
if (structural) {
|
|
1594
|
+
snapshotAllSelects();
|
|
1595
|
+
if (state2.isValidated) validateNames();
|
|
1596
|
+
else syncVisualState();
|
|
1597
|
+
} else {
|
|
1598
|
+
const affected = /* @__PURE__ */ new Set();
|
|
1599
|
+
for (const name of changedNames) {
|
|
1600
|
+
for (const field of getAffectedValidationNames(name)) affected.add(field);
|
|
1601
|
+
}
|
|
1602
|
+
const names = Array.from(affected);
|
|
1603
|
+
syncVisualState(Array.from(changedNames));
|
|
1604
|
+
if (state2.isValidated && names.some((field) => state2.validators[field] !== void 0)) {
|
|
1605
|
+
validateNames(names);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
for (const name of changedNames) emitFieldWatchers(name);
|
|
1609
|
+
notifySubscribers();
|
|
1610
|
+
};
|
|
1611
|
+
const commitOwnMutations = (selects) => {
|
|
1612
|
+
selects.forEach(snapshotSelect);
|
|
1613
|
+
const pending = state2.mutationObserver?.takeRecords() ?? [];
|
|
1614
|
+
const foreign = pending.filter(
|
|
1615
|
+
(record) => !selects.some((select) => select.contains(record.target))
|
|
1616
|
+
);
|
|
1617
|
+
if (foreign.length > 0) handleMutations(foreign);
|
|
1618
|
+
};
|
|
1396
1619
|
const startMutationObserver = () => {
|
|
1397
1620
|
if (!state2.element || typeof MutationObserver === "undefined") return;
|
|
1398
|
-
|
|
1399
|
-
const isRelevant = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1400
|
-
state2.mutationObserver = new MutationObserver((records) => {
|
|
1401
|
-
if (state2.isDestroyed || !records.some(isRelevant)) return;
|
|
1402
|
-
clearFieldCache();
|
|
1403
|
-
if (state2.isValidated) {
|
|
1404
|
-
validateNames();
|
|
1405
|
-
} else syncVisualState();
|
|
1406
|
-
notifySubscribers();
|
|
1407
|
-
});
|
|
1621
|
+
state2.mutationObserver = new MutationObserver(handleMutations);
|
|
1408
1622
|
state2.mutationObserver.observe(state2.element, {
|
|
1409
1623
|
childList: true,
|
|
1410
1624
|
subtree: true,
|
|
@@ -1433,6 +1647,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1433
1647
|
setErrors: createSetErrors(state2, helpers),
|
|
1434
1648
|
clearErrors: createClearErrors(state2, helpers),
|
|
1435
1649
|
setValue: createSetValue(state2, helpers),
|
|
1650
|
+
setOptions: createSetOptions(state2, helpers),
|
|
1436
1651
|
getValue: createGetValue(state2, helpers),
|
|
1437
1652
|
getField: createGetField(state2, helpers),
|
|
1438
1653
|
validate: createValidate(state2, helpers),
|
|
@@ -1452,6 +1667,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1452
1667
|
addListener2(document, "input", handleExternalDelegatedEvent);
|
|
1453
1668
|
addListener2(state2.element, "submit", handleSubmitEvent);
|
|
1454
1669
|
addListener2(state2.element, "reset", handleResetEvent);
|
|
1670
|
+
snapshotAllSelects();
|
|
1455
1671
|
startMutationObserver();
|
|
1456
1672
|
}
|
|
1457
1673
|
if (normalizedOptions.autoSubmit) {
|