auto-webmcp 0.2.8 → 0.2.10
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/analyzer.d.ts.map +1 -1
- package/dist/auto-webmcp.cjs.js +197 -13
- package/dist/auto-webmcp.cjs.js.map +2 -2
- package/dist/auto-webmcp.esm.js +197 -13
- package/dist/auto-webmcp.esm.js.map +2 -2
- package/dist/auto-webmcp.iife.js +2 -2
- package/dist/auto-webmcp.iife.js.map +3 -3
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/schema.d.ts +6 -0
- package/dist/schema.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAmJ,MAAM,aAAa,CAAC;AAC1L,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAKD,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,YAAY,CAMxF;AAsgBD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,KAAK,CAAC,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC,EACzE,SAAS,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,IAAI,GACrD,YAAY,CAKd"}
|
package/dist/auto-webmcp.cjs.js
CHANGED
|
@@ -207,6 +207,14 @@ function buildStringSchema(input) {
|
|
|
207
207
|
}
|
|
208
208
|
return prop;
|
|
209
209
|
}
|
|
210
|
+
var PLACEHOLDER_PATTERNS = /^(select|choose|pick)\b|^--+|---/i;
|
|
211
|
+
function isPlaceholderOption(opt) {
|
|
212
|
+
if (opt.disabled)
|
|
213
|
+
return true;
|
|
214
|
+
if (opt.value !== "")
|
|
215
|
+
return false;
|
|
216
|
+
return PLACEHOLDER_PATTERNS.test(opt.text.trim());
|
|
217
|
+
}
|
|
210
218
|
function mapSelectElement(select) {
|
|
211
219
|
const enumValues = [];
|
|
212
220
|
const oneOf = [];
|
|
@@ -218,7 +226,7 @@ function mapSelectElement(select) {
|
|
|
218
226
|
for (const opt of Array.from(child.children)) {
|
|
219
227
|
if (!(opt instanceof HTMLOptionElement))
|
|
220
228
|
continue;
|
|
221
|
-
if (opt
|
|
229
|
+
if (isPlaceholderOption(opt))
|
|
222
230
|
continue;
|
|
223
231
|
enumValues.push(opt.value);
|
|
224
232
|
const entry = {
|
|
@@ -230,7 +238,7 @@ function mapSelectElement(select) {
|
|
|
230
238
|
oneOf.push(entry);
|
|
231
239
|
}
|
|
232
240
|
} else if (child instanceof HTMLOptionElement) {
|
|
233
|
-
if (child
|
|
241
|
+
if (isPlaceholderOption(child))
|
|
234
242
|
continue;
|
|
235
243
|
enumValues.push(child.value);
|
|
236
244
|
oneOf.push({ const: child.value, title: child.text.trim() || child.value });
|
|
@@ -238,8 +246,16 @@ function mapSelectElement(select) {
|
|
|
238
246
|
}
|
|
239
247
|
if (enumValues.length === 0)
|
|
240
248
|
return { type: "string" };
|
|
249
|
+
if (select.multiple) {
|
|
250
|
+
return { type: "array", items: { type: "string", enum: enumValues } };
|
|
251
|
+
}
|
|
241
252
|
return { type: "string", enum: enumValues, oneOf };
|
|
242
253
|
}
|
|
254
|
+
function collectCheckboxEnum(form, name) {
|
|
255
|
+
return Array.from(
|
|
256
|
+
form.querySelectorAll(`input[type="checkbox"][name="${CSS.escape(name)}"]`)
|
|
257
|
+
).map((cb) => cb.value).filter((v) => v !== "" && v !== "on");
|
|
258
|
+
}
|
|
243
259
|
function collectRadioEnum(form, name) {
|
|
244
260
|
const radios = Array.from(
|
|
245
261
|
form.querySelectorAll(`input[type="radio"][name="${CSS.escape(name)}"]`)
|
|
@@ -426,6 +442,7 @@ function buildSchema(form) {
|
|
|
426
442
|
const required = [];
|
|
427
443
|
const fieldElements = /* @__PURE__ */ new Map();
|
|
428
444
|
const processedRadioGroups = /* @__PURE__ */ new Set();
|
|
445
|
+
const processedCheckboxGroups = /* @__PURE__ */ new Set();
|
|
429
446
|
const controls = Array.from(
|
|
430
447
|
form.querySelectorAll(
|
|
431
448
|
"input, textarea, select"
|
|
@@ -441,6 +458,11 @@ function buildSchema(form) {
|
|
|
441
458
|
continue;
|
|
442
459
|
processedRadioGroups.add(fieldKey);
|
|
443
460
|
}
|
|
461
|
+
if (control instanceof HTMLInputElement && control.type === "checkbox") {
|
|
462
|
+
if (processedCheckboxGroups.has(fieldKey))
|
|
463
|
+
continue;
|
|
464
|
+
processedCheckboxGroups.add(fieldKey);
|
|
465
|
+
}
|
|
444
466
|
const schemaProp = inputTypeToSchema(control);
|
|
445
467
|
if (!schemaProp)
|
|
446
468
|
continue;
|
|
@@ -456,6 +478,22 @@ function buildSchema(form) {
|
|
|
456
478
|
if (radioOneOf.length > 0)
|
|
457
479
|
schemaProp.oneOf = radioOneOf;
|
|
458
480
|
}
|
|
481
|
+
if (control instanceof HTMLInputElement && control.type === "checkbox") {
|
|
482
|
+
const checkboxValues = collectCheckboxEnum(form, fieldKey);
|
|
483
|
+
if (checkboxValues.length > 1) {
|
|
484
|
+
const arrayProp = {
|
|
485
|
+
type: "array",
|
|
486
|
+
items: { type: "string", enum: checkboxValues },
|
|
487
|
+
title: schemaProp.title
|
|
488
|
+
};
|
|
489
|
+
if (schemaProp.description)
|
|
490
|
+
arrayProp.description = schemaProp.description;
|
|
491
|
+
properties[fieldKey] = arrayProp;
|
|
492
|
+
if (control.required)
|
|
493
|
+
required.push(fieldKey);
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
459
497
|
properties[fieldKey] = schemaProp;
|
|
460
498
|
if (!name) {
|
|
461
499
|
fieldElements.set(fieldKey, control);
|
|
@@ -466,7 +504,7 @@ function buildSchema(form) {
|
|
|
466
504
|
}
|
|
467
505
|
const ariaControls = collectAriaControls(form);
|
|
468
506
|
const processedAriaRadioGroups = /* @__PURE__ */ new Set();
|
|
469
|
-
for (const { el, role, key } of ariaControls) {
|
|
507
|
+
for (const { el, role, key, enumValues, enumOneOf } of ariaControls) {
|
|
470
508
|
if (properties[key])
|
|
471
509
|
continue;
|
|
472
510
|
if (role === "radio") {
|
|
@@ -475,6 +513,11 @@ function buildSchema(form) {
|
|
|
475
513
|
processedAriaRadioGroups.add(key);
|
|
476
514
|
}
|
|
477
515
|
const schemaProp = ariaRoleToSchema(el, role);
|
|
516
|
+
if (enumValues && enumValues.length > 0) {
|
|
517
|
+
schemaProp.enum = enumValues;
|
|
518
|
+
if (enumOneOf && enumOneOf.length > 0)
|
|
519
|
+
schemaProp.oneOf = enumOneOf;
|
|
520
|
+
}
|
|
478
521
|
schemaProp.title = inferAriaFieldTitle(el);
|
|
479
522
|
const desc = inferAriaFieldDescription(el);
|
|
480
523
|
if (desc)
|
|
@@ -506,7 +549,7 @@ function resolveNativeControlFallbackKey(control) {
|
|
|
506
549
|
}
|
|
507
550
|
function collectAriaControls(form) {
|
|
508
551
|
const selector = ARIA_ROLES_TO_SCAN.map((r) => `[role="${r}"]`).join(", ");
|
|
509
|
-
const
|
|
552
|
+
const rawResults = [];
|
|
510
553
|
for (const el of Array.from(form.querySelectorAll(selector))) {
|
|
511
554
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)
|
|
512
555
|
continue;
|
|
@@ -516,9 +559,38 @@ function collectAriaControls(form) {
|
|
|
516
559
|
const key = resolveAriaFieldKey(el);
|
|
517
560
|
if (!key)
|
|
518
561
|
continue;
|
|
519
|
-
|
|
562
|
+
rawResults.push({ el, role, key });
|
|
563
|
+
}
|
|
564
|
+
const radioEntries = rawResults.filter((e) => e.role === "radio");
|
|
565
|
+
const nonRadioEntries = rawResults.filter((e) => e.role !== "radio");
|
|
566
|
+
const radioGroupMap = /* @__PURE__ */ new Map();
|
|
567
|
+
const ungroupedRadios = [];
|
|
568
|
+
for (const entry of radioEntries) {
|
|
569
|
+
const group = entry.el.closest('[role="radiogroup"]');
|
|
570
|
+
if (group) {
|
|
571
|
+
if (!radioGroupMap.has(group))
|
|
572
|
+
radioGroupMap.set(group, []);
|
|
573
|
+
radioGroupMap.get(group).push(entry.el);
|
|
574
|
+
} else {
|
|
575
|
+
ungroupedRadios.push(entry);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
const groupedEntries = [];
|
|
579
|
+
for (const [group, members] of radioGroupMap) {
|
|
580
|
+
const groupKey = resolveAriaFieldKey(group);
|
|
581
|
+
if (!groupKey)
|
|
582
|
+
continue;
|
|
583
|
+
const enumValues = members.map((el) => (el.getAttribute("data-value") ?? el.getAttribute("aria-label") ?? el.textContent ?? "").trim()).filter(Boolean);
|
|
584
|
+
const enumOneOf = members.map((el) => {
|
|
585
|
+
const val = (el.getAttribute("data-value") ?? el.getAttribute("aria-label") ?? el.textContent ?? "").trim();
|
|
586
|
+
const title = (el.getAttribute("aria-label") ?? el.textContent ?? "").trim();
|
|
587
|
+
return { const: val, title: title || val };
|
|
588
|
+
}).filter((e) => e.const !== "");
|
|
589
|
+
if (enumValues.length > 0) {
|
|
590
|
+
groupedEntries.push({ el: group, role: "radio", key: groupKey, enumValues, enumOneOf });
|
|
591
|
+
}
|
|
520
592
|
}
|
|
521
|
-
return
|
|
593
|
+
return [...nonRadioEntries, ...groupedEntries, ...ungroupedRadios];
|
|
522
594
|
}
|
|
523
595
|
function resolveAriaFieldKey(el) {
|
|
524
596
|
const htmlEl = el;
|
|
@@ -714,6 +786,7 @@ function buildSchemaFromInputs(inputs) {
|
|
|
714
786
|
const required = [];
|
|
715
787
|
const fieldElements = /* @__PURE__ */ new Map();
|
|
716
788
|
const processedRadioGroups = /* @__PURE__ */ new Set();
|
|
789
|
+
const processedCheckboxGroups = /* @__PURE__ */ new Set();
|
|
717
790
|
for (const control of inputs) {
|
|
718
791
|
const name = control.name;
|
|
719
792
|
const fieldKey = name || resolveNativeControlFallbackKey(control);
|
|
@@ -724,6 +797,11 @@ function buildSchemaFromInputs(inputs) {
|
|
|
724
797
|
continue;
|
|
725
798
|
processedRadioGroups.add(fieldKey);
|
|
726
799
|
}
|
|
800
|
+
if (control instanceof HTMLInputElement && control.type === "checkbox") {
|
|
801
|
+
if (processedCheckboxGroups.has(fieldKey))
|
|
802
|
+
continue;
|
|
803
|
+
processedCheckboxGroups.add(fieldKey);
|
|
804
|
+
}
|
|
727
805
|
const schemaProp = inputTypeToSchema(control);
|
|
728
806
|
if (!schemaProp)
|
|
729
807
|
continue;
|
|
@@ -733,6 +811,22 @@ function buildSchemaFromInputs(inputs) {
|
|
|
733
811
|
const desc = inferFieldDescription(control);
|
|
734
812
|
if (desc)
|
|
735
813
|
schemaProp.description = desc;
|
|
814
|
+
if (control instanceof HTMLInputElement && control.type === "checkbox") {
|
|
815
|
+
const checkboxValues = inputs.filter((i) => i instanceof HTMLInputElement && i.type === "checkbox" && i.name === fieldKey).map((cb) => cb.value).filter((v) => v !== "" && v !== "on");
|
|
816
|
+
if (checkboxValues.length > 1) {
|
|
817
|
+
const arrayProp = {
|
|
818
|
+
type: "array",
|
|
819
|
+
items: { type: "string", enum: checkboxValues },
|
|
820
|
+
title: schemaProp.title
|
|
821
|
+
};
|
|
822
|
+
if (schemaProp.description)
|
|
823
|
+
arrayProp.description = schemaProp.description;
|
|
824
|
+
properties[fieldKey] = arrayProp;
|
|
825
|
+
if (control.required)
|
|
826
|
+
required.push(fieldKey);
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
736
830
|
properties[fieldKey] = schemaProp;
|
|
737
831
|
if (!name)
|
|
738
832
|
fieldElements.set(fieldKey, control);
|
|
@@ -750,6 +844,8 @@ var pendingExecutions = /* @__PURE__ */ new WeakMap();
|
|
|
750
844
|
var lastParams = /* @__PURE__ */ new WeakMap();
|
|
751
845
|
var formFieldElements = /* @__PURE__ */ new WeakMap();
|
|
752
846
|
var pendingWarnings = /* @__PURE__ */ new WeakMap();
|
|
847
|
+
var pendingFillWarnings = /* @__PURE__ */ new WeakMap();
|
|
848
|
+
var lastFilledSnapshot = /* @__PURE__ */ new WeakMap();
|
|
753
849
|
var _inputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
|
754
850
|
var _textareaValueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
|
|
755
851
|
var _checkedSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "checked")?.set;
|
|
@@ -759,6 +855,7 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
759
855
|
}
|
|
760
856
|
attachSubmitInterceptor(form, toolName);
|
|
761
857
|
return async (params) => {
|
|
858
|
+
pendingFillWarnings.set(form, []);
|
|
762
859
|
fillFormFields(form, params);
|
|
763
860
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
764
861
|
return new Promise((resolve, reject) => {
|
|
@@ -809,9 +906,16 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
809
906
|
const { resolve } = pending;
|
|
810
907
|
pendingExecutions.delete(form);
|
|
811
908
|
const formData = serializeFormData(form, lastParams.get(form), formFieldElements.get(form));
|
|
909
|
+
lastFilledSnapshot.delete(form);
|
|
812
910
|
const missing = pendingWarnings.get(form);
|
|
813
911
|
pendingWarnings.delete(form);
|
|
814
|
-
const
|
|
912
|
+
const fillWarnings = pendingFillWarnings.get(form) ?? [];
|
|
913
|
+
pendingFillWarnings.delete(form);
|
|
914
|
+
const allWarnings = [
|
|
915
|
+
...missing?.length ? [`required fields were not filled: ${missing.join(", ")}`] : [],
|
|
916
|
+
...fillWarnings
|
|
917
|
+
];
|
|
918
|
+
const warningText = allWarnings.length ? ` Note: ${allWarnings.join("; ")}.` : "";
|
|
815
919
|
const text = `Form submitted. Fields: ${JSON.stringify(formData)}${warningText}`;
|
|
816
920
|
const result = { content: [{ type: "text", text }] };
|
|
817
921
|
if (e.agentInvoked && typeof e.respondWith === "function") {
|
|
@@ -821,6 +925,7 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
821
925
|
resolve(result);
|
|
822
926
|
});
|
|
823
927
|
form.addEventListener("reset", () => {
|
|
928
|
+
lastFilledSnapshot.delete(form);
|
|
824
929
|
window.dispatchEvent(new CustomEvent("toolcancel", { detail: { toolName } }));
|
|
825
930
|
});
|
|
826
931
|
}
|
|
@@ -873,16 +978,30 @@ function findNativeField(form, key) {
|
|
|
873
978
|
function fillFormFields(form, params) {
|
|
874
979
|
lastParams.set(form, params);
|
|
875
980
|
const fieldEls = formFieldElements.get(form);
|
|
981
|
+
const snapshot = {};
|
|
876
982
|
for (const [key, value] of Object.entries(params)) {
|
|
877
983
|
const input = findNativeField(form, key);
|
|
878
984
|
if (input) {
|
|
879
985
|
if (input instanceof HTMLInputElement) {
|
|
880
986
|
fillInput(input, form, key, value);
|
|
987
|
+
if (input.type === "checkbox") {
|
|
988
|
+
if (Array.isArray(value)) {
|
|
989
|
+
const esc = CSS.escape(key);
|
|
990
|
+
snapshot[key] = Array.from(
|
|
991
|
+
form.querySelectorAll(`input[type="checkbox"][name="${esc}"]`)
|
|
992
|
+
).filter((b) => b.checked).map((b) => b.value);
|
|
993
|
+
} else {
|
|
994
|
+
snapshot[key] = input.checked;
|
|
995
|
+
}
|
|
996
|
+
} else {
|
|
997
|
+
snapshot[key] = input.value;
|
|
998
|
+
}
|
|
881
999
|
} else if (input instanceof HTMLTextAreaElement) {
|
|
882
1000
|
setReactValue(input, String(value ?? ""));
|
|
1001
|
+
snapshot[key] = input.value;
|
|
883
1002
|
} else if (input instanceof HTMLSelectElement) {
|
|
884
|
-
input
|
|
885
|
-
input.
|
|
1003
|
+
fillSelectElement(input, value);
|
|
1004
|
+
snapshot[key] = input.multiple ? Array.from(input.options).filter((o) => o.selected).map((o) => o.value) : input.value;
|
|
886
1005
|
}
|
|
887
1006
|
continue;
|
|
888
1007
|
}
|
|
@@ -899,23 +1018,56 @@ function fillFormFields(form, params) {
|
|
|
899
1018
|
}
|
|
900
1019
|
if (effectiveEl instanceof HTMLInputElement) {
|
|
901
1020
|
fillInput(effectiveEl, form, key, value);
|
|
1021
|
+
snapshot[key] = effectiveEl.type === "checkbox" ? effectiveEl.checked : effectiveEl.value;
|
|
902
1022
|
} else if (effectiveEl instanceof HTMLTextAreaElement) {
|
|
903
1023
|
setReactValue(effectiveEl, String(value ?? ""));
|
|
1024
|
+
snapshot[key] = effectiveEl.value;
|
|
904
1025
|
} else if (effectiveEl instanceof HTMLSelectElement) {
|
|
905
|
-
effectiveEl
|
|
906
|
-
effectiveEl.
|
|
1026
|
+
fillSelectElement(effectiveEl, value);
|
|
1027
|
+
snapshot[key] = effectiveEl.multiple ? Array.from(effectiveEl.options).filter((o) => o.selected).map((o) => o.value) : effectiveEl.value;
|
|
907
1028
|
} else {
|
|
908
1029
|
fillAriaField(effectiveEl, value);
|
|
1030
|
+
snapshot[key] = value;
|
|
909
1031
|
}
|
|
910
1032
|
}
|
|
911
1033
|
}
|
|
1034
|
+
lastFilledSnapshot.set(form, snapshot);
|
|
912
1035
|
}
|
|
913
1036
|
function fillInput(input, form, key, value) {
|
|
914
1037
|
const type = input.type.toLowerCase();
|
|
915
1038
|
if (type === "checkbox") {
|
|
1039
|
+
if (Array.isArray(value)) {
|
|
1040
|
+
const esc = CSS.escape(key);
|
|
1041
|
+
const allBoxes = form.querySelectorAll(`input[type="checkbox"][name="${esc}"]`);
|
|
1042
|
+
for (const box of allBoxes) {
|
|
1043
|
+
setReactChecked(box, value.map(String).includes(box.value));
|
|
1044
|
+
}
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
916
1047
|
setReactChecked(input, Boolean(value));
|
|
917
1048
|
return;
|
|
918
1049
|
}
|
|
1050
|
+
if (type === "number" || type === "range") {
|
|
1051
|
+
const raw = String(value ?? "");
|
|
1052
|
+
const num = Number(raw);
|
|
1053
|
+
if (raw === "" || isNaN(num)) {
|
|
1054
|
+
pendingFillWarnings.get(form)?.push(`"${key}" expects a number, got: ${JSON.stringify(value)}`);
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const min = input.min !== "" ? parseFloat(input.min) : -Infinity;
|
|
1058
|
+
const max = input.max !== "" ? parseFloat(input.max) : Infinity;
|
|
1059
|
+
if (num < min || num > max) {
|
|
1060
|
+
pendingFillWarnings.get(form)?.push(
|
|
1061
|
+
`"${key}" value ${num} is outside allowed range [${input.min || "?"}, ${input.max || "?"}]`
|
|
1062
|
+
);
|
|
1063
|
+
input.value = String(Math.min(Math.max(num, min), max));
|
|
1064
|
+
} else {
|
|
1065
|
+
input.value = String(num);
|
|
1066
|
+
}
|
|
1067
|
+
input.dispatchEvent(new InputEvent("input", { bubbles: true, cancelable: true, inputType: "insertText", data: String(num) }));
|
|
1068
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
919
1071
|
if (type === "radio") {
|
|
920
1072
|
const esc = CSS.escape(key);
|
|
921
1073
|
const radios = form.querySelectorAll(
|
|
@@ -936,6 +1088,18 @@ function fillInput(input, form, key, value) {
|
|
|
936
1088
|
}
|
|
937
1089
|
setReactValue(input, String(value ?? ""));
|
|
938
1090
|
}
|
|
1091
|
+
function fillSelectElement(select, value) {
|
|
1092
|
+
if (select.multiple) {
|
|
1093
|
+
const vals = Array.isArray(value) ? value.map(String) : [String(value ?? "")];
|
|
1094
|
+
for (const opt of Array.from(select.options)) {
|
|
1095
|
+
opt.selected = vals.includes(opt.value);
|
|
1096
|
+
}
|
|
1097
|
+
select.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
select.value = String(value ?? "");
|
|
1101
|
+
select.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1102
|
+
}
|
|
939
1103
|
function fillAriaField(el, value) {
|
|
940
1104
|
const role = el.getAttribute("role");
|
|
941
1105
|
if (role === "checkbox" || role === "switch") {
|
|
@@ -948,6 +1112,22 @@ function fillAriaField(el, value) {
|
|
|
948
1112
|
el.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
949
1113
|
return;
|
|
950
1114
|
}
|
|
1115
|
+
if (role === "radiogroup") {
|
|
1116
|
+
const radios = Array.from(el.querySelectorAll('[role="radio"]'));
|
|
1117
|
+
for (const radio of radios) {
|
|
1118
|
+
const val = (radio.getAttribute("data-value") ?? radio.getAttribute("aria-label") ?? radio.textContent ?? "").trim();
|
|
1119
|
+
if (val === String(value)) {
|
|
1120
|
+
radio.setAttribute("aria-checked", "true");
|
|
1121
|
+
radio.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
1122
|
+
for (const other of radios) {
|
|
1123
|
+
if (other !== radio)
|
|
1124
|
+
other.setAttribute("aria-checked", "false");
|
|
1125
|
+
}
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
951
1131
|
const htmlEl = el;
|
|
952
1132
|
if (htmlEl.isContentEditable) {
|
|
953
1133
|
htmlEl.textContent = String(value ?? "");
|
|
@@ -958,6 +1138,7 @@ function fillAriaField(el, value) {
|
|
|
958
1138
|
function serializeFormData(form, params, fieldEls) {
|
|
959
1139
|
const result = {};
|
|
960
1140
|
const data = new FormData(form);
|
|
1141
|
+
const snapshot = lastFilledSnapshot.get(form);
|
|
961
1142
|
for (const [key, val] of data.entries()) {
|
|
962
1143
|
if (result[key] !== void 0) {
|
|
963
1144
|
const existing = result[key];
|
|
@@ -974,6 +1155,10 @@ function serializeFormData(form, params, fieldEls) {
|
|
|
974
1155
|
for (const key of Object.keys(params)) {
|
|
975
1156
|
if (key in result)
|
|
976
1157
|
continue;
|
|
1158
|
+
if (snapshot && key in snapshot) {
|
|
1159
|
+
result[key] = snapshot[key];
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
977
1162
|
const el = findNativeField(form, key) ?? fieldEls?.get(key) ?? null;
|
|
978
1163
|
if (!el)
|
|
979
1164
|
continue;
|
|
@@ -1012,8 +1197,7 @@ function fillElement(el, value) {
|
|
|
1012
1197
|
} else if (el instanceof HTMLTextAreaElement) {
|
|
1013
1198
|
setReactValue(el, String(value ?? ""));
|
|
1014
1199
|
} else if (el instanceof HTMLSelectElement) {
|
|
1015
|
-
el
|
|
1016
|
-
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1200
|
+
fillSelectElement(el, value);
|
|
1017
1201
|
} else {
|
|
1018
1202
|
fillAriaField(el, value);
|
|
1019
1203
|
}
|