@dmitryvim/form-builder 0.2.25 → 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.
@@ -10,7 +10,10 @@ function t(key, state, params) {
10
10
  let text = (localeTranslations == null ? void 0 : localeTranslations[key]) || (fallbackTranslations == null ? void 0 : fallbackTranslations[key]) || key;
11
11
  if (params) {
12
12
  for (const [paramKey, paramValue] of Object.entries(params)) {
13
- text = text.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
13
+ text = text.replace(
14
+ new RegExp(`\\{${paramKey}\\}`, "g"),
15
+ String(paramValue)
16
+ );
14
17
  }
15
18
  }
16
19
  return text;
@@ -255,6 +258,9 @@ function validateSchema(schema) {
255
258
  }
256
259
 
257
260
  // src/utils/helpers.ts
261
+ function isElementReadonly(element, state, ctx) {
262
+ return element.readonly === true || state.config.readonly === true || (ctx == null ? void 0 : ctx.inheritedReadonly) === true;
263
+ }
258
264
  function isPlainObject(obj) {
259
265
  return obj && typeof obj === "object" && obj.constructor === Object;
260
266
  }
@@ -414,6 +420,7 @@ function createCharCounter(element, input, isTextarea = false) {
414
420
  }
415
421
  function renderTextElement(element, ctx, wrapper, pathKey) {
416
422
  const state = ctx.state;
423
+ const readonly = isElementReadonly(element, state, ctx);
417
424
  const inputWrapper = document.createElement("div");
418
425
  inputWrapper.style.cssText = "position: relative;";
419
426
  const textInput = document.createElement("input");
@@ -424,7 +431,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
424
431
  padding-right: 60px;
425
432
  border: var(--fb-border-width) solid var(--fb-border-color);
426
433
  border-radius: var(--fb-border-radius);
427
- background-color: ${state.config.readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
434
+ background-color: ${readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
428
435
  color: var(--fb-text-color);
429
436
  font-size: var(--fb-font-size);
430
437
  font-family: var(--fb-font-family);
@@ -435,8 +442,8 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
435
442
  textInput.name = pathKey;
436
443
  textInput.placeholder = element.placeholder || "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
437
444
  textInput.value = ctx.prefill[element.key] || element.default || "";
438
- textInput.readOnly = state.config.readonly;
439
- if (!state.config.readonly) {
445
+ textInput.readOnly = readonly;
446
+ if (!readonly) {
440
447
  textInput.addEventListener("focus", () => {
441
448
  textInput.style.borderColor = "var(--fb-border-focus-color)";
442
449
  textInput.style.outline = `var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)`;
@@ -457,7 +464,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
457
464
  }
458
465
  });
459
466
  }
460
- if (!state.config.readonly && ctx.instance) {
467
+ if (!readonly && ctx.instance) {
461
468
  const handleChange = () => {
462
469
  const value = textInput.value === "" ? null : textInput.value;
463
470
  ctx.instance.triggerOnChange(pathKey, value);
@@ -466,7 +473,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
466
473
  textInput.addEventListener("input", handleChange);
467
474
  }
468
475
  inputWrapper.appendChild(textInput);
469
- if (!state.config.readonly && (element.minLength != null || element.maxLength != null)) {
476
+ if (!readonly && (element.minLength != null || element.maxLength != null)) {
470
477
  const counter = createCharCounter(element, textInput, false);
471
478
  inputWrapper.appendChild(counter);
472
479
  }
@@ -475,6 +482,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
475
482
  function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
476
483
  var _a, _b;
477
484
  const state = ctx.state;
485
+ const readonly = isElementReadonly(element, state, ctx);
478
486
  const prefillValues = ctx.prefill[element.key] || [];
479
487
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
480
488
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -506,7 +514,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
506
514
  padding-right: 60px;
507
515
  border: var(--fb-border-width) solid var(--fb-border-color);
508
516
  border-radius: var(--fb-border-radius);
509
- background-color: ${state.config.readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
517
+ background-color: ${readonly ? "var(--fb-background-readonly-color)" : "var(--fb-background-color)"};
510
518
  color: var(--fb-text-color);
511
519
  font-size: var(--fb-font-size);
512
520
  font-family: var(--fb-font-family);
@@ -516,8 +524,8 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
516
524
  `;
517
525
  textInput.placeholder = element.placeholder || t("placeholderText", state);
518
526
  textInput.value = value;
519
- textInput.readOnly = state.config.readonly;
520
- if (!state.config.readonly) {
527
+ textInput.readOnly = readonly;
528
+ if (!readonly) {
521
529
  textInput.addEventListener("focus", () => {
522
530
  textInput.style.borderColor = "var(--fb-border-focus-color)";
523
531
  textInput.style.outline = `var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)`;
@@ -538,7 +546,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
538
546
  }
539
547
  });
540
548
  }
541
- if (!state.config.readonly && ctx.instance) {
549
+ if (!readonly && ctx.instance) {
542
550
  const handleChange = () => {
543
551
  const value2 = textInput.value === "" ? null : textInput.value;
544
552
  ctx.instance.triggerOnChange(textInput.name, value2);
@@ -547,7 +555,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
547
555
  textInput.addEventListener("input", handleChange);
548
556
  }
549
557
  inputContainer.appendChild(textInput);
550
- if (!state.config.readonly && (element.minLength != null || element.maxLength != null)) {
558
+ if (!readonly && (element.minLength != null || element.maxLength != null)) {
551
559
  const counter = createCharCounter(element, textInput, false);
552
560
  inputContainer.appendChild(counter);
553
561
  }
@@ -561,7 +569,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
561
569
  return itemWrapper;
562
570
  }
563
571
  function updateRemoveButtons() {
564
- if (state.config.readonly) return;
572
+ if (readonly) return;
565
573
  const items = container.querySelectorAll(".multiple-text-item");
566
574
  const currentCount = items.length;
567
575
  items.forEach((item) => {
@@ -606,7 +614,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
606
614
  }
607
615
  let addRow = null;
608
616
  let countDisplay = null;
609
- if (!state.config.readonly) {
617
+ if (!readonly) {
610
618
  addRow = document.createElement("div");
611
619
  addRow.className = "flex items-center gap-3 mt-2";
612
620
  const addBtn = document.createElement("button");
@@ -817,6 +825,7 @@ function applyAutoExpand(textarea) {
817
825
  }
818
826
  function renderTextareaElement(element, ctx, wrapper, pathKey) {
819
827
  const state = ctx.state;
828
+ const readonly = isElementReadonly(element, state, ctx);
820
829
  const textareaWrapper = document.createElement("div");
821
830
  textareaWrapper.style.cssText = "position: relative;";
822
831
  const textareaInput = document.createElement("textarea");
@@ -826,8 +835,8 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
826
835
  textareaInput.placeholder = element.placeholder || "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
827
836
  textareaInput.rows = element.rows || 4;
828
837
  textareaInput.value = ctx.prefill[element.key] || element.default || "";
829
- textareaInput.readOnly = state.config.readonly;
830
- if (!state.config.readonly && ctx.instance) {
838
+ textareaInput.readOnly = readonly;
839
+ if (!readonly && ctx.instance) {
831
840
  const handleChange = () => {
832
841
  const value = textareaInput.value === "" ? null : textareaInput.value;
833
842
  ctx.instance.triggerOnChange(pathKey, value);
@@ -835,11 +844,11 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
835
844
  textareaInput.addEventListener("blur", handleChange);
836
845
  textareaInput.addEventListener("input", handleChange);
837
846
  }
838
- if (element.autoExpand || state.config.readonly) {
847
+ if (element.autoExpand || readonly) {
839
848
  applyAutoExpand(textareaInput);
840
849
  }
841
850
  textareaWrapper.appendChild(textareaInput);
842
- if (!state.config.readonly && (element.minLength != null || element.maxLength != null)) {
851
+ if (!readonly && (element.minLength != null || element.maxLength != null)) {
843
852
  const counter = createCharCounter(element, textareaInput, true);
844
853
  textareaWrapper.appendChild(counter);
845
854
  }
@@ -848,6 +857,7 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
848
857
  function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
849
858
  var _a, _b;
850
859
  const state = ctx.state;
860
+ const readonly = isElementReadonly(element, state, ctx);
851
861
  const prefillValues = ctx.prefill[element.key] || [];
852
862
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
853
863
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -878,8 +888,8 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
878
888
  textareaInput.placeholder = element.placeholder || t("placeholderText", state);
879
889
  textareaInput.rows = element.rows || 4;
880
890
  textareaInput.value = value;
881
- textareaInput.readOnly = state.config.readonly;
882
- if (!state.config.readonly && ctx.instance) {
891
+ textareaInput.readOnly = readonly;
892
+ if (!readonly && ctx.instance) {
883
893
  const handleChange = () => {
884
894
  const value2 = textareaInput.value === "" ? null : textareaInput.value;
885
895
  ctx.instance.triggerOnChange(textareaInput.name, value2);
@@ -887,11 +897,11 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
887
897
  textareaInput.addEventListener("blur", handleChange);
888
898
  textareaInput.addEventListener("input", handleChange);
889
899
  }
890
- if (element.autoExpand || state.config.readonly) {
900
+ if (element.autoExpand || readonly) {
891
901
  applyAutoExpand(textareaInput);
892
902
  }
893
903
  textareaContainer.appendChild(textareaInput);
894
- if (!state.config.readonly && (element.minLength != null || element.maxLength != null)) {
904
+ if (!readonly && (element.minLength != null || element.maxLength != null)) {
895
905
  const counter = createCharCounter(element, textareaInput, true);
896
906
  textareaContainer.appendChild(counter);
897
907
  }
@@ -905,7 +915,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
905
915
  return itemWrapper;
906
916
  }
907
917
  function updateRemoveButtons() {
908
- if (state.config.readonly) return;
918
+ if (readonly) return;
909
919
  const items = container.querySelectorAll(".multiple-textarea-item");
910
920
  const currentCount = items.length;
911
921
  items.forEach((item) => {
@@ -939,7 +949,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
939
949
  }
940
950
  let addRow = null;
941
951
  let countDisplay = null;
942
- if (!state.config.readonly) {
952
+ if (!readonly) {
943
953
  addRow = document.createElement("div");
944
954
  addRow.className = "flex items-center gap-3 mt-2";
945
955
  const addBtn = document.createElement("button");
@@ -973,7 +983,9 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
973
983
  }
974
984
  function updateAddButton() {
975
985
  if (!addRow || !countDisplay) return;
976
- const addBtn = addRow.querySelector(".add-textarea-btn");
986
+ const addBtn = addRow.querySelector(
987
+ ".add-textarea-btn"
988
+ );
977
989
  if (addBtn) {
978
990
  const disabled = values.length >= maxCount;
979
991
  addBtn.disabled = disabled;
@@ -992,7 +1004,7 @@ function validateTextareaElement(element, key, context) {
992
1004
  function updateTextareaField(element, fieldPath, value, context) {
993
1005
  updateTextField(element, fieldPath, value, context);
994
1006
  const { scopeRoot, state } = context;
995
- const shouldAutoExpand = element.autoExpand || state.config.readonly;
1007
+ const shouldAutoExpand = element.autoExpand || isElementReadonly(element, state);
996
1008
  if (!shouldAutoExpand) return;
997
1009
  if (element.multiple) {
998
1010
  const textareas = scopeRoot.querySelectorAll(
@@ -1053,6 +1065,7 @@ function createNumberRangeHint(element, input) {
1053
1065
  }
1054
1066
  function renderNumberElement(element, ctx, wrapper, pathKey) {
1055
1067
  const state = ctx.state;
1068
+ const readonly = isElementReadonly(element, state, ctx);
1056
1069
  const inputWrapper = document.createElement("div");
1057
1070
  inputWrapper.style.cssText = "position: relative;";
1058
1071
  const numberInput = document.createElement("input");
@@ -1065,8 +1078,8 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
1065
1078
  if (element.max !== void 0) numberInput.max = element.max.toString();
1066
1079
  if (element.step !== void 0) numberInput.step = element.step.toString();
1067
1080
  numberInput.value = ctx.prefill[element.key] || element.default || "";
1068
- numberInput.readOnly = state.config.readonly;
1069
- if (!state.config.readonly && ctx.instance) {
1081
+ numberInput.readOnly = readonly;
1082
+ if (!readonly && ctx.instance) {
1070
1083
  const handleChange = () => {
1071
1084
  const value = numberInput.value ? parseFloat(numberInput.value) : null;
1072
1085
  ctx.instance.triggerOnChange(pathKey, value);
@@ -1075,7 +1088,7 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
1075
1088
  numberInput.addEventListener("input", handleChange);
1076
1089
  }
1077
1090
  inputWrapper.appendChild(numberInput);
1078
- if (!state.config.readonly && (element.min != null || element.max != null)) {
1091
+ if (!readonly && (element.min != null || element.max != null)) {
1079
1092
  const counter = createNumberRangeHint(element, numberInput);
1080
1093
  inputWrapper.appendChild(counter);
1081
1094
  }
@@ -1084,6 +1097,7 @@ function renderNumberElement(element, ctx, wrapper, pathKey) {
1084
1097
  function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
1085
1098
  var _a, _b;
1086
1099
  const state = ctx.state;
1100
+ const readonly = isElementReadonly(element, state, ctx);
1087
1101
  const prefillValues = ctx.prefill[element.key] || [];
1088
1102
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
1089
1103
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -1117,8 +1131,8 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
1117
1131
  if (element.max !== void 0) numberInput.max = element.max.toString();
1118
1132
  if (element.step !== void 0) numberInput.step = element.step.toString();
1119
1133
  numberInput.value = value.toString();
1120
- numberInput.readOnly = state.config.readonly;
1121
- if (!state.config.readonly && ctx.instance) {
1134
+ numberInput.readOnly = readonly;
1135
+ if (!readonly && ctx.instance) {
1122
1136
  const handleChange = () => {
1123
1137
  const val = numberInput.value ? parseFloat(numberInput.value) : null;
1124
1138
  ctx.instance.triggerOnChange(numberInput.name, val);
@@ -1127,7 +1141,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
1127
1141
  numberInput.addEventListener("input", handleChange);
1128
1142
  }
1129
1143
  inputContainer.appendChild(numberInput);
1130
- if (!state.config.readonly && (element.min != null || element.max != null)) {
1144
+ if (!readonly && (element.min != null || element.max != null)) {
1131
1145
  const counter = createNumberRangeHint(element, numberInput);
1132
1146
  inputContainer.appendChild(counter);
1133
1147
  }
@@ -1141,7 +1155,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
1141
1155
  return itemWrapper;
1142
1156
  }
1143
1157
  function updateRemoveButtons() {
1144
- if (state.config.readonly) return;
1158
+ if (readonly) return;
1145
1159
  const items = container.querySelectorAll(".multiple-number-item");
1146
1160
  const currentCount = items.length;
1147
1161
  items.forEach((item) => {
@@ -1175,7 +1189,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
1175
1189
  }
1176
1190
  let addRow = null;
1177
1191
  let countDisplay = null;
1178
- if (!state.config.readonly) {
1192
+ if (!readonly) {
1179
1193
  addRow = document.createElement("div");
1180
1194
  addRow.className = "flex items-center gap-3 mt-2";
1181
1195
  const addBtn = document.createElement("button");
@@ -1383,10 +1397,11 @@ function updateNumberField(element, fieldPath, value, context) {
1383
1397
  // src/components/select.ts
1384
1398
  function renderSelectElement(element, ctx, wrapper, pathKey) {
1385
1399
  const state = ctx.state;
1400
+ const readonly = isElementReadonly(element, state, ctx);
1386
1401
  const selectInput = document.createElement("select");
1387
1402
  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";
1388
1403
  selectInput.name = pathKey;
1389
- selectInput.disabled = state.config.readonly;
1404
+ selectInput.disabled = readonly;
1390
1405
  (element.options || []).forEach((option) => {
1391
1406
  const optionEl = document.createElement("option");
1392
1407
  optionEl.value = option.value;
@@ -1396,14 +1411,14 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
1396
1411
  }
1397
1412
  selectInput.appendChild(optionEl);
1398
1413
  });
1399
- if (!state.config.readonly && ctx.instance) {
1414
+ if (!readonly && ctx.instance) {
1400
1415
  const handleChange = () => {
1401
1416
  ctx.instance.triggerOnChange(pathKey, selectInput.value);
1402
1417
  };
1403
1418
  selectInput.addEventListener("change", handleChange);
1404
1419
  }
1405
1420
  wrapper.appendChild(selectInput);
1406
- if (!state.config.readonly) {
1421
+ if (!readonly) {
1407
1422
  const selectHint = document.createElement("p");
1408
1423
  selectHint.className = "text-xs text-gray-500 mt-1";
1409
1424
  selectHint.textContent = makeFieldHint(element, state);
@@ -1413,6 +1428,7 @@ function renderSelectElement(element, ctx, wrapper, pathKey) {
1413
1428
  function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1414
1429
  var _a, _b, _c, _d;
1415
1430
  const state = ctx.state;
1431
+ const readonly = isElementReadonly(element, state, ctx);
1416
1432
  const prefillValues = ctx.prefill[element.key] || [];
1417
1433
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
1418
1434
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -1437,7 +1453,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1437
1453
  itemWrapper.className = "multiple-select-item flex items-center gap-2";
1438
1454
  const selectInput = document.createElement("select");
1439
1455
  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";
1440
- selectInput.disabled = state.config.readonly;
1456
+ selectInput.disabled = readonly;
1441
1457
  (element.options || []).forEach((option) => {
1442
1458
  const optionElement = document.createElement("option");
1443
1459
  optionElement.value = option.value;
@@ -1447,7 +1463,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1447
1463
  }
1448
1464
  selectInput.appendChild(optionElement);
1449
1465
  });
1450
- if (!state.config.readonly && ctx.instance) {
1466
+ if (!readonly && ctx.instance) {
1451
1467
  const handleChange = () => {
1452
1468
  ctx.instance.triggerOnChange(selectInput.name, selectInput.value);
1453
1469
  };
@@ -1463,7 +1479,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1463
1479
  return itemWrapper;
1464
1480
  }
1465
1481
  function updateRemoveButtons() {
1466
- if (state.config.readonly) return;
1482
+ if (readonly) return;
1467
1483
  const items = container.querySelectorAll(".multiple-select-item");
1468
1484
  const currentCount = items.length;
1469
1485
  items.forEach((item) => {
@@ -1495,7 +1511,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1495
1511
  }
1496
1512
  let addRow = null;
1497
1513
  let countDisplay = null;
1498
- if (!state.config.readonly) {
1514
+ if (!readonly) {
1499
1515
  addRow = document.createElement("div");
1500
1516
  addRow.className = "flex items-center gap-3 mt-2";
1501
1517
  const addBtn = document.createElement("button");
@@ -1543,7 +1559,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
1543
1559
  values.forEach((value) => addSelectItem(value));
1544
1560
  updateAddButton();
1545
1561
  updateRemoveButtons();
1546
- if (!state.config.readonly) {
1562
+ if (!readonly) {
1547
1563
  const hint = document.createElement("p");
1548
1564
  hint.className = "text-xs text-gray-500 mt-1";
1549
1565
  hint.textContent = makeFieldHint(element, state);
@@ -1764,12 +1780,14 @@ function buildSegmentedGroup(element, currentValue, hiddenInput, readonly, onCha
1764
1780
  function renderSwitcherElement(element, ctx, wrapper, pathKey) {
1765
1781
  var _a, _b;
1766
1782
  const state = ctx.state;
1767
- const initialValue = String((_b = (_a = ctx.prefill[element.key]) != null ? _a : element.default) != null ? _b : "");
1783
+ const initialValue = String(
1784
+ (_b = (_a = ctx.prefill[element.key]) != null ? _a : element.default) != null ? _b : ""
1785
+ );
1768
1786
  const hiddenInput = document.createElement("input");
1769
1787
  hiddenInput.type = "hidden";
1770
1788
  hiddenInput.name = pathKey;
1771
1789
  hiddenInput.value = initialValue;
1772
- const readonly = state.config.readonly;
1790
+ const readonly = isElementReadonly(element, state, ctx);
1773
1791
  const onChange = !readonly && ctx.instance ? (value) => {
1774
1792
  ctx.instance.triggerOnChange(pathKey, value);
1775
1793
  } : null;
@@ -1799,7 +1817,7 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
1799
1817
  while (values.length < minCount) {
1800
1818
  values.push(element.default || ((_d = (_c = element.options) == null ? void 0 : _c[0]) == null ? void 0 : _d.value) || "");
1801
1819
  }
1802
- const readonly = state.config.readonly;
1820
+ const readonly = isElementReadonly(element, state, ctx);
1803
1821
  const container = document.createElement("div");
1804
1822
  container.className = "space-y-2";
1805
1823
  wrapper.appendChild(container);
@@ -2212,9 +2230,7 @@ function renderUploadedVideoPreview(container, thumbnailUrl, _videoType, state)
2212
2230
  video.preload = "metadata";
2213
2231
  video.muted = true;
2214
2232
  video.src = thumbnailUrl;
2215
- video.appendChild(
2216
- document.createTextNode(t("videoNotSupported", state))
2217
- );
2233
+ video.appendChild(document.createTextNode(t("videoNotSupported", state)));
2218
2234
  container.appendChild(video);
2219
2235
  }
2220
2236
  function renderDeleteButton(container, resourceId, state) {
@@ -3038,9 +3054,15 @@ function setupFilesPickerHandler(filesPicker, initialFiles, state, updateCallbac
3038
3054
  function renderFileElement(element, ctx, wrapper, pathKey) {
3039
3055
  var _a, _b;
3040
3056
  const state = ctx.state;
3041
- if (state.config.readonly) {
3042
- const initial = ctx.prefill[element.key];
3057
+ if (isElementReadonly(element, state, ctx)) {
3058
+ const rawInitial = ctx.prefill[element.key];
3059
+ const initial = typeof rawInitial === "string" ? rawInitial : "";
3043
3060
  if (initial) {
3061
+ const hiddenInput = document.createElement("input");
3062
+ hiddenInput.type = "hidden";
3063
+ hiddenInput.name = pathKey;
3064
+ hiddenInput.value = initial;
3065
+ wrapper.appendChild(hiddenInput);
3044
3066
  renderFilePreviewReadonly(initial, state).then((filePreview) => {
3045
3067
  wrapper.appendChild(filePreview);
3046
3068
  }).catch((err) => {
@@ -3129,10 +3151,24 @@ function renderFileElement(element, ctx, wrapper, pathKey) {
3129
3151
  function renderFilesElement(element, ctx, wrapper, pathKey) {
3130
3152
  var _a, _b;
3131
3153
  const state = ctx.state;
3132
- if (state.config.readonly) {
3154
+ if (isElementReadonly(element, state, ctx)) {
3155
+ const rawPrefill = ctx.prefill[element.key];
3156
+ const initialFiles = Array.isArray(rawPrefill) ? rawPrefill : [];
3157
+ const filesWrapper = document.createElement("div");
3158
+ filesWrapper.className = "space-y-2";
3159
+ filesWrapper.dataset.filesWrapper = pathKey;
3160
+ const filesList = document.createElement("div");
3161
+ filesList.className = "files-list";
3162
+ initialFiles.forEach((resourceId) => {
3163
+ const pill = document.createElement("div");
3164
+ pill.className = "resource-pill";
3165
+ pill.dataset.resourceId = resourceId;
3166
+ filesList.appendChild(pill);
3167
+ });
3168
+ filesWrapper.appendChild(filesList);
3169
+ wrapper.appendChild(filesWrapper);
3133
3170
  const resultsWrapper = document.createElement("div");
3134
3171
  resultsWrapper.className = "space-y-4";
3135
- const initialFiles = ctx.prefill[element.key] || [];
3136
3172
  if (initialFiles.length > 0) {
3137
3173
  initialFiles.forEach((resourceId) => {
3138
3174
  renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
@@ -3163,6 +3199,7 @@ function renderFilesElement(element, ctx, wrapper, pathKey) {
3163
3199
  };
3164
3200
  const filesWrapper = document.createElement("div");
3165
3201
  filesWrapper.className = "space-y-2";
3202
+ filesWrapper.dataset.filesWrapper = pathKey;
3166
3203
  const filesPicker = document.createElement("input");
3167
3204
  filesPicker.type = "file";
3168
3205
  filesPicker.name = pathKey;
@@ -3213,10 +3250,24 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
3213
3250
  const state = ctx.state;
3214
3251
  const minFiles = (_a = element.minCount) != null ? _a : 0;
3215
3252
  const maxFiles = (_b = element.maxCount) != null ? _b : Infinity;
3216
- if (state.config.readonly) {
3253
+ if (isElementReadonly(element, state, ctx)) {
3254
+ const rawPrefill = ctx.prefill[element.key];
3255
+ const initialFiles = Array.isArray(rawPrefill) ? rawPrefill : [];
3256
+ const filesWrapper = document.createElement("div");
3257
+ filesWrapper.className = "space-y-2";
3258
+ filesWrapper.dataset.filesWrapper = pathKey;
3259
+ const filesList = document.createElement("div");
3260
+ filesList.className = "files-list";
3261
+ initialFiles.forEach((resourceId) => {
3262
+ const pill = document.createElement("div");
3263
+ pill.className = "resource-pill";
3264
+ pill.dataset.resourceId = resourceId;
3265
+ filesList.appendChild(pill);
3266
+ });
3267
+ filesWrapper.appendChild(filesList);
3268
+ wrapper.appendChild(filesWrapper);
3217
3269
  const resultsWrapper = document.createElement("div");
3218
3270
  resultsWrapper.className = "space-y-4";
3219
- const initialFiles = ctx.prefill[element.key] || [];
3220
3271
  if (initialFiles.length > 0) {
3221
3272
  initialFiles.forEach((resourceId) => {
3222
3273
  renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
@@ -3232,6 +3283,7 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
3232
3283
  } else {
3233
3284
  const filesWrapper = document.createElement("div");
3234
3285
  filesWrapper.className = "space-y-2";
3286
+ filesWrapper.dataset.filesWrapper = pathKey;
3235
3287
  const filesPicker = document.createElement("input");
3236
3288
  filesPicker.type = "file";
3237
3289
  filesPicker.name = pathKey;
@@ -3349,10 +3401,9 @@ function validateFileElement(element, key, context) {
3349
3401
  };
3350
3402
  if (isMultipleField) {
3351
3403
  const fullKey = pathJoin(path, key);
3352
- const pickerInput = scopeRoot.querySelector(
3353
- `input[type="file"][name="${fullKey}"]`
3404
+ const filesWrapper = scopeRoot.querySelector(
3405
+ `[data-files-wrapper="${fullKey}"]`
3354
3406
  );
3355
- const filesWrapper = pickerInput == null ? void 0 : pickerInput.closest(".space-y-2");
3356
3407
  const container = (filesWrapper == null ? void 0 : filesWrapper.querySelector(".files-list")) || null;
3357
3408
  const resourceIds = [];
3358
3409
  if (container) {
@@ -3613,15 +3664,16 @@ function createEditColourUI(value, pathKey, ctx) {
3613
3664
  }
3614
3665
  function renderColourElement(element, ctx, wrapper, pathKey) {
3615
3666
  const state = ctx.state;
3667
+ const readonly = isElementReadonly(element, state, ctx);
3616
3668
  const initialValue = ctx.prefill[element.key] || element.default || "#000000";
3617
- if (state.config.readonly) {
3669
+ if (readonly) {
3618
3670
  const readonlyUI = createReadonlyColourUI(initialValue);
3619
3671
  wrapper.appendChild(readonlyUI);
3620
3672
  } else {
3621
3673
  const editUI = createEditColourUI(initialValue, pathKey, ctx);
3622
3674
  wrapper.appendChild(editUI);
3623
3675
  }
3624
- if (!state.config.readonly) {
3676
+ if (!readonly) {
3625
3677
  const colourHint = document.createElement("p");
3626
3678
  colourHint.className = "mt-1";
3627
3679
  colourHint.style.cssText = `
@@ -3635,6 +3687,7 @@ function renderColourElement(element, ctx, wrapper, pathKey) {
3635
3687
  function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3636
3688
  var _a, _b;
3637
3689
  const state = ctx.state;
3690
+ const readonly = isElementReadonly(element, state, ctx);
3638
3691
  const prefillValues = ctx.prefill[element.key] || [];
3639
3692
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
3640
3693
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -3657,7 +3710,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3657
3710
  function addColourItem(value = "#000000", index = -1) {
3658
3711
  const itemWrapper = document.createElement("div");
3659
3712
  itemWrapper.className = "multiple-colour-item flex items-center gap-2";
3660
- if (state.config.readonly) {
3713
+ if (readonly) {
3661
3714
  const readonlyUI = createReadonlyColourUI(value);
3662
3715
  while (readonlyUI.firstChild) {
3663
3716
  itemWrapper.appendChild(readonlyUI.firstChild);
@@ -3677,7 +3730,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3677
3730
  return itemWrapper;
3678
3731
  }
3679
3732
  function updateRemoveButtons() {
3680
- if (state.config.readonly) return;
3733
+ if (readonly) return;
3681
3734
  const items = container.querySelectorAll(".multiple-colour-item");
3682
3735
  const currentCount = items.length;
3683
3736
  items.forEach((item) => {
@@ -3722,7 +3775,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3722
3775
  }
3723
3776
  let addRow = null;
3724
3777
  let countDisplay = null;
3725
- if (!state.config.readonly) {
3778
+ if (!readonly) {
3726
3779
  addRow = document.createElement("div");
3727
3780
  addRow.className = "flex items-center gap-3 mt-2";
3728
3781
  const addBtn = document.createElement("button");
@@ -3769,7 +3822,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3769
3822
  values.forEach((value) => addColourItem(value));
3770
3823
  updateAddButton();
3771
3824
  updateRemoveButtons();
3772
- if (!state.config.readonly) {
3825
+ if (!readonly) {
3773
3826
  const hint = document.createElement("p");
3774
3827
  hint.className = "mt-1";
3775
3828
  hint.style.cssText = `
@@ -3840,7 +3893,9 @@ function validateColourElement(element, key, context) {
3840
3893
  return normalized;
3841
3894
  };
3842
3895
  if (element.multiple) {
3843
- const hexInputs = scopeRoot.querySelectorAll(`[name^="${key}["].colour-hex-input`);
3896
+ const hexInputs = scopeRoot.querySelectorAll(
3897
+ `[name^="${key}["].colour-hex-input`
3898
+ );
3844
3899
  const values = [];
3845
3900
  hexInputs.forEach((input, index) => {
3846
3901
  var _a2;
@@ -3888,7 +3943,9 @@ function updateColourField(element, fieldPath, value, context) {
3888
3943
  );
3889
3944
  return;
3890
3945
  }
3891
- const hexInputs = scopeRoot.querySelectorAll(`[name^="${fieldPath}["].colour-hex-input`);
3946
+ const hexInputs = scopeRoot.querySelectorAll(
3947
+ `[name^="${fieldPath}["].colour-hex-input`
3948
+ );
3892
3949
  hexInputs.forEach((hexInput, index) => {
3893
3950
  if (index < value.length) {
3894
3951
  const normalized = normalizeColourValue(value[index]);
@@ -4085,6 +4142,7 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
4085
4142
  );
4086
4143
  }
4087
4144
  const state = ctx.state;
4145
+ const readonly = isElementReadonly(element, state, ctx);
4088
4146
  const defaultValue = element.default !== void 0 ? element.default : (element.min + element.max) / 2;
4089
4147
  const initialValue = (_a = ctx.prefill[element.key]) != null ? _a : defaultValue;
4090
4148
  const sliderUI = createSliderUI(
@@ -4092,10 +4150,10 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
4092
4150
  pathKey,
4093
4151
  element,
4094
4152
  ctx,
4095
- state.config.readonly
4153
+ readonly
4096
4154
  );
4097
4155
  wrapper.appendChild(sliderUI);
4098
- if (!state.config.readonly) {
4156
+ if (!readonly) {
4099
4157
  const hint = document.createElement("p");
4100
4158
  hint.className = "mt-1";
4101
4159
  hint.style.cssText = `
@@ -4120,6 +4178,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4120
4178
  );
4121
4179
  }
4122
4180
  const state = ctx.state;
4181
+ const readonly = isElementReadonly(element, state, ctx);
4123
4182
  const prefillValues = ctx.prefill[element.key] || [];
4124
4183
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
4125
4184
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -4144,13 +4203,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4144
4203
  const itemWrapper = document.createElement("div");
4145
4204
  itemWrapper.className = "multiple-slider-item flex items-start gap-2";
4146
4205
  const tempPathKey = `${pathKey}[${container.children.length}]`;
4147
- const sliderUI = createSliderUI(
4148
- value,
4149
- tempPathKey,
4150
- element,
4151
- ctx,
4152
- state.config.readonly
4153
- );
4206
+ const sliderUI = createSliderUI(value, tempPathKey, element, ctx, readonly);
4154
4207
  sliderUI.style.flex = "1";
4155
4208
  itemWrapper.appendChild(sliderUI);
4156
4209
  if (index === -1) {
@@ -4162,7 +4215,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4162
4215
  return itemWrapper;
4163
4216
  }
4164
4217
  function updateRemoveButtons() {
4165
- if (state.config.readonly) return;
4218
+ if (readonly) return;
4166
4219
  const items = container.querySelectorAll(".multiple-slider-item");
4167
4220
  const currentCount = items.length;
4168
4221
  items.forEach((item) => {
@@ -4208,7 +4261,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4208
4261
  }
4209
4262
  let addRow = null;
4210
4263
  let countDisplay = null;
4211
- if (!state.config.readonly) {
4264
+ if (!readonly) {
4212
4265
  addRow = document.createElement("div");
4213
4266
  addRow.className = "flex items-center gap-3 mt-2";
4214
4267
  const addBtn = document.createElement("button");
@@ -4254,7 +4307,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4254
4307
  values.forEach((value) => addSliderItem(value));
4255
4308
  updateAddButton();
4256
4309
  updateRemoveButtons();
4257
- if (!state.config.readonly) {
4310
+ if (!readonly) {
4258
4311
  const hint = document.createElement("p");
4259
4312
  hint.className = "mt-1";
4260
4313
  hint.style.cssText = `
@@ -4496,9 +4549,7 @@ function mergeWithDefaults(prefill, defaults) {
4496
4549
  }
4497
4550
  function extractRootFormData(formRoot) {
4498
4551
  const data = {};
4499
- const inputs = formRoot.querySelectorAll(
4500
- "input, select, textarea"
4501
- );
4552
+ const inputs = formRoot.querySelectorAll("input, select, textarea");
4502
4553
  inputs.forEach((input) => {
4503
4554
  const fieldName = input.getAttribute("name");
4504
4555
  if (fieldName && !fieldName.includes("[") && !fieldName.includes(".")) {
@@ -4563,7 +4614,8 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4563
4614
  } else {
4564
4615
  itemsWrap.className = `grid grid-cols-${columns} gap-4`;
4565
4616
  }
4566
- if (!ctx.state.config.readonly) {
4617
+ const containerIsReadonly = isElementReadonly(element, ctx.state, ctx);
4618
+ if (!containerIsReadonly) {
4567
4619
  const hintsElement = createPrefillHints(element, pathKey);
4568
4620
  if (hintsElement) {
4569
4621
  containerWrap.appendChild(hintsElement);
@@ -4578,13 +4630,16 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4578
4630
  // Merged prefill with defaults for enableIf evaluation
4579
4631
  formData: (_b = ctx.formData) != null ? _b : ctx.prefill,
4580
4632
  // Complete root data for enableIf evaluation
4581
- state: ctx.state
4633
+ state: ctx.state,
4634
+ inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
4582
4635
  };
4583
4636
  element.elements.forEach((child) => {
4584
4637
  var _a2, _b2;
4585
4638
  if (child.hidden || child.type === "hidden") {
4586
4639
  const prefillVal = (_b2 = (_a2 = containerPrefill[child.key]) != null ? _a2 : child.default) != null ? _b2 : null;
4587
- itemsWrap.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal));
4640
+ itemsWrap.appendChild(
4641
+ createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
4642
+ );
4588
4643
  } else {
4589
4644
  itemsWrap.appendChild(renderElement(child, subCtx));
4590
4645
  }
@@ -4595,13 +4650,15 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4595
4650
  function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4596
4651
  var _a, _b, _c, _d;
4597
4652
  const state = ctx.state;
4653
+ const containerIsReadonly = isElementReadonly(element, state, ctx);
4654
+ const childInheritedReadonly = containerIsReadonly || ctx.inheritedReadonly;
4598
4655
  const containerWrap = document.createElement("div");
4599
4656
  containerWrap.className = "border border-gray-200 rounded-lg p-4 bg-gray-50";
4600
4657
  const countDisplay = document.createElement("span");
4601
4658
  countDisplay.className = "text-sm text-gray-500";
4602
4659
  const itemsWrap = document.createElement("div");
4603
4660
  itemsWrap.className = "space-y-4";
4604
- if (!ctx.state.config.readonly) {
4661
+ if (!containerIsReadonly) {
4605
4662
  const hintsElement = createPrefillHints(element, element.key);
4606
4663
  if (hintsElement) {
4607
4664
  containerWrap.appendChild(hintsElement);
@@ -4639,8 +4696,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4639
4696
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4640
4697
  prefill: childDefaults,
4641
4698
  // Defaults for enableIf evaluation
4642
- formData: currentFormData
4699
+ formData: currentFormData,
4643
4700
  // Current root data from DOM for enableIf
4701
+ inheritedReadonly: childInheritedReadonly
4644
4702
  };
4645
4703
  const item = document.createElement("div");
4646
4704
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4655,13 +4713,18 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4655
4713
  element.elements.forEach((child) => {
4656
4714
  var _a2;
4657
4715
  if (child.hidden || child.type === "hidden") {
4658
- childWrapper.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), (_a2 = child.default) != null ? _a2 : null));
4716
+ childWrapper.appendChild(
4717
+ createHiddenInput(
4718
+ pathJoin(subCtx.path, child.key),
4719
+ (_a2 = child.default) != null ? _a2 : null
4720
+ )
4721
+ );
4659
4722
  } else {
4660
4723
  childWrapper.appendChild(renderElement(child, subCtx));
4661
4724
  }
4662
4725
  });
4663
4726
  item.appendChild(childWrapper);
4664
- if (!state.config.readonly) {
4727
+ if (!containerIsReadonly) {
4665
4728
  const rem = document.createElement("button");
4666
4729
  rem.type = "button";
4667
4730
  rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
@@ -4712,8 +4775,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4712
4775
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4713
4776
  prefill: mergedPrefill,
4714
4777
  // Merged prefill with defaults for enableIf
4715
- formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill
4778
+ formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill,
4716
4779
  // Complete root data for enableIf
4780
+ inheritedReadonly: childInheritedReadonly
4717
4781
  };
4718
4782
  const item = document.createElement("div");
4719
4783
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4729,13 +4793,15 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4729
4793
  var _a3, _b2;
4730
4794
  if (child.hidden || child.type === "hidden") {
4731
4795
  const prefillVal = (_b2 = (_a3 = prefillObj == null ? void 0 : prefillObj[child.key]) != null ? _a3 : child.default) != null ? _b2 : null;
4732
- childWrapper.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal));
4796
+ childWrapper.appendChild(
4797
+ createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
4798
+ );
4733
4799
  } else {
4734
4800
  childWrapper.appendChild(renderElement(child, subCtx));
4735
4801
  }
4736
4802
  });
4737
4803
  item.appendChild(childWrapper);
4738
- if (!state.config.readonly) {
4804
+ if (!containerIsReadonly) {
4739
4805
  const rem = document.createElement("button");
4740
4806
  rem.type = "button";
4741
4807
  rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
@@ -4758,7 +4824,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4758
4824
  itemsWrap.appendChild(item);
4759
4825
  });
4760
4826
  }
4761
- if (!state.config.readonly) {
4827
+ if (!containerIsReadonly) {
4762
4828
  while (countItems() < min) {
4763
4829
  const idx = countItems();
4764
4830
  const subCtx = {
@@ -4766,8 +4832,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4766
4832
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4767
4833
  prefill: childDefaults,
4768
4834
  // Defaults for enableIf evaluation
4769
- formData: (_d = ctx.formData) != null ? _d : ctx.prefill
4835
+ formData: (_d = ctx.formData) != null ? _d : ctx.prefill,
4770
4836
  // Complete root data for enableIf
4837
+ inheritedReadonly: childInheritedReadonly
4771
4838
  };
4772
4839
  const item = document.createElement("div");
4773
4840
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4782,7 +4849,12 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4782
4849
  element.elements.forEach((child) => {
4783
4850
  var _a2;
4784
4851
  if (child.hidden || child.type === "hidden") {
4785
- childWrapper.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), (_a2 = child.default) != null ? _a2 : null));
4852
+ childWrapper.appendChild(
4853
+ createHiddenInput(
4854
+ pathJoin(subCtx.path, child.key),
4855
+ (_a2 = child.default) != null ? _a2 : null
4856
+ )
4857
+ );
4786
4858
  } else {
4787
4859
  childWrapper.appendChild(renderElement(child, subCtx));
4788
4860
  }
@@ -4814,7 +4886,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4814
4886
  }
4815
4887
  }
4816
4888
  containerWrap.appendChild(itemsWrap);
4817
- if (!state.config.readonly) {
4889
+ if (!containerIsReadonly) {
4818
4890
  const addRow = document.createElement("div");
4819
4891
  addRow.className = "flex items-center gap-3 mt-2";
4820
4892
  addRow.appendChild(createAddButton());
@@ -4977,8 +5049,10 @@ function updateContainerField(element, fieldPath, value, context) {
4977
5049
  const filesKey = (_b = richChild.filesKey) != null ? _b : "files";
4978
5050
  const containerValue = itemValue;
4979
5051
  const compositeValue = {};
4980
- if (textKey in containerValue) compositeValue[textKey] = containerValue[textKey];
4981
- if (filesKey in containerValue) compositeValue[filesKey] = containerValue[filesKey];
5052
+ if (textKey in containerValue)
5053
+ compositeValue[textKey] = containerValue[textKey];
5054
+ if (filesKey in containerValue)
5055
+ compositeValue[filesKey] = containerValue[filesKey];
4982
5056
  if (Object.keys(compositeValue).length > 0) {
4983
5057
  instance.updateField(childPath, compositeValue);
4984
5058
  }
@@ -5015,8 +5089,10 @@ function updateContainerField(element, fieldPath, value, context) {
5015
5089
  const filesKey = (_b = richChild.filesKey) != null ? _b : "files";
5016
5090
  const containerValue = value;
5017
5091
  const compositeValue = {};
5018
- if (textKey in containerValue) compositeValue[textKey] = containerValue[textKey];
5019
- if (filesKey in containerValue) compositeValue[filesKey] = containerValue[filesKey];
5092
+ if (textKey in containerValue)
5093
+ compositeValue[textKey] = containerValue[textKey];
5094
+ if (filesKey in containerValue)
5095
+ compositeValue[filesKey] = containerValue[filesKey];
5020
5096
  if (Object.keys(compositeValue).length > 0) {
5021
5097
  instance.updateField(childPath, compositeValue);
5022
5098
  }
@@ -5362,12 +5438,21 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5362
5438
  const hiddenInput = document.createElement("input");
5363
5439
  hiddenInput.type = "hidden";
5364
5440
  hiddenInput.name = pathKey;
5365
- hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
5441
+ hiddenInput.value = JSON.stringify({
5442
+ [cellsKey]: cells,
5443
+ [mergesKey]: merges
5444
+ });
5366
5445
  wrapper.appendChild(hiddenInput);
5367
5446
  function persistValue() {
5368
- hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
5447
+ hiddenInput.value = JSON.stringify({
5448
+ [cellsKey]: cells,
5449
+ [mergesKey]: merges
5450
+ });
5369
5451
  if (instance) {
5370
- instance.triggerOnChange(pathKey, { [cellsKey]: cells, [mergesKey]: merges });
5452
+ instance.triggerOnChange(pathKey, {
5453
+ [cellsKey]: cells,
5454
+ [mergesKey]: merges
5455
+ });
5371
5456
  }
5372
5457
  }
5373
5458
  hiddenInput._applyExternalUpdate = (data) => {
@@ -5427,9 +5512,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5427
5512
  rebuild();
5428
5513
  } catch (e) {
5429
5514
  const errMsg = e instanceof Error ? e.message : String(e);
5430
- console.error(
5431
- t("tableImportError", state).replace("{error}", errMsg)
5432
- );
5515
+ console.error(t("tableImportError", state).replace("{error}", errMsg));
5433
5516
  } finally {
5434
5517
  overlay.remove();
5435
5518
  }
@@ -5579,15 +5662,19 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5579
5662
  contextMenu.style.display = "none";
5580
5663
  }
5581
5664
  const menuDismissCtrl = new AbortController();
5582
- document.addEventListener("mousedown", (e) => {
5583
- if (!wrapper.isConnected) {
5584
- menuDismissCtrl.abort();
5585
- return;
5586
- }
5587
- if (!contextMenu.contains(e.target)) {
5588
- hideContextMenu();
5589
- }
5590
- }, { signal: menuDismissCtrl.signal });
5665
+ document.addEventListener(
5666
+ "mousedown",
5667
+ (e) => {
5668
+ if (!wrapper.isConnected) {
5669
+ menuDismissCtrl.abort();
5670
+ return;
5671
+ }
5672
+ if (!contextMenu.contains(e.target)) {
5673
+ hideContextMenu();
5674
+ }
5675
+ },
5676
+ { signal: menuDismissCtrl.signal }
5677
+ );
5591
5678
  function applySelectionStyles() {
5592
5679
  const range = selectionRange(sel);
5593
5680
  const allTds = tableEl.querySelectorAll("td[data-row]");
@@ -5940,7 +6027,9 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5940
6027
  if (!anchor) return;
5941
6028
  const text = (_b3 = (_a3 = e.clipboardData) == null ? void 0 : _a3.getData("text/plain")) != null ? _b3 : "";
5942
6029
  const isMultiCell = text.includes(" ") || text.split(/\r?\n/).filter((l) => l).length > 1;
5943
- const editing = tableEl.querySelector("[contenteditable='true']");
6030
+ const editing = tableEl.querySelector(
6031
+ "[contenteditable='true']"
6032
+ );
5944
6033
  if (editing && !isMultiCell) return;
5945
6034
  e.preventDefault();
5946
6035
  if (editing) {
@@ -6100,7 +6189,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6100
6189
  }
6101
6190
  function updateTopZoneOverlays(mx, wr, tblR, scrollL, active) {
6102
6191
  var _a3;
6103
- const headerCells = active ? Array.from(tableEl.querySelectorAll("thead td[data-col]")) : [];
6192
+ const headerCells = active ? Array.from(
6193
+ tableEl.querySelectorAll(
6194
+ "thead td[data-col]"
6195
+ )
6196
+ ) : [];
6104
6197
  let closestColIdx = -1;
6105
6198
  let closestColDist = Infinity;
6106
6199
  let closestBorderX = -1;
@@ -6118,7 +6211,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6118
6211
  if (borderDist < closestBorderDist && borderDist < 20) {
6119
6212
  closestBorderDist = borderDist;
6120
6213
  closestBorderX = cellRect.right - wr.left + scrollL;
6121
- closestAfterCol = parseInt((_a3 = headerCells[i].getAttribute("data-col")) != null ? _a3 : "0", 10);
6214
+ closestAfterCol = parseInt(
6215
+ (_a3 = headerCells[i].getAttribute("data-col")) != null ? _a3 : "0",
6216
+ 10
6217
+ );
6122
6218
  }
6123
6219
  }
6124
6220
  colRemoveBtns.forEach((btn, idx) => {
@@ -6174,7 +6270,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6174
6270
  closestRowBorderDist = borderDist;
6175
6271
  closestBorderY = trRect.bottom - wr.top;
6176
6272
  const firstTd = allRowEls[i].querySelector("td[data-row]");
6177
- closestAfterRow = parseInt((_a3 = firstTd == null ? void 0 : firstTd.getAttribute("data-row")) != null ? _a3 : "0", 10);
6273
+ closestAfterRow = parseInt(
6274
+ (_a3 = firstTd == null ? void 0 : firstTd.getAttribute("data-row")) != null ? _a3 : "0",
6275
+ 10
6276
+ );
6178
6277
  }
6179
6278
  }
6180
6279
  rowRemoveBtns.forEach((btn, idx) => {
@@ -6200,7 +6299,8 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6200
6299
  let rafPending = false;
6201
6300
  tableWrapper.onmousemove = (e) => {
6202
6301
  const target = e.target;
6203
- if (target.tagName === "BUTTON" && target.parentElement === tableWrapper) return;
6302
+ if (target.tagName === "BUTTON" && target.parentElement === tableWrapper)
6303
+ return;
6204
6304
  if (rafPending) return;
6205
6305
  rafPending = true;
6206
6306
  const mx = e.clientX;
@@ -6261,6 +6361,7 @@ function isTableDataWithFieldNames(v, cellsKey) {
6261
6361
  function renderTableElement(element, ctx, wrapper, pathKey) {
6262
6362
  var _a, _b, _c, _d;
6263
6363
  const state = ctx.state;
6364
+ const readonly = isElementReadonly(element, state, ctx);
6264
6365
  const rawPrefill = ctx.prefill[element.key];
6265
6366
  const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
6266
6367
  const mergesKey = (_d = (_c = element.fieldNames) == null ? void 0 : _c.merges) != null ? _d : "merges";
@@ -6295,11 +6396,13 @@ function renderTableElement(element, ctx, wrapper, pathKey) {
6295
6396
  const cols = rows > 0 ? initialData.cells[0].length : 0;
6296
6397
  const err = validateMerges(initialData.merges, rows, cols);
6297
6398
  if (err) {
6298
- console.warn(`Table "${element.key}": invalid prefill merges stripped (${err})`);
6399
+ console.warn(
6400
+ `Table "${element.key}": invalid prefill merges stripped (${err})`
6401
+ );
6299
6402
  initialData = { ...initialData, merges: [] };
6300
6403
  }
6301
6404
  }
6302
- if (state.config.readonly) {
6405
+ if (readonly) {
6303
6406
  renderReadonlyTable(initialData, wrapper);
6304
6407
  } else {
6305
6408
  renderEditTable(element, initialData, pathKey, ctx, wrapper);
@@ -6995,14 +7098,20 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
6995
7098
  let mentionTooltip = null;
6996
7099
  backdrop.addEventListener("mouseover", (e) => {
6997
7100
  var _a2, _b;
6998
- const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(_a2, "mark");
7101
+ const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(
7102
+ _a2,
7103
+ "mark"
7104
+ );
6999
7105
  if (!(mark == null ? void 0 : mark.dataset.rid)) return;
7000
7106
  mentionTooltip = removePortalTooltip(mentionTooltip);
7001
7107
  mentionTooltip = showMentionTooltip(mark, mark.dataset.rid, state);
7002
7108
  });
7003
7109
  backdrop.addEventListener("mouseout", (e) => {
7004
7110
  var _a2, _b, _c;
7005
- const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(_a2, "mark");
7111
+ const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(
7112
+ _a2,
7113
+ "mark"
7114
+ );
7006
7115
  if (!mark) return;
7007
7116
  const related = e.relatedTarget;
7008
7117
  if ((_c = related == null ? void 0 : related.closest) == null ? void 0 : _c.call(related, "mark")) return;
@@ -7010,7 +7119,10 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
7010
7119
  });
7011
7120
  backdrop.addEventListener("mousedown", (e) => {
7012
7121
  var _a2, _b;
7013
- const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(_a2, "mark");
7122
+ const mark = (_b = (_a2 = e.target).closest) == null ? void 0 : _b.call(
7123
+ _a2,
7124
+ "mark"
7125
+ );
7014
7126
  if (!mark) return;
7015
7127
  mentionTooltip = removePortalTooltip(mentionTooltip);
7016
7128
  const marks = backdrop.querySelectorAll("mark");
@@ -7263,11 +7375,7 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
7263
7375
  textarea.addEventListener("keydown", (e) => {
7264
7376
  if (!dropdownState.open) return;
7265
7377
  const labels = buildFileLabelsFromClosure();
7266
- const filtered = filterFilesForDropdown(
7267
- dropdownState.query,
7268
- files,
7269
- labels
7270
- );
7378
+ const filtered = filterFilesForDropdown(dropdownState.query, files, labels);
7271
7379
  if (e.key === "ArrowDown") {
7272
7380
  e.preventDefault();
7273
7381
  dropdownState.selectedIndex = Math.min(
@@ -7602,6 +7710,7 @@ function renderReadonlyMode(_element, ctx, wrapper, _pathKey, value) {
7602
7710
  function renderRichInputElement(element, ctx, wrapper, pathKey) {
7603
7711
  var _a, _b, _c, _d;
7604
7712
  const state = ctx.state;
7713
+ const readonly = isElementReadonly(element, state, ctx);
7605
7714
  const textKey = (_a = element.textKey) != null ? _a : "text";
7606
7715
  const filesKey = (_b = element.filesKey) != null ? _b : "files";
7607
7716
  let initialValue;
@@ -7639,7 +7748,7 @@ function renderRichInputElement(element, ctx, wrapper, pathKey) {
7639
7748
  });
7640
7749
  }
7641
7750
  }
7642
- if (state.config.readonly) {
7751
+ if (readonly) {
7643
7752
  renderReadonlyMode(element, ctx, wrapper, pathKey, initialValue);
7644
7753
  } else {
7645
7754
  if (!state.config.uploadFile) {
@@ -7702,9 +7811,7 @@ function validateRichInputElement(element, key, context) {
7702
7811
  }
7703
7812
  }
7704
7813
  if (element.maxFiles != null && files.length > element.maxFiles) {
7705
- errors.push(
7706
- `${key}: ${t("maxFiles", state, { max: element.maxFiles })}`
7707
- );
7814
+ errors.push(`${key}: ${t("maxFiles", state, { max: element.maxFiles })}`);
7708
7815
  }
7709
7816
  }
7710
7817
  return { value, errors, spread: !!element.flatOutput };
@@ -7822,9 +7929,7 @@ function shouldDisableElement(element, ctx) {
7822
7929
  return false;
7823
7930
  }
7824
7931
  function extractDOMValue(fieldPath, formRoot) {
7825
- const input = formRoot.querySelector(
7826
- `[name="${fieldPath}"]`
7827
- );
7932
+ const input = formRoot.querySelector(`[name="${fieldPath}"]`);
7828
7933
  if (!input) {
7829
7934
  return void 0;
7830
7935
  }
@@ -7870,9 +7975,7 @@ function reevaluateEnableIf(wrapper, element, ctx) {
7870
7975
  `[data-container-item="${containerKey}[${containerIndex}]"]`
7871
7976
  );
7872
7977
  if (containerItemElement) {
7873
- const inputs = containerItemElement.querySelectorAll(
7874
- "input, select, textarea"
7875
- );
7978
+ const inputs = containerItemElement.querySelectorAll("input, select, textarea");
7876
7979
  inputs.forEach((input) => {
7877
7980
  const fieldName = input.getAttribute("name");
7878
7981
  if (fieldName) {
@@ -7924,7 +8027,10 @@ function reevaluateEnableIf(wrapper, element, ctx) {
7924
8027
  wrapper.setAttribute("data-conditionally-disabled", "true");
7925
8028
  }
7926
8029
  } catch (error) {
7927
- console.error(`Error re-evaluating enableIf for field "${element.key}":`, error);
8030
+ console.error(
8031
+ `Error re-evaluating enableIf for field "${element.key}":`,
8032
+ error
8033
+ );
7928
8034
  }
7929
8035
  }
7930
8036
  function setupEnableIfListeners(wrapper, element, ctx) {
@@ -7946,14 +8052,10 @@ function setupEnableIfListeners(wrapper, element, ctx) {
7946
8052
  } else {
7947
8053
  dependencyFieldPath = dependencyKey;
7948
8054
  }
7949
- const dependencyInput = formRoot.querySelector(
7950
- `[name="${dependencyFieldPath}"]`
7951
- );
8055
+ const dependencyInput = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
7952
8056
  if (!dependencyInput) {
7953
8057
  const observer = new MutationObserver(() => {
7954
- const input = formRoot.querySelector(
7955
- `[name="${dependencyFieldPath}"]`
7956
- );
8058
+ const input = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
7957
8059
  if (input) {
7958
8060
  input.addEventListener("change", () => {
7959
8061
  reevaluateEnableIf(wrapper, element, ctx);
@@ -8100,7 +8202,9 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
8100
8202
  default: {
8101
8203
  const unsupported = document.createElement("div");
8102
8204
  unsupported.className = "text-red-500 text-sm";
8103
- unsupported.textContent = t("unsupportedFieldType", ctx.state, { type: element.type });
8205
+ unsupported.textContent = t("unsupportedFieldType", ctx.state, {
8206
+ type: element.type
8207
+ });
8104
8208
  wrapper.appendChild(unsupported);
8105
8209
  }
8106
8210
  }
@@ -9054,7 +9158,10 @@ var FormBuilderInstance = class {
9054
9158
  );
9055
9159
  if (componentResult !== null) {
9056
9160
  errors.push(...componentResult.errors);
9057
- return { value: componentResult.value, spread: !!componentResult.spread };
9161
+ return {
9162
+ value: componentResult.value,
9163
+ spread: !!componentResult.spread
9164
+ };
9058
9165
  }
9059
9166
  console.warn(`Unknown field type "${element.type}" for key "${key}"`);
9060
9167
  return { value: null, spread: false };
@@ -9064,10 +9171,7 @@ var FormBuilderInstance = class {
9064
9171
  var _a;
9065
9172
  if (element.enableIf) {
9066
9173
  try {
9067
- const shouldEnable = evaluateEnableCondition(
9068
- element.enableIf,
9069
- data
9070
- );
9174
+ const shouldEnable = evaluateEnableCondition(element.enableIf, data);
9071
9175
  if (!shouldEnable) {
9072
9176
  return;
9073
9177
  }
@@ -9364,7 +9468,10 @@ var FormBuilderInstance = class {
9364
9468
  disabledWrapper.className = "fb-field-wrapper-disabled";
9365
9469
  disabledWrapper.style.display = "none";
9366
9470
  disabledWrapper.setAttribute("data-field-key", element.key);
9367
- disabledWrapper.setAttribute("data-conditionally-disabled", "true");
9471
+ disabledWrapper.setAttribute(
9472
+ "data-conditionally-disabled",
9473
+ "true"
9474
+ );
9368
9475
  (_c = wrapper.parentNode) == null ? void 0 : _c.replaceChild(disabledWrapper, wrapper);
9369
9476
  }
9370
9477
  } catch (error) {