@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.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v as FormsApi, w as FormsAvailable, F as FormTarget, a as FormControllerOptions, b as FormController, N as NewFormInput } from '../registry-CPe_lf8-.cjs';
|
|
2
2
|
|
|
3
3
|
declare const Forms: FormsApi;
|
|
4
4
|
declare const form: (target: FormTarget, options?: FormControllerOptions) => FormController;
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v as FormsApi, w as FormsAvailable, F as FormTarget, a as FormControllerOptions, b as FormController, N as NewFormInput } from '../registry-CPe_lf8-.js';
|
|
2
2
|
|
|
3
3
|
declare const Forms: FormsApi;
|
|
4
4
|
declare const form: (target: FormTarget, options?: FormControllerOptions) => FormController;
|
package/dist/browser/index.js
CHANGED
|
@@ -372,12 +372,37 @@ var restoreCursor = (field, position) => {
|
|
|
372
372
|
var state = null;
|
|
373
373
|
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).";
|
|
374
374
|
var warned = false;
|
|
375
|
+
var phonePromise = null;
|
|
376
|
+
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.";
|
|
375
377
|
var warnOnce = () => {
|
|
376
378
|
if (warned) return;
|
|
377
379
|
warned = true;
|
|
378
380
|
console.error(MISSING_MESSAGE);
|
|
379
381
|
};
|
|
380
|
-
var
|
|
382
|
+
var ensurePhone = (formatter) => {
|
|
383
|
+
if (typeof formatter.isPhoneRegistered !== "function") return Promise.resolve(true);
|
|
384
|
+
if (formatter.isPhoneRegistered()) return Promise.resolve(true);
|
|
385
|
+
if (!phonePromise) {
|
|
386
|
+
phonePromise = (async () => {
|
|
387
|
+
try {
|
|
388
|
+
const mod = await import("@samline/formatter/phone");
|
|
389
|
+
mod.registerPhone();
|
|
390
|
+
return true;
|
|
391
|
+
} catch {
|
|
392
|
+
console.error(PHONE_MESSAGE);
|
|
393
|
+
phonePromise = null;
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
})();
|
|
397
|
+
}
|
|
398
|
+
return phonePromise;
|
|
399
|
+
};
|
|
400
|
+
var loadFormatter = async (options = {}) => {
|
|
401
|
+
const formatter = await loadFormatterModule();
|
|
402
|
+
if (!formatter || !options.phone) return formatter;
|
|
403
|
+
return await ensurePhone(formatter) ? formatter : null;
|
|
404
|
+
};
|
|
405
|
+
var loadFormatterModule = () => {
|
|
381
406
|
if (state && state.status === "resolved") {
|
|
382
407
|
if (!state.module) warnOnce();
|
|
383
408
|
return Promise.resolve(state.module);
|
|
@@ -512,7 +537,7 @@ var applyFormat = async (state2, helpers, config) => {
|
|
|
512
537
|
phase1Entries.push(entry);
|
|
513
538
|
}
|
|
514
539
|
}
|
|
515
|
-
const formatter = await loadFormatter();
|
|
540
|
+
const formatter = await loadFormatter({ phone: formatType === "phone" });
|
|
516
541
|
if (state2.isDestroyed) {
|
|
517
542
|
rollbackPhase1(phase1Entries, bucket, state2.formattedFields);
|
|
518
543
|
return;
|
|
@@ -651,6 +676,7 @@ var createDestroy = (state2, _helpers) => () => {
|
|
|
651
676
|
}
|
|
652
677
|
}
|
|
653
678
|
state2.watchedFields.clear();
|
|
679
|
+
state2.groupWatchers.clear();
|
|
654
680
|
state2.subscribers.clear();
|
|
655
681
|
state2.submitHandlers.clear();
|
|
656
682
|
state2.fieldCache.clear();
|
|
@@ -847,9 +873,9 @@ var writeFieldValue = (fields, value) => {
|
|
|
847
873
|
continue;
|
|
848
874
|
}
|
|
849
875
|
if (field instanceof HTMLSelectElement && field.multiple) {
|
|
850
|
-
const
|
|
876
|
+
const selectedValues2 = normalizedArray ?? [normalizedValue];
|
|
851
877
|
for (const option of field.options) {
|
|
852
|
-
option.selected =
|
|
878
|
+
option.selected = selectedValues2.includes(option.value);
|
|
853
879
|
}
|
|
854
880
|
continue;
|
|
855
881
|
}
|
|
@@ -884,8 +910,7 @@ var submitForm = (form2) => {
|
|
|
884
910
|
var createGetValue = (state2, helpers) => (name) => readFieldValue(helpers.getFieldsByName(name));
|
|
885
911
|
|
|
886
912
|
// src/api/observe.ts
|
|
887
|
-
var
|
|
888
|
-
if (state2.isDestroyed) return () => void 0;
|
|
913
|
+
var observeField = (state2, field, callback) => {
|
|
889
914
|
const callbacks = state2.watchedFields.get(field) ?? /* @__PURE__ */ new Set();
|
|
890
915
|
callbacks.add(callback);
|
|
891
916
|
state2.watchedFields.set(field, callbacks);
|
|
@@ -900,6 +925,26 @@ var createObserve = (state2, helpers) => (field, callback) => {
|
|
|
900
925
|
}
|
|
901
926
|
};
|
|
902
927
|
};
|
|
928
|
+
var observeFields = (state2, fields, callback) => {
|
|
929
|
+
const names = Array.from(new Set(fields));
|
|
930
|
+
if (names.length === 0) return () => void 0;
|
|
931
|
+
const entry = { fields: names, callback };
|
|
932
|
+
state2.groupWatchers.add(entry);
|
|
933
|
+
if (state2.element) {
|
|
934
|
+
const values = Object.fromEntries(names.map((name) => [name, state2.api.getValue(name)]));
|
|
935
|
+
callback(values, null, state2.element, state2.api.getState());
|
|
936
|
+
}
|
|
937
|
+
return () => {
|
|
938
|
+
state2.groupWatchers.delete(entry);
|
|
939
|
+
};
|
|
940
|
+
};
|
|
941
|
+
var createObserve = (state2, _helpers) => {
|
|
942
|
+
function observe(field, callback) {
|
|
943
|
+
if (state2.isDestroyed) return () => void 0;
|
|
944
|
+
return Array.isArray(field) ? observeFields(state2, field, callback) : observeField(state2, field, callback);
|
|
945
|
+
}
|
|
946
|
+
return observe;
|
|
947
|
+
};
|
|
903
948
|
|
|
904
949
|
// src/api/on-submit.ts
|
|
905
950
|
var createOnSubmit = (state2, _helpers) => (callback, preventDefault = true) => {
|
|
@@ -971,6 +1016,75 @@ var createSetErrors = (state2, helpers) => (fields) => {
|
|
|
971
1016
|
return state2.api;
|
|
972
1017
|
};
|
|
973
1018
|
|
|
1019
|
+
// src/api/set-options.ts
|
|
1020
|
+
var isGroup = (entry) => typeof entry === "object" && entry !== null && Array.isArray(entry.options);
|
|
1021
|
+
var createOption = (entry) => {
|
|
1022
|
+
const option = document.createElement("option");
|
|
1023
|
+
if (typeof entry === "object") {
|
|
1024
|
+
option.value = String(entry.value);
|
|
1025
|
+
option.textContent = entry.label ?? String(entry.value);
|
|
1026
|
+
option.disabled = Boolean(entry.disabled);
|
|
1027
|
+
if (entry.selected) option.defaultSelected = true;
|
|
1028
|
+
} else {
|
|
1029
|
+
option.value = String(entry);
|
|
1030
|
+
option.textContent = String(entry);
|
|
1031
|
+
}
|
|
1032
|
+
return option;
|
|
1033
|
+
};
|
|
1034
|
+
var buildNodes = (options) => {
|
|
1035
|
+
const nodes = [];
|
|
1036
|
+
let hasExplicitSelection = false;
|
|
1037
|
+
const track = (option) => {
|
|
1038
|
+
if (option.defaultSelected) hasExplicitSelection = true;
|
|
1039
|
+
return option;
|
|
1040
|
+
};
|
|
1041
|
+
for (const entry of options) {
|
|
1042
|
+
if (entry === null || entry === void 0) continue;
|
|
1043
|
+
if (isGroup(entry)) {
|
|
1044
|
+
const group = document.createElement("optgroup");
|
|
1045
|
+
group.label = entry.label;
|
|
1046
|
+
group.disabled = Boolean(entry.disabled);
|
|
1047
|
+
for (const child of entry.options) {
|
|
1048
|
+
if (child === null || child === void 0) continue;
|
|
1049
|
+
group.appendChild(track(createOption(child)));
|
|
1050
|
+
}
|
|
1051
|
+
nodes.push(group);
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
nodes.push(track(createOption(entry)));
|
|
1055
|
+
}
|
|
1056
|
+
return { nodes, hasExplicitSelection };
|
|
1057
|
+
};
|
|
1058
|
+
var selectedValues = (select) => Array.from(select.selectedOptions, (option) => option.value);
|
|
1059
|
+
var restoreSelection = (select, previous) => {
|
|
1060
|
+
if (previous.length === 0) return;
|
|
1061
|
+
const options = Array.from(select.options);
|
|
1062
|
+
if (select.multiple) {
|
|
1063
|
+
for (const option of options) option.selected = previous.includes(option.value);
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
const match = options.find((option) => option.value === previous[0]);
|
|
1067
|
+
if (match) match.selected = true;
|
|
1068
|
+
};
|
|
1069
|
+
var sameValues = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
1070
|
+
var createSetOptions = (state2, helpers) => (name, options, config = {}) => {
|
|
1071
|
+
if (!state2.element || state2.isDestroyed) return state2.api;
|
|
1072
|
+
const selects = helpers.getFieldsByName(name).filter((field) => field instanceof HTMLSelectElement);
|
|
1073
|
+
if (selects.length === 0) return state2.api;
|
|
1074
|
+
const keepValue = config.keepValue ?? true;
|
|
1075
|
+
const changed = [];
|
|
1076
|
+
for (const select of selects) {
|
|
1077
|
+
const previous = selectedValues(select);
|
|
1078
|
+
const { nodes, hasExplicitSelection } = buildNodes(options);
|
|
1079
|
+
select.replaceChildren(...nodes);
|
|
1080
|
+
if (keepValue && !hasExplicitSelection) restoreSelection(select, previous);
|
|
1081
|
+
if (!sameValues(previous, selectedValues(select))) changed.push(select);
|
|
1082
|
+
}
|
|
1083
|
+
helpers.commitOwnMutations(selects);
|
|
1084
|
+
changed[0]?.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1085
|
+
return state2.api;
|
|
1086
|
+
};
|
|
1087
|
+
|
|
974
1088
|
// src/api/set-value.ts
|
|
975
1089
|
var createSetValue = (state2, helpers) => (name, value) => {
|
|
976
1090
|
if (state2.isDestroyed) return state2.api;
|
|
@@ -994,28 +1108,46 @@ var createSubscribe = (state2, _helpers) => (listener) => {
|
|
|
994
1108
|
};
|
|
995
1109
|
|
|
996
1110
|
// src/api/unwatch.ts
|
|
997
|
-
var
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1111
|
+
var sameFields = (left, right) => left.length === right.size && left.every((name) => right.has(name));
|
|
1112
|
+
var createUnwatch = (state2, _helpers) => {
|
|
1113
|
+
function unwatch(field, callback) {
|
|
1114
|
+
if (field === void 0 || field === "") {
|
|
1115
|
+
state2.watchedFields.clear();
|
|
1116
|
+
state2.groupWatchers.clear();
|
|
1117
|
+
return state2.api;
|
|
1118
|
+
}
|
|
1119
|
+
if (Array.isArray(field)) {
|
|
1120
|
+
const names = new Set(field);
|
|
1121
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
1122
|
+
if (!sameFields(entry.fields, names)) continue;
|
|
1123
|
+
if (callback && entry.callback !== callback) continue;
|
|
1124
|
+
state2.groupWatchers.delete(entry);
|
|
1125
|
+
}
|
|
1126
|
+
return state2.api;
|
|
1127
|
+
}
|
|
1128
|
+
if (!callback) {
|
|
1129
|
+
state2.watchedFields.delete(field);
|
|
1130
|
+
return state2.api;
|
|
1131
|
+
}
|
|
1132
|
+
const callbacks = state2.watchedFields.get(field);
|
|
1133
|
+
callbacks?.delete(callback);
|
|
1134
|
+
if (callbacks && callbacks.size === 0) {
|
|
1135
|
+
state2.watchedFields.delete(field);
|
|
1136
|
+
}
|
|
1004
1137
|
return state2.api;
|
|
1005
1138
|
}
|
|
1006
|
-
|
|
1007
|
-
callbacks?.delete(callback);
|
|
1008
|
-
if (callbacks && callbacks.size === 0) {
|
|
1009
|
-
state2.watchedFields.delete(field);
|
|
1010
|
-
}
|
|
1011
|
-
return state2.api;
|
|
1139
|
+
return unwatch;
|
|
1012
1140
|
};
|
|
1013
1141
|
|
|
1014
1142
|
// src/api/watch.ts
|
|
1015
|
-
var createWatch = (state2, helpers) =>
|
|
1143
|
+
var createWatch = (state2, helpers) => {
|
|
1016
1144
|
const observe = createObserve(state2, helpers);
|
|
1017
|
-
|
|
1018
|
-
|
|
1145
|
+
function watch(field, callback) {
|
|
1146
|
+
if (Array.isArray(field)) observe(field, callback);
|
|
1147
|
+
else observe(field, callback);
|
|
1148
|
+
return state2.api;
|
|
1149
|
+
}
|
|
1150
|
+
return watch;
|
|
1019
1151
|
};
|
|
1020
1152
|
|
|
1021
1153
|
// src/core/controller.ts
|
|
@@ -1042,6 +1174,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1042
1174
|
attributes,
|
|
1043
1175
|
validators: normalizedOptions.validators ?? {},
|
|
1044
1176
|
watchedFields: /* @__PURE__ */ new Map(),
|
|
1177
|
+
groupWatchers: /* @__PURE__ */ new Set(),
|
|
1045
1178
|
subscribers: /* @__PURE__ */ new Set(),
|
|
1046
1179
|
submitHandlers: /* @__PURE__ */ new Set(),
|
|
1047
1180
|
fieldCache: /* @__PURE__ */ new Map(),
|
|
@@ -1212,7 +1345,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1212
1345
|
}
|
|
1213
1346
|
return affected;
|
|
1214
1347
|
};
|
|
1215
|
-
const
|
|
1348
|
+
const emitSingleWatchers = (name) => {
|
|
1216
1349
|
if (!state2.element || !state2.api) return;
|
|
1217
1350
|
const callbacks = state2.watchedFields.get(name);
|
|
1218
1351
|
if (!callbacks || callbacks.size === 0) return;
|
|
@@ -1221,6 +1354,23 @@ var createFormController = (target, options = {}) => {
|
|
|
1221
1354
|
const snapshot = state2.api.getState();
|
|
1222
1355
|
callbacks.forEach((callback) => callback(value, fieldElement, state2.element, snapshot));
|
|
1223
1356
|
};
|
|
1357
|
+
const emitGroupWatchers = (names) => {
|
|
1358
|
+
if (!state2.element || !state2.api || state2.groupWatchers.size === 0) return;
|
|
1359
|
+
let snapshot;
|
|
1360
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
1361
|
+
const changed = names ? names.find((name) => entry.fields.includes(name)) : null;
|
|
1362
|
+
if (changed === void 0) continue;
|
|
1363
|
+
snapshot ?? (snapshot = state2.api.getState());
|
|
1364
|
+
const values = Object.fromEntries(
|
|
1365
|
+
entry.fields.map((field) => [field, state2.api.getValue(field)])
|
|
1366
|
+
);
|
|
1367
|
+
entry.callback(values, changed, state2.element, snapshot);
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
const emitFieldWatchers = (name) => {
|
|
1371
|
+
emitSingleWatchers(name);
|
|
1372
|
+
emitGroupWatchers([name]);
|
|
1373
|
+
};
|
|
1224
1374
|
const runAutoSubmit = () => {
|
|
1225
1375
|
state2.autoSubmitTimer = null;
|
|
1226
1376
|
if (!state2.element || state2.isDestroyed || !state2.autoSubmitEnabled) return;
|
|
@@ -1241,8 +1391,20 @@ var createFormController = (target, options = {}) => {
|
|
|
1241
1391
|
}
|
|
1242
1392
|
runAutoSubmit();
|
|
1243
1393
|
};
|
|
1394
|
+
const selectSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1395
|
+
const readSelectSnapshot = (select) => Array.from(select.selectedOptions, (option) => option.value).join("\0");
|
|
1396
|
+
const snapshotSelect = (select) => {
|
|
1397
|
+
selectSnapshots.set(select, readSelectSnapshot(select));
|
|
1398
|
+
};
|
|
1399
|
+
const snapshotAllSelects = () => {
|
|
1400
|
+
if (!state2.element) return;
|
|
1401
|
+
for (const field of getNamedFields(state2.element)) {
|
|
1402
|
+
if (field instanceof HTMLSelectElement) snapshotSelect(field);
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1244
1405
|
const emitAllFieldWatchers = () => {
|
|
1245
|
-
for (const name of Array.from(state2.watchedFields.keys()))
|
|
1406
|
+
for (const name of Array.from(state2.watchedFields.keys())) emitSingleWatchers(name);
|
|
1407
|
+
emitGroupWatchers(null);
|
|
1246
1408
|
};
|
|
1247
1409
|
const applyReset = () => {
|
|
1248
1410
|
if (!state2.element || state2.isDestroyed) return;
|
|
@@ -1254,6 +1416,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1254
1416
|
state2.validationElementErrors.clear();
|
|
1255
1417
|
clearAttributes(state2.element, [attributes.error, attributes.filled, "aria-invalid"]);
|
|
1256
1418
|
syncVisualState();
|
|
1419
|
+
snapshotAllSelects();
|
|
1257
1420
|
emitAllFieldWatchers();
|
|
1258
1421
|
notifySubscribers();
|
|
1259
1422
|
};
|
|
@@ -1268,7 +1431,8 @@ var createFormController = (target, options = {}) => {
|
|
|
1268
1431
|
validateNames,
|
|
1269
1432
|
emitFieldWatchers,
|
|
1270
1433
|
scheduleAutoSubmit,
|
|
1271
|
-
applyReset
|
|
1434
|
+
applyReset,
|
|
1435
|
+
commitOwnMutations: (selects) => commitOwnMutations(selects)
|
|
1272
1436
|
};
|
|
1273
1437
|
const handleDelegatedEvent = (event) => {
|
|
1274
1438
|
const target2 = event.target;
|
|
@@ -1276,6 +1440,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1276
1440
|
const name = target2.name;
|
|
1277
1441
|
if (!name) return;
|
|
1278
1442
|
clearFieldCache();
|
|
1443
|
+
if (target2 instanceof HTMLSelectElement) snapshotSelect(target2);
|
|
1279
1444
|
const canonical = resolveCanonicalForName(state2, name) ?? name;
|
|
1280
1445
|
const displayName = resolveDisplayNameForName(state2, name);
|
|
1281
1446
|
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
@@ -1286,8 +1451,9 @@ var createFormController = (target, options = {}) => {
|
|
|
1286
1451
|
if (state2.isValidated && affectedValidationNames.some((field) => state2.validators[field] !== void 0)) {
|
|
1287
1452
|
validateNames(affectedValidationNames);
|
|
1288
1453
|
}
|
|
1289
|
-
|
|
1290
|
-
if (canonical !== name)
|
|
1454
|
+
emitSingleWatchers(canonical);
|
|
1455
|
+
if (canonical !== name) emitSingleWatchers(name);
|
|
1456
|
+
emitGroupWatchers(canonical !== name ? [canonical, name] : [canonical]);
|
|
1291
1457
|
notifySubscribers();
|
|
1292
1458
|
scheduleAutoSubmit();
|
|
1293
1459
|
};
|
|
@@ -1316,6 +1482,10 @@ var createFormController = (target, options = {}) => {
|
|
|
1316
1482
|
};
|
|
1317
1483
|
const handleSubmitEvent = (event) => {
|
|
1318
1484
|
if (!state2.element || state2.isDestroyed || !state2.api) return;
|
|
1485
|
+
if (!state2.isAutoSubmitting && state2.autoSubmitTimer) {
|
|
1486
|
+
clearTimeout(state2.autoSubmitTimer);
|
|
1487
|
+
state2.autoSubmitTimer = null;
|
|
1488
|
+
}
|
|
1319
1489
|
if (normalizedOptions.clearErrorsOnSubmit) state2.manualErrors = {};
|
|
1320
1490
|
const validation = state2.api.validate();
|
|
1321
1491
|
const handlers = Array.from(state2.submitHandlers);
|
|
@@ -1368,18 +1538,62 @@ var createFormController = (target, options = {}) => {
|
|
|
1368
1538
|
const cancel = () => clearTimeout(timer);
|
|
1369
1539
|
state2.cleanups.add(cancel);
|
|
1370
1540
|
};
|
|
1541
|
+
const touchesFields = (node) => node instanceof Element && (isFieldElement(node) || node.querySelector("input, select, textarea") !== null);
|
|
1542
|
+
const isStructural = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1543
|
+
const isOptionNode = (node) => node instanceof HTMLOptionElement || node instanceof HTMLOptGroupElement;
|
|
1544
|
+
const optionListOwner = (record) => {
|
|
1545
|
+
if (record.type !== "childList") return null;
|
|
1546
|
+
const touchesOptions = Array.from(record.addedNodes).some(isOptionNode) || Array.from(record.removedNodes).some(isOptionNode);
|
|
1547
|
+
if (!touchesOptions) return null;
|
|
1548
|
+
const target2 = record.target;
|
|
1549
|
+
if (target2 instanceof HTMLSelectElement) return target2;
|
|
1550
|
+
if (target2 instanceof HTMLOptGroupElement && target2.parentElement instanceof HTMLSelectElement) {
|
|
1551
|
+
return target2.parentElement;
|
|
1552
|
+
}
|
|
1553
|
+
return null;
|
|
1554
|
+
};
|
|
1555
|
+
const handleMutations = (records) => {
|
|
1556
|
+
if (state2.isDestroyed) return;
|
|
1557
|
+
const structural = records.some(isStructural);
|
|
1558
|
+
const changedNames = /* @__PURE__ */ new Set();
|
|
1559
|
+
for (const record of records) {
|
|
1560
|
+
const select = optionListOwner(record);
|
|
1561
|
+
if (!select || !select.name) continue;
|
|
1562
|
+
const next = readSelectSnapshot(select);
|
|
1563
|
+
if (selectSnapshots.get(select) !== next) changedNames.add(select.name);
|
|
1564
|
+
selectSnapshots.set(select, next);
|
|
1565
|
+
}
|
|
1566
|
+
if (!structural && changedNames.size === 0) return;
|
|
1567
|
+
clearFieldCache();
|
|
1568
|
+
if (structural) {
|
|
1569
|
+
snapshotAllSelects();
|
|
1570
|
+
if (state2.isValidated) validateNames();
|
|
1571
|
+
else syncVisualState();
|
|
1572
|
+
} else {
|
|
1573
|
+
const affected = /* @__PURE__ */ new Set();
|
|
1574
|
+
for (const name of changedNames) {
|
|
1575
|
+
for (const field of getAffectedValidationNames(name)) affected.add(field);
|
|
1576
|
+
}
|
|
1577
|
+
const names = Array.from(affected);
|
|
1578
|
+
syncVisualState(Array.from(changedNames));
|
|
1579
|
+
if (state2.isValidated && names.some((field) => state2.validators[field] !== void 0)) {
|
|
1580
|
+
validateNames(names);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
for (const name of changedNames) emitFieldWatchers(name);
|
|
1584
|
+
notifySubscribers();
|
|
1585
|
+
};
|
|
1586
|
+
const commitOwnMutations = (selects) => {
|
|
1587
|
+
selects.forEach(snapshotSelect);
|
|
1588
|
+
const pending = state2.mutationObserver?.takeRecords() ?? [];
|
|
1589
|
+
const foreign = pending.filter(
|
|
1590
|
+
(record) => !selects.some((select) => select.contains(record.target))
|
|
1591
|
+
);
|
|
1592
|
+
if (foreign.length > 0) handleMutations(foreign);
|
|
1593
|
+
};
|
|
1371
1594
|
const startMutationObserver = () => {
|
|
1372
1595
|
if (!state2.element || typeof MutationObserver === "undefined") return;
|
|
1373
|
-
|
|
1374
|
-
const isRelevant = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1375
|
-
state2.mutationObserver = new MutationObserver((records) => {
|
|
1376
|
-
if (state2.isDestroyed || !records.some(isRelevant)) return;
|
|
1377
|
-
clearFieldCache();
|
|
1378
|
-
if (state2.isValidated) {
|
|
1379
|
-
validateNames();
|
|
1380
|
-
} else syncVisualState();
|
|
1381
|
-
notifySubscribers();
|
|
1382
|
-
});
|
|
1596
|
+
state2.mutationObserver = new MutationObserver(handleMutations);
|
|
1383
1597
|
state2.mutationObserver.observe(state2.element, {
|
|
1384
1598
|
childList: true,
|
|
1385
1599
|
subtree: true,
|
|
@@ -1408,6 +1622,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1408
1622
|
setErrors: createSetErrors(state2, helpers),
|
|
1409
1623
|
clearErrors: createClearErrors(state2, helpers),
|
|
1410
1624
|
setValue: createSetValue(state2, helpers),
|
|
1625
|
+
setOptions: createSetOptions(state2, helpers),
|
|
1411
1626
|
getValue: createGetValue(state2, helpers),
|
|
1412
1627
|
getField: createGetField(state2, helpers),
|
|
1413
1628
|
validate: createValidate(state2, helpers),
|
|
@@ -1427,6 +1642,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1427
1642
|
addListener2(document, "input", handleExternalDelegatedEvent);
|
|
1428
1643
|
addListener2(state2.element, "submit", handleSubmitEvent);
|
|
1429
1644
|
addListener2(state2.element, "reset", handleResetEvent);
|
|
1645
|
+
snapshotAllSelects();
|
|
1430
1646
|
startMutationObserver();
|
|
1431
1647
|
}
|
|
1432
1648
|
if (normalizedOptions.autoSubmit) {
|
|
@@ -1486,4 +1702,4 @@ export {
|
|
|
1486
1702
|
form,
|
|
1487
1703
|
browser
|
|
1488
1704
|
};
|
|
1489
|
-
//# sourceMappingURL=chunk-
|
|
1705
|
+
//# sourceMappingURL=chunk-JAEFD56I.js.map
|