@samline/forms 2.3.4 → 2.6.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/LICENSE +21 -0
- package/README.md +8 -7
- package/dist/browser/global.d.ts +10 -16
- package/dist/browser/global.global.js +328 -51
- package/dist/browser/global.global.js.map +1 -1
- package/dist/browser/index.cjs +1309 -0
- package/dist/browser/index.cjs.map +1 -0
- package/dist/browser/index.d.cts +14 -0
- package/dist/browser/index.d.ts +14 -0
- package/dist/browser/index.js +23 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/chunk-L4GRKSQ5.js +1270 -0
- package/dist/chunk-L4GRKSQ5.js.map +1 -0
- package/dist/index.cjs +143 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -158
- package/dist/index.d.ts +4 -158
- package/dist/index.js +7 -1141
- package/dist/index.js.map +1 -1
- package/dist/registry-BpqJetAt.d.cts +148 -0
- package/dist/registry-BpqJetAt.d.ts +148 -0
- package/docs/api/append.md +96 -0
- package/docs/api/auto-submit.md +91 -0
- package/docs/api/clear-errors.md +69 -0
- package/docs/api/destroy.md +65 -0
- package/docs/api/disable-auto-submit.md +65 -0
- package/docs/api/element.md +78 -0
- package/docs/api/form.md +154 -0
- package/docs/api/format.md +270 -0
- package/docs/api/get-data.md +90 -0
- package/docs/api/get-field.md +87 -0
- package/docs/api/get-state.md +95 -0
- package/docs/api/get-value.md +114 -0
- package/docs/api/index.md +54 -0
- package/docs/api/observe.md +126 -0
- package/docs/api/on-submit.md +90 -0
- package/docs/api/parse-form-data.md +94 -0
- package/docs/api/prefill.md +89 -0
- package/docs/api/regex.md +155 -0
- package/docs/api/reset.md +60 -0
- package/docs/api/revalidate.md +50 -0
- package/docs/api/set-errors.md +97 -0
- package/docs/api/set-value.md +120 -0
- package/docs/api/subscribe.md +91 -0
- package/docs/api/unwatch.md +74 -0
- package/docs/api/validate-field-value.md +108 -0
- package/docs/api/validate-values.md +100 -0
- package/docs/api/validate.md +100 -0
- package/docs/api/watch.md +117 -0
- package/docs/browser.md +156 -0
- package/docs/css-styling.md +187 -0
- package/docs/getting-started.md +217 -0
- package/docs/options.md +259 -0
- package/docs/recipes.md +477 -0
- package/docs/typescript.md +576 -0
- package/docs/vanilla.md +12 -0
- package/package.json +60 -16
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,7 @@ var createAppend = (state2, helpers) => ({ tag, content, class: className, atSta
|
|
|
45
45
|
helpers.clearFieldCache();
|
|
46
46
|
if (className) {
|
|
47
47
|
const classSelector = className.trim().split(/\s+/)[0];
|
|
48
|
-
const existing = classSelector ? state2.element.
|
|
48
|
+
const existing = classSelector ? state2.element.getElementsByClassName(classSelector)[0] : null;
|
|
49
49
|
existing?.remove();
|
|
50
50
|
}
|
|
51
51
|
const node = document.createElement(tag);
|
|
@@ -62,6 +62,10 @@ var createAppend = (state2, helpers) => ({ tag, content, class: className, atSta
|
|
|
62
62
|
// src/api/auto-submit.ts
|
|
63
63
|
var createAutoSubmit = (state2, helpers) => (next = true) => {
|
|
64
64
|
state2.autoSubmitEnabled = next !== false;
|
|
65
|
+
if (!state2.autoSubmitEnabled && state2.autoSubmitTimer) {
|
|
66
|
+
clearTimeout(state2.autoSubmitTimer);
|
|
67
|
+
state2.autoSubmitTimer = null;
|
|
68
|
+
}
|
|
65
69
|
state2.autoSubmitDebounce = typeof next === "object" && next ? next.debounce ?? 0 : 0;
|
|
66
70
|
helpers.notifySubscribers();
|
|
67
71
|
return state2.api;
|
|
@@ -272,6 +276,11 @@ var readInputType = (event) => {
|
|
|
272
276
|
const candidate = event;
|
|
273
277
|
return typeof candidate.inputType === "string" ? candidate.inputType : void 0;
|
|
274
278
|
};
|
|
279
|
+
var buildAutoInterpretedOptions = (formatOptions) => ({
|
|
280
|
+
...formatOptions ?? {},
|
|
281
|
+
interpretInputAs: "auto"
|
|
282
|
+
});
|
|
283
|
+
var shouldForceAutoInterpretation = (formatOptions) => formatOptions?.interpretInputAs === void 0;
|
|
275
284
|
var buildHandler = (visible, mirror, formatFn, formatType, formatOptions) => {
|
|
276
285
|
const handler = (event) => {
|
|
277
286
|
if (!visible.isConnected || !mirror.isConnected) return;
|
|
@@ -280,7 +289,8 @@ var buildHandler = (visible, mirror, formatFn, formatType, formatOptions) => {
|
|
|
280
289
|
if (!isVisible && !isMirror) return;
|
|
281
290
|
const rawInput = isMirror ? mirror.value : visible.value;
|
|
282
291
|
const inputType = readInputType(event);
|
|
283
|
-
const
|
|
292
|
+
const sourceOptions = isMirror && shouldForceAutoInterpretation(formatOptions) ? buildAutoInterpretedOptions(formatOptions) : formatOptions;
|
|
293
|
+
const { formatted, raw } = formatFn(rawInput, formatType, sourceOptions);
|
|
284
294
|
if (!formatted && !raw) {
|
|
285
295
|
visible.value = "";
|
|
286
296
|
if (mirror.value !== "") mirror.value = "";
|
|
@@ -292,6 +302,12 @@ var buildHandler = (visible, mirror, formatFn, formatType, formatOptions) => {
|
|
|
292
302
|
};
|
|
293
303
|
var applyFormat = async (state2, helpers, config) => {
|
|
294
304
|
if (!state2.element || !state2.api) return;
|
|
305
|
+
if (Array.isArray(config.field) && config.displayField) {
|
|
306
|
+
console.error(
|
|
307
|
+
"[samline/forms] `displayField` can only be used when `field` is a string."
|
|
308
|
+
);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
295
311
|
const formatType = config.type;
|
|
296
312
|
const formatOptions = config.options;
|
|
297
313
|
const fieldNames = resolveFieldNames(config);
|
|
@@ -329,6 +345,8 @@ var applyFormat = async (state2, helpers, config) => {
|
|
|
329
345
|
visible,
|
|
330
346
|
mirror,
|
|
331
347
|
mirrorIsOwned,
|
|
348
|
+
defaultVisible: null,
|
|
349
|
+
defaultRaw: null,
|
|
332
350
|
handler: UNBOUND
|
|
333
351
|
};
|
|
334
352
|
bucket.set(fieldName, entry);
|
|
@@ -341,6 +359,10 @@ var applyFormat = async (state2, helpers, config) => {
|
|
|
341
359
|
}
|
|
342
360
|
}
|
|
343
361
|
const formatter = await loadFormatter();
|
|
362
|
+
if (state2.isDestroyed) {
|
|
363
|
+
rollbackPhase1(phase1Entries, bucket, state2.formattedFields);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
344
366
|
if (!formatter) {
|
|
345
367
|
rollbackPhase1(phase1Entries, bucket, state2.formattedFields);
|
|
346
368
|
return;
|
|
@@ -365,11 +387,22 @@ var applyFormat = async (state2, helpers, config) => {
|
|
|
365
387
|
entry.handler = handler;
|
|
366
388
|
const initial = entry.visible.value;
|
|
367
389
|
if (initial !== "") {
|
|
368
|
-
const
|
|
390
|
+
const initialOptions = shouldForceAutoInterpretation(formatOptions) ? buildAutoInterpretedOptions(formatOptions) : formatOptions;
|
|
391
|
+
const { formatted, raw } = formatter.format(initial, formatType, initialOptions);
|
|
369
392
|
applyFormattedValue(entry.visible, entry.mirror, formatted, raw);
|
|
370
393
|
} else if (entry.mirrorIsOwned && entry.mirror.value !== "") {
|
|
371
394
|
entry.mirror.value = "";
|
|
372
395
|
}
|
|
396
|
+
entry.defaultVisible = entry.visible.value;
|
|
397
|
+
entry.defaultRaw = entry.mirror.value;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var resetFormattedFields = (state2) => {
|
|
401
|
+
const bucket = registry.get(state2);
|
|
402
|
+
if (!bucket) return;
|
|
403
|
+
for (const entry of bucket.values()) {
|
|
404
|
+
if (entry.defaultVisible !== null) entry.visible.value = entry.defaultVisible;
|
|
405
|
+
if (entry.defaultRaw !== null) entry.mirror.value = entry.defaultRaw;
|
|
373
406
|
}
|
|
374
407
|
};
|
|
375
408
|
var rollbackPhase1 = (entries, bucket, registry2) => {
|
|
@@ -476,19 +509,24 @@ var createDisableAutoSubmit = (state2, helpers) => () => {
|
|
|
476
509
|
// src/core/serialize.ts
|
|
477
510
|
var isEmptyFile = (value) => value instanceof File && value.size === 0 && value.name === "";
|
|
478
511
|
var appendValue = (data, key, value) => {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
512
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
513
|
+
Object.defineProperty(data, key, {
|
|
514
|
+
value,
|
|
515
|
+
writable: true,
|
|
516
|
+
enumerable: true,
|
|
517
|
+
configurable: true
|
|
518
|
+
});
|
|
482
519
|
return;
|
|
483
520
|
}
|
|
521
|
+
const current = data[key];
|
|
484
522
|
if (Array.isArray(current)) {
|
|
485
523
|
current.push(value);
|
|
486
524
|
return;
|
|
487
525
|
}
|
|
488
526
|
data[key] = [current, value];
|
|
489
527
|
};
|
|
490
|
-
var parseFormData = (formElement) => {
|
|
491
|
-
const raw = new FormData(formElement);
|
|
528
|
+
var parseFormData = (formElement, submitter) => {
|
|
529
|
+
const raw = submitter ? new FormData(formElement, submitter) : new FormData(formElement);
|
|
492
530
|
const formData = new FormData();
|
|
493
531
|
const data = {};
|
|
494
532
|
raw.forEach((value, key) => {
|
|
@@ -570,8 +608,8 @@ var resolveFormElement = (target) => {
|
|
|
570
608
|
}
|
|
571
609
|
return null;
|
|
572
610
|
};
|
|
573
|
-
var getNamedFields = (form2) => Array.from(form2.
|
|
574
|
-
isFormFieldElement
|
|
611
|
+
var getNamedFields = (form2) => Array.from(form2.elements).filter(
|
|
612
|
+
(element) => isFormFieldElement(element) && Boolean(element.name)
|
|
575
613
|
);
|
|
576
614
|
var queryNamedFields = (form2, name) => getNamedFields(form2).filter((field) => field.name === name);
|
|
577
615
|
var isFieldElement = (value) => isFormFieldElement(value);
|
|
@@ -618,6 +656,9 @@ var readFieldValue = (fields) => {
|
|
|
618
656
|
}
|
|
619
657
|
return fields.map((f) => f.value);
|
|
620
658
|
}
|
|
659
|
+
if (first instanceof HTMLSelectElement && first.multiple) {
|
|
660
|
+
return Array.from(first.selectedOptions, (option) => option.value);
|
|
661
|
+
}
|
|
621
662
|
if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {
|
|
622
663
|
return first.value;
|
|
623
664
|
}
|
|
@@ -667,6 +708,13 @@ var writeFieldValue = (fields, value) => {
|
|
|
667
708
|
field.value = normalizedValue;
|
|
668
709
|
continue;
|
|
669
710
|
}
|
|
711
|
+
if (field instanceof HTMLSelectElement && field.multiple) {
|
|
712
|
+
const selectedValues = normalizedArray ?? [normalizedValue];
|
|
713
|
+
for (const option of field.options) {
|
|
714
|
+
option.selected = selectedValues.includes(option.value);
|
|
715
|
+
}
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
670
718
|
if (distributeArray && normalizedArray) {
|
|
671
719
|
field.value = normalizedArray[index] ?? "";
|
|
672
720
|
continue;
|
|
@@ -676,7 +724,7 @@ var writeFieldValue = (fields, value) => {
|
|
|
676
724
|
};
|
|
677
725
|
var clearAttributes = (form2, attributes) => {
|
|
678
726
|
for (const attribute of attributes) {
|
|
679
|
-
form2
|
|
727
|
+
getNamedFields(form2).forEach((field) => field.removeAttribute(attribute));
|
|
680
728
|
}
|
|
681
729
|
};
|
|
682
730
|
var submitForm = (form2) => {
|
|
@@ -735,9 +783,14 @@ var createPrefill = (state2, _helpers) => (fieldName) => {
|
|
|
735
783
|
var createReset = (state2, helpers) => () => {
|
|
736
784
|
if (!state2.element) return state2.api;
|
|
737
785
|
state2.element.reset();
|
|
786
|
+
resetFormattedFields(state2);
|
|
738
787
|
state2.manualErrors = {};
|
|
739
788
|
state2.validationErrors = {};
|
|
740
|
-
clearAttributes(state2.element, [
|
|
789
|
+
clearAttributes(state2.element, [
|
|
790
|
+
state2.attributes.error,
|
|
791
|
+
state2.attributes.filled,
|
|
792
|
+
"aria-invalid"
|
|
793
|
+
]);
|
|
741
794
|
if (state2.isValidated) helpers.syncVisualState();
|
|
742
795
|
helpers.notifySubscribers();
|
|
743
796
|
return state2.api;
|
|
@@ -778,8 +831,7 @@ var createSetValue = (state2, helpers) => (name, value) => {
|
|
|
778
831
|
writeFieldValue(fields, value);
|
|
779
832
|
const firstField = fields[0];
|
|
780
833
|
if (!firstField) return state2.api;
|
|
781
|
-
|
|
782
|
-
firstField.dispatchEvent(new Event(eventType, { bubbles: true }));
|
|
834
|
+
firstField.dispatchEvent(new Event("input", { bubbles: true }));
|
|
783
835
|
return state2.api;
|
|
784
836
|
};
|
|
785
837
|
|
|
@@ -844,6 +896,12 @@ var toPatternTarget = (value) => {
|
|
|
844
896
|
}
|
|
845
897
|
return "";
|
|
846
898
|
};
|
|
899
|
+
var valuesAreEqual = (left, right) => {
|
|
900
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
901
|
+
return left.length === right.length && left.every((entry, index) => entry === right[index]);
|
|
902
|
+
}
|
|
903
|
+
return left === right;
|
|
904
|
+
};
|
|
847
905
|
var validateFieldValue = (field, value, rules, values) => {
|
|
848
906
|
const errors = [];
|
|
849
907
|
const context = { field, value, values };
|
|
@@ -851,6 +909,7 @@ var validateFieldValue = (field, value, rules, values) => {
|
|
|
851
909
|
const minLength = resolveRule(rules.minLength);
|
|
852
910
|
const maxLength = resolveRule(rules.maxLength);
|
|
853
911
|
const pattern = resolveRule(rules.pattern);
|
|
912
|
+
const sameAs = resolveRule(rules.sameAs);
|
|
854
913
|
if (required.value && !hasValue(value)) {
|
|
855
914
|
errors.push(required.message ?? "This field is required.");
|
|
856
915
|
}
|
|
@@ -860,8 +919,19 @@ var validateFieldValue = (field, value, rules, values) => {
|
|
|
860
919
|
if (maxLength.value !== void 0 && getValueLength(value) > maxLength.value) {
|
|
861
920
|
errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`);
|
|
862
921
|
}
|
|
863
|
-
if (pattern.value && hasValue(value)
|
|
864
|
-
|
|
922
|
+
if (pattern.value && hasValue(value)) {
|
|
923
|
+
pattern.value.lastIndex = 0;
|
|
924
|
+
const matches = pattern.value.test(toPatternTarget(value));
|
|
925
|
+
pattern.value.lastIndex = 0;
|
|
926
|
+
if (!matches) {
|
|
927
|
+
errors.push(pattern.message ?? "Value does not match the required pattern.");
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
if (sameAs.value !== void 0) {
|
|
931
|
+
const otherValue = values[sameAs.value];
|
|
932
|
+
if (hasValue(value) && hasValue(otherValue) && !valuesAreEqual(value, otherValue)) {
|
|
933
|
+
errors.push(sameAs.message ?? `Value must match ${sameAs.value}.`);
|
|
934
|
+
}
|
|
865
935
|
}
|
|
866
936
|
const custom = rules.validate ? Array.isArray(rules.validate) ? rules.validate : [rules.validate] : [];
|
|
867
937
|
for (const validator of custom) {
|
|
@@ -923,6 +993,15 @@ var createFormController = (target, options = {}) => {
|
|
|
923
993
|
formattedFields: /* @__PURE__ */ new Map(),
|
|
924
994
|
api: null
|
|
925
995
|
};
|
|
996
|
+
const validationDependents = /* @__PURE__ */ new Map();
|
|
997
|
+
for (const [field, rules] of Object.entries(state2.validators)) {
|
|
998
|
+
const sameAs = rules.sameAs;
|
|
999
|
+
if (sameAs === void 0) continue;
|
|
1000
|
+
const source = typeof sameAs === "string" ? sameAs : sameAs.value;
|
|
1001
|
+
const dependents = validationDependents.get(source) ?? /* @__PURE__ */ new Set();
|
|
1002
|
+
dependents.add(field);
|
|
1003
|
+
validationDependents.set(source, dependents);
|
|
1004
|
+
}
|
|
926
1005
|
const notifySubscribers = () => {
|
|
927
1006
|
if (!state2.api) return;
|
|
928
1007
|
const snapshot = state2.api.getState();
|
|
@@ -941,10 +1020,9 @@ var createFormController = (target, options = {}) => {
|
|
|
941
1020
|
const clearFieldCache = () => state2.fieldCache.clear();
|
|
942
1021
|
const getFieldsByName = (name) => {
|
|
943
1022
|
if (!state2.element) return [];
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
return state2.fieldCache.get(name) ?? [];
|
|
1023
|
+
const fields = queryNamedFields(state2.element, name);
|
|
1024
|
+
state2.fieldCache.set(name, fields);
|
|
1025
|
+
return fields;
|
|
948
1026
|
};
|
|
949
1027
|
const getTrackedFieldNames = () => {
|
|
950
1028
|
if (!state2.element) return Object.keys(state2.validators);
|
|
@@ -980,6 +1058,8 @@ var createFormController = (target, options = {}) => {
|
|
|
980
1058
|
for (const field of fields) {
|
|
981
1059
|
applyBooleanAttribute(field, attributes.filled, isFieldFilled(field));
|
|
982
1060
|
applyBooleanAttribute(field, attributes.error, hasError);
|
|
1061
|
+
if (hasError) field.setAttribute("aria-invalid", "true");
|
|
1062
|
+
else field.removeAttribute("aria-invalid");
|
|
983
1063
|
}
|
|
984
1064
|
}
|
|
985
1065
|
};
|
|
@@ -1006,6 +1086,21 @@ var createFormController = (target, options = {}) => {
|
|
|
1006
1086
|
errors: cloneErrors(getMergedErrors())
|
|
1007
1087
|
};
|
|
1008
1088
|
};
|
|
1089
|
+
const getAffectedValidationNames = (name) => {
|
|
1090
|
+
const affected = [];
|
|
1091
|
+
const pending = [name];
|
|
1092
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1093
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
1094
|
+
const current = pending[index];
|
|
1095
|
+
if (visited.has(current)) continue;
|
|
1096
|
+
visited.add(current);
|
|
1097
|
+
affected.push(current);
|
|
1098
|
+
for (const dependent of validationDependents.get(current) ?? []) {
|
|
1099
|
+
if (!visited.has(dependent)) pending.push(dependent);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
return affected;
|
|
1103
|
+
};
|
|
1009
1104
|
const emitFieldWatchers = (name) => {
|
|
1010
1105
|
if (!state2.element || !state2.api) return;
|
|
1011
1106
|
const callbacks = state2.watchedFields.get(name);
|
|
@@ -1051,14 +1146,21 @@ var createFormController = (target, options = {}) => {
|
|
|
1051
1146
|
delete state2.manualErrors[canonical];
|
|
1052
1147
|
}
|
|
1053
1148
|
syncVisualState([displayName]);
|
|
1054
|
-
|
|
1055
|
-
|
|
1149
|
+
const affectedValidationNames = getAffectedValidationNames(canonical);
|
|
1150
|
+
if (state2.isValidated && affectedValidationNames.some((field) => state2.validators[field] !== void 0)) {
|
|
1151
|
+
validateNames(affectedValidationNames);
|
|
1056
1152
|
}
|
|
1057
1153
|
emitFieldWatchers(canonical);
|
|
1058
1154
|
if (canonical !== name) emitFieldWatchers(name);
|
|
1059
1155
|
notifySubscribers();
|
|
1060
1156
|
scheduleAutoSubmit();
|
|
1061
1157
|
};
|
|
1158
|
+
const handleExternalDelegatedEvent = (event) => {
|
|
1159
|
+
const target2 = event.target;
|
|
1160
|
+
if (!(target2 instanceof Element) || !isFieldElement(target2)) return;
|
|
1161
|
+
if (target2.form !== state2.element || state2.element?.contains(target2)) return;
|
|
1162
|
+
handleDelegatedEvent(event);
|
|
1163
|
+
};
|
|
1062
1164
|
const handleSubmitEvent = (event) => {
|
|
1063
1165
|
if (!state2.element || state2.isDestroyed || !state2.api) return;
|
|
1064
1166
|
if (normalizedOptions.clearErrorsOnSubmit) state2.manualErrors = {};
|
|
@@ -1068,8 +1170,23 @@ var createFormController = (target, options = {}) => {
|
|
|
1068
1170
|
if (shouldPrevent) event.preventDefault();
|
|
1069
1171
|
state2.submitCount += 1;
|
|
1070
1172
|
notifySubscribers();
|
|
1071
|
-
if (!validation.isValid)
|
|
1072
|
-
|
|
1173
|
+
if (!validation.isValid) {
|
|
1174
|
+
for (const name of Object.keys(validation.errors)) {
|
|
1175
|
+
const displayName = resolveDisplayNameForName(state2, name);
|
|
1176
|
+
const field = getFieldsByName(displayName).find((candidate2) => {
|
|
1177
|
+
if (!candidate2.isConnected || candidate2.disabled || candidate2.hidden) return false;
|
|
1178
|
+
return !(candidate2 instanceof HTMLInputElement && candidate2.type === "hidden");
|
|
1179
|
+
});
|
|
1180
|
+
if (field) {
|
|
1181
|
+
field.focus();
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
const candidate = event;
|
|
1188
|
+
const submitter = candidate.submitter instanceof HTMLElement ? candidate.submitter : null;
|
|
1189
|
+
const { data, formData } = parseFormData(state2.element, submitter);
|
|
1073
1190
|
const snapshot = state2.api.getState();
|
|
1074
1191
|
handlers.forEach(
|
|
1075
1192
|
(handler) => handler.callback(state2.element, data, formData, snapshot)
|
|
@@ -1128,7 +1245,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1128
1245
|
state2.api = api;
|
|
1129
1246
|
if (state2.element) {
|
|
1130
1247
|
addListener2(state2.element, "input", handleDelegatedEvent);
|
|
1131
|
-
addListener2(
|
|
1248
|
+
addListener2(document, "input", handleExternalDelegatedEvent);
|
|
1132
1249
|
addListener2(state2.element, "submit", handleSubmitEvent);
|
|
1133
1250
|
startMutationObserver();
|
|
1134
1251
|
}
|
|
@@ -1158,6 +1275,7 @@ var newForm = (input) => {
|
|
|
1158
1275
|
console.error("Form ID is required");
|
|
1159
1276
|
return;
|
|
1160
1277
|
}
|
|
1278
|
+
available[id]?.destroy();
|
|
1161
1279
|
const controller = form(id, { ...options });
|
|
1162
1280
|
available[id] = controller;
|
|
1163
1281
|
return controller;
|