@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.
@@ -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) {
@@ -2294,6 +2310,7 @@ async function renderUploadedFilePreview(container, resourceId, fileName, meta,
2294
2310
  }
2295
2311
  }
2296
2312
  async function renderFilePreview(container, resourceId, state, options = {}) {
2313
+ var _a;
2297
2314
  const { fileName = "", isReadonly = false, deps = null } = options;
2298
2315
  if (!isReadonly && deps && (!deps.picker || !deps.fileUploadHandler || !deps.dragHandler)) {
2299
2316
  throw new Error(
@@ -2323,6 +2340,10 @@ async function renderFilePreview(container, resourceId, state, options = {}) {
2323
2340
  meta,
2324
2341
  state
2325
2342
  );
2343
+ const isVideo = (_a = meta == null ? void 0 : meta.type) == null ? void 0 : _a.startsWith("video/");
2344
+ if (!isReadonly && !isVideo) {
2345
+ renderDeleteButton(container, resourceId, state);
2346
+ }
2326
2347
  }
2327
2348
  }
2328
2349
  async function renderFilePreviewReadonly(resourceId, state, fileName) {
@@ -3033,9 +3054,15 @@ function setupFilesPickerHandler(filesPicker, initialFiles, state, updateCallbac
3033
3054
  function renderFileElement(element, ctx, wrapper, pathKey) {
3034
3055
  var _a, _b;
3035
3056
  const state = ctx.state;
3036
- if (state.config.readonly) {
3037
- 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 : "";
3038
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);
3039
3066
  renderFilePreviewReadonly(initial, state).then((filePreview) => {
3040
3067
  wrapper.appendChild(filePreview);
3041
3068
  }).catch((err) => {
@@ -3124,10 +3151,24 @@ function renderFileElement(element, ctx, wrapper, pathKey) {
3124
3151
  function renderFilesElement(element, ctx, wrapper, pathKey) {
3125
3152
  var _a, _b;
3126
3153
  const state = ctx.state;
3127
- 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);
3128
3170
  const resultsWrapper = document.createElement("div");
3129
3171
  resultsWrapper.className = "space-y-4";
3130
- const initialFiles = ctx.prefill[element.key] || [];
3131
3172
  if (initialFiles.length > 0) {
3132
3173
  initialFiles.forEach((resourceId) => {
3133
3174
  renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
@@ -3158,6 +3199,7 @@ function renderFilesElement(element, ctx, wrapper, pathKey) {
3158
3199
  };
3159
3200
  const filesWrapper = document.createElement("div");
3160
3201
  filesWrapper.className = "space-y-2";
3202
+ filesWrapper.dataset.filesWrapper = pathKey;
3161
3203
  const filesPicker = document.createElement("input");
3162
3204
  filesPicker.type = "file";
3163
3205
  filesPicker.name = pathKey;
@@ -3208,10 +3250,24 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
3208
3250
  const state = ctx.state;
3209
3251
  const minFiles = (_a = element.minCount) != null ? _a : 0;
3210
3252
  const maxFiles = (_b = element.maxCount) != null ? _b : Infinity;
3211
- 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);
3212
3269
  const resultsWrapper = document.createElement("div");
3213
3270
  resultsWrapper.className = "space-y-4";
3214
- const initialFiles = ctx.prefill[element.key] || [];
3215
3271
  if (initialFiles.length > 0) {
3216
3272
  initialFiles.forEach((resourceId) => {
3217
3273
  renderFilePreviewReadonly(resourceId, state).then((filePreview) => {
@@ -3227,6 +3283,7 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
3227
3283
  } else {
3228
3284
  const filesWrapper = document.createElement("div");
3229
3285
  filesWrapper.className = "space-y-2";
3286
+ filesWrapper.dataset.filesWrapper = pathKey;
3230
3287
  const filesPicker = document.createElement("input");
3231
3288
  filesPicker.type = "file";
3232
3289
  filesPicker.name = pathKey;
@@ -3344,10 +3401,9 @@ function validateFileElement(element, key, context) {
3344
3401
  };
3345
3402
  if (isMultipleField) {
3346
3403
  const fullKey = pathJoin(path, key);
3347
- const pickerInput = scopeRoot.querySelector(
3348
- `input[type="file"][name="${fullKey}"]`
3404
+ const filesWrapper = scopeRoot.querySelector(
3405
+ `[data-files-wrapper="${fullKey}"]`
3349
3406
  );
3350
- const filesWrapper = pickerInput == null ? void 0 : pickerInput.closest(".space-y-2");
3351
3407
  const container = (filesWrapper == null ? void 0 : filesWrapper.querySelector(".files-list")) || null;
3352
3408
  const resourceIds = [];
3353
3409
  if (container) {
@@ -3608,15 +3664,16 @@ function createEditColourUI(value, pathKey, ctx) {
3608
3664
  }
3609
3665
  function renderColourElement(element, ctx, wrapper, pathKey) {
3610
3666
  const state = ctx.state;
3667
+ const readonly = isElementReadonly(element, state, ctx);
3611
3668
  const initialValue = ctx.prefill[element.key] || element.default || "#000000";
3612
- if (state.config.readonly) {
3669
+ if (readonly) {
3613
3670
  const readonlyUI = createReadonlyColourUI(initialValue);
3614
3671
  wrapper.appendChild(readonlyUI);
3615
3672
  } else {
3616
3673
  const editUI = createEditColourUI(initialValue, pathKey, ctx);
3617
3674
  wrapper.appendChild(editUI);
3618
3675
  }
3619
- if (!state.config.readonly) {
3676
+ if (!readonly) {
3620
3677
  const colourHint = document.createElement("p");
3621
3678
  colourHint.className = "mt-1";
3622
3679
  colourHint.style.cssText = `
@@ -3630,6 +3687,7 @@ function renderColourElement(element, ctx, wrapper, pathKey) {
3630
3687
  function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3631
3688
  var _a, _b;
3632
3689
  const state = ctx.state;
3690
+ const readonly = isElementReadonly(element, state, ctx);
3633
3691
  const prefillValues = ctx.prefill[element.key] || [];
3634
3692
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
3635
3693
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -3652,7 +3710,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3652
3710
  function addColourItem(value = "#000000", index = -1) {
3653
3711
  const itemWrapper = document.createElement("div");
3654
3712
  itemWrapper.className = "multiple-colour-item flex items-center gap-2";
3655
- if (state.config.readonly) {
3713
+ if (readonly) {
3656
3714
  const readonlyUI = createReadonlyColourUI(value);
3657
3715
  while (readonlyUI.firstChild) {
3658
3716
  itemWrapper.appendChild(readonlyUI.firstChild);
@@ -3672,7 +3730,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3672
3730
  return itemWrapper;
3673
3731
  }
3674
3732
  function updateRemoveButtons() {
3675
- if (state.config.readonly) return;
3733
+ if (readonly) return;
3676
3734
  const items = container.querySelectorAll(".multiple-colour-item");
3677
3735
  const currentCount = items.length;
3678
3736
  items.forEach((item) => {
@@ -3717,7 +3775,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3717
3775
  }
3718
3776
  let addRow = null;
3719
3777
  let countDisplay = null;
3720
- if (!state.config.readonly) {
3778
+ if (!readonly) {
3721
3779
  addRow = document.createElement("div");
3722
3780
  addRow.className = "flex items-center gap-3 mt-2";
3723
3781
  const addBtn = document.createElement("button");
@@ -3764,7 +3822,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
3764
3822
  values.forEach((value) => addColourItem(value));
3765
3823
  updateAddButton();
3766
3824
  updateRemoveButtons();
3767
- if (!state.config.readonly) {
3825
+ if (!readonly) {
3768
3826
  const hint = document.createElement("p");
3769
3827
  hint.className = "mt-1";
3770
3828
  hint.style.cssText = `
@@ -3835,7 +3893,9 @@ function validateColourElement(element, key, context) {
3835
3893
  return normalized;
3836
3894
  };
3837
3895
  if (element.multiple) {
3838
- const hexInputs = scopeRoot.querySelectorAll(`[name^="${key}["].colour-hex-input`);
3896
+ const hexInputs = scopeRoot.querySelectorAll(
3897
+ `[name^="${key}["].colour-hex-input`
3898
+ );
3839
3899
  const values = [];
3840
3900
  hexInputs.forEach((input, index) => {
3841
3901
  var _a2;
@@ -3883,7 +3943,9 @@ function updateColourField(element, fieldPath, value, context) {
3883
3943
  );
3884
3944
  return;
3885
3945
  }
3886
- const hexInputs = scopeRoot.querySelectorAll(`[name^="${fieldPath}["].colour-hex-input`);
3946
+ const hexInputs = scopeRoot.querySelectorAll(
3947
+ `[name^="${fieldPath}["].colour-hex-input`
3948
+ );
3887
3949
  hexInputs.forEach((hexInput, index) => {
3888
3950
  if (index < value.length) {
3889
3951
  const normalized = normalizeColourValue(value[index]);
@@ -4080,6 +4142,7 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
4080
4142
  );
4081
4143
  }
4082
4144
  const state = ctx.state;
4145
+ const readonly = isElementReadonly(element, state, ctx);
4083
4146
  const defaultValue = element.default !== void 0 ? element.default : (element.min + element.max) / 2;
4084
4147
  const initialValue = (_a = ctx.prefill[element.key]) != null ? _a : defaultValue;
4085
4148
  const sliderUI = createSliderUI(
@@ -4087,10 +4150,10 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
4087
4150
  pathKey,
4088
4151
  element,
4089
4152
  ctx,
4090
- state.config.readonly
4153
+ readonly
4091
4154
  );
4092
4155
  wrapper.appendChild(sliderUI);
4093
- if (!state.config.readonly) {
4156
+ if (!readonly) {
4094
4157
  const hint = document.createElement("p");
4095
4158
  hint.className = "mt-1";
4096
4159
  hint.style.cssText = `
@@ -4115,6 +4178,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4115
4178
  );
4116
4179
  }
4117
4180
  const state = ctx.state;
4181
+ const readonly = isElementReadonly(element, state, ctx);
4118
4182
  const prefillValues = ctx.prefill[element.key] || [];
4119
4183
  const values = Array.isArray(prefillValues) ? [...prefillValues] : [];
4120
4184
  const minCount = (_a = element.minCount) != null ? _a : 1;
@@ -4139,13 +4203,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4139
4203
  const itemWrapper = document.createElement("div");
4140
4204
  itemWrapper.className = "multiple-slider-item flex items-start gap-2";
4141
4205
  const tempPathKey = `${pathKey}[${container.children.length}]`;
4142
- const sliderUI = createSliderUI(
4143
- value,
4144
- tempPathKey,
4145
- element,
4146
- ctx,
4147
- state.config.readonly
4148
- );
4206
+ const sliderUI = createSliderUI(value, tempPathKey, element, ctx, readonly);
4149
4207
  sliderUI.style.flex = "1";
4150
4208
  itemWrapper.appendChild(sliderUI);
4151
4209
  if (index === -1) {
@@ -4157,7 +4215,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4157
4215
  return itemWrapper;
4158
4216
  }
4159
4217
  function updateRemoveButtons() {
4160
- if (state.config.readonly) return;
4218
+ if (readonly) return;
4161
4219
  const items = container.querySelectorAll(".multiple-slider-item");
4162
4220
  const currentCount = items.length;
4163
4221
  items.forEach((item) => {
@@ -4203,7 +4261,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4203
4261
  }
4204
4262
  let addRow = null;
4205
4263
  let countDisplay = null;
4206
- if (!state.config.readonly) {
4264
+ if (!readonly) {
4207
4265
  addRow = document.createElement("div");
4208
4266
  addRow.className = "flex items-center gap-3 mt-2";
4209
4267
  const addBtn = document.createElement("button");
@@ -4249,7 +4307,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
4249
4307
  values.forEach((value) => addSliderItem(value));
4250
4308
  updateAddButton();
4251
4309
  updateRemoveButtons();
4252
- if (!state.config.readonly) {
4310
+ if (!readonly) {
4253
4311
  const hint = document.createElement("p");
4254
4312
  hint.className = "mt-1";
4255
4313
  hint.style.cssText = `
@@ -4491,9 +4549,7 @@ function mergeWithDefaults(prefill, defaults) {
4491
4549
  }
4492
4550
  function extractRootFormData(formRoot) {
4493
4551
  const data = {};
4494
- const inputs = formRoot.querySelectorAll(
4495
- "input, select, textarea"
4496
- );
4552
+ const inputs = formRoot.querySelectorAll("input, select, textarea");
4497
4553
  inputs.forEach((input) => {
4498
4554
  const fieldName = input.getAttribute("name");
4499
4555
  if (fieldName && !fieldName.includes("[") && !fieldName.includes(".")) {
@@ -4558,7 +4614,8 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4558
4614
  } else {
4559
4615
  itemsWrap.className = `grid grid-cols-${columns} gap-4`;
4560
4616
  }
4561
- if (!ctx.state.config.readonly) {
4617
+ const containerIsReadonly = isElementReadonly(element, ctx.state, ctx);
4618
+ if (!containerIsReadonly) {
4562
4619
  const hintsElement = createPrefillHints(element, pathKey);
4563
4620
  if (hintsElement) {
4564
4621
  containerWrap.appendChild(hintsElement);
@@ -4573,13 +4630,16 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4573
4630
  // Merged prefill with defaults for enableIf evaluation
4574
4631
  formData: (_b = ctx.formData) != null ? _b : ctx.prefill,
4575
4632
  // Complete root data for enableIf evaluation
4576
- state: ctx.state
4633
+ state: ctx.state,
4634
+ inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
4577
4635
  };
4578
4636
  element.elements.forEach((child) => {
4579
4637
  var _a2, _b2;
4580
4638
  if (child.hidden || child.type === "hidden") {
4581
4639
  const prefillVal = (_b2 = (_a2 = containerPrefill[child.key]) != null ? _a2 : child.default) != null ? _b2 : null;
4582
- itemsWrap.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal));
4640
+ itemsWrap.appendChild(
4641
+ createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
4642
+ );
4583
4643
  } else {
4584
4644
  itemsWrap.appendChild(renderElement(child, subCtx));
4585
4645
  }
@@ -4590,13 +4650,15 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
4590
4650
  function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4591
4651
  var _a, _b, _c, _d;
4592
4652
  const state = ctx.state;
4653
+ const containerIsReadonly = isElementReadonly(element, state, ctx);
4654
+ const childInheritedReadonly = containerIsReadonly || ctx.inheritedReadonly;
4593
4655
  const containerWrap = document.createElement("div");
4594
4656
  containerWrap.className = "border border-gray-200 rounded-lg p-4 bg-gray-50";
4595
4657
  const countDisplay = document.createElement("span");
4596
4658
  countDisplay.className = "text-sm text-gray-500";
4597
4659
  const itemsWrap = document.createElement("div");
4598
4660
  itemsWrap.className = "space-y-4";
4599
- if (!ctx.state.config.readonly) {
4661
+ if (!containerIsReadonly) {
4600
4662
  const hintsElement = createPrefillHints(element, element.key);
4601
4663
  if (hintsElement) {
4602
4664
  containerWrap.appendChild(hintsElement);
@@ -4634,8 +4696,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4634
4696
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4635
4697
  prefill: childDefaults,
4636
4698
  // Defaults for enableIf evaluation
4637
- formData: currentFormData
4699
+ formData: currentFormData,
4638
4700
  // Current root data from DOM for enableIf
4701
+ inheritedReadonly: childInheritedReadonly
4639
4702
  };
4640
4703
  const item = document.createElement("div");
4641
4704
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4650,13 +4713,18 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4650
4713
  element.elements.forEach((child) => {
4651
4714
  var _a2;
4652
4715
  if (child.hidden || child.type === "hidden") {
4653
- 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
+ );
4654
4722
  } else {
4655
4723
  childWrapper.appendChild(renderElement(child, subCtx));
4656
4724
  }
4657
4725
  });
4658
4726
  item.appendChild(childWrapper);
4659
- if (!state.config.readonly) {
4727
+ if (!containerIsReadonly) {
4660
4728
  const rem = document.createElement("button");
4661
4729
  rem.type = "button";
4662
4730
  rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
@@ -4707,8 +4775,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4707
4775
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4708
4776
  prefill: mergedPrefill,
4709
4777
  // Merged prefill with defaults for enableIf
4710
- formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill
4778
+ formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill,
4711
4779
  // Complete root data for enableIf
4780
+ inheritedReadonly: childInheritedReadonly
4712
4781
  };
4713
4782
  const item = document.createElement("div");
4714
4783
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4724,13 +4793,15 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4724
4793
  var _a3, _b2;
4725
4794
  if (child.hidden || child.type === "hidden") {
4726
4795
  const prefillVal = (_b2 = (_a3 = prefillObj == null ? void 0 : prefillObj[child.key]) != null ? _a3 : child.default) != null ? _b2 : null;
4727
- childWrapper.appendChild(createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal));
4796
+ childWrapper.appendChild(
4797
+ createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
4798
+ );
4728
4799
  } else {
4729
4800
  childWrapper.appendChild(renderElement(child, subCtx));
4730
4801
  }
4731
4802
  });
4732
4803
  item.appendChild(childWrapper);
4733
- if (!state.config.readonly) {
4804
+ if (!containerIsReadonly) {
4734
4805
  const rem = document.createElement("button");
4735
4806
  rem.type = "button";
4736
4807
  rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
@@ -4753,7 +4824,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4753
4824
  itemsWrap.appendChild(item);
4754
4825
  });
4755
4826
  }
4756
- if (!state.config.readonly) {
4827
+ if (!containerIsReadonly) {
4757
4828
  while (countItems() < min) {
4758
4829
  const idx = countItems();
4759
4830
  const subCtx = {
@@ -4761,8 +4832,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4761
4832
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
4762
4833
  prefill: childDefaults,
4763
4834
  // Defaults for enableIf evaluation
4764
- formData: (_d = ctx.formData) != null ? _d : ctx.prefill
4835
+ formData: (_d = ctx.formData) != null ? _d : ctx.prefill,
4765
4836
  // Complete root data for enableIf
4837
+ inheritedReadonly: childInheritedReadonly
4766
4838
  };
4767
4839
  const item = document.createElement("div");
4768
4840
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -4777,7 +4849,12 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4777
4849
  element.elements.forEach((child) => {
4778
4850
  var _a2;
4779
4851
  if (child.hidden || child.type === "hidden") {
4780
- 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
+ );
4781
4858
  } else {
4782
4859
  childWrapper.appendChild(renderElement(child, subCtx));
4783
4860
  }
@@ -4809,7 +4886,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
4809
4886
  }
4810
4887
  }
4811
4888
  containerWrap.appendChild(itemsWrap);
4812
- if (!state.config.readonly) {
4889
+ if (!containerIsReadonly) {
4813
4890
  const addRow = document.createElement("div");
4814
4891
  addRow.className = "flex items-center gap-3 mt-2";
4815
4892
  addRow.appendChild(createAddButton());
@@ -4972,8 +5049,10 @@ function updateContainerField(element, fieldPath, value, context) {
4972
5049
  const filesKey = (_b = richChild.filesKey) != null ? _b : "files";
4973
5050
  const containerValue = itemValue;
4974
5051
  const compositeValue = {};
4975
- if (textKey in containerValue) compositeValue[textKey] = containerValue[textKey];
4976
- 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];
4977
5056
  if (Object.keys(compositeValue).length > 0) {
4978
5057
  instance.updateField(childPath, compositeValue);
4979
5058
  }
@@ -5010,8 +5089,10 @@ function updateContainerField(element, fieldPath, value, context) {
5010
5089
  const filesKey = (_b = richChild.filesKey) != null ? _b : "files";
5011
5090
  const containerValue = value;
5012
5091
  const compositeValue = {};
5013
- if (textKey in containerValue) compositeValue[textKey] = containerValue[textKey];
5014
- 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];
5015
5096
  if (Object.keys(compositeValue).length > 0) {
5016
5097
  instance.updateField(childPath, compositeValue);
5017
5098
  }
@@ -5357,12 +5438,21 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5357
5438
  const hiddenInput = document.createElement("input");
5358
5439
  hiddenInput.type = "hidden";
5359
5440
  hiddenInput.name = pathKey;
5360
- hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
5441
+ hiddenInput.value = JSON.stringify({
5442
+ [cellsKey]: cells,
5443
+ [mergesKey]: merges
5444
+ });
5361
5445
  wrapper.appendChild(hiddenInput);
5362
5446
  function persistValue() {
5363
- hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
5447
+ hiddenInput.value = JSON.stringify({
5448
+ [cellsKey]: cells,
5449
+ [mergesKey]: merges
5450
+ });
5364
5451
  if (instance) {
5365
- instance.triggerOnChange(pathKey, { [cellsKey]: cells, [mergesKey]: merges });
5452
+ instance.triggerOnChange(pathKey, {
5453
+ [cellsKey]: cells,
5454
+ [mergesKey]: merges
5455
+ });
5366
5456
  }
5367
5457
  }
5368
5458
  hiddenInput._applyExternalUpdate = (data) => {
@@ -5422,9 +5512,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5422
5512
  rebuild();
5423
5513
  } catch (e) {
5424
5514
  const errMsg = e instanceof Error ? e.message : String(e);
5425
- console.error(
5426
- t("tableImportError", state).replace("{error}", errMsg)
5427
- );
5515
+ console.error(t("tableImportError", state).replace("{error}", errMsg));
5428
5516
  } finally {
5429
5517
  overlay.remove();
5430
5518
  }
@@ -5574,15 +5662,19 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5574
5662
  contextMenu.style.display = "none";
5575
5663
  }
5576
5664
  const menuDismissCtrl = new AbortController();
5577
- document.addEventListener("mousedown", (e) => {
5578
- if (!wrapper.isConnected) {
5579
- menuDismissCtrl.abort();
5580
- return;
5581
- }
5582
- if (!contextMenu.contains(e.target)) {
5583
- hideContextMenu();
5584
- }
5585
- }, { 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
+ );
5586
5678
  function applySelectionStyles() {
5587
5679
  const range = selectionRange(sel);
5588
5680
  const allTds = tableEl.querySelectorAll("td[data-row]");
@@ -5935,7 +6027,9 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5935
6027
  if (!anchor) return;
5936
6028
  const text = (_b3 = (_a3 = e.clipboardData) == null ? void 0 : _a3.getData("text/plain")) != null ? _b3 : "";
5937
6029
  const isMultiCell = text.includes(" ") || text.split(/\r?\n/).filter((l) => l).length > 1;
5938
- const editing = tableEl.querySelector("[contenteditable='true']");
6030
+ const editing = tableEl.querySelector(
6031
+ "[contenteditable='true']"
6032
+ );
5939
6033
  if (editing && !isMultiCell) return;
5940
6034
  e.preventDefault();
5941
6035
  if (editing) {
@@ -6095,7 +6189,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6095
6189
  }
6096
6190
  function updateTopZoneOverlays(mx, wr, tblR, scrollL, active) {
6097
6191
  var _a3;
6098
- 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
+ ) : [];
6099
6197
  let closestColIdx = -1;
6100
6198
  let closestColDist = Infinity;
6101
6199
  let closestBorderX = -1;
@@ -6113,7 +6211,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6113
6211
  if (borderDist < closestBorderDist && borderDist < 20) {
6114
6212
  closestBorderDist = borderDist;
6115
6213
  closestBorderX = cellRect.right - wr.left + scrollL;
6116
- 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
+ );
6117
6218
  }
6118
6219
  }
6119
6220
  colRemoveBtns.forEach((btn, idx) => {
@@ -6169,7 +6270,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6169
6270
  closestRowBorderDist = borderDist;
6170
6271
  closestBorderY = trRect.bottom - wr.top;
6171
6272
  const firstTd = allRowEls[i].querySelector("td[data-row]");
6172
- 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
+ );
6173
6277
  }
6174
6278
  }
6175
6279
  rowRemoveBtns.forEach((btn, idx) => {
@@ -6195,7 +6299,8 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
6195
6299
  let rafPending = false;
6196
6300
  tableWrapper.onmousemove = (e) => {
6197
6301
  const target = e.target;
6198
- if (target.tagName === "BUTTON" && target.parentElement === tableWrapper) return;
6302
+ if (target.tagName === "BUTTON" && target.parentElement === tableWrapper)
6303
+ return;
6199
6304
  if (rafPending) return;
6200
6305
  rafPending = true;
6201
6306
  const mx = e.clientX;
@@ -6256,6 +6361,7 @@ function isTableDataWithFieldNames(v, cellsKey) {
6256
6361
  function renderTableElement(element, ctx, wrapper, pathKey) {
6257
6362
  var _a, _b, _c, _d;
6258
6363
  const state = ctx.state;
6364
+ const readonly = isElementReadonly(element, state, ctx);
6259
6365
  const rawPrefill = ctx.prefill[element.key];
6260
6366
  const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
6261
6367
  const mergesKey = (_d = (_c = element.fieldNames) == null ? void 0 : _c.merges) != null ? _d : "merges";
@@ -6290,11 +6396,13 @@ function renderTableElement(element, ctx, wrapper, pathKey) {
6290
6396
  const cols = rows > 0 ? initialData.cells[0].length : 0;
6291
6397
  const err = validateMerges(initialData.merges, rows, cols);
6292
6398
  if (err) {
6293
- console.warn(`Table "${element.key}": invalid prefill merges stripped (${err})`);
6399
+ console.warn(
6400
+ `Table "${element.key}": invalid prefill merges stripped (${err})`
6401
+ );
6294
6402
  initialData = { ...initialData, merges: [] };
6295
6403
  }
6296
6404
  }
6297
- if (state.config.readonly) {
6405
+ if (readonly) {
6298
6406
  renderReadonlyTable(initialData, wrapper);
6299
6407
  } else {
6300
6408
  renderEditTable(element, initialData, pathKey, ctx, wrapper);
@@ -6990,14 +7098,20 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
6990
7098
  let mentionTooltip = null;
6991
7099
  backdrop.addEventListener("mouseover", (e) => {
6992
7100
  var _a2, _b;
6993
- 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
+ );
6994
7105
  if (!(mark == null ? void 0 : mark.dataset.rid)) return;
6995
7106
  mentionTooltip = removePortalTooltip(mentionTooltip);
6996
7107
  mentionTooltip = showMentionTooltip(mark, mark.dataset.rid, state);
6997
7108
  });
6998
7109
  backdrop.addEventListener("mouseout", (e) => {
6999
7110
  var _a2, _b, _c;
7000
- 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
+ );
7001
7115
  if (!mark) return;
7002
7116
  const related = e.relatedTarget;
7003
7117
  if ((_c = related == null ? void 0 : related.closest) == null ? void 0 : _c.call(related, "mark")) return;
@@ -7005,7 +7119,10 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
7005
7119
  });
7006
7120
  backdrop.addEventListener("mousedown", (e) => {
7007
7121
  var _a2, _b;
7008
- 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
+ );
7009
7126
  if (!mark) return;
7010
7127
  mentionTooltip = removePortalTooltip(mentionTooltip);
7011
7128
  const marks = backdrop.querySelectorAll("mark");
@@ -7258,11 +7375,7 @@ function renderEditMode(element, ctx, wrapper, pathKey, initialValue) {
7258
7375
  textarea.addEventListener("keydown", (e) => {
7259
7376
  if (!dropdownState.open) return;
7260
7377
  const labels = buildFileLabelsFromClosure();
7261
- const filtered = filterFilesForDropdown(
7262
- dropdownState.query,
7263
- files,
7264
- labels
7265
- );
7378
+ const filtered = filterFilesForDropdown(dropdownState.query, files, labels);
7266
7379
  if (e.key === "ArrowDown") {
7267
7380
  e.preventDefault();
7268
7381
  dropdownState.selectedIndex = Math.min(
@@ -7597,6 +7710,7 @@ function renderReadonlyMode(_element, ctx, wrapper, _pathKey, value) {
7597
7710
  function renderRichInputElement(element, ctx, wrapper, pathKey) {
7598
7711
  var _a, _b, _c, _d;
7599
7712
  const state = ctx.state;
7713
+ const readonly = isElementReadonly(element, state, ctx);
7600
7714
  const textKey = (_a = element.textKey) != null ? _a : "text";
7601
7715
  const filesKey = (_b = element.filesKey) != null ? _b : "files";
7602
7716
  let initialValue;
@@ -7634,7 +7748,7 @@ function renderRichInputElement(element, ctx, wrapper, pathKey) {
7634
7748
  });
7635
7749
  }
7636
7750
  }
7637
- if (state.config.readonly) {
7751
+ if (readonly) {
7638
7752
  renderReadonlyMode(element, ctx, wrapper, pathKey, initialValue);
7639
7753
  } else {
7640
7754
  if (!state.config.uploadFile) {
@@ -7697,9 +7811,7 @@ function validateRichInputElement(element, key, context) {
7697
7811
  }
7698
7812
  }
7699
7813
  if (element.maxFiles != null && files.length > element.maxFiles) {
7700
- errors.push(
7701
- `${key}: ${t("maxFiles", state, { max: element.maxFiles })}`
7702
- );
7814
+ errors.push(`${key}: ${t("maxFiles", state, { max: element.maxFiles })}`);
7703
7815
  }
7704
7816
  }
7705
7817
  return { value, errors, spread: !!element.flatOutput };
@@ -7817,9 +7929,7 @@ function shouldDisableElement(element, ctx) {
7817
7929
  return false;
7818
7930
  }
7819
7931
  function extractDOMValue(fieldPath, formRoot) {
7820
- const input = formRoot.querySelector(
7821
- `[name="${fieldPath}"]`
7822
- );
7932
+ const input = formRoot.querySelector(`[name="${fieldPath}"]`);
7823
7933
  if (!input) {
7824
7934
  return void 0;
7825
7935
  }
@@ -7865,9 +7975,7 @@ function reevaluateEnableIf(wrapper, element, ctx) {
7865
7975
  `[data-container-item="${containerKey}[${containerIndex}]"]`
7866
7976
  );
7867
7977
  if (containerItemElement) {
7868
- const inputs = containerItemElement.querySelectorAll(
7869
- "input, select, textarea"
7870
- );
7978
+ const inputs = containerItemElement.querySelectorAll("input, select, textarea");
7871
7979
  inputs.forEach((input) => {
7872
7980
  const fieldName = input.getAttribute("name");
7873
7981
  if (fieldName) {
@@ -7919,7 +8027,10 @@ function reevaluateEnableIf(wrapper, element, ctx) {
7919
8027
  wrapper.setAttribute("data-conditionally-disabled", "true");
7920
8028
  }
7921
8029
  } catch (error) {
7922
- 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
+ );
7923
8034
  }
7924
8035
  }
7925
8036
  function setupEnableIfListeners(wrapper, element, ctx) {
@@ -7941,14 +8052,10 @@ function setupEnableIfListeners(wrapper, element, ctx) {
7941
8052
  } else {
7942
8053
  dependencyFieldPath = dependencyKey;
7943
8054
  }
7944
- const dependencyInput = formRoot.querySelector(
7945
- `[name="${dependencyFieldPath}"]`
7946
- );
8055
+ const dependencyInput = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
7947
8056
  if (!dependencyInput) {
7948
8057
  const observer = new MutationObserver(() => {
7949
- const input = formRoot.querySelector(
7950
- `[name="${dependencyFieldPath}"]`
7951
- );
8058
+ const input = formRoot.querySelector(`[name="${dependencyFieldPath}"]`);
7952
8059
  if (input) {
7953
8060
  input.addEventListener("change", () => {
7954
8061
  reevaluateEnableIf(wrapper, element, ctx);
@@ -8095,7 +8202,9 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
8095
8202
  default: {
8096
8203
  const unsupported = document.createElement("div");
8097
8204
  unsupported.className = "text-red-500 text-sm";
8098
- unsupported.textContent = t("unsupportedFieldType", ctx.state, { type: element.type });
8205
+ unsupported.textContent = t("unsupportedFieldType", ctx.state, {
8206
+ type: element.type
8207
+ });
8099
8208
  wrapper.appendChild(unsupported);
8100
8209
  }
8101
8210
  }
@@ -9049,7 +9158,10 @@ var FormBuilderInstance = class {
9049
9158
  );
9050
9159
  if (componentResult !== null) {
9051
9160
  errors.push(...componentResult.errors);
9052
- return { value: componentResult.value, spread: !!componentResult.spread };
9161
+ return {
9162
+ value: componentResult.value,
9163
+ spread: !!componentResult.spread
9164
+ };
9053
9165
  }
9054
9166
  console.warn(`Unknown field type "${element.type}" for key "${key}"`);
9055
9167
  return { value: null, spread: false };
@@ -9059,10 +9171,7 @@ var FormBuilderInstance = class {
9059
9171
  var _a;
9060
9172
  if (element.enableIf) {
9061
9173
  try {
9062
- const shouldEnable = evaluateEnableCondition(
9063
- element.enableIf,
9064
- data
9065
- );
9174
+ const shouldEnable = evaluateEnableCondition(element.enableIf, data);
9066
9175
  if (!shouldEnable) {
9067
9176
  return;
9068
9177
  }
@@ -9359,7 +9468,10 @@ var FormBuilderInstance = class {
9359
9468
  disabledWrapper.className = "fb-field-wrapper-disabled";
9360
9469
  disabledWrapper.style.display = "none";
9361
9470
  disabledWrapper.setAttribute("data-field-key", element.key);
9362
- disabledWrapper.setAttribute("data-conditionally-disabled", "true");
9471
+ disabledWrapper.setAttribute(
9472
+ "data-conditionally-disabled",
9473
+ "true"
9474
+ );
9363
9475
  (_c = wrapper.parentNode) == null ? void 0 : _c.replaceChild(disabledWrapper, wrapper);
9364
9476
  }
9365
9477
  } catch (error) {