@dmitryvim/form-builder 0.5.4 → 0.6.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 +7 -1
- package/dist/browser/formbuilder.min.js +136 -154
- package/dist/browser/formbuilder.v0.6.4.min.js +1472 -0
- package/dist/cjs/index.cjs +423 -445
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +368 -394
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +136 -154
- package/dist/types/components/container.d.ts +0 -7
- package/dist/types/components/index.d.ts +1 -2
- package/dist/types/instance/FormBuilderInstance.d.ts +17 -4
- package/dist/types/instance/state.d.ts +8 -0
- package/dist/types/types/component-operations.d.ts +15 -0
- package/dist/types/types/config.d.ts +2 -0
- package/dist/types/types/state.d.ts +8 -0
- package/dist/types/utils/helpers.d.ts +18 -1
- package/dist/types/utils/styles.d.ts +13 -7
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.5.4.min.js +0 -1490
package/dist/cjs/index.cjs
CHANGED
|
@@ -4,15 +4,16 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
// src/utils/translation.ts
|
|
6
6
|
function t(key, state, params) {
|
|
7
|
+
var _a, _b;
|
|
7
8
|
const locale = state.config.locale || "en";
|
|
8
9
|
const localeTranslations = state.config.translations[locale];
|
|
9
10
|
const fallbackTranslations = state.config.translations.en;
|
|
10
|
-
let text = (localeTranslations == null ? void 0 : localeTranslations[key])
|
|
11
|
+
let text = (_b = (_a = localeTranslations == null ? void 0 : localeTranslations[key]) != null ? _a : fallbackTranslations == null ? void 0 : fallbackTranslations[key]) != null ? _b : key;
|
|
11
12
|
if (params) {
|
|
12
13
|
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
13
14
|
text = text.replace(
|
|
14
15
|
new RegExp(`\\{${paramKey}\\}`, "g"),
|
|
15
|
-
String(paramValue)
|
|
16
|
+
() => String(paramValue)
|
|
16
17
|
);
|
|
17
18
|
}
|
|
18
19
|
}
|
|
@@ -62,7 +63,7 @@ function formatFileSize(bytes) {
|
|
|
62
63
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
63
64
|
}
|
|
64
65
|
function serializeHiddenValue(value) {
|
|
65
|
-
if (value ===
|
|
66
|
+
if (value === void 0) return "";
|
|
66
67
|
return JSON.stringify(value);
|
|
67
68
|
}
|
|
68
69
|
function deserializeHiddenValue(raw) {
|
|
@@ -73,6 +74,23 @@ function deserializeHiddenValue(raw) {
|
|
|
73
74
|
return raw;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
77
|
+
function readTypedInputValue(input) {
|
|
78
|
+
if (input instanceof HTMLInputElement) {
|
|
79
|
+
if (input.type === "checkbox") return input.checked;
|
|
80
|
+
if (input.dataset.hiddenField) return deserializeHiddenValue(input.value);
|
|
81
|
+
if (input.dataset.booleanField) return input.value === "true";
|
|
82
|
+
if (input.type === "number" || input.type === "range") {
|
|
83
|
+
if (input.value === "") return null;
|
|
84
|
+
const parsed = parseFloat(input.value);
|
|
85
|
+
const decimals = input.dataset.decimals;
|
|
86
|
+
return decimals !== void 0 ? Number(parsed.toFixed(parseInt(decimals, 10))) : parsed;
|
|
87
|
+
}
|
|
88
|
+
if (input.dataset.colourField) {
|
|
89
|
+
return input.value.toUpperCase();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return input.value === "" ? null : input.value;
|
|
93
|
+
}
|
|
76
94
|
function createHiddenInput(name, value) {
|
|
77
95
|
const input = document.createElement("input");
|
|
78
96
|
input.type = "hidden";
|
|
@@ -314,6 +332,14 @@ function validateSchema(schema) {
|
|
|
314
332
|
}
|
|
315
333
|
}
|
|
316
334
|
function validateElements(elements, path) {
|
|
335
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
336
|
+
elements.forEach((element, index) => {
|
|
337
|
+
if (!element.key) return;
|
|
338
|
+
if (seenKeys.has(element.key)) {
|
|
339
|
+
errors.push(`${path}[${index}]: duplicate key "${element.key}"`);
|
|
340
|
+
}
|
|
341
|
+
seenKeys.add(element.key);
|
|
342
|
+
});
|
|
317
343
|
elements.forEach((element, index) => {
|
|
318
344
|
const elementPath = `${path}[${index}]`;
|
|
319
345
|
if (!element.type) {
|
|
@@ -482,12 +508,58 @@ function deepEqual(a, b) {
|
|
|
482
508
|
}
|
|
483
509
|
|
|
484
510
|
// src/utils/styles.ts
|
|
485
|
-
function
|
|
511
|
+
function findErrorAnchor(input) {
|
|
512
|
+
var _a, _b, _c, _d;
|
|
513
|
+
return (_d = (_c = (_a = input.closest) == null ? void 0 : _a.call(input, ".fb-chip")) != null ? _c : (_b = input.closest) == null ? void 0 : _b.call(input, ".slider-container")) != null ? _d : input;
|
|
514
|
+
}
|
|
515
|
+
function findErrorNode(input) {
|
|
516
|
+
const anchor = findErrorAnchor(input);
|
|
486
517
|
const name = input.getAttribute("name");
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
518
|
+
const parent = anchor.parentElement;
|
|
519
|
+
if (name && parent) {
|
|
520
|
+
for (const child of Array.from(parent.children)) {
|
|
521
|
+
if (child.classList.contains("error-message") && child.getAttribute("data-error-for") === name) {
|
|
522
|
+
return child;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const sibling = anchor.nextElementSibling;
|
|
527
|
+
return sibling && sibling.classList.contains("error-message") ? sibling : null;
|
|
528
|
+
}
|
|
529
|
+
function markFieldValidity(input, errorMessage) {
|
|
530
|
+
var _a, _b, _c, _d;
|
|
531
|
+
if (!input) return;
|
|
532
|
+
if (errorMessage == null) {
|
|
533
|
+
input.classList.remove("invalid");
|
|
534
|
+
input.title = "";
|
|
535
|
+
(_a = findErrorNode(input)) == null ? void 0 : _a.remove();
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
input.classList.add("invalid");
|
|
539
|
+
input.title = errorMessage;
|
|
540
|
+
if (errorMessage === "") {
|
|
541
|
+
(_b = findErrorNode(input)) == null ? void 0 : _b.remove();
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
let errorElement = findErrorNode(input);
|
|
545
|
+
if (!errorElement) {
|
|
546
|
+
const anchor = findErrorAnchor(input);
|
|
547
|
+
errorElement = document.createElement("div");
|
|
548
|
+
errorElement.className = "error-message";
|
|
549
|
+
errorElement.style.cssText = `
|
|
550
|
+
color: var(--fb-error-color);
|
|
551
|
+
font-size: var(--fb-font-size-small);
|
|
552
|
+
margin-top: 0.25rem;
|
|
553
|
+
`;
|
|
554
|
+
(_c = anchor.parentNode) == null ? void 0 : _c.insertBefore(errorElement, anchor.nextSibling);
|
|
555
|
+
}
|
|
556
|
+
errorElement.setAttribute("data-error-for", (_d = input.getAttribute("name")) != null ? _d : "");
|
|
557
|
+
errorElement.textContent = errorMessage;
|
|
558
|
+
errorElement.style.display = "block";
|
|
559
|
+
}
|
|
560
|
+
function clearFieldError(input) {
|
|
561
|
+
var _a;
|
|
562
|
+
(_a = findErrorNode(input)) == null ? void 0 : _a.remove();
|
|
491
563
|
}
|
|
492
564
|
var BIN_ICON_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>';
|
|
493
565
|
function ensureThemingHooks(doc) {
|
|
@@ -609,8 +681,8 @@ function ensureThemingHooks(doc) {
|
|
|
609
681
|
`;
|
|
610
682
|
doc.head.appendChild(style);
|
|
611
683
|
}
|
|
612
|
-
function applyAutoExpand(textarea, options
|
|
613
|
-
var _a;
|
|
684
|
+
function applyAutoExpand(textarea, options) {
|
|
685
|
+
var _a, _b;
|
|
614
686
|
textarea.style.overflow = "hidden";
|
|
615
687
|
textarea.style.resize = "none";
|
|
616
688
|
const minRows = Math.max(1, (_a = options.minRows) != null ? _a : 1);
|
|
@@ -638,18 +710,20 @@ function applyAutoExpand(textarea, options = {}) {
|
|
|
638
710
|
if (typeof ResizeObserver === "undefined") return;
|
|
639
711
|
let lastWidth = -1;
|
|
640
712
|
const ro = new ResizeObserver((entries) => {
|
|
641
|
-
var _a2,
|
|
713
|
+
var _a2, _b2, _c, _d, _e, _f;
|
|
642
714
|
if (!textarea.isConnected) {
|
|
643
715
|
ro.disconnect();
|
|
716
|
+
(_a2 = options.observers) == null ? void 0 : _a2.delete(ro);
|
|
644
717
|
return;
|
|
645
718
|
}
|
|
646
719
|
const entry = entries[0];
|
|
647
|
-
const w = (
|
|
720
|
+
const w = (_f = (_e = (_c = (_b2 = entry == null ? void 0 : entry.contentBoxSize) == null ? void 0 : _b2[0]) == null ? void 0 : _c.inlineSize) != null ? _e : (_d = entry == null ? void 0 : entry.contentRect) == null ? void 0 : _d.width) != null ? _f : 0;
|
|
648
721
|
if (w === lastWidth) return;
|
|
649
722
|
lastWidth = w;
|
|
650
723
|
resize();
|
|
651
724
|
});
|
|
652
725
|
ro.observe(textarea);
|
|
726
|
+
(_b = options.observers) == null ? void 0 : _b.add(ro);
|
|
653
727
|
}
|
|
654
728
|
function applySingleLineMode(textarea) {
|
|
655
729
|
textarea.addEventListener("keydown", (e) => {
|
|
@@ -937,7 +1011,7 @@ function createCharCounter(element, input) {
|
|
|
937
1011
|
return counter;
|
|
938
1012
|
}
|
|
939
1013
|
function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
940
|
-
var _a;
|
|
1014
|
+
var _a, _b, _c;
|
|
941
1015
|
const state = ctx.state;
|
|
942
1016
|
const readonly = isElementReadonly(element, state, ctx);
|
|
943
1017
|
const inputWrapper = document.createElement("div");
|
|
@@ -965,10 +1039,10 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
965
1039
|
`;
|
|
966
1040
|
textInput.name = pathKey;
|
|
967
1041
|
textInput.placeholder = (_a = element.placeholder) != null ? _a : t("placeholderText", state);
|
|
968
|
-
textInput.value = ctx.prefill[element.key]
|
|
1042
|
+
textInput.value = (_c = (_b = ctx.prefill[element.key]) != null ? _b : element.default) != null ? _c : "";
|
|
969
1043
|
textInput.readOnly = readonly;
|
|
970
1044
|
applySingleLineMode(textInput);
|
|
971
|
-
applyAutoExpand(textInput);
|
|
1045
|
+
applyAutoExpand(textInput, { observers: state.autoExpandObservers });
|
|
972
1046
|
if (!readonly) {
|
|
973
1047
|
textInput.addEventListener("focus", () => {
|
|
974
1048
|
textInput.style.borderColor = "var(--fb-border-focus-color)";
|
|
@@ -1027,11 +1101,12 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1027
1101
|
const chip = input.closest(".fb-chip");
|
|
1028
1102
|
const sib = chip == null ? void 0 : chip.nextElementSibling;
|
|
1029
1103
|
if (sib && sib.classList.contains("error-message")) {
|
|
1030
|
-
sib.
|
|
1104
|
+
sib.setAttribute("data-error-for", input.name);
|
|
1031
1105
|
}
|
|
1032
1106
|
});
|
|
1033
1107
|
}
|
|
1034
1108
|
function addChip(value = "") {
|
|
1109
|
+
var _a2;
|
|
1035
1110
|
const chip = document.createElement("div");
|
|
1036
1111
|
chip.className = "fb-chip";
|
|
1037
1112
|
const dot = document.createElement("span");
|
|
@@ -1042,7 +1117,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1042
1117
|
input.rows = 1;
|
|
1043
1118
|
input.className = "fb-chip-input";
|
|
1044
1119
|
input.value = value;
|
|
1045
|
-
input.placeholder = element.placeholder
|
|
1120
|
+
input.placeholder = (_a2 = element.placeholder) != null ? _a2 : t("placeholderText", state);
|
|
1046
1121
|
input.readOnly = readonly;
|
|
1047
1122
|
chip.appendChild(input);
|
|
1048
1123
|
if (!readonly && ctx.instance) {
|
|
@@ -1056,7 +1131,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1056
1131
|
input.addEventListener("input", handleChange);
|
|
1057
1132
|
}
|
|
1058
1133
|
applySingleLineMode(input);
|
|
1059
|
-
applyAutoExpand(input);
|
|
1134
|
+
applyAutoExpand(input, { observers: state.autoExpandObservers });
|
|
1060
1135
|
if (!readonly) {
|
|
1061
1136
|
const rem = document.createElement("button");
|
|
1062
1137
|
rem.type = "button";
|
|
@@ -1064,7 +1139,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1064
1139
|
rem.setAttribute("aria-label", t("removeElement", state));
|
|
1065
1140
|
rem.innerHTML = BIN_ICON_SVG;
|
|
1066
1141
|
rem.onclick = () => {
|
|
1067
|
-
var
|
|
1142
|
+
var _a3;
|
|
1068
1143
|
const chips = list.querySelectorAll(".fb-chip");
|
|
1069
1144
|
const idx = Array.prototype.indexOf.call(chips, chip);
|
|
1070
1145
|
if (idx < 0) return;
|
|
@@ -1078,7 +1153,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
1078
1153
|
updateIndices();
|
|
1079
1154
|
updateAddButton();
|
|
1080
1155
|
updateRemoveButtons();
|
|
1081
|
-
(
|
|
1156
|
+
(_a3 = ctx.instance) == null ? void 0 : _a3.triggerOnChange(pathKey);
|
|
1082
1157
|
};
|
|
1083
1158
|
chip.appendChild(rem);
|
|
1084
1159
|
}
|
|
@@ -1123,41 +1198,6 @@ function validateTextElement(element, key, context) {
|
|
|
1123
1198
|
var _a, _b, _c;
|
|
1124
1199
|
const errors = [];
|
|
1125
1200
|
const { scopeRoot, skipValidation } = context;
|
|
1126
|
-
const markValidity = (input, errorMessage) => {
|
|
1127
|
-
var _a2, _b2, _c2;
|
|
1128
|
-
if (!input) return;
|
|
1129
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
1130
|
-
let errorElement = document.getElementById(errorId);
|
|
1131
|
-
if (errorMessage) {
|
|
1132
|
-
input.classList.add("invalid");
|
|
1133
|
-
input.title = errorMessage;
|
|
1134
|
-
if (!errorElement) {
|
|
1135
|
-
errorElement = document.createElement("div");
|
|
1136
|
-
errorElement.id = errorId;
|
|
1137
|
-
errorElement.className = "error-message";
|
|
1138
|
-
errorElement.style.cssText = `
|
|
1139
|
-
color: var(--fb-error-color);
|
|
1140
|
-
font-size: var(--fb-font-size-small);
|
|
1141
|
-
margin-top: 0.25rem;
|
|
1142
|
-
`;
|
|
1143
|
-
const chipAncestor = (_a2 = input.closest) == null ? void 0 : _a2.call(input, ".fb-chip");
|
|
1144
|
-
const anchor = chipAncestor || input;
|
|
1145
|
-
if (anchor.nextSibling) {
|
|
1146
|
-
(_b2 = anchor.parentNode) == null ? void 0 : _b2.insertBefore(errorElement, anchor.nextSibling);
|
|
1147
|
-
} else {
|
|
1148
|
-
(_c2 = anchor.parentNode) == null ? void 0 : _c2.appendChild(errorElement);
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
errorElement.textContent = errorMessage;
|
|
1152
|
-
errorElement.style.display = "block";
|
|
1153
|
-
} else {
|
|
1154
|
-
input.classList.remove("invalid");
|
|
1155
|
-
input.title = "";
|
|
1156
|
-
if (errorElement) {
|
|
1157
|
-
errorElement.remove();
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
};
|
|
1161
1201
|
const validateTextInput = (input, val, fieldKey) => {
|
|
1162
1202
|
let hasError = false;
|
|
1163
1203
|
const { state } = context;
|
|
@@ -1165,12 +1205,12 @@ function validateTextElement(element, key, context) {
|
|
|
1165
1205
|
if (element.minLength !== void 0 && element.minLength !== null && val.length < element.minLength) {
|
|
1166
1206
|
const msg = t("minLength", state, { min: element.minLength });
|
|
1167
1207
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1168
|
-
|
|
1208
|
+
markFieldValidity(input, msg);
|
|
1169
1209
|
hasError = true;
|
|
1170
1210
|
} else if (element.maxLength !== void 0 && element.maxLength !== null && val.length > element.maxLength) {
|
|
1171
1211
|
const msg = t("maxLength", state, { max: element.maxLength });
|
|
1172
1212
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1173
|
-
|
|
1213
|
+
markFieldValidity(input, msg);
|
|
1174
1214
|
hasError = true;
|
|
1175
1215
|
} else if (element.pattern) {
|
|
1176
1216
|
try {
|
|
@@ -1178,19 +1218,19 @@ function validateTextElement(element, key, context) {
|
|
|
1178
1218
|
if (!re.test(val)) {
|
|
1179
1219
|
const msg = t("patternMismatch", state);
|
|
1180
1220
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1181
|
-
|
|
1221
|
+
markFieldValidity(input, msg);
|
|
1182
1222
|
hasError = true;
|
|
1183
1223
|
}
|
|
1184
1224
|
} catch {
|
|
1185
1225
|
const msg = t("invalidPattern", state);
|
|
1186
1226
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1187
|
-
|
|
1227
|
+
markFieldValidity(input, msg);
|
|
1188
1228
|
hasError = true;
|
|
1189
1229
|
}
|
|
1190
1230
|
}
|
|
1191
1231
|
}
|
|
1192
1232
|
if (!hasError) {
|
|
1193
|
-
|
|
1233
|
+
markFieldValidity(input, null);
|
|
1194
1234
|
}
|
|
1195
1235
|
};
|
|
1196
1236
|
if (element.multiple) {
|
|
@@ -1226,7 +1266,7 @@ function validateTextElement(element, key, context) {
|
|
|
1226
1266
|
if (!skipValidation && element.required && val === "") {
|
|
1227
1267
|
const msg = t("required", context.state);
|
|
1228
1268
|
errors.push(`${key}: ${msg}`);
|
|
1229
|
-
|
|
1269
|
+
markFieldValidity(input, msg);
|
|
1230
1270
|
return { value: null, errors };
|
|
1231
1271
|
}
|
|
1232
1272
|
if (input) {
|
|
@@ -1275,7 +1315,7 @@ function updateTextField(element, fieldPath, value, context) {
|
|
|
1275
1315
|
|
|
1276
1316
|
// src/components/textarea.ts
|
|
1277
1317
|
function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
1278
|
-
var _a, _b;
|
|
1318
|
+
var _a, _b, _c, _d;
|
|
1279
1319
|
const state = ctx.state;
|
|
1280
1320
|
const readonly = isElementReadonly(element, state, ctx);
|
|
1281
1321
|
const textareaWrapper = document.createElement("div");
|
|
@@ -1289,8 +1329,8 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1289
1329
|
line-height: var(--fb-line-height, 1.5);
|
|
1290
1330
|
`;
|
|
1291
1331
|
textareaInput.name = pathKey;
|
|
1292
|
-
textareaInput.placeholder = (_a = element.placeholder) != null ? _a : "
|
|
1293
|
-
textareaInput.value = ctx.prefill[element.key]
|
|
1332
|
+
textareaInput.placeholder = (_a = element.placeholder) != null ? _a : t("placeholderText", state);
|
|
1333
|
+
textareaInput.value = (_c = (_b = ctx.prefill[element.key]) != null ? _b : element.default) != null ? _c : "";
|
|
1294
1334
|
textareaInput.readOnly = readonly;
|
|
1295
1335
|
if (!readonly && ctx.instance) {
|
|
1296
1336
|
const handleChange = () => {
|
|
@@ -1300,7 +1340,10 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1300
1340
|
textareaInput.addEventListener("blur", handleChange);
|
|
1301
1341
|
textareaInput.addEventListener("input", handleChange);
|
|
1302
1342
|
}
|
|
1303
|
-
applyAutoExpand(textareaInput, {
|
|
1343
|
+
applyAutoExpand(textareaInput, {
|
|
1344
|
+
minRows: (_d = element.rows) != null ? _d : 1,
|
|
1345
|
+
observers: state.autoExpandObservers
|
|
1346
|
+
});
|
|
1304
1347
|
textareaWrapper.appendChild(textareaInput);
|
|
1305
1348
|
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
1306
1349
|
const counter = createCharCounter(element, textareaInput);
|
|
@@ -1332,7 +1375,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1332
1375
|
});
|
|
1333
1376
|
}
|
|
1334
1377
|
function addTextareaItem(value = "", index = -1) {
|
|
1335
|
-
var _a2;
|
|
1378
|
+
var _a2, _b2;
|
|
1336
1379
|
const itemWrapper = document.createElement("div");
|
|
1337
1380
|
itemWrapper.className = "multiple-textarea-item";
|
|
1338
1381
|
const textareaContainer = document.createElement("div");
|
|
@@ -1345,7 +1388,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1345
1388
|
font-family: var(--fb-font-family);
|
|
1346
1389
|
line-height: var(--fb-line-height, 1.5);
|
|
1347
1390
|
`;
|
|
1348
|
-
textareaInput.placeholder = element.placeholder
|
|
1391
|
+
textareaInput.placeholder = (_a2 = element.placeholder) != null ? _a2 : t("placeholderText", state);
|
|
1349
1392
|
textareaInput.value = value;
|
|
1350
1393
|
textareaInput.readOnly = readonly;
|
|
1351
1394
|
if (!readonly && ctx.instance) {
|
|
@@ -1356,7 +1399,10 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1356
1399
|
textareaInput.addEventListener("blur", handleChange);
|
|
1357
1400
|
textareaInput.addEventListener("input", handleChange);
|
|
1358
1401
|
}
|
|
1359
|
-
applyAutoExpand(textareaInput, {
|
|
1402
|
+
applyAutoExpand(textareaInput, {
|
|
1403
|
+
minRows: (_b2 = element.rows) != null ? _b2 : 1,
|
|
1404
|
+
observers: state.autoExpandObservers
|
|
1405
|
+
});
|
|
1360
1406
|
textareaContainer.appendChild(textareaInput);
|
|
1361
1407
|
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
1362
1408
|
const counter = createCharCounter(element, textareaInput);
|
|
@@ -1579,7 +1625,19 @@ function createNumberRangeHint(element, input) {
|
|
|
1579
1625
|
updateColor();
|
|
1580
1626
|
return hint;
|
|
1581
1627
|
}
|
|
1628
|
+
function numberStepAttr(element) {
|
|
1629
|
+
if (element.step !== void 0) return element.step.toString();
|
|
1630
|
+
if (element.decimals !== void 0)
|
|
1631
|
+
return (10 ** -element.decimals).toString();
|
|
1632
|
+
return "any";
|
|
1633
|
+
}
|
|
1634
|
+
function applyDecimalsMarker(input, element) {
|
|
1635
|
+
if (element.decimals !== void 0) {
|
|
1636
|
+
input.setAttribute("data-decimals", String(element.decimals));
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1582
1639
|
function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
1640
|
+
var _a, _b, _c;
|
|
1583
1641
|
const state = ctx.state;
|
|
1584
1642
|
const readonly = isElementReadonly(element, state, ctx);
|
|
1585
1643
|
const inputWrapper = document.createElement("div");
|
|
@@ -1587,11 +1645,12 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1587
1645
|
const numberInput = document.createElement("input");
|
|
1588
1646
|
numberInput.type = "number";
|
|
1589
1647
|
numberInput.name = pathKey;
|
|
1590
|
-
numberInput.placeholder = element.placeholder
|
|
1648
|
+
numberInput.placeholder = (_a = element.placeholder) != null ? _a : "0";
|
|
1591
1649
|
if (element.min !== void 0) numberInput.min = element.min.toString();
|
|
1592
1650
|
if (element.max !== void 0) numberInput.max = element.max.toString();
|
|
1593
|
-
|
|
1594
|
-
numberInput
|
|
1651
|
+
numberInput.step = numberStepAttr(element);
|
|
1652
|
+
applyDecimalsMarker(numberInput, element);
|
|
1653
|
+
numberInput.value = (_c = (_b = ctx.prefill[element.key]) != null ? _b : element.default) != null ? _c : "";
|
|
1595
1654
|
numberInput.readOnly = readonly;
|
|
1596
1655
|
if (!element.stepper) {
|
|
1597
1656
|
numberInput.className = "w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500";
|
|
@@ -1623,7 +1682,7 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1623
1682
|
wrapper.appendChild(inputWrapper);
|
|
1624
1683
|
}
|
|
1625
1684
|
function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
1626
|
-
var _a, _b;
|
|
1685
|
+
var _a, _b, _c;
|
|
1627
1686
|
const state = ctx.state;
|
|
1628
1687
|
const readonly = isElementReadonly(element, state, ctx);
|
|
1629
1688
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
@@ -1631,7 +1690,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1631
1690
|
const minCount = (_a = element.minCount) != null ? _a : element.required ? 1 : 0;
|
|
1632
1691
|
const maxCount = (_b = element.maxCount) != null ? _b : Infinity;
|
|
1633
1692
|
while (values.length < minCount) {
|
|
1634
|
-
values.push(element.default
|
|
1693
|
+
values.push((_c = element.default) != null ? _c : "");
|
|
1635
1694
|
}
|
|
1636
1695
|
const container = document.createElement("div");
|
|
1637
1696
|
container.className = "fb-row";
|
|
@@ -1646,6 +1705,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1646
1705
|
});
|
|
1647
1706
|
}
|
|
1648
1707
|
function addNumberItem(value = "", index = -1) {
|
|
1708
|
+
var _a2;
|
|
1649
1709
|
const itemWrapper = document.createElement("div");
|
|
1650
1710
|
itemWrapper.className = "multiple-number-item flex items-center gap-2";
|
|
1651
1711
|
const inputContainer = document.createElement("div");
|
|
@@ -1660,10 +1720,11 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1660
1720
|
width: 100%;
|
|
1661
1721
|
box-sizing: border-box;
|
|
1662
1722
|
`;
|
|
1663
|
-
numberInput.placeholder = element.placeholder
|
|
1723
|
+
numberInput.placeholder = (_a2 = element.placeholder) != null ? _a2 : "0";
|
|
1664
1724
|
if (element.min !== void 0) numberInput.min = element.min.toString();
|
|
1665
1725
|
if (element.max !== void 0) numberInput.max = element.max.toString();
|
|
1666
|
-
|
|
1726
|
+
numberInput.step = numberStepAttr(element);
|
|
1727
|
+
applyDecimalsMarker(numberInput, element);
|
|
1667
1728
|
numberInput.value = value.toString();
|
|
1668
1729
|
numberInput.readOnly = readonly;
|
|
1669
1730
|
if (!readonly && ctx.instance) {
|
|
@@ -1728,12 +1789,12 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1728
1789
|
const handle = createAddItemRow(
|
|
1729
1790
|
"number",
|
|
1730
1791
|
() => {
|
|
1731
|
-
var _a2;
|
|
1732
|
-
values.push(element.default
|
|
1733
|
-
addNumberItem(element.default
|
|
1792
|
+
var _a2, _b2, _c2;
|
|
1793
|
+
values.push((_a2 = element.default) != null ? _a2 : "");
|
|
1794
|
+
addNumberItem((_b2 = element.default) != null ? _b2 : "");
|
|
1734
1795
|
updateAddButton();
|
|
1735
1796
|
updateRemoveButtons();
|
|
1736
|
-
(
|
|
1797
|
+
(_c2 = ctx.instance) == null ? void 0 : _c2.triggerOnChange(pathKey);
|
|
1737
1798
|
},
|
|
1738
1799
|
{ label: element.addLabel }
|
|
1739
1800
|
);
|
|
@@ -1752,55 +1813,22 @@ function validateNumberElement(element, key, context) {
|
|
|
1752
1813
|
var _a, _b, _c;
|
|
1753
1814
|
const errors = [];
|
|
1754
1815
|
const { scopeRoot, skipValidation } = context;
|
|
1755
|
-
const markValidity = (input, errorMessage) => {
|
|
1756
|
-
var _a2, _b2;
|
|
1757
|
-
if (!input) return;
|
|
1758
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
1759
|
-
let errorElement = document.getElementById(errorId);
|
|
1760
|
-
if (errorMessage) {
|
|
1761
|
-
input.classList.add("invalid");
|
|
1762
|
-
input.title = errorMessage;
|
|
1763
|
-
if (!errorElement) {
|
|
1764
|
-
errorElement = document.createElement("div");
|
|
1765
|
-
errorElement.id = errorId;
|
|
1766
|
-
errorElement.className = "error-message";
|
|
1767
|
-
errorElement.style.cssText = `
|
|
1768
|
-
color: var(--fb-error-color);
|
|
1769
|
-
font-size: var(--fb-font-size-small);
|
|
1770
|
-
margin-top: 0.25rem;
|
|
1771
|
-
`;
|
|
1772
|
-
if (input.nextSibling) {
|
|
1773
|
-
(_a2 = input.parentNode) == null ? void 0 : _a2.insertBefore(errorElement, input.nextSibling);
|
|
1774
|
-
} else {
|
|
1775
|
-
(_b2 = input.parentNode) == null ? void 0 : _b2.appendChild(errorElement);
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
errorElement.textContent = errorMessage;
|
|
1779
|
-
errorElement.style.display = "block";
|
|
1780
|
-
} else {
|
|
1781
|
-
input.classList.remove("invalid");
|
|
1782
|
-
input.title = "";
|
|
1783
|
-
if (errorElement) {
|
|
1784
|
-
errorElement.remove();
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
};
|
|
1788
1816
|
const validateNumberInput = (input, v, fieldKey) => {
|
|
1789
1817
|
let hasError = false;
|
|
1790
1818
|
const { state } = context;
|
|
1791
1819
|
if (!skipValidation && element.min !== void 0 && element.min !== null && v < element.min) {
|
|
1792
1820
|
const msg = t("minValue", state, { min: element.min });
|
|
1793
1821
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1794
|
-
|
|
1822
|
+
markFieldValidity(input, msg);
|
|
1795
1823
|
hasError = true;
|
|
1796
1824
|
} else if (!skipValidation && element.max !== void 0 && element.max !== null && v > element.max) {
|
|
1797
1825
|
const msg = t("maxValue", state, { max: element.max });
|
|
1798
1826
|
errors.push(`${fieldKey}: ${msg}`);
|
|
1799
|
-
|
|
1827
|
+
markFieldValidity(input, msg);
|
|
1800
1828
|
hasError = true;
|
|
1801
1829
|
}
|
|
1802
1830
|
if (!hasError) {
|
|
1803
|
-
|
|
1831
|
+
markFieldValidity(input, null);
|
|
1804
1832
|
}
|
|
1805
1833
|
};
|
|
1806
1834
|
if (element.multiple) {
|
|
@@ -1813,14 +1841,14 @@ function validateNumberElement(element, key, context) {
|
|
|
1813
1841
|
const raw = (_a2 = input == null ? void 0 : input.value) != null ? _a2 : "";
|
|
1814
1842
|
if (raw === "") {
|
|
1815
1843
|
values.push(null);
|
|
1816
|
-
|
|
1844
|
+
markFieldValidity(input, null);
|
|
1817
1845
|
return;
|
|
1818
1846
|
}
|
|
1819
1847
|
const v = parseFloat(raw);
|
|
1820
1848
|
if (!skipValidation && !Number.isFinite(v)) {
|
|
1821
1849
|
const msg = t("notANumber", context.state);
|
|
1822
1850
|
errors.push(`${key}[${index}]: ${msg}`);
|
|
1823
|
-
|
|
1851
|
+
markFieldValidity(input, msg);
|
|
1824
1852
|
values.push(null);
|
|
1825
1853
|
return;
|
|
1826
1854
|
}
|
|
@@ -1850,18 +1878,18 @@ function validateNumberElement(element, key, context) {
|
|
|
1850
1878
|
if (!skipValidation && element.required && raw === "") {
|
|
1851
1879
|
const msg = t("required", state);
|
|
1852
1880
|
errors.push(`${key}: ${msg}`);
|
|
1853
|
-
|
|
1881
|
+
markFieldValidity(input, msg);
|
|
1854
1882
|
return { value: null, errors };
|
|
1855
1883
|
}
|
|
1856
1884
|
if (raw === "") {
|
|
1857
|
-
|
|
1885
|
+
markFieldValidity(input, null);
|
|
1858
1886
|
return { value: null, errors };
|
|
1859
1887
|
}
|
|
1860
1888
|
const v = parseFloat(raw);
|
|
1861
1889
|
if (!skipValidation && !Number.isFinite(v)) {
|
|
1862
1890
|
const msg = t("notANumber", state);
|
|
1863
1891
|
errors.push(`${key}: ${msg}`);
|
|
1864
|
-
|
|
1892
|
+
markFieldValidity(input, msg);
|
|
1865
1893
|
return { value: null, errors };
|
|
1866
1894
|
}
|
|
1867
1895
|
validateNumberInput(input, v, key);
|
|
@@ -1911,7 +1939,41 @@ function updateNumberField(element, fieldPath, value, context) {
|
|
|
1911
1939
|
}
|
|
1912
1940
|
|
|
1913
1941
|
// src/components/select.ts
|
|
1942
|
+
function appendSelectOptions(select, element, selectedValue, state) {
|
|
1943
|
+
var _a;
|
|
1944
|
+
const options = element.options || [];
|
|
1945
|
+
if (!options.some((option) => option.value === "")) {
|
|
1946
|
+
const emptyOption = document.createElement("option");
|
|
1947
|
+
emptyOption.value = "";
|
|
1948
|
+
emptyOption.textContent = (_a = element.placeholder) != null ? _a : t("selectPlaceholder", state);
|
|
1949
|
+
select.appendChild(emptyOption);
|
|
1950
|
+
}
|
|
1951
|
+
const strSelected = selectedValue == null ? null : String(selectedValue);
|
|
1952
|
+
let anySelected = false;
|
|
1953
|
+
options.forEach((option) => {
|
|
1954
|
+
const optionEl = document.createElement("option");
|
|
1955
|
+
optionEl.value = option.value;
|
|
1956
|
+
optionEl.textContent = option.label;
|
|
1957
|
+
if (strSelected === option.value) {
|
|
1958
|
+
optionEl.selected = true;
|
|
1959
|
+
anySelected = true;
|
|
1960
|
+
}
|
|
1961
|
+
select.appendChild(optionEl);
|
|
1962
|
+
});
|
|
1963
|
+
if (!anySelected && strSelected !== null && strSelected !== "") {
|
|
1964
|
+
console.warn(
|
|
1965
|
+
`select "${element.key}": prefill value "${strSelected}" is not among the options; leaving the field unselected`
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
if (!anySelected) {
|
|
1969
|
+
const empty = Array.from(select.options).find(
|
|
1970
|
+
(option) => option.value === ""
|
|
1971
|
+
);
|
|
1972
|
+
if (empty) empty.selected = true;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1914
1975
|
function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
1976
|
+
var _a;
|
|
1915
1977
|
const state = ctx.state;
|
|
1916
1978
|
const readonly = isElementReadonly(element, state, ctx);
|
|
1917
1979
|
const selectInput = document.createElement("select");
|
|
@@ -1923,18 +1985,18 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1923
1985
|
`;
|
|
1924
1986
|
selectInput.name = pathKey;
|
|
1925
1987
|
selectInput.disabled = readonly;
|
|
1926
|
-
(
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
}
|
|
1933
|
-
selectInput.appendChild(optionEl);
|
|
1934
|
-
});
|
|
1988
|
+
appendSelectOptions(
|
|
1989
|
+
selectInput,
|
|
1990
|
+
element,
|
|
1991
|
+
(_a = ctx.prefill[element.key]) != null ? _a : element.default,
|
|
1992
|
+
state
|
|
1993
|
+
);
|
|
1935
1994
|
if (!readonly && ctx.instance) {
|
|
1936
1995
|
const handleChange = () => {
|
|
1937
|
-
ctx.instance.triggerOnChange(
|
|
1996
|
+
ctx.instance.triggerOnChange(
|
|
1997
|
+
pathKey,
|
|
1998
|
+
selectInput.value === "" ? null : selectInput.value
|
|
1999
|
+
);
|
|
1938
2000
|
};
|
|
1939
2001
|
selectInput.addEventListener("change", handleChange);
|
|
1940
2002
|
}
|
|
@@ -1947,7 +2009,7 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1947
2009
|
}
|
|
1948
2010
|
}
|
|
1949
2011
|
function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
1950
|
-
var _a, _b, _c
|
|
2012
|
+
var _a, _b, _c;
|
|
1951
2013
|
const state = ctx.state;
|
|
1952
2014
|
const readonly = isElementReadonly(element, state, ctx);
|
|
1953
2015
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
@@ -1955,7 +2017,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1955
2017
|
const minCount = (_a = element.minCount) != null ? _a : element.required ? 1 : 0;
|
|
1956
2018
|
const maxCount = (_b = element.maxCount) != null ? _b : Infinity;
|
|
1957
2019
|
while (values.length < minCount) {
|
|
1958
|
-
values.push(
|
|
2020
|
+
values.push((_c = element.default) != null ? _c : "");
|
|
1959
2021
|
}
|
|
1960
2022
|
const container = document.createElement("div");
|
|
1961
2023
|
container.className = "fb-row";
|
|
@@ -1980,15 +2042,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1980
2042
|
font-family: var(--fb-font-family);
|
|
1981
2043
|
`;
|
|
1982
2044
|
selectInput.disabled = readonly;
|
|
1983
|
-
(element
|
|
1984
|
-
const optionElement = document.createElement("option");
|
|
1985
|
-
optionElement.value = option.value;
|
|
1986
|
-
optionElement.textContent = option.label;
|
|
1987
|
-
if (value === option.value) {
|
|
1988
|
-
optionElement.selected = true;
|
|
1989
|
-
}
|
|
1990
|
-
selectInput.appendChild(optionElement);
|
|
1991
|
-
});
|
|
2045
|
+
appendSelectOptions(selectInput, element, value, state);
|
|
1992
2046
|
if (!readonly && ctx.instance) {
|
|
1993
2047
|
const handleChange = () => {
|
|
1994
2048
|
ctx.instance.triggerOnChange(selectInput.name, selectInput.value);
|
|
@@ -2042,13 +2096,13 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
2042
2096
|
const handle = createAddItemRow(
|
|
2043
2097
|
"select",
|
|
2044
2098
|
() => {
|
|
2045
|
-
var _a2, _b2
|
|
2046
|
-
const defaultValue =
|
|
2099
|
+
var _a2, _b2;
|
|
2100
|
+
const defaultValue = (_a2 = element.default) != null ? _a2 : "";
|
|
2047
2101
|
values.push(defaultValue);
|
|
2048
2102
|
addSelectItem(defaultValue);
|
|
2049
2103
|
updateAddButton();
|
|
2050
2104
|
updateRemoveButtons();
|
|
2051
|
-
(
|
|
2105
|
+
(_b2 = ctx.instance) == null ? void 0 : _b2.triggerOnChange(pathKey);
|
|
2052
2106
|
},
|
|
2053
2107
|
{ label: element.addLabel }
|
|
2054
2108
|
);
|
|
@@ -2073,39 +2127,6 @@ function validateSelectElement(element, key, context) {
|
|
|
2073
2127
|
var _a;
|
|
2074
2128
|
const errors = [];
|
|
2075
2129
|
const { scopeRoot, skipValidation } = context;
|
|
2076
|
-
const markValidity = (input, errorMessage) => {
|
|
2077
|
-
var _a2, _b;
|
|
2078
|
-
if (!input) return;
|
|
2079
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
2080
|
-
let errorElement = document.getElementById(errorId);
|
|
2081
|
-
if (errorMessage) {
|
|
2082
|
-
input.classList.add("invalid");
|
|
2083
|
-
input.title = errorMessage;
|
|
2084
|
-
if (!errorElement) {
|
|
2085
|
-
errorElement = document.createElement("div");
|
|
2086
|
-
errorElement.id = errorId;
|
|
2087
|
-
errorElement.className = "error-message";
|
|
2088
|
-
errorElement.style.cssText = `
|
|
2089
|
-
color: var(--fb-error-color);
|
|
2090
|
-
font-size: var(--fb-font-size-small);
|
|
2091
|
-
margin-top: 0.25rem;
|
|
2092
|
-
`;
|
|
2093
|
-
if (input.nextSibling) {
|
|
2094
|
-
(_a2 = input.parentNode) == null ? void 0 : _a2.insertBefore(errorElement, input.nextSibling);
|
|
2095
|
-
} else {
|
|
2096
|
-
(_b = input.parentNode) == null ? void 0 : _b.appendChild(errorElement);
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
errorElement.textContent = errorMessage;
|
|
2100
|
-
errorElement.style.display = "block";
|
|
2101
|
-
} else {
|
|
2102
|
-
input.classList.remove("invalid");
|
|
2103
|
-
input.title = "";
|
|
2104
|
-
if (errorElement) {
|
|
2105
|
-
errorElement.remove();
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
};
|
|
2109
2130
|
const validateMultipleCount = (key2, values, element2, filterFn) => {
|
|
2110
2131
|
var _a2, _b;
|
|
2111
2132
|
if (skipValidation) return;
|
|
@@ -2131,27 +2152,36 @@ function validateSelectElement(element, key, context) {
|
|
|
2131
2152
|
inputs.forEach((input) => {
|
|
2132
2153
|
var _a2;
|
|
2133
2154
|
const val = (_a2 = input == null ? void 0 : input.value) != null ? _a2 : "";
|
|
2134
|
-
values.push(val);
|
|
2135
|
-
|
|
2155
|
+
values.push(val === "" ? null : val);
|
|
2156
|
+
markFieldValidity(input, null);
|
|
2136
2157
|
});
|
|
2137
|
-
validateMultipleCount(key, values, element, (v) => v
|
|
2158
|
+
validateMultipleCount(key, values, element, (v) => v != null);
|
|
2138
2159
|
return { value: values, errors };
|
|
2139
2160
|
} else {
|
|
2140
|
-
const input = scopeRoot.querySelector(
|
|
2141
|
-
`[name="${key}"]`
|
|
2142
|
-
);
|
|
2161
|
+
const input = scopeRoot.querySelector(`[name="${key}"]`);
|
|
2143
2162
|
const val = (_a = input == null ? void 0 : input.value) != null ? _a : "";
|
|
2144
2163
|
if (!skipValidation && element.required && val === "") {
|
|
2145
2164
|
const msg = t("required", context.state);
|
|
2146
2165
|
errors.push(`${key}: ${msg}`);
|
|
2147
|
-
|
|
2166
|
+
markFieldValidity(input, msg);
|
|
2148
2167
|
return { value: null, errors };
|
|
2149
2168
|
} else {
|
|
2150
|
-
|
|
2169
|
+
markFieldValidity(input, null);
|
|
2151
2170
|
}
|
|
2152
2171
|
return { value: val === "" ? null : val, errors };
|
|
2153
2172
|
}
|
|
2154
2173
|
}
|
|
2174
|
+
function assertValueInOptions(select, strValue, fieldPath) {
|
|
2175
|
+
if (strValue === "") return;
|
|
2176
|
+
const match = Array.from(select.options).some(
|
|
2177
|
+
(option) => option.value === strValue
|
|
2178
|
+
);
|
|
2179
|
+
if (!match) {
|
|
2180
|
+
throw new Error(
|
|
2181
|
+
`updateSelectField: value "${strValue}" is not among the options of "${fieldPath}"`
|
|
2182
|
+
);
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2155
2185
|
function updateSelectField(element, fieldPath, value, context) {
|
|
2156
2186
|
const { scopeRoot } = context;
|
|
2157
2187
|
if ("multiple" in element && element.multiple) {
|
|
@@ -2166,10 +2196,17 @@ function updateSelectField(element, fieldPath, value, context) {
|
|
|
2166
2196
|
);
|
|
2167
2197
|
selects.forEach((select, index) => {
|
|
2168
2198
|
if (index < value.length) {
|
|
2169
|
-
|
|
2199
|
+
const strValue = value[index] != null ? String(value[index]) : "";
|
|
2200
|
+
assertValueInOptions(select, strValue, `${fieldPath}[${index}]`);
|
|
2201
|
+
}
|
|
2202
|
+
});
|
|
2203
|
+
selects.forEach((select, index) => {
|
|
2204
|
+
if (index < value.length) {
|
|
2205
|
+
const strValue = value[index] != null ? String(value[index]) : "";
|
|
2206
|
+
select.value = strValue;
|
|
2170
2207
|
const options = select.querySelectorAll("option");
|
|
2171
2208
|
options.forEach((option) => {
|
|
2172
|
-
option.selected = option.value ===
|
|
2209
|
+
option.selected = option.value === strValue;
|
|
2173
2210
|
});
|
|
2174
2211
|
select.classList.remove("invalid");
|
|
2175
2212
|
select.title = "";
|
|
@@ -2186,10 +2223,12 @@ function updateSelectField(element, fieldPath, value, context) {
|
|
|
2186
2223
|
`[name="${fieldPath}"]`
|
|
2187
2224
|
);
|
|
2188
2225
|
if (select) {
|
|
2189
|
-
|
|
2226
|
+
const strValue = value != null ? String(value) : "";
|
|
2227
|
+
assertValueInOptions(select, strValue, fieldPath);
|
|
2228
|
+
select.value = strValue;
|
|
2190
2229
|
const options = select.querySelectorAll("option");
|
|
2191
2230
|
options.forEach((option) => {
|
|
2192
|
-
option.selected = option.value ===
|
|
2231
|
+
option.selected = option.value === strValue;
|
|
2193
2232
|
});
|
|
2194
2233
|
select.classList.remove("invalid");
|
|
2195
2234
|
select.title = "";
|
|
@@ -2387,14 +2426,14 @@ function renderSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2387
2426
|
}
|
|
2388
2427
|
}
|
|
2389
2428
|
function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
2390
|
-
var _a, _b, _c
|
|
2429
|
+
var _a, _b, _c;
|
|
2391
2430
|
const state = ctx.state;
|
|
2392
2431
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
2393
2432
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
2394
2433
|
const minCount = (_a = element.minCount) != null ? _a : element.required ? 1 : 0;
|
|
2395
2434
|
const maxCount = (_b = element.maxCount) != null ? _b : Infinity;
|
|
2396
2435
|
while (values.length < minCount) {
|
|
2397
|
-
values.push(
|
|
2436
|
+
values.push((_c = element.default) != null ? _c : "");
|
|
2398
2437
|
}
|
|
2399
2438
|
const readonly = isElementReadonly(element, state, ctx);
|
|
2400
2439
|
const container = document.createElement("div");
|
|
@@ -2489,13 +2528,13 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2489
2528
|
const handle = createAddItemRow(
|
|
2490
2529
|
"switcher",
|
|
2491
2530
|
() => {
|
|
2492
|
-
var _a2, _b2
|
|
2493
|
-
const defaultValue =
|
|
2531
|
+
var _a2, _b2;
|
|
2532
|
+
const defaultValue = (_a2 = element.default) != null ? _a2 : "";
|
|
2494
2533
|
values.push(defaultValue);
|
|
2495
2534
|
addSwitcherItem(defaultValue);
|
|
2496
2535
|
updateAddButton();
|
|
2497
2536
|
updateRemoveButtons();
|
|
2498
|
-
(
|
|
2537
|
+
(_b2 = ctx.instance) == null ? void 0 : _b2.triggerOnChange(pathKey);
|
|
2499
2538
|
},
|
|
2500
2539
|
{ label: element.addLabel }
|
|
2501
2540
|
);
|
|
@@ -2520,39 +2559,6 @@ function validateSwitcherElement(element, key, context) {
|
|
|
2520
2559
|
var _a;
|
|
2521
2560
|
const errors = [];
|
|
2522
2561
|
const { scopeRoot, skipValidation } = context;
|
|
2523
|
-
const markValidity = (input, errorMessage) => {
|
|
2524
|
-
var _a2, _b;
|
|
2525
|
-
if (!input) return;
|
|
2526
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
2527
|
-
let errorElement = document.getElementById(errorId);
|
|
2528
|
-
if (errorMessage) {
|
|
2529
|
-
input.classList.add("invalid");
|
|
2530
|
-
input.title = errorMessage;
|
|
2531
|
-
if (!errorElement) {
|
|
2532
|
-
errorElement = document.createElement("div");
|
|
2533
|
-
errorElement.id = errorId;
|
|
2534
|
-
errorElement.className = "error-message";
|
|
2535
|
-
errorElement.style.cssText = `
|
|
2536
|
-
color: var(--fb-error-color);
|
|
2537
|
-
font-size: var(--fb-font-size-small);
|
|
2538
|
-
margin-top: 0.25rem;
|
|
2539
|
-
`;
|
|
2540
|
-
if (input.nextSibling) {
|
|
2541
|
-
(_a2 = input.parentNode) == null ? void 0 : _a2.insertBefore(errorElement, input.nextSibling);
|
|
2542
|
-
} else {
|
|
2543
|
-
(_b = input.parentNode) == null ? void 0 : _b.appendChild(errorElement);
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
errorElement.textContent = errorMessage;
|
|
2547
|
-
errorElement.style.display = "block";
|
|
2548
|
-
} else {
|
|
2549
|
-
input.classList.remove("invalid");
|
|
2550
|
-
input.title = "";
|
|
2551
|
-
if (errorElement) {
|
|
2552
|
-
errorElement.remove();
|
|
2553
|
-
}
|
|
2554
|
-
}
|
|
2555
|
-
};
|
|
2556
2562
|
const validateMultipleCount = (fieldKey, values, el, filterFn) => {
|
|
2557
2563
|
var _a2, _b;
|
|
2558
2564
|
if (skipValidation) return;
|
|
@@ -2581,16 +2587,16 @@ function validateSwitcherElement(element, key, context) {
|
|
|
2581
2587
|
inputs.forEach((input) => {
|
|
2582
2588
|
var _a2;
|
|
2583
2589
|
const val = (_a2 = input == null ? void 0 : input.value) != null ? _a2 : "";
|
|
2584
|
-
values.push(val);
|
|
2590
|
+
values.push(val === "" ? null : val);
|
|
2585
2591
|
if (!skipValidation && val !== "" && !validOptionValues.has(val)) {
|
|
2586
2592
|
const msg = t("invalidOption", context.state);
|
|
2587
|
-
|
|
2593
|
+
markFieldValidity(input, msg);
|
|
2588
2594
|
errors.push(`${key}: ${msg}`);
|
|
2589
2595
|
} else {
|
|
2590
|
-
|
|
2596
|
+
markFieldValidity(input, null);
|
|
2591
2597
|
}
|
|
2592
2598
|
});
|
|
2593
|
-
validateMultipleCount(key, values, element, (v) => v
|
|
2599
|
+
validateMultipleCount(key, values, element, (v) => v != null);
|
|
2594
2600
|
return { value: values, errors };
|
|
2595
2601
|
} else {
|
|
2596
2602
|
const input = scopeRoot.querySelector(
|
|
@@ -2600,16 +2606,16 @@ function validateSwitcherElement(element, key, context) {
|
|
|
2600
2606
|
if (!skipValidation && element.required && val === "") {
|
|
2601
2607
|
const msg = t("required", context.state);
|
|
2602
2608
|
errors.push(`${key}: ${msg}`);
|
|
2603
|
-
|
|
2609
|
+
markFieldValidity(input, msg);
|
|
2604
2610
|
return { value: null, errors };
|
|
2605
2611
|
}
|
|
2606
2612
|
if (!skipValidation && val !== "" && !validOptionValues.has(val)) {
|
|
2607
2613
|
const msg = t("invalidOption", context.state);
|
|
2608
2614
|
errors.push(`${key}: ${msg}`);
|
|
2609
|
-
|
|
2615
|
+
markFieldValidity(input, msg);
|
|
2610
2616
|
return { value: null, errors };
|
|
2611
2617
|
}
|
|
2612
|
-
|
|
2618
|
+
markFieldValidity(input, null);
|
|
2613
2619
|
return { value: val === "" ? null : val, errors };
|
|
2614
2620
|
}
|
|
2615
2621
|
}
|
|
@@ -2784,6 +2790,7 @@ function renderBooleanElement(element, ctx, wrapper, pathKey) {
|
|
|
2784
2790
|
const hiddenInput = document.createElement("input");
|
|
2785
2791
|
hiddenInput.type = "hidden";
|
|
2786
2792
|
hiddenInput.name = pathKey;
|
|
2793
|
+
hiddenInput.setAttribute("data-boolean-field", "true");
|
|
2787
2794
|
hiddenInput.value = initial ? "true" : "false";
|
|
2788
2795
|
const row = document.createElement("div");
|
|
2789
2796
|
row.className = "fb-toggle-row";
|
|
@@ -5910,7 +5917,7 @@ function createReadonlyColourUI(value) {
|
|
|
5910
5917
|
container.appendChild(hexText);
|
|
5911
5918
|
return container;
|
|
5912
5919
|
}
|
|
5913
|
-
function createEditColourUI(value, pathKey, ctx) {
|
|
5920
|
+
function createEditColourUI(value, pathKey, ctx, placeholder) {
|
|
5914
5921
|
const normalizedValue = normalizeColourValue(value);
|
|
5915
5922
|
const pickerWrapper = document.createElement("div");
|
|
5916
5923
|
pickerWrapper.className = "colour-picker-wrapper";
|
|
@@ -5934,9 +5941,10 @@ function createEditColourUI(value, pathKey, ctx) {
|
|
|
5934
5941
|
const hexInput = document.createElement("input");
|
|
5935
5942
|
hexInput.type = "text";
|
|
5936
5943
|
hexInput.className = "colour-hex-input";
|
|
5944
|
+
hexInput.setAttribute("data-colour-field", "true");
|
|
5937
5945
|
hexInput.name = pathKey;
|
|
5938
5946
|
hexInput.value = normalizedValue;
|
|
5939
|
-
hexInput.placeholder = "#000000";
|
|
5947
|
+
hexInput.placeholder = placeholder != null ? placeholder : "#000000";
|
|
5940
5948
|
hexInput.style.cssText = `
|
|
5941
5949
|
width: 100px;
|
|
5942
5950
|
padding: var(--fb-input-padding-y) var(--fb-input-padding-x);
|
|
@@ -6023,14 +6031,20 @@ function createEditColourUI(value, pathKey, ctx) {
|
|
|
6023
6031
|
return pickerWrapper;
|
|
6024
6032
|
}
|
|
6025
6033
|
function renderColourElement(element, ctx, wrapper, pathKey) {
|
|
6034
|
+
var _a, _b;
|
|
6026
6035
|
const state = ctx.state;
|
|
6027
6036
|
const readonly = isElementReadonly(element, state, ctx);
|
|
6028
|
-
const initialValue = ctx.prefill[element.key]
|
|
6037
|
+
const initialValue = (_b = (_a = ctx.prefill[element.key]) != null ? _a : element.default) != null ? _b : "#000000";
|
|
6029
6038
|
if (readonly) {
|
|
6030
6039
|
const readonlyUI = createReadonlyColourUI(initialValue);
|
|
6031
6040
|
wrapper.appendChild(readonlyUI);
|
|
6032
6041
|
} else {
|
|
6033
|
-
const editUI = createEditColourUI(
|
|
6042
|
+
const editUI = createEditColourUI(
|
|
6043
|
+
initialValue,
|
|
6044
|
+
pathKey,
|
|
6045
|
+
ctx,
|
|
6046
|
+
element.placeholder
|
|
6047
|
+
);
|
|
6034
6048
|
wrapper.appendChild(editUI);
|
|
6035
6049
|
}
|
|
6036
6050
|
if (!readonly) {
|
|
@@ -6045,7 +6059,7 @@ function renderColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6045
6059
|
}
|
|
6046
6060
|
}
|
|
6047
6061
|
function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
6048
|
-
var _a, _b;
|
|
6062
|
+
var _a, _b, _c;
|
|
6049
6063
|
const state = ctx.state;
|
|
6050
6064
|
const readonly = isElementReadonly(element, state, ctx);
|
|
6051
6065
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
@@ -6053,7 +6067,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6053
6067
|
const minCount = (_a = element.minCount) != null ? _a : element.required ? 1 : 0;
|
|
6054
6068
|
const maxCount = (_b = element.maxCount) != null ? _b : Infinity;
|
|
6055
6069
|
while (values.length < minCount) {
|
|
6056
|
-
values.push(element.default
|
|
6070
|
+
values.push((_c = element.default) != null ? _c : "#000000");
|
|
6057
6071
|
}
|
|
6058
6072
|
const container = document.createElement("div");
|
|
6059
6073
|
container.className = "fb-row";
|
|
@@ -6077,7 +6091,12 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6077
6091
|
}
|
|
6078
6092
|
} else {
|
|
6079
6093
|
const tempPathKey = `${pathKey}[${container.children.length}]`;
|
|
6080
|
-
const editUI = createEditColourUI(
|
|
6094
|
+
const editUI = createEditColourUI(
|
|
6095
|
+
value,
|
|
6096
|
+
tempPathKey,
|
|
6097
|
+
ctx,
|
|
6098
|
+
element.placeholder
|
|
6099
|
+
);
|
|
6081
6100
|
editUI.style.flex = "1";
|
|
6082
6101
|
itemWrapper.appendChild(editUI);
|
|
6083
6102
|
}
|
|
@@ -6140,13 +6159,13 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
6140
6159
|
const handle = createAddItemRow(
|
|
6141
6160
|
"colour",
|
|
6142
6161
|
() => {
|
|
6143
|
-
var _a2;
|
|
6144
|
-
const defaultColour = element.default
|
|
6162
|
+
var _a2, _b2;
|
|
6163
|
+
const defaultColour = (_a2 = element.default) != null ? _a2 : "#000000";
|
|
6145
6164
|
values.push(defaultColour);
|
|
6146
6165
|
addColourItem(defaultColour);
|
|
6147
6166
|
updateAddButton();
|
|
6148
6167
|
updateRemoveButtons();
|
|
6149
|
-
(
|
|
6168
|
+
(_b2 = ctx.instance) == null ? void 0 : _b2.triggerOnChange(pathKey);
|
|
6150
6169
|
},
|
|
6151
6170
|
{ label: element.addLabel }
|
|
6152
6171
|
);
|
|
@@ -6175,59 +6194,26 @@ function validateColourElement(element, key, context) {
|
|
|
6175
6194
|
var _a, _b, _c;
|
|
6176
6195
|
const errors = [];
|
|
6177
6196
|
const { scopeRoot, skipValidation } = context;
|
|
6178
|
-
const markValidity = (input, errorMessage) => {
|
|
6179
|
-
var _a2, _b2;
|
|
6180
|
-
if (!input) return;
|
|
6181
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
6182
|
-
let errorElement = document.getElementById(errorId);
|
|
6183
|
-
if (errorMessage) {
|
|
6184
|
-
input.classList.add("invalid");
|
|
6185
|
-
input.title = errorMessage;
|
|
6186
|
-
if (!errorElement) {
|
|
6187
|
-
errorElement = document.createElement("div");
|
|
6188
|
-
errorElement.id = errorId;
|
|
6189
|
-
errorElement.className = "error-message";
|
|
6190
|
-
errorElement.style.cssText = `
|
|
6191
|
-
color: var(--fb-error-color);
|
|
6192
|
-
font-size: var(--fb-font-size-small);
|
|
6193
|
-
margin-top: 0.25rem;
|
|
6194
|
-
`;
|
|
6195
|
-
if (input.nextSibling) {
|
|
6196
|
-
(_a2 = input.parentNode) == null ? void 0 : _a2.insertBefore(errorElement, input.nextSibling);
|
|
6197
|
-
} else {
|
|
6198
|
-
(_b2 = input.parentNode) == null ? void 0 : _b2.appendChild(errorElement);
|
|
6199
|
-
}
|
|
6200
|
-
}
|
|
6201
|
-
errorElement.textContent = errorMessage;
|
|
6202
|
-
errorElement.style.display = "block";
|
|
6203
|
-
} else {
|
|
6204
|
-
input.classList.remove("invalid");
|
|
6205
|
-
input.title = "";
|
|
6206
|
-
if (errorElement) {
|
|
6207
|
-
errorElement.remove();
|
|
6208
|
-
}
|
|
6209
|
-
}
|
|
6210
|
-
};
|
|
6211
6197
|
const validateColourValue = (input, val, fieldKey) => {
|
|
6212
6198
|
const { state } = context;
|
|
6213
6199
|
if (!val) {
|
|
6214
6200
|
if (!skipValidation && element.required) {
|
|
6215
6201
|
const msg = t("required", state);
|
|
6216
6202
|
errors.push(`${fieldKey}: ${msg}`);
|
|
6217
|
-
|
|
6203
|
+
markFieldValidity(input, msg);
|
|
6218
6204
|
return "";
|
|
6219
6205
|
}
|
|
6220
|
-
|
|
6206
|
+
markFieldValidity(input, null);
|
|
6221
6207
|
return "";
|
|
6222
6208
|
}
|
|
6223
6209
|
const normalized = normalizeColourValue(val);
|
|
6224
6210
|
if (!skipValidation && !isValidHexColour(normalized)) {
|
|
6225
6211
|
const msg = t("invalidHexColour", state);
|
|
6226
6212
|
errors.push(`${fieldKey}: ${msg}`);
|
|
6227
|
-
|
|
6213
|
+
markFieldValidity(input, msg);
|
|
6228
6214
|
return val;
|
|
6229
6215
|
}
|
|
6230
|
-
|
|
6216
|
+
markFieldValidity(input, null);
|
|
6231
6217
|
return normalized;
|
|
6232
6218
|
};
|
|
6233
6219
|
if (element.multiple) {
|
|
@@ -6265,7 +6251,7 @@ function validateColourElement(element, key, context) {
|
|
|
6265
6251
|
if (!skipValidation && element.required && val === "") {
|
|
6266
6252
|
const msg = t("required", context.state);
|
|
6267
6253
|
errors.push(`${key}: ${msg}`);
|
|
6268
|
-
|
|
6254
|
+
markFieldValidity(hexInput, msg);
|
|
6269
6255
|
return { value: "", errors };
|
|
6270
6256
|
}
|
|
6271
6257
|
const validated = validateColourValue(hexInput, val, key);
|
|
@@ -6654,43 +6640,6 @@ function validateSliderElement(element, key, context) {
|
|
|
6654
6640
|
const max = element.max;
|
|
6655
6641
|
const step = (_a = element.step) != null ? _a : 1;
|
|
6656
6642
|
const scale = element.scale || "linear";
|
|
6657
|
-
const markValidity = (input, errorMessage) => {
|
|
6658
|
-
var _a2, _b2;
|
|
6659
|
-
if (!input) return;
|
|
6660
|
-
const errorId = `error-${input.getAttribute("name") || Math.random().toString(36).substring(7)}`;
|
|
6661
|
-
let errorElement = document.getElementById(errorId);
|
|
6662
|
-
if (errorMessage) {
|
|
6663
|
-
input.classList.add("invalid");
|
|
6664
|
-
input.title = errorMessage;
|
|
6665
|
-
if (!errorElement) {
|
|
6666
|
-
errorElement = document.createElement("div");
|
|
6667
|
-
errorElement.id = errorId;
|
|
6668
|
-
errorElement.className = "error-message";
|
|
6669
|
-
errorElement.style.cssText = `
|
|
6670
|
-
color: var(--fb-error-color);
|
|
6671
|
-
font-size: var(--fb-font-size-small);
|
|
6672
|
-
margin-top: 0.25rem;
|
|
6673
|
-
`;
|
|
6674
|
-
const sliderContainer = input.closest(".slider-container");
|
|
6675
|
-
if (sliderContainer && sliderContainer.nextSibling) {
|
|
6676
|
-
(_a2 = sliderContainer.parentNode) == null ? void 0 : _a2.insertBefore(
|
|
6677
|
-
errorElement,
|
|
6678
|
-
sliderContainer.nextSibling
|
|
6679
|
-
);
|
|
6680
|
-
} else if (sliderContainer) {
|
|
6681
|
-
(_b2 = sliderContainer.parentNode) == null ? void 0 : _b2.appendChild(errorElement);
|
|
6682
|
-
}
|
|
6683
|
-
}
|
|
6684
|
-
errorElement.textContent = errorMessage;
|
|
6685
|
-
errorElement.style.display = "block";
|
|
6686
|
-
} else {
|
|
6687
|
-
input.classList.remove("invalid");
|
|
6688
|
-
input.title = "";
|
|
6689
|
-
if (errorElement) {
|
|
6690
|
-
errorElement.remove();
|
|
6691
|
-
}
|
|
6692
|
-
}
|
|
6693
|
-
};
|
|
6694
6643
|
const validateSliderValue = (slider, fieldKey) => {
|
|
6695
6644
|
const { state } = context;
|
|
6696
6645
|
const rawValue = slider.value;
|
|
@@ -6698,10 +6647,10 @@ function validateSliderElement(element, key, context) {
|
|
|
6698
6647
|
if (!skipValidation && element.required) {
|
|
6699
6648
|
const msg = t("required", state);
|
|
6700
6649
|
errors.push(`${fieldKey}: ${msg}`);
|
|
6701
|
-
|
|
6650
|
+
markFieldValidity(slider, msg);
|
|
6702
6651
|
return null;
|
|
6703
6652
|
}
|
|
6704
|
-
|
|
6653
|
+
markFieldValidity(slider, null);
|
|
6705
6654
|
return null;
|
|
6706
6655
|
}
|
|
6707
6656
|
let value;
|
|
@@ -6717,17 +6666,17 @@ function validateSliderElement(element, key, context) {
|
|
|
6717
6666
|
if (value < min) {
|
|
6718
6667
|
const msg = t("minValue", state, { min });
|
|
6719
6668
|
errors.push(`${fieldKey}: ${msg}`);
|
|
6720
|
-
|
|
6669
|
+
markFieldValidity(slider, msg);
|
|
6721
6670
|
return value;
|
|
6722
6671
|
}
|
|
6723
6672
|
if (value > max) {
|
|
6724
6673
|
const msg = t("maxValue", state, { max });
|
|
6725
6674
|
errors.push(`${fieldKey}: ${msg}`);
|
|
6726
|
-
|
|
6675
|
+
markFieldValidity(slider, msg);
|
|
6727
6676
|
return value;
|
|
6728
6677
|
}
|
|
6729
6678
|
}
|
|
6730
|
-
|
|
6679
|
+
markFieldValidity(slider, null);
|
|
6731
6680
|
return value;
|
|
6732
6681
|
};
|
|
6733
6682
|
if (element.multiple) {
|
|
@@ -6873,22 +6822,12 @@ function extractRootFormData(formRoot) {
|
|
|
6873
6822
|
inputs.forEach((input) => {
|
|
6874
6823
|
const fieldName = input.getAttribute("name");
|
|
6875
6824
|
if (fieldName && !fieldName.includes("[") && !fieldName.includes(".")) {
|
|
6876
|
-
if (input instanceof
|
|
6877
|
-
|
|
6878
|
-
} else if (input instanceof HTMLInputElement) {
|
|
6879
|
-
if (input.type === "checkbox") {
|
|
6880
|
-
data[fieldName] = input.checked;
|
|
6881
|
-
} else if (input.type === "radio") {
|
|
6882
|
-
if (input.checked) {
|
|
6883
|
-
data[fieldName] = input.value;
|
|
6884
|
-
}
|
|
6885
|
-
} else if (input.dataset.hiddenField) {
|
|
6886
|
-
data[fieldName] = deserializeHiddenValue(input.value);
|
|
6887
|
-
} else {
|
|
6825
|
+
if (input instanceof HTMLInputElement && input.type === "radio") {
|
|
6826
|
+
if (input.checked) {
|
|
6888
6827
|
data[fieldName] = input.value;
|
|
6889
6828
|
}
|
|
6890
|
-
} else
|
|
6891
|
-
data[fieldName] = input
|
|
6829
|
+
} else {
|
|
6830
|
+
data[fieldName] = readTypedInputValue(input);
|
|
6892
6831
|
}
|
|
6893
6832
|
}
|
|
6894
6833
|
});
|
|
@@ -6957,9 +6896,9 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
6957
6896
|
inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
|
|
6958
6897
|
};
|
|
6959
6898
|
element.elements.forEach((child) => {
|
|
6960
|
-
var _a2
|
|
6899
|
+
var _a2;
|
|
6961
6900
|
if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
|
|
6962
|
-
const prefillVal =
|
|
6901
|
+
const prefillVal = child.key in containerPrefill ? containerPrefill[child.key] : (_a2 = "default" in child ? child.default : null) != null ? _a2 : null;
|
|
6963
6902
|
itemsWrap.appendChild(
|
|
6964
6903
|
createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
|
|
6965
6904
|
);
|
|
@@ -7061,9 +7000,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
7061
7000
|
isSlides ? void 0 : element.columns
|
|
7062
7001
|
);
|
|
7063
7002
|
element.elements.forEach((child) => {
|
|
7064
|
-
var _a2
|
|
7003
|
+
var _a2;
|
|
7065
7004
|
if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
|
|
7066
|
-
const hiddenValue =
|
|
7005
|
+
const hiddenValue = rowPrefill && child.key in rowPrefill ? rowPrefill[child.key] : (_a2 = "default" in child ? child.default : null) != null ? _a2 : null;
|
|
7067
7006
|
childWrapper.appendChild(
|
|
7068
7007
|
createHiddenInput(pathJoin(subCtx.path, child.key), hiddenValue)
|
|
7069
7008
|
);
|
|
@@ -7174,19 +7113,16 @@ function renderMultipleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
7174
7113
|
}
|
|
7175
7114
|
}
|
|
7176
7115
|
}
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
validateElementFunc = fn;
|
|
7180
|
-
}
|
|
7181
|
-
function validateElement(element, ctx, customScopeRoot) {
|
|
7182
|
-
if (!validateElementFunc) {
|
|
7116
|
+
function requireValidateElement(context) {
|
|
7117
|
+
if (!context.validateElement) {
|
|
7183
7118
|
throw new Error(
|
|
7184
|
-
"validateElement
|
|
7119
|
+
"validateContainerElement: context.validateElement missing \u2014 container validation requires the instance validator"
|
|
7185
7120
|
);
|
|
7186
7121
|
}
|
|
7187
|
-
return
|
|
7122
|
+
return context.validateElement;
|
|
7188
7123
|
}
|
|
7189
7124
|
function validateContainerElement(element, key, context) {
|
|
7125
|
+
const validateChild = requireValidateElement(context);
|
|
7190
7126
|
const errors = [];
|
|
7191
7127
|
const { scopeRoot, skipValidation, path } = context;
|
|
7192
7128
|
if (!("elements" in element)) {
|
|
@@ -7239,7 +7175,7 @@ function validateContainerElement(element, key, context) {
|
|
|
7239
7175
|
}
|
|
7240
7176
|
}
|
|
7241
7177
|
const childKey = `${key}[${domIndex}].${child.key}`;
|
|
7242
|
-
const childResult =
|
|
7178
|
+
const childResult = validateChild(
|
|
7243
7179
|
{ ...child, key: childKey },
|
|
7244
7180
|
{ path },
|
|
7245
7181
|
itemContainer
|
|
@@ -7281,7 +7217,7 @@ function validateContainerElement(element, key, context) {
|
|
|
7281
7217
|
}
|
|
7282
7218
|
{
|
|
7283
7219
|
const childKey = `${key}.${child.key}`;
|
|
7284
|
-
const childResult =
|
|
7220
|
+
const childResult = validateChild(
|
|
7285
7221
|
{ ...child, key: childKey },
|
|
7286
7222
|
{ path },
|
|
7287
7223
|
containerContainer
|
|
@@ -7784,7 +7720,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
7784
7720
|
rebuild();
|
|
7785
7721
|
} catch (e) {
|
|
7786
7722
|
const errMsg = e instanceof Error ? e.message : String(e);
|
|
7787
|
-
console.error(t("tableImportError", state
|
|
7723
|
+
console.error(t("tableImportError", state, { error: errMsg }));
|
|
7788
7724
|
} finally {
|
|
7789
7725
|
overlay.remove();
|
|
7790
7726
|
}
|
|
@@ -8744,7 +8680,7 @@ function updateTableField(element, fieldPath, value, context) {
|
|
|
8744
8680
|
}
|
|
8745
8681
|
|
|
8746
8682
|
// src/components/richinput.ts
|
|
8747
|
-
function applyAutoExpand2(textarea, backdrop) {
|
|
8683
|
+
function applyAutoExpand2(textarea, backdrop, observers) {
|
|
8748
8684
|
textarea.style.overflow = "hidden";
|
|
8749
8685
|
textarea.style.resize = "none";
|
|
8750
8686
|
const lineCount = (textarea.value.match(/\n/g) || []).length + 1;
|
|
@@ -8767,6 +8703,7 @@ function applyAutoExpand2(textarea, backdrop) {
|
|
|
8767
8703
|
var _a, _b, _c, _d, _e;
|
|
8768
8704
|
if (!textarea.isConnected) {
|
|
8769
8705
|
ro.disconnect();
|
|
8706
|
+
observers.delete(ro);
|
|
8770
8707
|
return;
|
|
8771
8708
|
}
|
|
8772
8709
|
const entry = entries[0];
|
|
@@ -8776,6 +8713,7 @@ function applyAutoExpand2(textarea, backdrop) {
|
|
|
8776
8713
|
resize();
|
|
8777
8714
|
});
|
|
8778
8715
|
ro.observe(textarea);
|
|
8716
|
+
observers.add(ro);
|
|
8779
8717
|
}
|
|
8780
8718
|
function buildFileLabels(files, state) {
|
|
8781
8719
|
var _a, _b, _c, _d;
|
|
@@ -9204,7 +9142,7 @@ function filterFilesForDropdown(query, files, labels) {
|
|
|
9204
9142
|
var TEXTAREA_FONT = "font-size: var(--fb-font-size, 14px); font-family: var(--fb-font-family, inherit); line-height: 1.6;";
|
|
9205
9143
|
var TEXTAREA_PADDING = "padding: 8px 40px 8px 10px;";
|
|
9206
9144
|
function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
9207
|
-
var _a;
|
|
9145
|
+
var _a, _b;
|
|
9208
9146
|
const state = ctx.state;
|
|
9209
9147
|
const files = [...initialValue.files];
|
|
9210
9148
|
const dropdownState = {
|
|
@@ -9218,12 +9156,12 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9218
9156
|
hiddenInput.type = "hidden";
|
|
9219
9157
|
hiddenInput.name = pathKey;
|
|
9220
9158
|
function getCurrentValue() {
|
|
9221
|
-
var _a2,
|
|
9159
|
+
var _a2, _b2;
|
|
9222
9160
|
const rawText = textarea.value;
|
|
9223
9161
|
const nameToRid = buildNameToRid(files, state);
|
|
9224
9162
|
const submissionText = rawText ? replaceFilenamesWithRids(rawText, nameToRid) : null;
|
|
9225
9163
|
const textKey = (_a2 = element.textKey) != null ? _a2 : "text";
|
|
9226
|
-
const filesKey = (
|
|
9164
|
+
const filesKey = (_b2 = element.filesKey) != null ? _b2 : "files";
|
|
9227
9165
|
return {
|
|
9228
9166
|
[textKey]: rawText === "" ? null : submissionText,
|
|
9229
9167
|
[filesKey]: [...files]
|
|
@@ -9305,14 +9243,14 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9305
9243
|
}
|
|
9306
9244
|
});
|
|
9307
9245
|
outerDiv.addEventListener("drop", (e) => {
|
|
9308
|
-
var _a2,
|
|
9246
|
+
var _a2, _b2;
|
|
9309
9247
|
e.preventDefault();
|
|
9310
9248
|
dragCounter = 0;
|
|
9311
9249
|
outerDiv.style.borderColor = "var(--fb-border-color, #d1d5db)";
|
|
9312
9250
|
outerDiv.style.boxShadow = "none";
|
|
9313
9251
|
const droppedFiles = (_a2 = e.dataTransfer) == null ? void 0 : _a2.files;
|
|
9314
9252
|
if (!droppedFiles || !state.config.uploadFile) return;
|
|
9315
|
-
const maxFiles = (
|
|
9253
|
+
const maxFiles = (_b2 = element.maxFiles) != null ? _b2 : Infinity;
|
|
9316
9254
|
for (let i = 0; i < droppedFiles.length; i++) {
|
|
9317
9255
|
if (files.length >= maxFiles) {
|
|
9318
9256
|
showUploadError(
|
|
@@ -9361,8 +9299,8 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9361
9299
|
`;
|
|
9362
9300
|
const textarea = document.createElement("textarea");
|
|
9363
9301
|
textarea.name = `${pathKey}__text`;
|
|
9364
|
-
textarea.placeholder = element.placeholder
|
|
9365
|
-
const rawInitialText = (
|
|
9302
|
+
textarea.placeholder = (_a = element.placeholder) != null ? _a : t("richinputPlaceholder", state);
|
|
9303
|
+
const rawInitialText = (_b = initialValue.text) != null ? _b : "";
|
|
9366
9304
|
textarea.value = rawInitialText ? replaceRidsWithFilenames(rawInitialText, files, state) : "";
|
|
9367
9305
|
textarea.style.cssText = `
|
|
9368
9306
|
width: 100%;
|
|
@@ -9378,14 +9316,14 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9378
9316
|
z-index: 1;
|
|
9379
9317
|
caret-color: var(--fb-text-color, #111827);
|
|
9380
9318
|
`;
|
|
9381
|
-
applyAutoExpand2(textarea, backdrop);
|
|
9319
|
+
applyAutoExpand2(textarea, backdrop, ctx.state.autoExpandObservers);
|
|
9382
9320
|
textarea.addEventListener("scroll", () => {
|
|
9383
9321
|
backdrop.scrollTop = textarea.scrollTop;
|
|
9384
9322
|
});
|
|
9385
9323
|
let mentionTooltip = null;
|
|
9386
9324
|
backdrop.addEventListener("mouseover", (e) => {
|
|
9387
|
-
var _a2,
|
|
9388
|
-
const mark = (
|
|
9325
|
+
var _a2, _b2;
|
|
9326
|
+
const mark = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(
|
|
9389
9327
|
_a2,
|
|
9390
9328
|
"mark"
|
|
9391
9329
|
);
|
|
@@ -9394,8 +9332,8 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9394
9332
|
mentionTooltip = showMentionTooltip(mark, mark.dataset.rid, state);
|
|
9395
9333
|
});
|
|
9396
9334
|
backdrop.addEventListener("mouseout", (e) => {
|
|
9397
|
-
var _a2,
|
|
9398
|
-
const mark = (
|
|
9335
|
+
var _a2, _b2, _c;
|
|
9336
|
+
const mark = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(
|
|
9399
9337
|
_a2,
|
|
9400
9338
|
"mark"
|
|
9401
9339
|
);
|
|
@@ -9405,8 +9343,8 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9405
9343
|
mentionTooltip = removePortalTooltip(mentionTooltip);
|
|
9406
9344
|
});
|
|
9407
9345
|
backdrop.addEventListener("mousedown", (e) => {
|
|
9408
|
-
var _a2,
|
|
9409
|
-
const mark = (
|
|
9346
|
+
var _a2, _b2;
|
|
9347
|
+
const mark = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(
|
|
9410
9348
|
_a2,
|
|
9411
9349
|
"mark"
|
|
9412
9350
|
);
|
|
@@ -9579,8 +9517,8 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9579
9517
|
dropdown.appendChild(item);
|
|
9580
9518
|
});
|
|
9581
9519
|
dropdown.onmousemove = (e) => {
|
|
9582
|
-
var _a2,
|
|
9583
|
-
const target = (
|
|
9520
|
+
var _a2, _b2, _c;
|
|
9521
|
+
const target = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(
|
|
9584
9522
|
_a2,
|
|
9585
9523
|
".fb-richinput-dropdown-item"
|
|
9586
9524
|
);
|
|
@@ -9596,10 +9534,10 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9596
9534
|
dropdownState.selectedIndex = newIdx;
|
|
9597
9535
|
};
|
|
9598
9536
|
dropdown.onmousedown = (e) => {
|
|
9599
|
-
var _a2,
|
|
9537
|
+
var _a2, _b2;
|
|
9600
9538
|
e.preventDefault();
|
|
9601
9539
|
e.stopPropagation();
|
|
9602
|
-
const target = (
|
|
9540
|
+
const target = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(
|
|
9603
9541
|
_a2,
|
|
9604
9542
|
".fb-richinput-dropdown-item"
|
|
9605
9543
|
);
|
|
@@ -9627,9 +9565,9 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9627
9565
|
dropdownState.open = false;
|
|
9628
9566
|
}
|
|
9629
9567
|
function insertMention(rid) {
|
|
9630
|
-
var _a2,
|
|
9568
|
+
var _a2, _b2, _c, _d;
|
|
9631
9569
|
const labels = buildFileLabelsFromClosure();
|
|
9632
|
-
const label = (_c = (
|
|
9570
|
+
const label = (_c = (_b2 = labels.get(rid)) != null ? _b2 : (_a2 = state.resourceIndex.get(rid)) == null ? void 0 : _a2.name) != null ? _c : rid;
|
|
9633
9571
|
const cursorPos = (_d = textarea.selectionStart) != null ? _d : 0;
|
|
9634
9572
|
const before = textarea.value.slice(0, dropdownState.triggerPos);
|
|
9635
9573
|
const after = textarea.value.slice(cursorPos);
|
|
@@ -9721,10 +9659,10 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9721
9659
|
thumbWrapper.appendChild(thumbInner);
|
|
9722
9660
|
const tooltipHandle = createTooltipHandle();
|
|
9723
9661
|
const doMention = () => {
|
|
9724
|
-
var _a2,
|
|
9662
|
+
var _a2, _b2, _c;
|
|
9725
9663
|
const cursorPos = (_a2 = textarea.selectionStart) != null ? _a2 : textarea.value.length;
|
|
9726
9664
|
const labels = buildFileLabelsFromClosure();
|
|
9727
|
-
const label = (_c = (
|
|
9665
|
+
const label = (_c = (_b2 = labels.get(rid)) != null ? _b2 : meta == null ? void 0 : meta.name) != null ? _c : rid;
|
|
9728
9666
|
const before = textarea.value.slice(0, cursorPos);
|
|
9729
9667
|
const after = textarea.value.slice(cursorPos);
|
|
9730
9668
|
const prefix = before.length > 0 && !/[\s\n]$/.test(before) ? "\n" : "";
|
|
@@ -9802,12 +9740,12 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
9802
9740
|
writeHidden();
|
|
9803
9741
|
(_a2 = ctx.instance) == null ? void 0 : _a2.triggerOnChange(pathKey, getCurrentValue());
|
|
9804
9742
|
}).catch((err) => {
|
|
9805
|
-
var _a2,
|
|
9743
|
+
var _a2, _b2;
|
|
9806
9744
|
const idx = files.indexOf(tempId);
|
|
9807
9745
|
if (idx !== -1) files.splice(idx, 1);
|
|
9808
9746
|
state.resourceIndex.delete(tempId);
|
|
9809
9747
|
renderFilesRow();
|
|
9810
|
-
(
|
|
9748
|
+
(_b2 = (_a2 = state.config).onUploadError) == null ? void 0 : _b2.call(_a2, err, file);
|
|
9811
9749
|
});
|
|
9812
9750
|
}
|
|
9813
9751
|
fileInput.addEventListener("change", () => {
|
|
@@ -10379,12 +10317,7 @@ function validateHiddenElement(element, key, context) {
|
|
|
10379
10317
|
const input = scopeRoot.querySelector(
|
|
10380
10318
|
`input[type="hidden"][data-hidden-field="true"][name="${key}"]`
|
|
10381
10319
|
);
|
|
10382
|
-
|
|
10383
|
-
if (raw === "") {
|
|
10384
|
-
const defaultVal = "default" in element ? element.default : null;
|
|
10385
|
-
return { value: defaultVal !== void 0 ? defaultVal : null, errors: [] };
|
|
10386
|
-
}
|
|
10387
|
-
return { value: deserializeHiddenValue(raw), errors: [] };
|
|
10320
|
+
return { value: deserializeHiddenValue((_a = input == null ? void 0 : input.value) != null ? _a : ""), errors: [] };
|
|
10388
10321
|
}
|
|
10389
10322
|
function updateHiddenField(_element, fieldPath, value, context) {
|
|
10390
10323
|
const { scopeRoot } = context;
|
|
@@ -10576,25 +10509,13 @@ function extractDOMValue(fieldPath, formRoot) {
|
|
|
10576
10509
|
if (!input) {
|
|
10577
10510
|
return void 0;
|
|
10578
10511
|
}
|
|
10579
|
-
if (input instanceof
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
|
|
10584
|
-
} else if (input.type === "radio") {
|
|
10585
|
-
const checked = formRoot.querySelector(
|
|
10586
|
-
`[name="${fieldPath}"]:checked`
|
|
10587
|
-
);
|
|
10588
|
-
return checked ? checked.value : void 0;
|
|
10589
|
-
} else if (input.dataset.hiddenField) {
|
|
10590
|
-
return deserializeHiddenValue(input.value);
|
|
10591
|
-
} else {
|
|
10592
|
-
return input.value;
|
|
10593
|
-
}
|
|
10594
|
-
} else if (input instanceof HTMLTextAreaElement) {
|
|
10595
|
-
return input.value;
|
|
10512
|
+
if (input instanceof HTMLInputElement && input.type === "radio") {
|
|
10513
|
+
const checked = formRoot.querySelector(
|
|
10514
|
+
`[name="${fieldPath}"]:checked`
|
|
10515
|
+
);
|
|
10516
|
+
return checked ? checked.value : void 0;
|
|
10596
10517
|
}
|
|
10597
|
-
return
|
|
10518
|
+
return readTypedInputValue(input);
|
|
10598
10519
|
}
|
|
10599
10520
|
function buildScopedDataAtPath(path, value) {
|
|
10600
10521
|
const segments = path.match(/[^.[\]]+|\[\d+\]/g);
|
|
@@ -10726,11 +10647,19 @@ function createFieldLabel(element) {
|
|
|
10726
10647
|
}
|
|
10727
10648
|
return title;
|
|
10728
10649
|
}
|
|
10650
|
+
function ensureTooltipStyles(doc) {
|
|
10651
|
+
if (doc.head.querySelector("[data-fb-tooltip-styles]")) return;
|
|
10652
|
+
const style = doc.createElement("style");
|
|
10653
|
+
style.setAttribute("data-fb-tooltip-styles", "");
|
|
10654
|
+
style.textContent = `[id^="tooltip-"].hidden { display: none; }`;
|
|
10655
|
+
doc.head.appendChild(style);
|
|
10656
|
+
}
|
|
10729
10657
|
function createInfoButton(element, state) {
|
|
10730
10658
|
const infoBtn = document.createElement("button");
|
|
10731
10659
|
infoBtn.type = "button";
|
|
10732
10660
|
infoBtn.className = "ml-2 text-gray-400 hover:text-gray-600";
|
|
10733
10661
|
infoBtn.innerHTML = '<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>';
|
|
10662
|
+
ensureTooltipStyles(document);
|
|
10734
10663
|
const tooltipId = `tooltip-${element.key}-${Math.random().toString(36).substr(2, 9)}`;
|
|
10735
10664
|
const tooltip = document.createElement("div");
|
|
10736
10665
|
tooltip.id = tooltipId;
|
|
@@ -10911,6 +10840,7 @@ var defaultConfig = {
|
|
|
10911
10840
|
onDownloadError: null,
|
|
10912
10841
|
debounceMs: 300,
|
|
10913
10842
|
verboseErrors: false,
|
|
10843
|
+
postMessageTarget: null,
|
|
10914
10844
|
enableFilePreview: true,
|
|
10915
10845
|
maxPreviewSize: "200px",
|
|
10916
10846
|
readonly: false,
|
|
@@ -10932,6 +10862,7 @@ var defaultConfig = {
|
|
|
10932
10862
|
openInNewTab: "Open in new tab",
|
|
10933
10863
|
changeButton: "Change",
|
|
10934
10864
|
placeholderText: "Enter text",
|
|
10865
|
+
selectPlaceholder: "Select\u2026",
|
|
10935
10866
|
previewAlt: "Preview",
|
|
10936
10867
|
previewUnavailable: "Preview unavailable",
|
|
10937
10868
|
previewError: "Preview error",
|
|
@@ -11007,6 +10938,7 @@ var defaultConfig = {
|
|
|
11007
10938
|
openInNewTab: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043D\u043E\u0432\u043E\u0439 \u0432\u043A\u043B\u0430\u0434\u043A\u0435",
|
|
11008
10939
|
changeButton: "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C",
|
|
11009
10940
|
placeholderText: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442",
|
|
10941
|
+
selectPlaceholder: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435\u2026",
|
|
11010
10942
|
previewAlt: "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440",
|
|
11011
10943
|
previewUnavailable: "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D",
|
|
11012
10944
|
previewError: "\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430",
|
|
@@ -11071,20 +11003,23 @@ var defaultConfig = {
|
|
|
11071
11003
|
},
|
|
11072
11004
|
theme: {}
|
|
11073
11005
|
};
|
|
11074
|
-
function
|
|
11075
|
-
const
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
config.translations
|
|
11081
|
-
)) {
|
|
11082
|
-
mergedTranslations[locale] = {
|
|
11083
|
-
...defaultConfig.translations[locale] || {},
|
|
11006
|
+
function mergeTranslations(base, overrides) {
|
|
11007
|
+
const merged = { ...base };
|
|
11008
|
+
if (overrides) {
|
|
11009
|
+
for (const [locale, userTranslations] of Object.entries(overrides)) {
|
|
11010
|
+
merged[locale] = {
|
|
11011
|
+
...base[locale] || {},
|
|
11084
11012
|
...userTranslations
|
|
11085
11013
|
};
|
|
11086
11014
|
}
|
|
11087
11015
|
}
|
|
11016
|
+
return merged;
|
|
11017
|
+
}
|
|
11018
|
+
function createInstanceState(config) {
|
|
11019
|
+
const mergedTranslations = mergeTranslations(
|
|
11020
|
+
defaultConfig.translations,
|
|
11021
|
+
config == null ? void 0 : config.translations
|
|
11022
|
+
);
|
|
11088
11023
|
return {
|
|
11089
11024
|
schema: null,
|
|
11090
11025
|
formRoot: null,
|
|
@@ -11101,6 +11036,7 @@ function createInstanceState(config) {
|
|
|
11101
11036
|
syntheticElementIds: /* @__PURE__ */ new WeakMap(),
|
|
11102
11037
|
syntheticElementIdCounter: 0,
|
|
11103
11038
|
enableIfObservers: /* @__PURE__ */ new Set(),
|
|
11039
|
+
autoExpandObservers: /* @__PURE__ */ new Set(),
|
|
11104
11040
|
tooltipElements: /* @__PURE__ */ new Set()
|
|
11105
11041
|
};
|
|
11106
11042
|
}
|
|
@@ -11402,6 +11338,11 @@ function findOwnField(scope, lookupKey, ownBoundary) {
|
|
|
11402
11338
|
}
|
|
11403
11339
|
var FormBuilderInstance = class {
|
|
11404
11340
|
constructor(config) {
|
|
11341
|
+
// The bound prefill-hint click handler currently attached to the form root.
|
|
11342
|
+
// Kept so renderForm()/destroy() can remove it — re-binding on every render
|
|
11343
|
+
// stacked listeners (hint clicks applied values N times) and destroy()
|
|
11344
|
+
// left the last one on the host-owned root, retaining the instance.
|
|
11345
|
+
this.prefillHintHandler = null;
|
|
11405
11346
|
this.instanceId = generateInstanceId();
|
|
11406
11347
|
this.state = createInstanceState(config);
|
|
11407
11348
|
if (this.state.config.verboseErrors) {
|
|
@@ -11435,10 +11376,21 @@ var FormBuilderInstance = class {
|
|
|
11435
11376
|
this.state.formRoot = element;
|
|
11436
11377
|
}
|
|
11437
11378
|
/**
|
|
11438
|
-
* Configure the form builder
|
|
11379
|
+
* Configure the form builder. Translations deep-merge per locale (same as
|
|
11380
|
+
* the constructor); a locale without translations — configured or default —
|
|
11381
|
+
* is rejected, matching setLocale.
|
|
11439
11382
|
*/
|
|
11440
11383
|
configure(config) {
|
|
11441
|
-
|
|
11384
|
+
const translations = mergeTranslations(
|
|
11385
|
+
this.state.config.translations,
|
|
11386
|
+
config.translations
|
|
11387
|
+
);
|
|
11388
|
+
if (config.locale !== void 0 && !translations[config.locale]) {
|
|
11389
|
+
throw new Error(
|
|
11390
|
+
`configure: no translations configured for locale "${config.locale}"`
|
|
11391
|
+
);
|
|
11392
|
+
}
|
|
11393
|
+
Object.assign(this.state.config, config, { translations });
|
|
11442
11394
|
}
|
|
11443
11395
|
/**
|
|
11444
11396
|
* Set file upload handler
|
|
@@ -11471,12 +11423,16 @@ var FormBuilderInstance = class {
|
|
|
11471
11423
|
this.state.config.readonly = mode === "readonly";
|
|
11472
11424
|
}
|
|
11473
11425
|
/**
|
|
11474
|
-
* Set locale
|
|
11426
|
+
* Set locale. Custom locales are allowed — their translations must have
|
|
11427
|
+
* been provided via the constructor or configure() first.
|
|
11475
11428
|
*/
|
|
11476
11429
|
setLocale(locale) {
|
|
11477
|
-
if (this.state.config.translations[locale]) {
|
|
11478
|
-
|
|
11430
|
+
if (!this.state.config.translations[locale]) {
|
|
11431
|
+
throw new Error(
|
|
11432
|
+
`setLocale: no translations configured for locale "${locale}"`
|
|
11433
|
+
);
|
|
11479
11434
|
}
|
|
11435
|
+
this.state.config.locale = locale;
|
|
11480
11436
|
}
|
|
11481
11437
|
/**
|
|
11482
11438
|
* Trigger onChange callbacks with debouncing
|
|
@@ -11829,11 +11785,13 @@ var FormBuilderInstance = class {
|
|
|
11829
11785
|
renderForm(root, schema, prefill, actions) {
|
|
11830
11786
|
const errors = validateSchema(schema);
|
|
11831
11787
|
if (errors.length > 0) {
|
|
11832
|
-
|
|
11833
|
-
|
|
11788
|
+
throw new Error(`renderForm: invalid schema:
|
|
11789
|
+
- ${errors.join("\n- ")}`);
|
|
11834
11790
|
}
|
|
11835
11791
|
this.disconnectEnableIfObservers();
|
|
11792
|
+
this.disconnectAutoExpandObservers();
|
|
11836
11793
|
this.removeTooltipElements();
|
|
11794
|
+
this.removePrefillHintListener();
|
|
11837
11795
|
this.state.formRoot = root;
|
|
11838
11796
|
this.state.schema = schema;
|
|
11839
11797
|
this.state.externalActions = actions || null;
|
|
@@ -11855,9 +11813,9 @@ var FormBuilderInstance = class {
|
|
|
11855
11813
|
fieldsWrapper.className = `grid grid-cols-${columns} gap-2`;
|
|
11856
11814
|
}
|
|
11857
11815
|
schema.elements.forEach((element) => {
|
|
11858
|
-
var _a
|
|
11816
|
+
var _a;
|
|
11859
11817
|
if (element.type !== "markdown" && (element.hidden || element.type === "hidden")) {
|
|
11860
|
-
const val =
|
|
11818
|
+
const val = prefill && element.key in prefill ? prefill[element.key] : (_a = element.default) != null ? _a : null;
|
|
11861
11819
|
fieldsWrapper.appendChild(createHiddenInput(element.key, val));
|
|
11862
11820
|
return;
|
|
11863
11821
|
}
|
|
@@ -11874,7 +11832,10 @@ var FormBuilderInstance = class {
|
|
|
11874
11832
|
rootContainer.appendChild(fieldsWrapper);
|
|
11875
11833
|
root.appendChild(rootContainer);
|
|
11876
11834
|
if (!this.state.config.readonly) {
|
|
11877
|
-
|
|
11835
|
+
this.prefillHintHandler = this.handlePrefillHintClick.bind(
|
|
11836
|
+
this
|
|
11837
|
+
);
|
|
11838
|
+
root.addEventListener("click", this.prefillHintHandler);
|
|
11878
11839
|
}
|
|
11879
11840
|
if (this.state.config.readonly && this.state.externalActions && Array.isArray(this.state.externalActions)) {
|
|
11880
11841
|
this.renderExternalActions();
|
|
@@ -11890,7 +11851,7 @@ var FormBuilderInstance = class {
|
|
|
11890
11851
|
return { valid: true, errors: [], data: {} };
|
|
11891
11852
|
const errors = [];
|
|
11892
11853
|
const data = {};
|
|
11893
|
-
const
|
|
11854
|
+
const validateElement = (element, ctx, customScopeRoot = null) => {
|
|
11894
11855
|
var _a;
|
|
11895
11856
|
const key = (_a = element.key) != null ? _a : "";
|
|
11896
11857
|
const scopeRoot = customScopeRoot || this.state.formRoot;
|
|
@@ -11899,7 +11860,10 @@ var FormBuilderInstance = class {
|
|
|
11899
11860
|
state: this.state,
|
|
11900
11861
|
instance: this,
|
|
11901
11862
|
path: ctx.path,
|
|
11902
|
-
skipValidation
|
|
11863
|
+
skipValidation,
|
|
11864
|
+
// Containers recurse into their children through this — threaded per
|
|
11865
|
+
// pass, never module state (see ComponentContext.validateElement).
|
|
11866
|
+
validateElement
|
|
11903
11867
|
};
|
|
11904
11868
|
const componentResult = validateElementWithComponent(
|
|
11905
11869
|
element,
|
|
@@ -11917,7 +11881,6 @@ var FormBuilderInstance = class {
|
|
|
11917
11881
|
console.warn(`Unknown field type "${element.type}" for key "${key}"`);
|
|
11918
11882
|
return { value: null, spread: false };
|
|
11919
11883
|
};
|
|
11920
|
-
setValidateElement(validateElement2);
|
|
11921
11884
|
this.state.schema.elements.forEach((element) => {
|
|
11922
11885
|
if (element.enableIf) {
|
|
11923
11886
|
try {
|
|
@@ -11935,7 +11898,7 @@ var FormBuilderInstance = class {
|
|
|
11935
11898
|
if (element.type === "markdown") {
|
|
11936
11899
|
return;
|
|
11937
11900
|
}
|
|
11938
|
-
const result =
|
|
11901
|
+
const result = validateElement(element, { path: "" });
|
|
11939
11902
|
if (result.skip) return;
|
|
11940
11903
|
if (result.spread && result.value !== null && typeof result.value === "object") {
|
|
11941
11904
|
Object.assign(data, result.value);
|
|
@@ -11961,16 +11924,7 @@ var FormBuilderInstance = class {
|
|
|
11961
11924
|
submitForm() {
|
|
11962
11925
|
const result = this.validateForm(false);
|
|
11963
11926
|
if (result.valid) {
|
|
11964
|
-
|
|
11965
|
-
window.parent.postMessage(
|
|
11966
|
-
{
|
|
11967
|
-
type: "formSubmit",
|
|
11968
|
-
data: result.data,
|
|
11969
|
-
schema: this.state.schema
|
|
11970
|
-
},
|
|
11971
|
-
"*"
|
|
11972
|
-
);
|
|
11973
|
-
}
|
|
11927
|
+
this.postToParent("formSubmit", result.data);
|
|
11974
11928
|
}
|
|
11975
11929
|
return result;
|
|
11976
11930
|
}
|
|
@@ -11979,17 +11933,27 @@ var FormBuilderInstance = class {
|
|
|
11979
11933
|
*/
|
|
11980
11934
|
saveDraft() {
|
|
11981
11935
|
const result = this.validateForm(true);
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
|
|
11989
|
-
|
|
11936
|
+
this.postToParent("formDraft", result.data);
|
|
11937
|
+
return result;
|
|
11938
|
+
}
|
|
11939
|
+
/**
|
|
11940
|
+
* Post form data to the parent frame — only when the host opted in via
|
|
11941
|
+
* `postMessageTarget`. Outside an iframe `window.parent === window`, so an
|
|
11942
|
+
* unconditional post broadcast form data and the full schema to any
|
|
11943
|
+
* embedding page (targetOrigin "*") on every submit. See CHANGELOG 0.6.0.
|
|
11944
|
+
*/
|
|
11945
|
+
postToParent(type, data) {
|
|
11946
|
+
const target = this.state.config.postMessageTarget;
|
|
11947
|
+
if (target === "") {
|
|
11948
|
+
throw new Error(
|
|
11949
|
+
'postMessageTarget: "" is not a valid target origin \u2014 use null to disable posting or "*" to knowingly broadcast'
|
|
11990
11950
|
);
|
|
11991
11951
|
}
|
|
11992
|
-
return
|
|
11952
|
+
if (!target || typeof window === "undefined" || !window.parent) return;
|
|
11953
|
+
window.parent.postMessage(
|
|
11954
|
+
{ type, data, schema: this.state.schema },
|
|
11955
|
+
target
|
|
11956
|
+
);
|
|
11993
11957
|
}
|
|
11994
11958
|
/**
|
|
11995
11959
|
* Clear the form - reset all field values to empty while preserving form structure
|
|
@@ -12263,7 +12227,9 @@ var FormBuilderInstance = class {
|
|
|
12263
12227
|
this.state.debounceTimer = null;
|
|
12264
12228
|
}
|
|
12265
12229
|
this.disconnectEnableIfObservers();
|
|
12230
|
+
this.disconnectAutoExpandObservers();
|
|
12266
12231
|
this.removeTooltipElements();
|
|
12232
|
+
this.removePrefillHintListener();
|
|
12267
12233
|
this.state.resourceIndex.clear();
|
|
12268
12234
|
if (this.state.formRoot) {
|
|
12269
12235
|
clear(this.state.formRoot);
|
|
@@ -12281,6 +12247,18 @@ var FormBuilderInstance = class {
|
|
|
12281
12247
|
}
|
|
12282
12248
|
this.state.enableIfObservers.clear();
|
|
12283
12249
|
}
|
|
12250
|
+
disconnectAutoExpandObservers() {
|
|
12251
|
+
for (const observer of this.state.autoExpandObservers) {
|
|
12252
|
+
observer.disconnect();
|
|
12253
|
+
}
|
|
12254
|
+
this.state.autoExpandObservers.clear();
|
|
12255
|
+
}
|
|
12256
|
+
removePrefillHintListener() {
|
|
12257
|
+
if (this.prefillHintHandler && this.state.formRoot) {
|
|
12258
|
+
this.state.formRoot.removeEventListener("click", this.prefillHintHandler);
|
|
12259
|
+
}
|
|
12260
|
+
this.prefillHintHandler = null;
|
|
12261
|
+
}
|
|
12284
12262
|
removeTooltipElements() {
|
|
12285
12263
|
for (const tooltip of this.state.tooltipElements) {
|
|
12286
12264
|
tooltip.remove();
|