@dmitryvim/form-builder 0.2.24 → 0.2.26
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 +65 -11
- package/dist/browser/formbuilder.min.js +122 -122
- package/dist/browser/formbuilder.v0.2.26.min.js +606 -0
- package/dist/cjs/index.cjs +263 -151
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +259 -151
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +122 -122
- package/dist/types/types/schema.d.ts +2 -0
- package/dist/types/utils/helpers.d.ts +6 -0
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.2.24.min.js +0 -606
package/dist/esm/index.js
CHANGED
|
@@ -6,7 +6,10 @@ function t(key, state, params) {
|
|
|
6
6
|
let text = localeTranslations?.[key] || fallbackTranslations?.[key] || key;
|
|
7
7
|
if (params) {
|
|
8
8
|
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
9
|
-
text = text.replace(
|
|
9
|
+
text = text.replace(
|
|
10
|
+
new RegExp(`\\{${paramKey}\\}`, "g"),
|
|
11
|
+
String(paramValue)
|
|
12
|
+
);
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
15
|
return text;
|
|
@@ -249,6 +252,9 @@ function validateSchema(schema) {
|
|
|
249
252
|
}
|
|
250
253
|
|
|
251
254
|
// src/utils/helpers.ts
|
|
255
|
+
function isElementReadonly(element, state, ctx) {
|
|
256
|
+
return element.readonly === true || state.config.readonly === true || ctx?.inheritedReadonly === true;
|
|
257
|
+
}
|
|
252
258
|
function isPlainObject(obj) {
|
|
253
259
|
return obj && typeof obj === "object" && obj.constructor === Object;
|
|
254
260
|
}
|
|
@@ -407,6 +413,7 @@ function createCharCounter(element, input, isTextarea = false) {
|
|
|
407
413
|
}
|
|
408
414
|
function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
409
415
|
const state = ctx.state;
|
|
416
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
410
417
|
const inputWrapper = document.createElement("div");
|
|
411
418
|
inputWrapper.style.cssText = "position: relative;";
|
|
412
419
|
const textInput = document.createElement("input");
|
|
@@ -417,7 +424,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
417
424
|
padding-right: 60px;
|
|
418
425
|
border: var(--fb-border-width) solid var(--fb-border-color);
|
|
419
426
|
border-radius: var(--fb-border-radius);
|
|
420
|
-
background-color: ${
|
|
427
|
+
background-color: ${readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
|
|
421
428
|
color: var(--fb-text-color);
|
|
422
429
|
font-size: var(--fb-font-size);
|
|
423
430
|
font-family: var(--fb-font-family);
|
|
@@ -428,8 +435,8 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
428
435
|
textInput.name = pathKey;
|
|
429
436
|
textInput.placeholder = element.placeholder || "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
|
|
430
437
|
textInput.value = ctx.prefill[element.key] || element.default || "";
|
|
431
|
-
textInput.readOnly =
|
|
432
|
-
if (!
|
|
438
|
+
textInput.readOnly = readonly;
|
|
439
|
+
if (!readonly) {
|
|
433
440
|
textInput.addEventListener("focus", () => {
|
|
434
441
|
textInput.style.borderColor = "var(--fb-border-focus-color)";
|
|
435
442
|
textInput.style.outline = `var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)`;
|
|
@@ -450,7 +457,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
450
457
|
}
|
|
451
458
|
});
|
|
452
459
|
}
|
|
453
|
-
if (!
|
|
460
|
+
if (!readonly && ctx.instance) {
|
|
454
461
|
const handleChange = () => {
|
|
455
462
|
const value = textInput.value === "" ? null : textInput.value;
|
|
456
463
|
ctx.instance.triggerOnChange(pathKey, value);
|
|
@@ -459,7 +466,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
459
466
|
textInput.addEventListener("input", handleChange);
|
|
460
467
|
}
|
|
461
468
|
inputWrapper.appendChild(textInput);
|
|
462
|
-
if (!
|
|
469
|
+
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
463
470
|
const counter = createCharCounter(element, textInput, false);
|
|
464
471
|
inputWrapper.appendChild(counter);
|
|
465
472
|
}
|
|
@@ -467,6 +474,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
467
474
|
}
|
|
468
475
|
function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
469
476
|
const state = ctx.state;
|
|
477
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
470
478
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
471
479
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
472
480
|
const minCount = element.minCount ?? 1;
|
|
@@ -498,7 +506,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
498
506
|
padding-right: 60px;
|
|
499
507
|
border: var(--fb-border-width) solid var(--fb-border-color);
|
|
500
508
|
border-radius: var(--fb-border-radius);
|
|
501
|
-
background-color: ${
|
|
509
|
+
background-color: ${readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
|
|
502
510
|
color: var(--fb-text-color);
|
|
503
511
|
font-size: var(--fb-font-size);
|
|
504
512
|
font-family: var(--fb-font-family);
|
|
@@ -508,8 +516,8 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
508
516
|
`;
|
|
509
517
|
textInput.placeholder = element.placeholder || t("placeholderText", state);
|
|
510
518
|
textInput.value = value;
|
|
511
|
-
textInput.readOnly =
|
|
512
|
-
if (!
|
|
519
|
+
textInput.readOnly = readonly;
|
|
520
|
+
if (!readonly) {
|
|
513
521
|
textInput.addEventListener("focus", () => {
|
|
514
522
|
textInput.style.borderColor = "var(--fb-border-focus-color)";
|
|
515
523
|
textInput.style.outline = `var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)`;
|
|
@@ -530,7 +538,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
530
538
|
}
|
|
531
539
|
});
|
|
532
540
|
}
|
|
533
|
-
if (!
|
|
541
|
+
if (!readonly && ctx.instance) {
|
|
534
542
|
const handleChange = () => {
|
|
535
543
|
const value2 = textInput.value === "" ? null : textInput.value;
|
|
536
544
|
ctx.instance.triggerOnChange(textInput.name, value2);
|
|
@@ -539,7 +547,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
539
547
|
textInput.addEventListener("input", handleChange);
|
|
540
548
|
}
|
|
541
549
|
inputContainer.appendChild(textInput);
|
|
542
|
-
if (!
|
|
550
|
+
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
543
551
|
const counter = createCharCounter(element, textInput, false);
|
|
544
552
|
inputContainer.appendChild(counter);
|
|
545
553
|
}
|
|
@@ -553,7 +561,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
553
561
|
return itemWrapper;
|
|
554
562
|
}
|
|
555
563
|
function updateRemoveButtons() {
|
|
556
|
-
if (
|
|
564
|
+
if (readonly) return;
|
|
557
565
|
const items = container.querySelectorAll(".multiple-text-item");
|
|
558
566
|
const currentCount = items.length;
|
|
559
567
|
items.forEach((item) => {
|
|
@@ -598,7 +606,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
598
606
|
}
|
|
599
607
|
let addRow = null;
|
|
600
608
|
let countDisplay = null;
|
|
601
|
-
if (!
|
|
609
|
+
if (!readonly) {
|
|
602
610
|
addRow = document.createElement("div");
|
|
603
611
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
604
612
|
const addBtn = document.createElement("button");
|
|
@@ -806,6 +814,7 @@ function applyAutoExpand(textarea) {
|
|
|
806
814
|
}
|
|
807
815
|
function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
808
816
|
const state = ctx.state;
|
|
817
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
809
818
|
const textareaWrapper = document.createElement("div");
|
|
810
819
|
textareaWrapper.style.cssText = "position: relative;";
|
|
811
820
|
const textareaInput = document.createElement("textarea");
|
|
@@ -815,8 +824,8 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
815
824
|
textareaInput.placeholder = element.placeholder || "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
|
|
816
825
|
textareaInput.rows = element.rows || 4;
|
|
817
826
|
textareaInput.value = ctx.prefill[element.key] || element.default || "";
|
|
818
|
-
textareaInput.readOnly =
|
|
819
|
-
if (!
|
|
827
|
+
textareaInput.readOnly = readonly;
|
|
828
|
+
if (!readonly && ctx.instance) {
|
|
820
829
|
const handleChange = () => {
|
|
821
830
|
const value = textareaInput.value === "" ? null : textareaInput.value;
|
|
822
831
|
ctx.instance.triggerOnChange(pathKey, value);
|
|
@@ -824,11 +833,11 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
824
833
|
textareaInput.addEventListener("blur", handleChange);
|
|
825
834
|
textareaInput.addEventListener("input", handleChange);
|
|
826
835
|
}
|
|
827
|
-
if (element.autoExpand ||
|
|
836
|
+
if (element.autoExpand || readonly) {
|
|
828
837
|
applyAutoExpand(textareaInput);
|
|
829
838
|
}
|
|
830
839
|
textareaWrapper.appendChild(textareaInput);
|
|
831
|
-
if (!
|
|
840
|
+
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
832
841
|
const counter = createCharCounter(element, textareaInput, true);
|
|
833
842
|
textareaWrapper.appendChild(counter);
|
|
834
843
|
}
|
|
@@ -836,6 +845,7 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
836
845
|
}
|
|
837
846
|
function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
838
847
|
const state = ctx.state;
|
|
848
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
839
849
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
840
850
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
841
851
|
const minCount = element.minCount ?? 1;
|
|
@@ -866,8 +876,8 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
866
876
|
textareaInput.placeholder = element.placeholder || t("placeholderText", state);
|
|
867
877
|
textareaInput.rows = element.rows || 4;
|
|
868
878
|
textareaInput.value = value;
|
|
869
|
-
textareaInput.readOnly =
|
|
870
|
-
if (!
|
|
879
|
+
textareaInput.readOnly = readonly;
|
|
880
|
+
if (!readonly && ctx.instance) {
|
|
871
881
|
const handleChange = () => {
|
|
872
882
|
const value2 = textareaInput.value === "" ? null : textareaInput.value;
|
|
873
883
|
ctx.instance.triggerOnChange(textareaInput.name, value2);
|
|
@@ -875,11 +885,11 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
875
885
|
textareaInput.addEventListener("blur", handleChange);
|
|
876
886
|
textareaInput.addEventListener("input", handleChange);
|
|
877
887
|
}
|
|
878
|
-
if (element.autoExpand ||
|
|
888
|
+
if (element.autoExpand || readonly) {
|
|
879
889
|
applyAutoExpand(textareaInput);
|
|
880
890
|
}
|
|
881
891
|
textareaContainer.appendChild(textareaInput);
|
|
882
|
-
if (!
|
|
892
|
+
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
883
893
|
const counter = createCharCounter(element, textareaInput, true);
|
|
884
894
|
textareaContainer.appendChild(counter);
|
|
885
895
|
}
|
|
@@ -893,7 +903,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
893
903
|
return itemWrapper;
|
|
894
904
|
}
|
|
895
905
|
function updateRemoveButtons() {
|
|
896
|
-
if (
|
|
906
|
+
if (readonly) return;
|
|
897
907
|
const items = container.querySelectorAll(".multiple-textarea-item");
|
|
898
908
|
const currentCount = items.length;
|
|
899
909
|
items.forEach((item) => {
|
|
@@ -927,7 +937,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
927
937
|
}
|
|
928
938
|
let addRow = null;
|
|
929
939
|
let countDisplay = null;
|
|
930
|
-
if (!
|
|
940
|
+
if (!readonly) {
|
|
931
941
|
addRow = document.createElement("div");
|
|
932
942
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
933
943
|
const addBtn = document.createElement("button");
|
|
@@ -961,7 +971,9 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
961
971
|
}
|
|
962
972
|
function updateAddButton() {
|
|
963
973
|
if (!addRow || !countDisplay) return;
|
|
964
|
-
const addBtn = addRow.querySelector(
|
|
974
|
+
const addBtn = addRow.querySelector(
|
|
975
|
+
".add-textarea-btn"
|
|
976
|
+
);
|
|
965
977
|
if (addBtn) {
|
|
966
978
|
const disabled = values.length >= maxCount;
|
|
967
979
|
addBtn.disabled = disabled;
|
|
@@ -980,7 +992,7 @@ function validateTextareaElement(element, key, context) {
|
|
|
980
992
|
function updateTextareaField(element, fieldPath, value, context) {
|
|
981
993
|
updateTextField(element, fieldPath, value, context);
|
|
982
994
|
const { scopeRoot, state } = context;
|
|
983
|
-
const shouldAutoExpand = element.autoExpand || state
|
|
995
|
+
const shouldAutoExpand = element.autoExpand || isElementReadonly(element, state);
|
|
984
996
|
if (!shouldAutoExpand) return;
|
|
985
997
|
if (element.multiple) {
|
|
986
998
|
const textareas = scopeRoot.querySelectorAll(
|
|
@@ -1041,6 +1053,7 @@ function createNumberRangeHint(element, input) {
|
|
|
1041
1053
|
}
|
|
1042
1054
|
function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
1043
1055
|
const state = ctx.state;
|
|
1056
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1044
1057
|
const inputWrapper = document.createElement("div");
|
|
1045
1058
|
inputWrapper.style.cssText = "position: relative;";
|
|
1046
1059
|
const numberInput = document.createElement("input");
|
|
@@ -1053,8 +1066,8 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1053
1066
|
if (element.max !== void 0) numberInput.max = element.max.toString();
|
|
1054
1067
|
if (element.step !== void 0) numberInput.step = element.step.toString();
|
|
1055
1068
|
numberInput.value = ctx.prefill[element.key] || element.default || "";
|
|
1056
|
-
numberInput.readOnly =
|
|
1057
|
-
if (!
|
|
1069
|
+
numberInput.readOnly = readonly;
|
|
1070
|
+
if (!readonly && ctx.instance) {
|
|
1058
1071
|
const handleChange = () => {
|
|
1059
1072
|
const value = numberInput.value ? parseFloat(numberInput.value) : null;
|
|
1060
1073
|
ctx.instance.triggerOnChange(pathKey, value);
|
|
@@ -1063,7 +1076,7 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1063
1076
|
numberInput.addEventListener("input", handleChange);
|
|
1064
1077
|
}
|
|
1065
1078
|
inputWrapper.appendChild(numberInput);
|
|
1066
|
-
if (!
|
|
1079
|
+
if (!readonly && (element.min != null || element.max != null)) {
|
|
1067
1080
|
const counter = createNumberRangeHint(element, numberInput);
|
|
1068
1081
|
inputWrapper.appendChild(counter);
|
|
1069
1082
|
}
|
|
@@ -1071,6 +1084,7 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1071
1084
|
}
|
|
1072
1085
|
function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
1073
1086
|
const state = ctx.state;
|
|
1087
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1074
1088
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
1075
1089
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
1076
1090
|
const minCount = element.minCount ?? 1;
|
|
@@ -1104,8 +1118,8 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1104
1118
|
if (element.max !== void 0) numberInput.max = element.max.toString();
|
|
1105
1119
|
if (element.step !== void 0) numberInput.step = element.step.toString();
|
|
1106
1120
|
numberInput.value = value.toString();
|
|
1107
|
-
numberInput.readOnly =
|
|
1108
|
-
if (!
|
|
1121
|
+
numberInput.readOnly = readonly;
|
|
1122
|
+
if (!readonly && ctx.instance) {
|
|
1109
1123
|
const handleChange = () => {
|
|
1110
1124
|
const val = numberInput.value ? parseFloat(numberInput.value) : null;
|
|
1111
1125
|
ctx.instance.triggerOnChange(numberInput.name, val);
|
|
@@ -1114,7 +1128,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1114
1128
|
numberInput.addEventListener("input", handleChange);
|
|
1115
1129
|
}
|
|
1116
1130
|
inputContainer.appendChild(numberInput);
|
|
1117
|
-
if (!
|
|
1131
|
+
if (!readonly && (element.min != null || element.max != null)) {
|
|
1118
1132
|
const counter = createNumberRangeHint(element, numberInput);
|
|
1119
1133
|
inputContainer.appendChild(counter);
|
|
1120
1134
|
}
|
|
@@ -1128,7 +1142,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1128
1142
|
return itemWrapper;
|
|
1129
1143
|
}
|
|
1130
1144
|
function updateRemoveButtons() {
|
|
1131
|
-
if (
|
|
1145
|
+
if (readonly) return;
|
|
1132
1146
|
const items = container.querySelectorAll(".multiple-number-item");
|
|
1133
1147
|
const currentCount = items.length;
|
|
1134
1148
|
items.forEach((item) => {
|
|
@@ -1162,7 +1176,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1162
1176
|
}
|
|
1163
1177
|
let addRow = null;
|
|
1164
1178
|
let countDisplay = null;
|
|
1165
|
-
if (!
|
|
1179
|
+
if (!readonly) {
|
|
1166
1180
|
addRow = document.createElement("div");
|
|
1167
1181
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
1168
1182
|
const addBtn = document.createElement("button");
|
|
@@ -1367,10 +1381,11 @@ function updateNumberField(element, fieldPath, value, context) {
|
|
|
1367
1381
|
// src/components/select.ts
|
|
1368
1382
|
function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
1369
1383
|
const state = ctx.state;
|
|
1384
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1370
1385
|
const selectInput = document.createElement("select");
|
|
1371
1386
|
selectInput.className = "w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500";
|
|
1372
1387
|
selectInput.name = pathKey;
|
|
1373
|
-
selectInput.disabled =
|
|
1388
|
+
selectInput.disabled = readonly;
|
|
1374
1389
|
(element.options || []).forEach((option) => {
|
|
1375
1390
|
const optionEl = document.createElement("option");
|
|
1376
1391
|
optionEl.value = option.value;
|
|
@@ -1380,14 +1395,14 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1380
1395
|
}
|
|
1381
1396
|
selectInput.appendChild(optionEl);
|
|
1382
1397
|
});
|
|
1383
|
-
if (!
|
|
1398
|
+
if (!readonly && ctx.instance) {
|
|
1384
1399
|
const handleChange = () => {
|
|
1385
1400
|
ctx.instance.triggerOnChange(pathKey, selectInput.value);
|
|
1386
1401
|
};
|
|
1387
1402
|
selectInput.addEventListener("change", handleChange);
|
|
1388
1403
|
}
|
|
1389
1404
|
wrapper.appendChild(selectInput);
|
|
1390
|
-
if (!
|
|
1405
|
+
if (!readonly) {
|
|
1391
1406
|
const selectHint = document.createElement("p");
|
|
1392
1407
|
selectHint.className = "text-xs text-gray-500 mt-1";
|
|
1393
1408
|
selectHint.textContent = makeFieldHint(element, state);
|
|
@@ -1396,6 +1411,7 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1396
1411
|
}
|
|
1397
1412
|
function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
1398
1413
|
const state = ctx.state;
|
|
1414
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1399
1415
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
1400
1416
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
1401
1417
|
const minCount = element.minCount ?? 1;
|
|
@@ -1420,7 +1436,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1420
1436
|
itemWrapper.className = "multiple-select-item flex items-center gap-2";
|
|
1421
1437
|
const selectInput = document.createElement("select");
|
|
1422
1438
|
selectInput.className = "flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500";
|
|
1423
|
-
selectInput.disabled =
|
|
1439
|
+
selectInput.disabled = readonly;
|
|
1424
1440
|
(element.options || []).forEach((option) => {
|
|
1425
1441
|
const optionElement = document.createElement("option");
|
|
1426
1442
|
optionElement.value = option.value;
|
|
@@ -1430,7 +1446,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1430
1446
|
}
|
|
1431
1447
|
selectInput.appendChild(optionElement);
|
|
1432
1448
|
});
|
|
1433
|
-
if (!
|
|
1449
|
+
if (!readonly && ctx.instance) {
|
|
1434
1450
|
const handleChange = () => {
|
|
1435
1451
|
ctx.instance.triggerOnChange(selectInput.name, selectInput.value);
|
|
1436
1452
|
};
|
|
@@ -1446,7 +1462,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1446
1462
|
return itemWrapper;
|
|
1447
1463
|
}
|
|
1448
1464
|
function updateRemoveButtons() {
|
|
1449
|
-
if (
|
|
1465
|
+
if (readonly) return;
|
|
1450
1466
|
const items = container.querySelectorAll(".multiple-select-item");
|
|
1451
1467
|
const currentCount = items.length;
|
|
1452
1468
|
items.forEach((item) => {
|
|
@@ -1478,7 +1494,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1478
1494
|
}
|
|
1479
1495
|
let addRow = null;
|
|
1480
1496
|
let countDisplay = null;
|
|
1481
|
-
if (!
|
|
1497
|
+
if (!readonly) {
|
|
1482
1498
|
addRow = document.createElement("div");
|
|
1483
1499
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
1484
1500
|
const addBtn = document.createElement("button");
|
|
@@ -1525,7 +1541,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1525
1541
|
values.forEach((value) => addSelectItem(value));
|
|
1526
1542
|
updateAddButton();
|
|
1527
1543
|
updateRemoveButtons();
|
|
1528
|
-
if (!
|
|
1544
|
+
if (!readonly) {
|
|
1529
1545
|
const hint = document.createElement("p");
|
|
1530
1546
|
hint.className = "text-xs text-gray-500 mt-1";
|
|
1531
1547
|
hint.textContent = makeFieldHint(element, state);
|
|
@@ -1741,12 +1757,14 @@ function buildSegmentedGroup(element, currentValue, hiddenInput, readonly, onCha
|
|
|
1741
1757
|
}
|
|
1742
1758
|
function renderSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
1743
1759
|
const state = ctx.state;
|
|
1744
|
-
const initialValue = String(
|
|
1760
|
+
const initialValue = String(
|
|
1761
|
+
ctx.prefill[element.key] ?? element.default ?? ""
|
|
1762
|
+
);
|
|
1745
1763
|
const hiddenInput = document.createElement("input");
|
|
1746
1764
|
hiddenInput.type = "hidden";
|
|
1747
1765
|
hiddenInput.name = pathKey;
|
|
1748
1766
|
hiddenInput.value = initialValue;
|
|
1749
|
-
const readonly = state
|
|
1767
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1750
1768
|
const onChange = !readonly && ctx.instance ? (value) => {
|
|
1751
1769
|
ctx.instance.triggerOnChange(pathKey, value);
|
|
1752
1770
|
} : null;
|
|
@@ -1775,7 +1793,7 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
1775
1793
|
while (values.length < minCount) {
|
|
1776
1794
|
values.push(element.default || element.options?.[0]?.value || "");
|
|
1777
1795
|
}
|
|
1778
|
-
const readonly = state
|
|
1796
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
1779
1797
|
const container = document.createElement("div");
|
|
1780
1798
|
container.className = "space-y-2";
|
|
1781
1799
|
wrapper.appendChild(container);
|
|
@@ -2178,9 +2196,7 @@ function renderUploadedVideoPreview(container, thumbnailUrl, _videoType, state)
|
|
|
2178
2196
|
video.preload = "metadata";
|
|
2179
2197
|
video.muted = true;
|
|
2180
2198
|
video.src = thumbnailUrl;
|
|
2181
|
-
video.appendChild(
|
|
2182
|
-
document.createTextNode(t("videoNotSupported", state))
|
|
2183
|
-
);
|
|
2199
|
+
video.appendChild(document.createTextNode(t("videoNotSupported", state)));
|
|
2184
2200
|
container.appendChild(video);
|
|
2185
2201
|
}
|
|
2186
2202
|
function renderDeleteButton(container, resourceId, state) {
|
|
@@ -2288,6 +2304,10 @@ async function renderFilePreview(container, resourceId, state, options = {}) {
|
|
|
2288
2304
|
meta,
|
|
2289
2305
|
state
|
|
2290
2306
|
);
|
|
2307
|
+
const isVideo = meta?.type?.startsWith("video/");
|
|
2308
|
+
if (!isReadonly && !isVideo) {
|
|
2309
|
+
renderDeleteButton(container, resourceId, state);
|
|
2310
|
+
}
|
|
2291
2311
|
}
|
|
2292
2312
|
}
|
|
2293
2313
|
async function renderFilePreviewReadonly(resourceId, state, fileName) {
|
|
@@ -2988,9 +3008,15 @@ function setupFilesPickerHandler(filesPicker, initialFiles, state, updateCallbac
|
|
|
2988
3008
|
}
|
|
2989
3009
|
function renderFileElement(element, ctx, wrapper, pathKey) {
|
|
2990
3010
|
const state = ctx.state;
|
|
2991
|
-
if (state
|
|
2992
|
-
const
|
|
3011
|
+
if (isElementReadonly(element, state, ctx)) {
|
|
3012
|
+
const rawInitial = ctx.prefill[element.key];
|
|
3013
|
+
const initial = typeof rawInitial === "string" ? rawInitial : "";
|
|
2993
3014
|
if (initial) {
|
|
3015
|
+
const hiddenInput = document.createElement("input");
|
|
3016
|
+
hiddenInput.type = "hidden";
|
|
3017
|
+
hiddenInput.name = pathKey;
|
|
3018
|
+
hiddenInput.value = initial;
|
|
3019
|
+
wrapper.appendChild(hiddenInput);
|
|
2994
3020
|
renderFilePreviewReadonly(initial, state).then((filePreview) => {
|
|
2995
3021
|
wrapper.appendChild(filePreview);
|
|
2996
3022
|
}).catch((err) => {
|
|
@@ -3078,10 +3104,24 @@ function renderFileElement(element, ctx, wrapper, pathKey) {
|
|
|
3078
3104
|
}
|
|
3079
3105
|
function renderFilesElement(element, ctx, wrapper, pathKey) {
|
|
3080
3106
|
const state = ctx.state;
|
|
3081
|
-
if (state
|
|
3107
|
+
if (isElementReadonly(element, state, ctx)) {
|
|
3108
|
+
const rawPrefill = ctx.prefill[element.key];
|
|
3109
|
+
const initialFiles = Array.isArray(rawPrefill) ? rawPrefill : [];
|
|
3110
|
+
const filesWrapper = document.createElement("div");
|
|
3111
|
+
filesWrapper.className = "space-y-2";
|
|
3112
|
+
filesWrapper.dataset.filesWrapper = pathKey;
|
|
3113
|
+
const filesList = document.createElement("div");
|
|
3114
|
+
filesList.className = "files-list";
|
|
3115
|
+
initialFiles.forEach((resourceId) => {
|
|
3116
|
+
const pill = document.createElement("div");
|
|
3117
|
+
pill.className = "resource-pill";
|
|
3118
|
+
pill.dataset.resourceId = resourceId;
|
|
3119
|
+
filesList.appendChild(pill);
|
|
3120
|
+
});
|
|
3121
|
+
filesWrapper.appendChild(filesList);
|
|
3122
|
+
wrapper.appendChild(filesWrapper);
|
|
3082
3123
|
const resultsWrapper = document.createElement("div");
|
|
3083
3124
|
resultsWrapper.className = "space-y-4";
|
|
3084
|
-
const initialFiles = ctx.prefill[element.key] || [];
|
|
3085
3125
|
if (initialFiles.length > 0) {
|
|
3086
3126
|
initialFiles.forEach((resourceId) => {
|
|
3087
3127
|
renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
|
|
@@ -3112,6 +3152,7 @@ function renderFilesElement(element, ctx, wrapper, pathKey) {
|
|
|
3112
3152
|
};
|
|
3113
3153
|
const filesWrapper = document.createElement("div");
|
|
3114
3154
|
filesWrapper.className = "space-y-2";
|
|
3155
|
+
filesWrapper.dataset.filesWrapper = pathKey;
|
|
3115
3156
|
const filesPicker = document.createElement("input");
|
|
3116
3157
|
filesPicker.type = "file";
|
|
3117
3158
|
filesPicker.name = pathKey;
|
|
@@ -3161,10 +3202,24 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
|
|
|
3161
3202
|
const state = ctx.state;
|
|
3162
3203
|
const minFiles = element.minCount ?? 0;
|
|
3163
3204
|
const maxFiles = element.maxCount ?? Infinity;
|
|
3164
|
-
if (state
|
|
3205
|
+
if (isElementReadonly(element, state, ctx)) {
|
|
3206
|
+
const rawPrefill = ctx.prefill[element.key];
|
|
3207
|
+
const initialFiles = Array.isArray(rawPrefill) ? rawPrefill : [];
|
|
3208
|
+
const filesWrapper = document.createElement("div");
|
|
3209
|
+
filesWrapper.className = "space-y-2";
|
|
3210
|
+
filesWrapper.dataset.filesWrapper = pathKey;
|
|
3211
|
+
const filesList = document.createElement("div");
|
|
3212
|
+
filesList.className = "files-list";
|
|
3213
|
+
initialFiles.forEach((resourceId) => {
|
|
3214
|
+
const pill = document.createElement("div");
|
|
3215
|
+
pill.className = "resource-pill";
|
|
3216
|
+
pill.dataset.resourceId = resourceId;
|
|
3217
|
+
filesList.appendChild(pill);
|
|
3218
|
+
});
|
|
3219
|
+
filesWrapper.appendChild(filesList);
|
|
3220
|
+
wrapper.appendChild(filesWrapper);
|
|
3165
3221
|
const resultsWrapper = document.createElement("div");
|
|
3166
3222
|
resultsWrapper.className = "space-y-4";
|
|
3167
|
-
const initialFiles = ctx.prefill[element.key] || [];
|
|
3168
3223
|
if (initialFiles.length > 0) {
|
|
3169
3224
|
initialFiles.forEach((resourceId) => {
|
|
3170
3225
|
renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
|
|
@@ -3180,6 +3235,7 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
|
|
|
3180
3235
|
} else {
|
|
3181
3236
|
const filesWrapper = document.createElement("div");
|
|
3182
3237
|
filesWrapper.className = "space-y-2";
|
|
3238
|
+
filesWrapper.dataset.filesWrapper = pathKey;
|
|
3183
3239
|
const filesPicker = document.createElement("input");
|
|
3184
3240
|
filesPicker.type = "file";
|
|
3185
3241
|
filesPicker.name = pathKey;
|
|
@@ -3293,10 +3349,9 @@ function validateFileElement(element, key, context) {
|
|
|
3293
3349
|
};
|
|
3294
3350
|
if (isMultipleField) {
|
|
3295
3351
|
const fullKey = pathJoin(path, key);
|
|
3296
|
-
const
|
|
3297
|
-
`
|
|
3352
|
+
const filesWrapper = scopeRoot.querySelector(
|
|
3353
|
+
`[data-files-wrapper="${fullKey}"]`
|
|
3298
3354
|
);
|
|
3299
|
-
const filesWrapper = pickerInput?.closest(".space-y-2");
|
|
3300
3355
|
const container = filesWrapper?.querySelector(".files-list") || null;
|
|
3301
3356
|
const resourceIds = [];
|
|
3302
3357
|
if (container) {
|
|
@@ -3555,15 +3610,16 @@ function createEditColourUI(value, pathKey, ctx) {
|
|
|
3555
3610
|
}
|
|
3556
3611
|
function renderColourElement(element, ctx, wrapper, pathKey) {
|
|
3557
3612
|
const state = ctx.state;
|
|
3613
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
3558
3614
|
const initialValue = ctx.prefill[element.key] || element.default || "#000000";
|
|
3559
|
-
if (
|
|
3615
|
+
if (readonly) {
|
|
3560
3616
|
const readonlyUI = createReadonlyColourUI(initialValue);
|
|
3561
3617
|
wrapper.appendChild(readonlyUI);
|
|
3562
3618
|
} else {
|
|
3563
3619
|
const editUI = createEditColourUI(initialValue, pathKey, ctx);
|
|
3564
3620
|
wrapper.appendChild(editUI);
|
|
3565
3621
|
}
|
|
3566
|
-
if (!
|
|
3622
|
+
if (!readonly) {
|
|
3567
3623
|
const colourHint = document.createElement("p");
|
|
3568
3624
|
colourHint.className = "mt-1";
|
|
3569
3625
|
colourHint.style.cssText = `
|
|
@@ -3576,6 +3632,7 @@ function renderColourElement(element, ctx, wrapper, pathKey) {
|
|
|
3576
3632
|
}
|
|
3577
3633
|
function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
3578
3634
|
const state = ctx.state;
|
|
3635
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
3579
3636
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
3580
3637
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
3581
3638
|
const minCount = element.minCount ?? 1;
|
|
@@ -3598,7 +3655,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
3598
3655
|
function addColourItem(value = "#000000", index = -1) {
|
|
3599
3656
|
const itemWrapper = document.createElement("div");
|
|
3600
3657
|
itemWrapper.className = "multiple-colour-item flex items-center gap-2";
|
|
3601
|
-
if (
|
|
3658
|
+
if (readonly) {
|
|
3602
3659
|
const readonlyUI = createReadonlyColourUI(value);
|
|
3603
3660
|
while (readonlyUI.firstChild) {
|
|
3604
3661
|
itemWrapper.appendChild(readonlyUI.firstChild);
|
|
@@ -3618,7 +3675,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
3618
3675
|
return itemWrapper;
|
|
3619
3676
|
}
|
|
3620
3677
|
function updateRemoveButtons() {
|
|
3621
|
-
if (
|
|
3678
|
+
if (readonly) return;
|
|
3622
3679
|
const items = container.querySelectorAll(".multiple-colour-item");
|
|
3623
3680
|
const currentCount = items.length;
|
|
3624
3681
|
items.forEach((item) => {
|
|
@@ -3663,7 +3720,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
3663
3720
|
}
|
|
3664
3721
|
let addRow = null;
|
|
3665
3722
|
let countDisplay = null;
|
|
3666
|
-
if (!
|
|
3723
|
+
if (!readonly) {
|
|
3667
3724
|
addRow = document.createElement("div");
|
|
3668
3725
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
3669
3726
|
const addBtn = document.createElement("button");
|
|
@@ -3710,7 +3767,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
3710
3767
|
values.forEach((value) => addColourItem(value));
|
|
3711
3768
|
updateAddButton();
|
|
3712
3769
|
updateRemoveButtons();
|
|
3713
|
-
if (!
|
|
3770
|
+
if (!readonly) {
|
|
3714
3771
|
const hint = document.createElement("p");
|
|
3715
3772
|
hint.className = "mt-1";
|
|
3716
3773
|
hint.style.cssText = `
|
|
@@ -3779,7 +3836,9 @@ function validateColourElement(element, key, context) {
|
|
|
3779
3836
|
return normalized;
|
|
3780
3837
|
};
|
|
3781
3838
|
if (element.multiple) {
|
|
3782
|
-
const hexInputs = scopeRoot.querySelectorAll(
|
|
3839
|
+
const hexInputs = scopeRoot.querySelectorAll(
|
|
3840
|
+
`[name^="${key}["].colour-hex-input`
|
|
3841
|
+
);
|
|
3783
3842
|
const values = [];
|
|
3784
3843
|
hexInputs.forEach((input, index) => {
|
|
3785
3844
|
const val = input?.value ?? "";
|
|
@@ -3826,7 +3885,9 @@ function updateColourField(element, fieldPath, value, context) {
|
|
|
3826
3885
|
);
|
|
3827
3886
|
return;
|
|
3828
3887
|
}
|
|
3829
|
-
const hexInputs = scopeRoot.querySelectorAll(
|
|
3888
|
+
const hexInputs = scopeRoot.querySelectorAll(
|
|
3889
|
+
`[name^="${fieldPath}["].colour-hex-input`
|
|
3890
|
+
);
|
|
3830
3891
|
hexInputs.forEach((hexInput, index) => {
|
|
3831
3892
|
if (index < value.length) {
|
|
3832
3893
|
const normalized = normalizeColourValue(value[index]);
|
|
@@ -4021,6 +4082,7 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4021
4082
|
);
|
|
4022
4083
|
}
|
|
4023
4084
|
const state = ctx.state;
|
|
4085
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
4024
4086
|
const defaultValue = element.default !== void 0 ? element.default : (element.min + element.max) / 2;
|
|
4025
4087
|
const initialValue = ctx.prefill[element.key] ?? defaultValue;
|
|
4026
4088
|
const sliderUI = createSliderUI(
|
|
@@ -4028,10 +4090,10 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4028
4090
|
pathKey,
|
|
4029
4091
|
element,
|
|
4030
4092
|
ctx,
|
|
4031
|
-
|
|
4093
|
+
readonly
|
|
4032
4094
|
);
|
|
4033
4095
|
wrapper.appendChild(sliderUI);
|
|
4034
|
-
if (!
|
|
4096
|
+
if (!readonly) {
|
|
4035
4097
|
const hint = document.createElement("p");
|
|
4036
4098
|
hint.className = "mt-1";
|
|
4037
4099
|
hint.style.cssText = `
|
|
@@ -4055,6 +4117,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4055
4117
|
);
|
|
4056
4118
|
}
|
|
4057
4119
|
const state = ctx.state;
|
|
4120
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
4058
4121
|
const prefillValues = ctx.prefill[element.key] || [];
|
|
4059
4122
|
const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
|
|
4060
4123
|
const minCount = element.minCount ?? 1;
|
|
@@ -4079,13 +4142,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4079
4142
|
const itemWrapper = document.createElement("div");
|
|
4080
4143
|
itemWrapper.className = "multiple-slider-item flex items-start gap-2";
|
|
4081
4144
|
const tempPathKey = `${pathKey}[${container.children.length}]`;
|
|
4082
|
-
const sliderUI = createSliderUI(
|
|
4083
|
-
value,
|
|
4084
|
-
tempPathKey,
|
|
4085
|
-
element,
|
|
4086
|
-
ctx,
|
|
4087
|
-
state.config.readonly
|
|
4088
|
-
);
|
|
4145
|
+
const sliderUI = createSliderUI(value, tempPathKey, element, ctx, readonly);
|
|
4089
4146
|
sliderUI.style.flex = "1";
|
|
4090
4147
|
itemWrapper.appendChild(sliderUI);
|
|
4091
4148
|
if (index === -1) {
|
|
@@ -4097,7 +4154,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4097
4154
|
return itemWrapper;
|
|
4098
4155
|
}
|
|
4099
4156
|
function updateRemoveButtons() {
|
|
4100
|
-
if (
|
|
4157
|
+
if (readonly) return;
|
|
4101
4158
|
const items = container.querySelectorAll(".multiple-slider-item");
|
|
4102
4159
|
const currentCount = items.length;
|
|
4103
4160
|
items.forEach((item) => {
|
|
@@ -4143,7 +4200,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4143
4200
|
}
|
|
4144
4201
|
let addRow = null;
|
|
4145
4202
|
let countDisplay = null;
|
|
4146
|
-
if (!
|
|
4203
|
+
if (!readonly) {
|
|
4147
4204
|
addRow = document.createElement("div");
|
|
4148
4205
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
4149
4206
|
const addBtn = document.createElement("button");
|
|
@@ -4189,7 +4246,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
4189
4246
|
values.forEach((value) => addSliderItem(value));
|
|
4190
4247
|
updateAddButton();
|
|
4191
4248
|
updateRemoveButtons();
|
|
4192
|
-
if (!
|
|
4249
|
+
if (!readonly) {
|
|
4193
4250
|
const hint = document.createElement("p");
|
|
4194
4251
|
hint.className = "mt-1";
|
|
4195
4252
|
hint.style.cssText = `
|
|
@@ -4428,9 +4485,7 @@ function mergeWithDefaults(prefill, defaults) {
|
|
|
4428
4485
|
}
|
|
4429
4486
|
function extractRootFormData(formRoot) {
|
|
4430
4487
|
const data = {};
|
|
4431
|
-
const inputs = formRoot.querySelectorAll(
|
|
4432
|
-
"input, select, textarea"
|
|
4433
|
-
);
|
|
4488
|
+
const inputs = formRoot.querySelectorAll("input, select, textarea");
|
|
4434
4489
|
inputs.forEach((input) => {
|
|
4435
4490
|
const fieldName = input.getAttribute("name");
|
|
4436
4491
|
if (fieldName && !fieldName.includes("[") && !fieldName.includes(".")) {
|
|
@@ -4494,7 +4549,8 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
4494
4549
|
} else {
|
|
4495
4550
|
itemsWrap.className = `grid grid-cols-${columns} gap-4`;
|
|
4496
4551
|
}
|
|
4497
|
-
|
|
4552
|
+
const containerIsReadonly = isElementReadonly(element, ctx.state, ctx);
|
|
4553
|
+
if (!containerIsReadonly) {
|
|
4498
4554
|
const hintsElement = createPrefillHints(element, pathKey);
|
|
4499
4555
|
if (hintsElement) {
|
|
4500
4556
|
containerWrap.appendChild(hintsElement);
|
|
@@ -4509,12 +4565,15 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
4509
4565
|
// Merged prefill with defaults for enableIf evaluation
|
|
4510
4566
|
formData: ctx.formData ?? ctx.prefill,
|
|
4511
4567
|
// Complete root data for enableIf evaluation
|
|
4512
|
-
state: ctx.state
|
|
4568
|
+
state: ctx.state,
|
|
4569
|
+
inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
|
|
4513
4570
|
};
|
|
4514
4571
|
element.elements.forEach((child) => {
|
|
4515
4572
|
if (child.hidden || child.type === "hidden") {
|
|
4516
4573
|
const prefillVal = containerPrefill[child.key] ?? child.default ?? null;
|
|
4517
|
-
itemsWrap.appendChild(
|
|
4574
|
+
itemsWrap.appendChild(
|
|
4575
|
+
createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
|
|
4576
|
+
);
|
|
4518
4577
|
} else {
|
|
4519
4578
|
itemsWrap.appendChild(renderElement(child, subCtx));
|
|
4520
4579
|
}
|
|
@@ -4524,13 +4583,15 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
4524
4583
|
}
|
|
4525
4584
|
function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
4526
4585
|
const state = ctx.state;
|
|
4586
|
+
const containerIsReadonly = isElementReadonly(element, state, ctx);
|
|
4587
|
+
const childInheritedReadonly = containerIsReadonly || ctx.inheritedReadonly;
|
|
4527
4588
|
const containerWrap = document.createElement("div");
|
|
4528
4589
|
containerWrap.className = "border border-gray-200 rounded-lg p-4 bg-gray-50";
|
|
4529
4590
|
const countDisplay = document.createElement("span");
|
|
4530
4591
|
countDisplay.className = "text-sm text-gray-500";
|
|
4531
4592
|
const itemsWrap = document.createElement("div");
|
|
4532
4593
|
itemsWrap.className = "space-y-4";
|
|
4533
|
-
if (!
|
|
4594
|
+
if (!containerIsReadonly) {
|
|
4534
4595
|
const hintsElement = createPrefillHints(element, element.key);
|
|
4535
4596
|
if (hintsElement) {
|
|
4536
4597
|
containerWrap.appendChild(hintsElement);
|
|
@@ -4568,8 +4629,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4568
4629
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
4569
4630
|
prefill: childDefaults,
|
|
4570
4631
|
// Defaults for enableIf evaluation
|
|
4571
|
-
formData: currentFormData
|
|
4632
|
+
formData: currentFormData,
|
|
4572
4633
|
// Current root data from DOM for enableIf
|
|
4634
|
+
inheritedReadonly: childInheritedReadonly
|
|
4573
4635
|
};
|
|
4574
4636
|
const item = document.createElement("div");
|
|
4575
4637
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -4583,13 +4645,18 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4583
4645
|
}
|
|
4584
4646
|
element.elements.forEach((child) => {
|
|
4585
4647
|
if (child.hidden || child.type === "hidden") {
|
|
4586
|
-
childWrapper.appendChild(
|
|
4648
|
+
childWrapper.appendChild(
|
|
4649
|
+
createHiddenInput(
|
|
4650
|
+
pathJoin(subCtx.path, child.key),
|
|
4651
|
+
child.default ?? null
|
|
4652
|
+
)
|
|
4653
|
+
);
|
|
4587
4654
|
} else {
|
|
4588
4655
|
childWrapper.appendChild(renderElement(child, subCtx));
|
|
4589
4656
|
}
|
|
4590
4657
|
});
|
|
4591
4658
|
item.appendChild(childWrapper);
|
|
4592
|
-
if (!
|
|
4659
|
+
if (!containerIsReadonly) {
|
|
4593
4660
|
const rem = document.createElement("button");
|
|
4594
4661
|
rem.type = "button";
|
|
4595
4662
|
rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
|
|
@@ -4639,8 +4706,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4639
4706
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
4640
4707
|
prefill: mergedPrefill,
|
|
4641
4708
|
// Merged prefill with defaults for enableIf
|
|
4642
|
-
formData: ctx.formData ?? ctx.prefill
|
|
4709
|
+
formData: ctx.formData ?? ctx.prefill,
|
|
4643
4710
|
// Complete root data for enableIf
|
|
4711
|
+
inheritedReadonly: childInheritedReadonly
|
|
4644
4712
|
};
|
|
4645
4713
|
const item = document.createElement("div");
|
|
4646
4714
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -4655,13 +4723,15 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4655
4723
|
element.elements.forEach((child) => {
|
|
4656
4724
|
if (child.hidden || child.type === "hidden") {
|
|
4657
4725
|
const prefillVal = prefillObj?.[child.key] ?? child.default ?? null;
|
|
4658
|
-
childWrapper.appendChild(
|
|
4726
|
+
childWrapper.appendChild(
|
|
4727
|
+
createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
|
|
4728
|
+
);
|
|
4659
4729
|
} else {
|
|
4660
4730
|
childWrapper.appendChild(renderElement(child, subCtx));
|
|
4661
4731
|
}
|
|
4662
4732
|
});
|
|
4663
4733
|
item.appendChild(childWrapper);
|
|
4664
|
-
if (!
|
|
4734
|
+
if (!containerIsReadonly) {
|
|
4665
4735
|
const rem = document.createElement("button");
|
|
4666
4736
|
rem.type = "button";
|
|
4667
4737
|
rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
|
|
@@ -4684,7 +4754,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4684
4754
|
itemsWrap.appendChild(item);
|
|
4685
4755
|
});
|
|
4686
4756
|
}
|
|
4687
|
-
if (!
|
|
4757
|
+
if (!containerIsReadonly) {
|
|
4688
4758
|
while (countItems() < min) {
|
|
4689
4759
|
const idx = countItems();
|
|
4690
4760
|
const subCtx = {
|
|
@@ -4692,8 +4762,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4692
4762
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
4693
4763
|
prefill: childDefaults,
|
|
4694
4764
|
// Defaults for enableIf evaluation
|
|
4695
|
-
formData: ctx.formData ?? ctx.prefill
|
|
4765
|
+
formData: ctx.formData ?? ctx.prefill,
|
|
4696
4766
|
// Complete root data for enableIf
|
|
4767
|
+
inheritedReadonly: childInheritedReadonly
|
|
4697
4768
|
};
|
|
4698
4769
|
const item = document.createElement("div");
|
|
4699
4770
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -4707,7 +4778,12 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4707
4778
|
}
|
|
4708
4779
|
element.elements.forEach((child) => {
|
|
4709
4780
|
if (child.hidden || child.type === "hidden") {
|
|
4710
|
-
childWrapper.appendChild(
|
|
4781
|
+
childWrapper.appendChild(
|
|
4782
|
+
createHiddenInput(
|
|
4783
|
+
pathJoin(subCtx.path, child.key),
|
|
4784
|
+
child.default ?? null
|
|
4785
|
+
)
|
|
4786
|
+
);
|
|
4711
4787
|
} else {
|
|
4712
4788
|
childWrapper.appendChild(renderElement(child, subCtx));
|
|
4713
4789
|
}
|
|
@@ -4739,7 +4815,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
4739
4815
|
}
|
|
4740
4816
|
}
|
|
4741
4817
|
containerWrap.appendChild(itemsWrap);
|
|
4742
|
-
if (!
|
|
4818
|
+
if (!containerIsReadonly) {
|
|
4743
4819
|
const addRow = document.createElement("div");
|
|
4744
4820
|
addRow.className = "flex items-center gap-3 mt-2";
|
|
4745
4821
|
addRow.appendChild(createAddButton());
|
|
@@ -4898,8 +4974,10 @@ function updateContainerField(element, fieldPath, value, context) {
|
|
|
4898
4974
|
const filesKey = richChild.filesKey ?? "files";
|
|
4899
4975
|
const containerValue = itemValue;
|
|
4900
4976
|
const compositeValue = {};
|
|
4901
|
-
if (textKey in containerValue)
|
|
4902
|
-
|
|
4977
|
+
if (textKey in containerValue)
|
|
4978
|
+
compositeValue[textKey] = containerValue[textKey];
|
|
4979
|
+
if (filesKey in containerValue)
|
|
4980
|
+
compositeValue[filesKey] = containerValue[filesKey];
|
|
4903
4981
|
if (Object.keys(compositeValue).length > 0) {
|
|
4904
4982
|
instance.updateField(childPath, compositeValue);
|
|
4905
4983
|
}
|
|
@@ -4935,8 +5013,10 @@ function updateContainerField(element, fieldPath, value, context) {
|
|
|
4935
5013
|
const filesKey = richChild.filesKey ?? "files";
|
|
4936
5014
|
const containerValue = value;
|
|
4937
5015
|
const compositeValue = {};
|
|
4938
|
-
if (textKey in containerValue)
|
|
4939
|
-
|
|
5016
|
+
if (textKey in containerValue)
|
|
5017
|
+
compositeValue[textKey] = containerValue[textKey];
|
|
5018
|
+
if (filesKey in containerValue)
|
|
5019
|
+
compositeValue[filesKey] = containerValue[filesKey];
|
|
4940
5020
|
if (Object.keys(compositeValue).length > 0) {
|
|
4941
5021
|
instance.updateField(childPath, compositeValue);
|
|
4942
5022
|
}
|
|
@@ -5274,12 +5354,21 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
5274
5354
|
const hiddenInput = document.createElement("input");
|
|
5275
5355
|
hiddenInput.type = "hidden";
|
|
5276
5356
|
hiddenInput.name = pathKey;
|
|
5277
|
-
hiddenInput.value = JSON.stringify({
|
|
5357
|
+
hiddenInput.value = JSON.stringify({
|
|
5358
|
+
[cellsKey]: cells,
|
|
5359
|
+
[mergesKey]: merges
|
|
5360
|
+
});
|
|
5278
5361
|
wrapper.appendChild(hiddenInput);
|
|
5279
5362
|
function persistValue() {
|
|
5280
|
-
hiddenInput.value = JSON.stringify({
|
|
5363
|
+
hiddenInput.value = JSON.stringify({
|
|
5364
|
+
[cellsKey]: cells,
|
|
5365
|
+
[mergesKey]: merges
|
|
5366
|
+
});
|
|
5281
5367
|
if (instance) {
|
|
5282
|
-
instance.triggerOnChange(pathKey, {
|
|
5368
|
+
instance.triggerOnChange(pathKey, {
|
|
5369
|
+
[cellsKey]: cells,
|
|
5370
|
+
[mergesKey]: merges
|
|
5371
|
+
});
|
|
5283
5372
|
}
|
|
5284
5373
|
}
|
|
5285
5374
|
hiddenInput._applyExternalUpdate = (data) => {
|
|
@@ -5338,9 +5427,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
5338
5427
|
rebuild();
|
|
5339
5428
|
} catch (e) {
|
|
5340
5429
|
const errMsg = e instanceof Error ? e.message : String(e);
|
|
5341
|
-
console.error(
|
|
5342
|
-
t("tableImportError", state).replace("{error}", errMsg)
|
|
5343
|
-
);
|
|
5430
|
+
console.error(t("tableImportError", state).replace("{error}", errMsg));
|
|
5344
5431
|
} finally {
|
|
5345
5432
|
overlay.remove();
|
|
5346
5433
|
}
|
|
@@ -5488,15 +5575,19 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
5488
5575
|
contextMenu.style.display = "none";
|
|
5489
5576
|
}
|
|
5490
5577
|
const menuDismissCtrl = new AbortController();
|
|
5491
|
-
document.addEventListener(
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5578
|
+
document.addEventListener(
|
|
5579
|
+
"mousedown",
|
|
5580
|
+
(e) => {
|
|
5581
|
+
if (!wrapper.isConnected) {
|
|
5582
|
+
menuDismissCtrl.abort();
|
|
5583
|
+
return;
|
|
5584
|
+
}
|
|
5585
|
+
if (!contextMenu.contains(e.target)) {
|
|
5586
|
+
hideContextMenu();
|
|
5587
|
+
}
|
|
5588
|
+
},
|
|
5589
|
+
{ signal: menuDismissCtrl.signal }
|
|
5590
|
+
);
|
|
5500
5591
|
function applySelectionStyles() {
|
|
5501
5592
|
const range = selectionRange(sel);
|
|
5502
5593
|
const allTds = tableEl.querySelectorAll("td[data-row]");
|
|
@@ -5842,7 +5933,9 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
5842
5933
|
if (!anchor) return;
|
|
5843
5934
|
const text = e.clipboardData?.getData("text/plain") ?? "";
|
|
5844
5935
|
const isMultiCell = text.includes(" ") || text.split(/\r?\n/).filter((l) => l).length > 1;
|
|
5845
|
-
const editing = tableEl.querySelector(
|
|
5936
|
+
const editing = tableEl.querySelector(
|
|
5937
|
+
"[contenteditable='true']"
|
|
5938
|
+
);
|
|
5846
5939
|
if (editing && !isMultiCell) return;
|
|
5847
5940
|
e.preventDefault();
|
|
5848
5941
|
if (editing) {
|
|
@@ -5998,7 +6091,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
5998
6091
|
}
|
|
5999
6092
|
}
|
|
6000
6093
|
function updateTopZoneOverlays(mx, wr, tblR, scrollL, active) {
|
|
6001
|
-
const headerCells = active ? Array.from(
|
|
6094
|
+
const headerCells = active ? Array.from(
|
|
6095
|
+
tableEl.querySelectorAll(
|
|
6096
|
+
"thead td[data-col]"
|
|
6097
|
+
)
|
|
6098
|
+
) : [];
|
|
6002
6099
|
let closestColIdx = -1;
|
|
6003
6100
|
let closestColDist = Infinity;
|
|
6004
6101
|
let closestBorderX = -1;
|
|
@@ -6016,7 +6113,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
6016
6113
|
if (borderDist < closestBorderDist && borderDist < 20) {
|
|
6017
6114
|
closestBorderDist = borderDist;
|
|
6018
6115
|
closestBorderX = cellRect.right - wr.left + scrollL;
|
|
6019
|
-
closestAfterCol = parseInt(
|
|
6116
|
+
closestAfterCol = parseInt(
|
|
6117
|
+
headerCells[i].getAttribute("data-col") ?? "0",
|
|
6118
|
+
10
|
|
6119
|
+
);
|
|
6020
6120
|
}
|
|
6021
6121
|
}
|
|
6022
6122
|
colRemoveBtns.forEach((btn, idx) => {
|
|
@@ -6071,7 +6171,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
6071
6171
|
closestRowBorderDist = borderDist;
|
|
6072
6172
|
closestBorderY = trRect.bottom - wr.top;
|
|
6073
6173
|
const firstTd = allRowEls[i].querySelector("td[data-row]");
|
|
6074
|
-
closestAfterRow = parseInt(
|
|
6174
|
+
closestAfterRow = parseInt(
|
|
6175
|
+
firstTd?.getAttribute("data-row") ?? "0",
|
|
6176
|
+
10
|
|
6177
|
+
);
|
|
6075
6178
|
}
|
|
6076
6179
|
}
|
|
6077
6180
|
rowRemoveBtns.forEach((btn, idx) => {
|
|
@@ -6097,7 +6200,8 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
|
|
|
6097
6200
|
let rafPending = false;
|
|
6098
6201
|
tableWrapper.onmousemove = (e) => {
|
|
6099
6202
|
const target = e.target;
|
|
6100
|
-
if (target.tagName === "BUTTON" && target.parentElement === tableWrapper)
|
|
6203
|
+
if (target.tagName === "BUTTON" && target.parentElement === tableWrapper)
|
|
6204
|
+
return;
|
|
6101
6205
|
if (rafPending) return;
|
|
6102
6206
|
rafPending = true;
|
|
6103
6207
|
const mx = e.clientX;
|
|
@@ -6156,6 +6260,7 @@ function isTableDataWithFieldNames(v, cellsKey) {
|
|
|
6156
6260
|
}
|
|
6157
6261
|
function renderTableElement(element, ctx, wrapper, pathKey) {
|
|
6158
6262
|
const state = ctx.state;
|
|
6263
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
6159
6264
|
const rawPrefill = ctx.prefill[element.key];
|
|
6160
6265
|
const cellsKey = element.fieldNames?.cells ?? "cells";
|
|
6161
6266
|
const mergesKey = element.fieldNames?.merges ?? "merges";
|
|
@@ -6190,11 +6295,13 @@ function renderTableElement(element, ctx, wrapper, pathKey) {
|
|
|
6190
6295
|
const cols = rows > 0 ? initialData.cells[0].length : 0;
|
|
6191
6296
|
const err = validateMerges(initialData.merges, rows, cols);
|
|
6192
6297
|
if (err) {
|
|
6193
|
-
console.warn(
|
|
6298
|
+
console.warn(
|
|
6299
|
+
`Table "${element.key}": invalid prefill merges stripped (${err})`
|
|
6300
|
+
);
|
|
6194
6301
|
initialData = { ...initialData, merges: [] };
|
|
6195
6302
|
}
|
|
6196
6303
|
}
|
|
6197
|
-
if (
|
|
6304
|
+
if (readonly) {
|
|
6198
6305
|
renderReadonlyTable(initialData, wrapper);
|
|
6199
6306
|
} else {
|
|
6200
6307
|
renderEditTable(element, initialData, pathKey, ctx, wrapper);
|
|
@@ -6871,20 +6978,26 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
6871
6978
|
});
|
|
6872
6979
|
let mentionTooltip = null;
|
|
6873
6980
|
backdrop.addEventListener("mouseover", (e) => {
|
|
6874
|
-
const mark = e.target.closest?.(
|
|
6981
|
+
const mark = e.target.closest?.(
|
|
6982
|
+
"mark"
|
|
6983
|
+
);
|
|
6875
6984
|
if (!mark?.dataset.rid) return;
|
|
6876
6985
|
mentionTooltip = removePortalTooltip(mentionTooltip);
|
|
6877
6986
|
mentionTooltip = showMentionTooltip(mark, mark.dataset.rid, state);
|
|
6878
6987
|
});
|
|
6879
6988
|
backdrop.addEventListener("mouseout", (e) => {
|
|
6880
|
-
const mark = e.target.closest?.(
|
|
6989
|
+
const mark = e.target.closest?.(
|
|
6990
|
+
"mark"
|
|
6991
|
+
);
|
|
6881
6992
|
if (!mark) return;
|
|
6882
6993
|
const related = e.relatedTarget;
|
|
6883
6994
|
if (related?.closest?.("mark")) return;
|
|
6884
6995
|
mentionTooltip = removePortalTooltip(mentionTooltip);
|
|
6885
6996
|
});
|
|
6886
6997
|
backdrop.addEventListener("mousedown", (e) => {
|
|
6887
|
-
const mark = e.target.closest?.(
|
|
6998
|
+
const mark = e.target.closest?.(
|
|
6999
|
+
"mark"
|
|
7000
|
+
);
|
|
6888
7001
|
if (!mark) return;
|
|
6889
7002
|
mentionTooltip = removePortalTooltip(mentionTooltip);
|
|
6890
7003
|
const marks = backdrop.querySelectorAll("mark");
|
|
@@ -7128,11 +7241,7 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
|
|
|
7128
7241
|
textarea.addEventListener("keydown", (e) => {
|
|
7129
7242
|
if (!dropdownState.open) return;
|
|
7130
7243
|
const labels = buildFileLabelsFromClosure();
|
|
7131
|
-
const filtered = filterFilesForDropdown(
|
|
7132
|
-
dropdownState.query,
|
|
7133
|
-
files,
|
|
7134
|
-
labels
|
|
7135
|
-
);
|
|
7244
|
+
const filtered = filterFilesForDropdown(dropdownState.query, files, labels);
|
|
7136
7245
|
if (e.key === "ArrowDown") {
|
|
7137
7246
|
e.preventDefault();
|
|
7138
7247
|
dropdownState.selectedIndex = Math.min(
|
|
@@ -7459,6 +7568,7 @@ function renderReadonlyMode(_element, ctx, wrapper, _pathKey, value) {
|
|
|
7459
7568
|
}
|
|
7460
7569
|
function renderRichInputElement(element, ctx, wrapper, pathKey) {
|
|
7461
7570
|
const state = ctx.state;
|
|
7571
|
+
const readonly = isElementReadonly(element, state, ctx);
|
|
7462
7572
|
const textKey = element.textKey ?? "text";
|
|
7463
7573
|
const filesKey = element.filesKey ?? "files";
|
|
7464
7574
|
let initialValue;
|
|
@@ -7496,7 +7606,7 @@ function renderRichInputElement(element, ctx, wrapper, pathKey) {
|
|
|
7496
7606
|
});
|
|
7497
7607
|
}
|
|
7498
7608
|
}
|
|
7499
|
-
if (
|
|
7609
|
+
if (readonly) {
|
|
7500
7610
|
renderReadonlyMode(element, ctx, wrapper, pathKey, initialValue);
|
|
7501
7611
|
} else {
|
|
7502
7612
|
if (!state.config.uploadFile) {
|
|
@@ -7558,9 +7668,7 @@ function validateRichInputElement(element, key, context) {
|
|
|
7558
7668
|
}
|
|
7559
7669
|
}
|
|
7560
7670
|
if (element.maxFiles != null && files.length > element.maxFiles) {
|
|
7561
|
-
errors.push(
|
|
7562
|
-
`${key}: ${t("maxFiles", state, { max: element.maxFiles })}`
|
|
7563
|
-
);
|
|
7671
|
+
errors.push(`${key}: ${t("maxFiles", state, { max: element.maxFiles })}`);
|
|
7564
7672
|
}
|
|
7565
7673
|
}
|
|
7566
7674
|
return { value, errors, spread: !!element.flatOutput };
|
|
@@ -7676,9 +7784,7 @@ function shouldDisableElement(element, ctx) {
|
|
|
7676
7784
|
return false;
|
|
7677
7785
|
}
|
|
7678
7786
|
function extractDOMValue(fieldPath, formRoot) {
|
|
7679
|
-
const input = formRoot.querySelector(
|
|
7680
|
-
`[name="${fieldPath}"]`
|
|
7681
|
-
);
|
|
7787
|
+
const input = formRoot.querySelector(`[name="${fieldPath}"]`);
|
|
7682
7788
|
if (!input) {
|
|
7683
7789
|
return void 0;
|
|
7684
7790
|
}
|
|
@@ -7723,9 +7829,7 @@ function reevaluateEnableIf(wrapper, element, ctx) {
|
|
|
7723
7829
|
`[data-container-item="${containerKey}[${containerIndex}]"]`
|
|
7724
7830
|
);
|
|
7725
7831
|
if (containerItemElement) {
|
|
7726
|
-
const inputs = containerItemElement.querySelectorAll(
|
|
7727
|
-
"input, select, textarea"
|
|
7728
|
-
);
|
|
7832
|
+
const inputs = containerItemElement.querySelectorAll("input, select, textarea");
|
|
7729
7833
|
inputs.forEach((input) => {
|
|
7730
7834
|
const fieldName = input.getAttribute("name");
|
|
7731
7835
|
if (fieldName) {
|
|
@@ -7777,7 +7881,10 @@ function reevaluateEnableIf(wrapper, element, ctx) {
|
|
|
7777
7881
|
wrapper.setAttribute("data-conditionally-disabled", "true");
|
|
7778
7882
|
}
|
|
7779
7883
|
} catch (error) {
|
|
7780
|
-
console.error(
|
|
7884
|
+
console.error(
|
|
7885
|
+
`Error re-evaluating enableIf for field "${element.key}":`,
|
|
7886
|
+
error
|
|
7887
|
+
);
|
|
7781
7888
|
}
|
|
7782
7889
|
}
|
|
7783
7890
|
function setupEnableIfListeners(wrapper, element, ctx) {
|
|
@@ -7798,14 +7905,10 @@ function setupEnableIfListeners(wrapper, element, ctx) {
|
|
|
7798
7905
|
} else {
|
|
7799
7906
|
dependencyFieldPath = dependencyKey;
|
|
7800
7907
|
}
|
|
7801
|
-
const dependencyInput = formRoot.querySelector(
|
|
7802
|
-
`[name="${dependencyFieldPath}"]`
|
|
7803
|
-
);
|
|
7908
|
+
const dependencyInput = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
|
|
7804
7909
|
if (!dependencyInput) {
|
|
7805
7910
|
const observer = new MutationObserver(() => {
|
|
7806
|
-
const input = formRoot.querySelector(
|
|
7807
|
-
`[name="${dependencyFieldPath}"]`
|
|
7808
|
-
);
|
|
7911
|
+
const input = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
|
|
7809
7912
|
if (input) {
|
|
7810
7913
|
input.addEventListener("change", () => {
|
|
7811
7914
|
reevaluateEnableIf(wrapper, element, ctx);
|
|
@@ -7952,7 +8055,9 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
|
|
|
7952
8055
|
default: {
|
|
7953
8056
|
const unsupported = document.createElement("div");
|
|
7954
8057
|
unsupported.className = "text-red-500 text-sm";
|
|
7955
|
-
unsupported.textContent = t("unsupportedFieldType", ctx.state, {
|
|
8058
|
+
unsupported.textContent = t("unsupportedFieldType", ctx.state, {
|
|
8059
|
+
type: element.type
|
|
8060
|
+
});
|
|
7956
8061
|
wrapper.appendChild(unsupported);
|
|
7957
8062
|
}
|
|
7958
8063
|
}
|
|
@@ -8904,7 +9009,10 @@ var FormBuilderInstance = class {
|
|
|
8904
9009
|
);
|
|
8905
9010
|
if (componentResult !== null) {
|
|
8906
9011
|
errors.push(...componentResult.errors);
|
|
8907
|
-
return {
|
|
9012
|
+
return {
|
|
9013
|
+
value: componentResult.value,
|
|
9014
|
+
spread: !!componentResult.spread
|
|
9015
|
+
};
|
|
8908
9016
|
}
|
|
8909
9017
|
console.warn(`Unknown field type "${element.type}" for key "${key}"`);
|
|
8910
9018
|
return { value: null, spread: false };
|
|
@@ -8913,10 +9021,7 @@ var FormBuilderInstance = class {
|
|
|
8913
9021
|
this.state.schema.elements.forEach((element) => {
|
|
8914
9022
|
if (element.enableIf) {
|
|
8915
9023
|
try {
|
|
8916
|
-
const shouldEnable = evaluateEnableCondition(
|
|
8917
|
-
element.enableIf,
|
|
8918
|
-
data
|
|
8919
|
-
);
|
|
9024
|
+
const shouldEnable = evaluateEnableCondition(element.enableIf, data);
|
|
8920
9025
|
if (!shouldEnable) {
|
|
8921
9026
|
return;
|
|
8922
9027
|
}
|
|
@@ -9211,7 +9316,10 @@ var FormBuilderInstance = class {
|
|
|
9211
9316
|
disabledWrapper.className = "fb-field-wrapper-disabled";
|
|
9212
9317
|
disabledWrapper.style.display = "none";
|
|
9213
9318
|
disabledWrapper.setAttribute("data-field-key", element.key);
|
|
9214
|
-
disabledWrapper.setAttribute(
|
|
9319
|
+
disabledWrapper.setAttribute(
|
|
9320
|
+
"data-conditionally-disabled",
|
|
9321
|
+
"true"
|
|
9322
|
+
);
|
|
9215
9323
|
wrapper.parentNode?.replaceChild(disabledWrapper, wrapper);
|
|
9216
9324
|
}
|
|
9217
9325
|
} catch (error) {
|