@dmitryvim/form-builder 0.5.3 → 0.5.4
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/README.md +1 -1
- package/dist/browser/formbuilder.min.js +111 -111
- package/dist/browser/formbuilder.v0.5.4.min.js +1490 -0
- package/dist/cjs/index.cjs +139 -62
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +121 -57
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +111 -111
- package/dist/types/components/container.d.ts +1 -1
- package/dist/types/instance/FormBuilderInstance.d.ts +19 -1
- package/dist/types/types/state.d.ts +7 -0
- package/dist/types/utils/helpers.d.ts +16 -4
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.5.3.min.js +0 -1490
package/dist/cjs/index.cjs
CHANGED
|
@@ -27,9 +27,7 @@ function isPlainObject(obj) {
|
|
|
27
27
|
return obj && typeof obj === "object" && obj.constructor === Object;
|
|
28
28
|
}
|
|
29
29
|
function escapeHtml(text) {
|
|
30
|
-
|
|
31
|
-
div.textContent = text;
|
|
32
|
-
return div.innerHTML;
|
|
30
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
33
31
|
}
|
|
34
32
|
function getElementLookupKey(element, state) {
|
|
35
33
|
if (element.key) {
|
|
@@ -65,7 +63,7 @@ function formatFileSize(bytes) {
|
|
|
65
63
|
}
|
|
66
64
|
function serializeHiddenValue(value) {
|
|
67
65
|
if (value === null || value === void 0) return "";
|
|
68
|
-
return
|
|
66
|
+
return JSON.stringify(value);
|
|
69
67
|
}
|
|
70
68
|
function deserializeHiddenValue(raw) {
|
|
71
69
|
if (raw === "") return null;
|
|
@@ -325,6 +323,14 @@ function validateSchema(schema) {
|
|
|
325
323
|
errors.push(`${elementPath}: missing key`);
|
|
326
324
|
}
|
|
327
325
|
validateCountBounds(element, elementPath, errors);
|
|
326
|
+
if (element.type === "number" && "decimals" in element) {
|
|
327
|
+
const decimals = element.decimals;
|
|
328
|
+
if (decimals !== void 0 && (!Number.isInteger(decimals) || decimals < 0)) {
|
|
329
|
+
errors.push(
|
|
330
|
+
`${elementPath}: decimals must be a non-negative integer (got ${JSON.stringify(decimals)})`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
328
334
|
if (element.type === "markdown") {
|
|
329
335
|
const content = element.content;
|
|
330
336
|
if (typeof content !== "string") {
|
|
@@ -958,7 +964,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
958
964
|
overflow-wrap: anywhere;
|
|
959
965
|
`;
|
|
960
966
|
textInput.name = pathKey;
|
|
961
|
-
textInput.placeholder = (_a = element.placeholder) != null ? _a : "
|
|
967
|
+
textInput.placeholder = (_a = element.placeholder) != null ? _a : t("placeholderText", state);
|
|
962
968
|
textInput.value = ctx.prefill[element.key] || element.default || "";
|
|
963
969
|
textInput.readOnly = readonly;
|
|
964
970
|
applySingleLineMode(textInput);
|
|
@@ -1058,6 +1064,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1058
1064
|
rem.setAttribute("aria-label", t("removeElement", state));
|
|
1059
1065
|
rem.innerHTML = BIN_ICON_SVG;
|
|
1060
1066
|
rem.onclick = () => {
|
|
1067
|
+
var _a2;
|
|
1061
1068
|
const chips = list.querySelectorAll(".fb-chip");
|
|
1062
1069
|
const idx = Array.prototype.indexOf.call(chips, chip);
|
|
1063
1070
|
if (idx < 0) return;
|
|
@@ -1071,6 +1078,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1071
1078
|
updateIndices();
|
|
1072
1079
|
updateAddButton();
|
|
1073
1080
|
updateRemoveButtons();
|
|
1081
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1074
1082
|
};
|
|
1075
1083
|
chip.appendChild(rem);
|
|
1076
1084
|
}
|
|
@@ -1091,10 +1099,12 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1091
1099
|
const handle = createAddItemRow(
|
|
1092
1100
|
"text",
|
|
1093
1101
|
() => {
|
|
1102
|
+
var _a2;
|
|
1094
1103
|
values.push(element.default || "");
|
|
1095
1104
|
addChip(element.default || "");
|
|
1096
1105
|
updateAddButton();
|
|
1097
1106
|
updateRemoveButtons();
|
|
1107
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1098
1108
|
},
|
|
1099
1109
|
{ label: element.addLabel }
|
|
1100
1110
|
);
|
|
@@ -1211,7 +1221,7 @@ function validateTextElement(element, key, context) {
|
|
|
1211
1221
|
}
|
|
1212
1222
|
return { value: values, errors };
|
|
1213
1223
|
} else {
|
|
1214
|
-
const input = scopeRoot.querySelector(`[name
|
|
1224
|
+
const input = scopeRoot.querySelector(`[name="${key}"]`);
|
|
1215
1225
|
const val = (_c = input == null ? void 0 : input.value) != null ? _c : "";
|
|
1216
1226
|
if (!skipValidation && element.required && val === "") {
|
|
1217
1227
|
const msg = t("required", context.state);
|
|
@@ -1375,6 +1385,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1375
1385
|
removeBtn.className = "remove-item-btn mt-1 px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm";
|
|
1376
1386
|
removeBtn.innerHTML = "\u2715";
|
|
1377
1387
|
removeBtn.onclick = () => {
|
|
1388
|
+
var _a2;
|
|
1378
1389
|
const currentIndex = Array.from(container.children).indexOf(
|
|
1379
1390
|
item
|
|
1380
1391
|
);
|
|
@@ -1384,6 +1395,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1384
1395
|
updateIndices();
|
|
1385
1396
|
updateAddButton();
|
|
1386
1397
|
updateRemoveButtons();
|
|
1398
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1387
1399
|
}
|
|
1388
1400
|
};
|
|
1389
1401
|
item.appendChild(removeBtn);
|
|
@@ -1399,10 +1411,12 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1399
1411
|
const handle = createAddItemRow(
|
|
1400
1412
|
"textarea",
|
|
1401
1413
|
() => {
|
|
1414
|
+
var _a2;
|
|
1402
1415
|
values.push(element.default || "");
|
|
1403
1416
|
addTextareaItem(element.default || "");
|
|
1404
1417
|
updateAddButton();
|
|
1405
1418
|
updateRemoveButtons();
|
|
1419
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1406
1420
|
},
|
|
1407
1421
|
{ label: element.addLabel }
|
|
1408
1422
|
);
|
|
@@ -1688,6 +1702,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1688
1702
|
removeBtn.className = "remove-item-btn px-2 py-1 text-red-600 hover:bg-red-50 rounded";
|
|
1689
1703
|
removeBtn.innerHTML = "\u2715";
|
|
1690
1704
|
removeBtn.onclick = () => {
|
|
1705
|
+
var _a2;
|
|
1691
1706
|
const currentIndex = Array.from(container.children).indexOf(
|
|
1692
1707
|
item
|
|
1693
1708
|
);
|
|
@@ -1697,6 +1712,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1697
1712
|
updateIndices();
|
|
1698
1713
|
updateAddButton();
|
|
1699
1714
|
updateRemoveButtons();
|
|
1715
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1700
1716
|
}
|
|
1701
1717
|
};
|
|
1702
1718
|
item.appendChild(removeBtn);
|
|
@@ -1712,10 +1728,12 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1712
1728
|
const handle = createAddItemRow(
|
|
1713
1729
|
"number",
|
|
1714
1730
|
() => {
|
|
1731
|
+
var _a2;
|
|
1715
1732
|
values.push(element.default || "");
|
|
1716
1733
|
addNumberItem(element.default || "");
|
|
1717
1734
|
updateAddButton();
|
|
1718
1735
|
updateRemoveButtons();
|
|
1736
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
1719
1737
|
},
|
|
1720
1738
|
{ label: element.addLabel }
|
|
1721
1739
|
);
|
|
@@ -1731,7 +1749,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1731
1749
|
updateRemoveButtons();
|
|
1732
1750
|
}
|
|
1733
1751
|
function validateNumberElement(element, key, context) {
|
|
1734
|
-
var _a, _b, _c
|
|
1752
|
+
var _a, _b, _c;
|
|
1735
1753
|
const errors = [];
|
|
1736
1754
|
const { scopeRoot, skipValidation } = context;
|
|
1737
1755
|
const markValidity = (input, errorMessage) => {
|
|
@@ -1791,7 +1809,7 @@ function validateNumberElement(element, key, context) {
|
|
|
1791
1809
|
);
|
|
1792
1810
|
const values = [];
|
|
1793
1811
|
inputs.forEach((input, index) => {
|
|
1794
|
-
var _a2
|
|
1812
|
+
var _a2;
|
|
1795
1813
|
const raw = (_a2 = input == null ? void 0 : input.value) != null ? _a2 : "";
|
|
1796
1814
|
if (raw === "") {
|
|
1797
1815
|
values.push(null);
|
|
@@ -1807,8 +1825,7 @@ function validateNumberElement(element, key, context) {
|
|
|
1807
1825
|
return;
|
|
1808
1826
|
}
|
|
1809
1827
|
validateNumberInput(input, v, `${key}[${index}]`);
|
|
1810
|
-
|
|
1811
|
-
values.push(Number(v.toFixed(d)));
|
|
1828
|
+
values.push(applyDecimals(v, element.decimals));
|
|
1812
1829
|
});
|
|
1813
1830
|
if (!skipValidation) {
|
|
1814
1831
|
const { state } = context;
|
|
@@ -1827,7 +1844,7 @@ function validateNumberElement(element, key, context) {
|
|
|
1827
1844
|
}
|
|
1828
1845
|
return { value: values, errors };
|
|
1829
1846
|
} else {
|
|
1830
|
-
const input = scopeRoot.querySelector(`[name
|
|
1847
|
+
const input = scopeRoot.querySelector(`[name="${key}"]`);
|
|
1831
1848
|
const raw = (_c = input == null ? void 0 : input.value) != null ? _c : "";
|
|
1832
1849
|
const { state } = context;
|
|
1833
1850
|
if (!skipValidation && element.required && raw === "") {
|
|
@@ -1848,10 +1865,13 @@ function validateNumberElement(element, key, context) {
|
|
|
1848
1865
|
return { value: null, errors };
|
|
1849
1866
|
}
|
|
1850
1867
|
validateNumberInput(input, v, key);
|
|
1851
|
-
|
|
1852
|
-
return { value: Number(v.toFixed(d)), errors };
|
|
1868
|
+
return { value: applyDecimals(v, element.decimals), errors };
|
|
1853
1869
|
}
|
|
1854
1870
|
}
|
|
1871
|
+
function applyDecimals(v, decimals) {
|
|
1872
|
+
if (!Number.isInteger(decimals) || decimals < 0) return v;
|
|
1873
|
+
return Number(v.toFixed(decimals));
|
|
1874
|
+
}
|
|
1855
1875
|
function updateNumberField(element, fieldPath, value, context) {
|
|
1856
1876
|
const { scopeRoot } = context;
|
|
1857
1877
|
if (element.multiple) {
|
|
@@ -1998,6 +2018,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1998
2018
|
removeBtn.className = "remove-item-btn px-2 py-1 text-red-600 hover:bg-red-50 rounded";
|
|
1999
2019
|
removeBtn.innerHTML = "\u2715";
|
|
2000
2020
|
removeBtn.onclick = () => {
|
|
2021
|
+
var _a2;
|
|
2001
2022
|
const currentIndex = Array.from(container.children).indexOf(item);
|
|
2002
2023
|
if (container.children.length > minCount) {
|
|
2003
2024
|
values.splice(currentIndex, 1);
|
|
@@ -2005,6 +2026,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
2005
2026
|
updateIndices();
|
|
2006
2027
|
updateAddButton();
|
|
2007
2028
|
updateRemoveButtons();
|
|
2029
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
2008
2030
|
}
|
|
2009
2031
|
};
|
|
2010
2032
|
item.appendChild(removeBtn);
|
|
@@ -2020,12 +2042,13 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
2020
2042
|
const handle = createAddItemRow(
|
|
2021
2043
|
"select",
|
|
2022
2044
|
() => {
|
|
2023
|
-
var _a2, _b2;
|
|
2045
|
+
var _a2, _b2, _c2;
|
|
2024
2046
|
const defaultValue = element.default || ((_b2 = (_a2 = element.options) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.value) || "";
|
|
2025
2047
|
values.push(defaultValue);
|
|
2026
2048
|
addSelectItem(defaultValue);
|
|
2027
2049
|
updateAddButton();
|
|
2028
2050
|
updateRemoveButtons();
|
|
2051
|
+
(_c2 = ctx.instance) == null ? void 0 : _c2.triggerOnChange(pathKey);
|
|
2029
2052
|
},
|
|
2030
2053
|
{ label: element.addLabel }
|
|
2031
2054
|
);
|
|
@@ -2115,7 +2138,7 @@ function validateSelectElement(element, key, context) {
|
|
|
2115
2138
|
return { value: values, errors };
|
|
2116
2139
|
} else {
|
|
2117
2140
|
const input = scopeRoot.querySelector(
|
|
2118
|
-
`[name
|
|
2141
|
+
`[name="${key}"]`
|
|
2119
2142
|
);
|
|
2120
2143
|
const val = (_a = input == null ? void 0 : input.value) != null ? _a : "";
|
|
2121
2144
|
if (!skipValidation && element.required && val === "") {
|
|
@@ -2440,6 +2463,7 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2440
2463
|
removeBtn.style.backgroundColor = "transparent";
|
|
2441
2464
|
});
|
|
2442
2465
|
removeBtn.onclick = () => {
|
|
2466
|
+
var _a2;
|
|
2443
2467
|
const currentIndex = Array.from(container.children).indexOf(
|
|
2444
2468
|
item
|
|
2445
2469
|
);
|
|
@@ -2449,6 +2473,7 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2449
2473
|
updateIndices();
|
|
2450
2474
|
updateAddButton();
|
|
2451
2475
|
updateRemoveButtons();
|
|
2476
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
2452
2477
|
}
|
|
2453
2478
|
};
|
|
2454
2479
|
item.appendChild(removeBtn);
|
|
@@ -2464,12 +2489,13 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2464
2489
|
const handle = createAddItemRow(
|
|
2465
2490
|
"switcher",
|
|
2466
2491
|
() => {
|
|
2467
|
-
var _a2, _b2;
|
|
2492
|
+
var _a2, _b2, _c2;
|
|
2468
2493
|
const defaultValue = element.default || ((_b2 = (_a2 = element.options) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.value) || "";
|
|
2469
2494
|
values.push(defaultValue);
|
|
2470
2495
|
addSwitcherItem(defaultValue);
|
|
2471
2496
|
updateAddButton();
|
|
2472
2497
|
updateRemoveButtons();
|
|
2498
|
+
(_c2 = ctx.instance) == null ? void 0 : _c2.triggerOnChange(pathKey);
|
|
2473
2499
|
},
|
|
2474
2500
|
{ label: element.addLabel }
|
|
2475
2501
|
);
|
|
@@ -2568,7 +2594,7 @@ function validateSwitcherElement(element, key, context) {
|
|
|
2568
2594
|
return { value: values, errors };
|
|
2569
2595
|
} else {
|
|
2570
2596
|
const input = scopeRoot.querySelector(
|
|
2571
|
-
`input[type="hidden"][name
|
|
2597
|
+
`input[type="hidden"][name="${key}"]`
|
|
2572
2598
|
);
|
|
2573
2599
|
const val = (_a = input == null ? void 0 : input.value) != null ? _a : "";
|
|
2574
2600
|
if (!skipValidation && element.required && val === "") {
|
|
@@ -5664,7 +5690,7 @@ function validateSingleFile(element, key, context) {
|
|
|
5664
5690
|
const { scopeRoot, skipValidation, state } = context;
|
|
5665
5691
|
const errors = [];
|
|
5666
5692
|
const input = scopeRoot.querySelector(
|
|
5667
|
-
`input[name
|
|
5693
|
+
`input[name="${key}"][type="hidden"]`
|
|
5668
5694
|
);
|
|
5669
5695
|
const rid = (_a = input == null ? void 0 : input.value) != null ? _a : "";
|
|
5670
5696
|
if (!skipValidation && element.required && rid === "") {
|
|
@@ -6088,6 +6114,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6088
6114
|
removeBtn.style.backgroundColor = "transparent";
|
|
6089
6115
|
});
|
|
6090
6116
|
removeBtn.onclick = () => {
|
|
6117
|
+
var _a2;
|
|
6091
6118
|
const currentIndex = Array.from(container.children).indexOf(
|
|
6092
6119
|
item
|
|
6093
6120
|
);
|
|
@@ -6097,6 +6124,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6097
6124
|
updateIndices();
|
|
6098
6125
|
updateAddButton();
|
|
6099
6126
|
updateRemoveButtons();
|
|
6127
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
6100
6128
|
}
|
|
6101
6129
|
};
|
|
6102
6130
|
item.appendChild(removeBtn);
|
|
@@ -6112,11 +6140,13 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6112
6140
|
const handle = createAddItemRow(
|
|
6113
6141
|
"colour",
|
|
6114
6142
|
() => {
|
|
6143
|
+
var _a2;
|
|
6115
6144
|
const defaultColour = element.default || "#000000";
|
|
6116
6145
|
values.push(defaultColour);
|
|
6117
6146
|
addColourItem(defaultColour);
|
|
6118
6147
|
updateAddButton();
|
|
6119
6148
|
updateRemoveButtons();
|
|
6149
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
6120
6150
|
},
|
|
6121
6151
|
{ label: element.addLabel }
|
|
6122
6152
|
);
|
|
@@ -6550,6 +6580,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
6550
6580
|
removeBtn.style.backgroundColor = "transparent";
|
|
6551
6581
|
});
|
|
6552
6582
|
removeBtn.onclick = () => {
|
|
6583
|
+
var _a2;
|
|
6553
6584
|
const currentIndex = Array.from(container.children).indexOf(
|
|
6554
6585
|
item
|
|
6555
6586
|
);
|
|
@@ -6559,6 +6590,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
6559
6590
|
updateIndices();
|
|
6560
6591
|
updateAddButton();
|
|
6561
6592
|
updateRemoveButtons();
|
|
6593
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
6562
6594
|
}
|
|
6563
6595
|
};
|
|
6564
6596
|
item.appendChild(removeBtn);
|
|
@@ -6574,10 +6606,12 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
6574
6606
|
const handle = createAddItemRow(
|
|
6575
6607
|
"slider",
|
|
6576
6608
|
() => {
|
|
6609
|
+
var _a2;
|
|
6577
6610
|
values.push(defaultValue);
|
|
6578
6611
|
addSliderItem(defaultValue);
|
|
6579
6612
|
updateAddButton();
|
|
6580
6613
|
updateRemoveButtons();
|
|
6614
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
6581
6615
|
},
|
|
6582
6616
|
{ label: element.addLabel }
|
|
6583
6617
|
);
|
|
@@ -6848,6 +6882,8 @@ function extractRootFormData(formRoot) {
|
|
|
6848
6882
|
if (input.checked) {
|
|
6849
6883
|
data[fieldName] = input.value;
|
|
6850
6884
|
}
|
|
6885
|
+
} else if (input.dataset.hiddenField) {
|
|
6886
|
+
data[fieldName] = deserializeHiddenValue(input.value);
|
|
6851
6887
|
} else {
|
|
6852
6888
|
data[fieldName] = input.value;
|
|
6853
6889
|
}
|
|
@@ -6968,7 +7004,7 @@ function mountRemoveButton(item, onRemove, state, containerLabel) {
|
|
|
6968
7004
|
item.classList.add("fb-row-removable");
|
|
6969
7005
|
item.insertBefore(rem, item.firstChild);
|
|
6970
7006
|
}
|
|
6971
|
-
function renderMultipleContainerElement(element, ctx, wrapper,
|
|
7007
|
+
function renderMultipleContainerElement(element, ctx, wrapper, pathKey) {
|
|
6972
7008
|
var _a, _b, _c, _d;
|
|
6973
7009
|
const state = ctx.state;
|
|
6974
7010
|
const containerIsReadonly = isElementReadonly(element, state, ctx);
|
|
@@ -6999,9 +7035,11 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6999
7035
|
);
|
|
7000
7036
|
const countItems = () => directRows().length;
|
|
7001
7037
|
const handleRemoveItem = (item) => {
|
|
7038
|
+
var _a2;
|
|
7002
7039
|
if (countItems() <= min) return;
|
|
7003
7040
|
item.remove();
|
|
7004
7041
|
updateAddButton();
|
|
7042
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
7005
7043
|
};
|
|
7006
7044
|
const createContainerItem = (idx, rowPrefill, formData) => {
|
|
7007
7045
|
const subCtx = {
|
|
@@ -7045,6 +7083,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
7045
7083
|
return item;
|
|
7046
7084
|
};
|
|
7047
7085
|
const handleAddItem = () => {
|
|
7086
|
+
var _a2;
|
|
7048
7087
|
if (countItems() >= max) return;
|
|
7049
7088
|
const item = createContainerItem(
|
|
7050
7089
|
takeRowIndex(),
|
|
@@ -7059,6 +7098,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
7059
7098
|
itemsWrap.appendChild(item);
|
|
7060
7099
|
}
|
|
7061
7100
|
updateAddButton();
|
|
7101
|
+
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey);
|
|
7062
7102
|
};
|
|
7063
7103
|
let slideAddTile = null;
|
|
7064
7104
|
let slideAddUpdate = null;
|
|
@@ -7360,7 +7400,7 @@ function renderGroupElement(element, ctx, wrapper, pathKey) {
|
|
|
7360
7400
|
maxCount: (_b = element.repeat) == null ? void 0 : _b.max
|
|
7361
7401
|
};
|
|
7362
7402
|
if (containerElement.multiple) {
|
|
7363
|
-
renderMultipleContainerElement(containerElement, ctx, wrapper);
|
|
7403
|
+
renderMultipleContainerElement(containerElement, ctx, wrapper, pathKey);
|
|
7364
7404
|
} else {
|
|
7365
7405
|
renderSingleContainerElement(containerElement, ctx, wrapper, pathKey);
|
|
7366
7406
|
}
|
|
@@ -10428,15 +10468,19 @@ var componentRegistry = {
|
|
|
10428
10468
|
function getComponentOperations(elementType) {
|
|
10429
10469
|
return componentRegistry[elementType] || null;
|
|
10430
10470
|
}
|
|
10471
|
+
function resolveOperations(element) {
|
|
10472
|
+
const isHiddenField = element.type !== "markdown" && (element.type === "hidden" || Boolean(element.hidden));
|
|
10473
|
+
return isHiddenField ? componentRegistry.hidden : getComponentOperations(element.type);
|
|
10474
|
+
}
|
|
10431
10475
|
function validateElementWithComponent(element, key, context) {
|
|
10432
|
-
const ops =
|
|
10476
|
+
const ops = resolveOperations(element);
|
|
10433
10477
|
if (ops && ops.validate) {
|
|
10434
10478
|
return ops.validate(element, key, context);
|
|
10435
10479
|
}
|
|
10436
10480
|
return null;
|
|
10437
10481
|
}
|
|
10438
10482
|
function updateElementWithComponent(element, fieldPath, value, context) {
|
|
10439
|
-
const ops =
|
|
10483
|
+
const ops = resolveOperations(element);
|
|
10440
10484
|
if (ops && ops.update) {
|
|
10441
10485
|
ops.update(element, fieldPath, value, context);
|
|
10442
10486
|
return true;
|
|
@@ -10448,6 +10492,10 @@ function updateElementWithComponent(element, fieldPath, value, context) {
|
|
|
10448
10492
|
function showTooltip(tooltipId, button) {
|
|
10449
10493
|
const tooltip = document.getElementById(tooltipId);
|
|
10450
10494
|
if (!tooltip) return;
|
|
10495
|
+
if (!button.isConnected) {
|
|
10496
|
+
tooltip.remove();
|
|
10497
|
+
return;
|
|
10498
|
+
}
|
|
10451
10499
|
const isCurrentlyVisible = !tooltip.classList.contains("hidden");
|
|
10452
10500
|
document.querySelectorAll('[id^="tooltip-"]').forEach((t2) => {
|
|
10453
10501
|
t2.classList.add("hidden");
|
|
@@ -10538,6 +10586,8 @@ function extractDOMValue(fieldPath, formRoot) {
|
|
|
10538
10586
|
`[name="${fieldPath}"]:checked`
|
|
10539
10587
|
);
|
|
10540
10588
|
return checked ? checked.value : void 0;
|
|
10589
|
+
} else if (input.dataset.hiddenField) {
|
|
10590
|
+
return deserializeHiddenValue(input.value);
|
|
10541
10591
|
} else {
|
|
10542
10592
|
return input.value;
|
|
10543
10593
|
}
|
|
@@ -10676,7 +10726,7 @@ function createFieldLabel(element) {
|
|
|
10676
10726
|
}
|
|
10677
10727
|
return title;
|
|
10678
10728
|
}
|
|
10679
|
-
function createInfoButton(element) {
|
|
10729
|
+
function createInfoButton(element, state) {
|
|
10680
10730
|
const infoBtn = document.createElement("button");
|
|
10681
10731
|
infoBtn.type = "button";
|
|
10682
10732
|
infoBtn.className = "ml-2 text-gray-400 hover:text-gray-600";
|
|
@@ -10688,6 +10738,7 @@ function createInfoButton(element) {
|
|
|
10688
10738
|
tooltip.style.position = "fixed";
|
|
10689
10739
|
tooltip.textContent = element.description || element.hint || "Field information";
|
|
10690
10740
|
document.body.appendChild(tooltip);
|
|
10741
|
+
state.tooltipElements.add(tooltip);
|
|
10691
10742
|
infoBtn.onclick = (e) => {
|
|
10692
10743
|
e.preventDefault();
|
|
10693
10744
|
e.stopPropagation();
|
|
@@ -10695,7 +10746,7 @@ function createInfoButton(element) {
|
|
|
10695
10746
|
};
|
|
10696
10747
|
return infoBtn;
|
|
10697
10748
|
}
|
|
10698
|
-
function createLabelContainer(element) {
|
|
10749
|
+
function createLabelContainer(element, state) {
|
|
10699
10750
|
const label = document.createElement("div");
|
|
10700
10751
|
label.className = "flex items-center";
|
|
10701
10752
|
label.style.marginBottom = "var(--fb-label-margin-bottom, 2px)";
|
|
@@ -10703,7 +10754,7 @@ function createLabelContainer(element) {
|
|
|
10703
10754
|
const title = createFieldLabel(element);
|
|
10704
10755
|
label.appendChild(title);
|
|
10705
10756
|
if (element.description || element.hint) {
|
|
10706
|
-
const infoBtn = createInfoButton(element);
|
|
10757
|
+
const infoBtn = createInfoButton(element, state);
|
|
10707
10758
|
label.appendChild(infoBtn);
|
|
10708
10759
|
}
|
|
10709
10760
|
return label;
|
|
@@ -10778,7 +10829,7 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
|
|
|
10778
10829
|
break;
|
|
10779
10830
|
case "container":
|
|
10780
10831
|
if (isMultiple) {
|
|
10781
|
-
renderMultipleContainerElement(element, ctx, wrapper);
|
|
10832
|
+
renderMultipleContainerElement(element, ctx, wrapper, pathKey);
|
|
10782
10833
|
} else {
|
|
10783
10834
|
renderSingleContainerElement(element, ctx, wrapper, pathKey);
|
|
10784
10835
|
}
|
|
@@ -10831,7 +10882,7 @@ function renderElement2(element, ctx) {
|
|
|
10831
10882
|
wrapper.setAttribute("data-fb-width", element.width || "full");
|
|
10832
10883
|
const ops = getComponentOperations(element.type);
|
|
10833
10884
|
if (!(ops == null ? void 0 : ops.ownsLabel)) {
|
|
10834
|
-
const label = createLabelContainer(element);
|
|
10885
|
+
const label = createLabelContainer(element, ctx.state);
|
|
10835
10886
|
wrapper.appendChild(label);
|
|
10836
10887
|
}
|
|
10837
10888
|
const pathKey = pathJoin(ctx.path, element.key);
|
|
@@ -11049,7 +11100,8 @@ function createInstanceState(config) {
|
|
|
11049
11100
|
prefill: {},
|
|
11050
11101
|
syntheticElementIds: /* @__PURE__ */ new WeakMap(),
|
|
11051
11102
|
syntheticElementIdCounter: 0,
|
|
11052
|
-
enableIfObservers: /* @__PURE__ */ new Set()
|
|
11103
|
+
enableIfObservers: /* @__PURE__ */ new Set(),
|
|
11104
|
+
tooltipElements: /* @__PURE__ */ new Set()
|
|
11053
11105
|
};
|
|
11054
11106
|
}
|
|
11055
11107
|
function generateInstanceId() {
|
|
@@ -11429,7 +11481,11 @@ var FormBuilderInstance = class {
|
|
|
11429
11481
|
/**
|
|
11430
11482
|
* Trigger onChange callbacks with debouncing
|
|
11431
11483
|
* @param fieldPath - Optional field path for field-specific change events
|
|
11432
|
-
* @param fieldValue - Optional field value for field-specific change events
|
|
11484
|
+
* @param fieldValue - Optional field value for field-specific change events.
|
|
11485
|
+
* When omitted while fieldPath is given, the value is read from the
|
|
11486
|
+
* freshly extracted form data at debounce time — used by structural
|
|
11487
|
+
* changes (multi-item add/remove), where the handler has no cheap
|
|
11488
|
+
* current value but the array is trivially derivable after the fact.
|
|
11433
11489
|
*/
|
|
11434
11490
|
triggerOnChange(fieldPath, fieldValue) {
|
|
11435
11491
|
if (this.state.config.readonly) return;
|
|
@@ -11442,12 +11498,49 @@ var FormBuilderInstance = class {
|
|
|
11442
11498
|
if (this.state.config.onChange) {
|
|
11443
11499
|
this.state.config.onChange(formData);
|
|
11444
11500
|
}
|
|
11445
|
-
if (this.state.config.onFieldChange && fieldPath !== void 0
|
|
11446
|
-
this.
|
|
11501
|
+
if (this.state.config.onFieldChange && fieldPath !== void 0) {
|
|
11502
|
+
const resolvedValue = fieldValue !== void 0 ? fieldValue : this.resolveDomPathValue(formData.data, fieldPath);
|
|
11503
|
+
this.state.config.onFieldChange(fieldPath, resolvedValue, formData);
|
|
11447
11504
|
}
|
|
11448
11505
|
this.state.debounceTimer = null;
|
|
11449
11506
|
}, this.state.config.debounceMs);
|
|
11450
11507
|
}
|
|
11508
|
+
/**
|
|
11509
|
+
* Resolve a DOM field path against the extracted form data.
|
|
11510
|
+
*
|
|
11511
|
+
* A plain getValueByPath is wrong for paths inside a multiple container:
|
|
11512
|
+
* row markers keep gaps after a deletion (`s[2]` may be the first surviving
|
|
11513
|
+
* row) while the extracted array is re-packed contiguously — the naive
|
|
11514
|
+
* lookup would read a different row, or nothing. Each `[N]` segment is
|
|
11515
|
+
* mapped from its marker to the row's position among the container's
|
|
11516
|
+
* rendered rows, the same DOM order extraction used to build the array.
|
|
11517
|
+
* A bracketed segment that is not a container marker (a multi-value leaf
|
|
11518
|
+
* like `tags[1]`, whose indices are contiguous) falls back to the index.
|
|
11519
|
+
*/
|
|
11520
|
+
resolveDomPathValue(data, domPath) {
|
|
11521
|
+
let cur = data;
|
|
11522
|
+
let domPrefix = "";
|
|
11523
|
+
for (const seg of domPath.split(".")) {
|
|
11524
|
+
if (cur === null || cur === void 0) return void 0;
|
|
11525
|
+
const marker = seg.match(/^(.+)\[(\d+)\]$/);
|
|
11526
|
+
if (!marker) {
|
|
11527
|
+
domPrefix = domPrefix ? `${domPrefix}.${seg}` : seg;
|
|
11528
|
+
cur = cur[seg];
|
|
11529
|
+
continue;
|
|
11530
|
+
}
|
|
11531
|
+
const key = marker[1];
|
|
11532
|
+
domPrefix = domPrefix ? `${domPrefix}.${key}` : key;
|
|
11533
|
+
const arr = cur[key];
|
|
11534
|
+
if (!Array.isArray(arr)) return void 0;
|
|
11535
|
+
const rows = this.state.formRoot ? findDirectContainerRows(this.state.formRoot, domPrefix) : [];
|
|
11536
|
+
domPrefix = `${domPrefix}[${marker[2]}]`;
|
|
11537
|
+
const pos = rows.findIndex(
|
|
11538
|
+
(row) => row.getAttribute("data-container-item") === domPrefix
|
|
11539
|
+
);
|
|
11540
|
+
cur = pos >= 0 ? arr[pos] : arr[parseInt(marker[2], 10)];
|
|
11541
|
+
}
|
|
11542
|
+
return cur;
|
|
11543
|
+
}
|
|
11451
11544
|
/**
|
|
11452
11545
|
* Register an external action that will be displayed as a button
|
|
11453
11546
|
* External actions can be form-level (no related_field) or field-level (with related_field)
|
|
@@ -11487,21 +11580,10 @@ var FormBuilderInstance = class {
|
|
|
11487
11580
|
*/
|
|
11488
11581
|
findFormElementByFieldPath(fieldPath) {
|
|
11489
11582
|
if (!this.state.formRoot) return null;
|
|
11490
|
-
|
|
11583
|
+
const element = this.state.formRoot.querySelector(
|
|
11491
11584
|
`[name="${fieldPath}"]`
|
|
11492
11585
|
);
|
|
11493
11586
|
if (element) return element;
|
|
11494
|
-
const variations = [
|
|
11495
|
-
fieldPath,
|
|
11496
|
-
fieldPath.replace(/\[(\d+)\]/g, "[$1]"),
|
|
11497
|
-
fieldPath.replace(/\./g, "[") + "]".repeat((fieldPath.match(/\./g) || []).length)
|
|
11498
|
-
];
|
|
11499
|
-
for (const variation of variations) {
|
|
11500
|
-
element = this.state.formRoot.querySelector(
|
|
11501
|
-
`[name="${variation}"]`
|
|
11502
|
-
);
|
|
11503
|
-
if (element) return element;
|
|
11504
|
-
}
|
|
11505
11587
|
const schemaElement = this.findSchemaElement(fieldPath);
|
|
11506
11588
|
if (!schemaElement) return null;
|
|
11507
11589
|
const fieldWrappers = this.state.formRoot.querySelectorAll(".fb-field-wrapper");
|
|
@@ -11751,6 +11833,7 @@ var FormBuilderInstance = class {
|
|
|
11751
11833
|
return;
|
|
11752
11834
|
}
|
|
11753
11835
|
this.disconnectEnableIfObservers();
|
|
11836
|
+
this.removeTooltipElements();
|
|
11754
11837
|
this.state.formRoot = root;
|
|
11755
11838
|
this.state.schema = schema;
|
|
11756
11839
|
this.state.externalActions = actions || null;
|
|
@@ -11836,7 +11919,6 @@ var FormBuilderInstance = class {
|
|
|
11836
11919
|
};
|
|
11837
11920
|
setValidateElement(validateElement2);
|
|
11838
11921
|
this.state.schema.elements.forEach((element) => {
|
|
11839
|
-
var _a;
|
|
11840
11922
|
if (element.enableIf) {
|
|
11841
11923
|
try {
|
|
11842
11924
|
const shouldEnable = evaluateEnableCondition(element.enableIf, data);
|
|
@@ -11853,24 +11935,12 @@ var FormBuilderInstance = class {
|
|
|
11853
11935
|
if (element.type === "markdown") {
|
|
11854
11936
|
return;
|
|
11855
11937
|
}
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
);
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
data[element.key] = deserializeHiddenValue(raw);
|
|
11863
|
-
} else {
|
|
11864
|
-
data[element.key] = element.default !== void 0 ? element.default : null;
|
|
11865
|
-
}
|
|
11866
|
-
} else {
|
|
11867
|
-
const result = validateElement2(element, { path: "" });
|
|
11868
|
-
if (result.skip) return;
|
|
11869
|
-
if (result.spread && result.value !== null && typeof result.value === "object") {
|
|
11870
|
-
Object.assign(data, result.value);
|
|
11871
|
-
} else if (element.key) {
|
|
11872
|
-
data[element.key] = result.value;
|
|
11873
|
-
}
|
|
11938
|
+
const result = validateElement2(element, { path: "" });
|
|
11939
|
+
if (result.skip) return;
|
|
11940
|
+
if (result.spread && result.value !== null && typeof result.value === "object") {
|
|
11941
|
+
Object.assign(data, result.value);
|
|
11942
|
+
} else if (element.key) {
|
|
11943
|
+
data[element.key] = result.value;
|
|
11874
11944
|
}
|
|
11875
11945
|
});
|
|
11876
11946
|
return {
|
|
@@ -12193,6 +12263,7 @@ var FormBuilderInstance = class {
|
|
|
12193
12263
|
this.state.debounceTimer = null;
|
|
12194
12264
|
}
|
|
12195
12265
|
this.disconnectEnableIfObservers();
|
|
12266
|
+
this.removeTooltipElements();
|
|
12196
12267
|
this.state.resourceIndex.clear();
|
|
12197
12268
|
if (this.state.formRoot) {
|
|
12198
12269
|
clear(this.state.formRoot);
|
|
@@ -12210,6 +12281,12 @@ var FormBuilderInstance = class {
|
|
|
12210
12281
|
}
|
|
12211
12282
|
this.state.enableIfObservers.clear();
|
|
12212
12283
|
}
|
|
12284
|
+
removeTooltipElements() {
|
|
12285
|
+
for (const tooltip of this.state.tooltipElements) {
|
|
12286
|
+
tooltip.remove();
|
|
12287
|
+
}
|
|
12288
|
+
this.state.tooltipElements.clear();
|
|
12289
|
+
}
|
|
12213
12290
|
};
|
|
12214
12291
|
|
|
12215
12292
|
// src/index.ts
|