@dmitryvim/form-builder 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -300,6 +300,15 @@ function getElementLookupKey(element, state) {
300
300
  function pathJoin(base, key) {
301
301
  return base ? `${base}.${key}` : key;
302
302
  }
303
+ function findDirectContainerRows(scopeRoot, containerPath) {
304
+ if (!containerPath) return [];
305
+ const all = scopeRoot.querySelectorAll("[data-container-item]");
306
+ return Array.from(all).filter((el) => {
307
+ const attr = el.getAttribute("data-container-item") || "";
308
+ if (!attr.startsWith(`${containerPath}[`)) return false;
309
+ return /^\[\d+\]$/.test(attr.slice(containerPath.length));
310
+ });
311
+ }
303
312
  function clear(node) {
304
313
  while (node.firstChild) node.removeChild(node.firstChild);
305
314
  }
@@ -449,6 +458,19 @@ function ensureThemingHooks(doc) {
449
458
  color: var(--fb-error-color);
450
459
  background-color: var(--fb-background-hover-color);
451
460
  }
461
+ .fb-item-remove:disabled {
462
+ opacity: 0.35;
463
+ cursor: not-allowed;
464
+ }
465
+ /* Cards carrying a row-level remove button reserve a right-hand lane for it
466
+ (24px button + inset + gap) so it never sits on top of the first field's
467
+ control. A class rather than an inline style, so host CSS can override the
468
+ gutter without !important; the compound selector keeps it ahead of the
469
+ card's own p-2 utility regardless of stylesheet order. Its own token, not
470
+ --fb-slide-card-padding, which is slides-only and always resolves. */
471
+ .containerItem.fb-row-removable {
472
+ padding-right: var(--fb-row-remove-gutter, 40px);
473
+ }
452
474
  /* Prefill-suggestion pills rendered by createPrefillHints. Outline pill at rest,
453
475
  soft-fill on hover, solid-fill when selected. All colors flow from the active
454
476
  theme \u2014 consumers don't need to ship their own CSS. */
@@ -3043,34 +3065,12 @@ function ensureFileStyles() {
3043
3065
  padding: 6px;
3044
3066
  }
3045
3067
 
3046
- /* \u2500\u2500\u2500 Meta line below multi grid \u2500\u2500\u2500 */
3047
- .fb-meta-line {
3068
+ /* \u2500\u2500\u2500 Clear-all row below multi grid \u2500\u2500\u2500 */
3069
+ .fb-clear-all-row {
3048
3070
  margin-top: 10px;
3049
3071
  display: flex;
3050
3072
  align-items: center;
3051
- justify-content: space-between;
3052
- gap: 8px;
3053
- flex-wrap: wrap;
3054
- }
3055
- .fb-meta-text {
3056
- font-size: 12px;
3057
- color: #94a3b8;
3058
- display: flex;
3059
- align-items: center;
3060
- gap: 8px;
3061
- flex-wrap: wrap;
3062
- }
3063
- .fb-meta-dot {
3064
- width: 4px;
3065
- height: 4px;
3066
- border-radius: 50%;
3067
- background: #cbd5e1;
3068
- flex-shrink: 0;
3069
- }
3070
- .fb-meta-mono {
3071
- font-family: ui-monospace, 'JetBrains Mono', monospace;
3072
- font-size: 11px;
3073
- letter-spacing: -0.02em;
3073
+ justify-content: flex-end;
3074
3074
  }
3075
3075
  .fb-clear-all-btn {
3076
3076
  font-size: 12px;
@@ -4860,66 +4860,39 @@ function buildPlaceholderTile(isDragOver = false) {
4860
4860
  div.className = `fb-multi-placeholder fb-checker${isDragOver ? " fb-drag-over" : ""}`;
4861
4861
  return div;
4862
4862
  }
4863
- function buildMetaLine(state, element, ridCount, maxCount, canClearAll, onClearAll) {
4864
- const line = document.createElement("div");
4865
- line.className = "fb-meta-line";
4866
- const metaText = document.createElement("div");
4867
- metaText.className = "fb-meta-text";
4868
- if (element.maxSize && element.maxSize !== Infinity) {
4869
- const sizeSpan = document.createElement("span");
4870
- sizeSpan.textContent = t("hintMaxSize", state, { size: element.maxSize });
4871
- metaText.appendChild(sizeSpan);
4872
- metaText.appendChild(buildMetaDot());
4873
- }
4874
- const exts = getAllowedExtensions(
4875
- element.accept
4876
- );
4877
- if (exts.length > 0) {
4878
- const fmtSpan = document.createElement("span");
4879
- fmtSpan.className = "fb-meta-mono";
4880
- fmtSpan.textContent = exts.map((e) => e.toUpperCase()).join(", ");
4881
- metaText.appendChild(fmtSpan);
4882
- metaText.appendChild(buildMetaDot());
4883
- }
4884
- const countSpan = document.createElement("span");
4885
- if (maxCount < Infinity) {
4886
- countSpan.textContent = t("fileCountWithMax", state, {
4887
- count: ridCount,
4888
- max: maxCount
4889
- });
4890
- } else {
4891
- const countKey = ridCount === 1 ? "fileCountSingle" : "fileCountPlural";
4892
- countSpan.textContent = t(countKey, state, { count: ridCount });
4893
- }
4894
- metaText.appendChild(countSpan);
4895
- line.appendChild(metaText);
4896
- if (canClearAll && ridCount > 1) {
4897
- const clearBtn = document.createElement("button");
4898
- clearBtn.type = "button";
4899
- clearBtn.className = "fb-clear-all-btn";
4900
- clearBtn.textContent = t("clearAll", state);
4901
- clearBtn.onclick = (e) => {
4902
- e.stopPropagation();
4903
- if (window.confirm(t("clearAll", state) + "?")) {
4904
- onClearAll();
4905
- }
4906
- };
4907
- line.appendChild(clearBtn);
4908
- }
4909
- return line;
4910
- }
4911
- function buildMetaDot() {
4912
- const dot = document.createElement("span");
4913
- dot.className = "fb-meta-dot";
4914
- return dot;
4863
+ function buildClearAllRow(state, ridCount, onClearAll) {
4864
+ if (ridCount <= 1) return null;
4865
+ const row = document.createElement("div");
4866
+ row.className = "fb-clear-all-row";
4867
+ const clearBtn = document.createElement("button");
4868
+ clearBtn.type = "button";
4869
+ clearBtn.className = "fb-clear-all-btn";
4870
+ clearBtn.textContent = t("clearAll", state);
4871
+ clearBtn.onclick = (e) => {
4872
+ e.stopPropagation();
4873
+ if (window.confirm(t("clearAll", state) + "?")) {
4874
+ onClearAll();
4875
+ }
4876
+ };
4877
+ row.appendChild(clearBtn);
4878
+ return row;
4915
4879
  }
4916
4880
  var gridResizeObservers = /* @__PURE__ */ new WeakMap();
4881
+ var gridMeasureFrames = /* @__PURE__ */ new WeakMap();
4882
+ function cancelPendingMeasure(container) {
4883
+ const frame = gridMeasureFrames.get(container);
4884
+ if (frame !== void 0) {
4885
+ cancelAnimationFrame(frame);
4886
+ gridMeasureFrames.delete(container);
4887
+ }
4888
+ }
4917
4889
  function disposePlaceholdersForUpload(container) {
4918
4890
  const observer = gridResizeObservers.get(container);
4919
4891
  if (observer) {
4920
4892
  observer.disconnect();
4921
4893
  gridResizeObservers.delete(container);
4922
4894
  }
4895
+ cancelPendingMeasure(container);
4923
4896
  container.querySelectorAll(".fb-multi-placeholder").forEach((p) => p.remove());
4924
4897
  }
4925
4898
  function renderResourcePills(opts) {
@@ -4931,7 +4904,6 @@ function renderResourcePills(opts) {
4931
4904
  maxCount,
4932
4905
  isReadonly = false,
4933
4906
  onLibraryPick,
4934
- element,
4935
4907
  onClearAll,
4936
4908
  openPicker: openPickerProp
4937
4909
  } = opts;
@@ -4945,6 +4917,7 @@ function renderResourcePills(opts) {
4945
4917
  previousObserver.disconnect();
4946
4918
  gridResizeObservers.delete(container);
4947
4919
  }
4920
+ cancelPendingMeasure(container);
4948
4921
  while (container.firstChild) container.removeChild(container.firstChild);
4949
4922
  const ridList = rids ?? [];
4950
4923
  const effectiveMax = maxCount ?? Infinity;
@@ -5044,7 +5017,7 @@ function renderResourcePills(opts) {
5044
5017
  if (effectiveMax === Infinity || effectiveMax > occupied) {
5045
5018
  grid.appendChild(buildPlaceholderTile());
5046
5019
  }
5047
- requestAnimationFrame(adjustPlaceholders);
5020
+ gridMeasureFrames.set(container, requestAnimationFrame(adjustPlaceholders));
5048
5021
  if (typeof ResizeObserver !== "undefined") {
5049
5022
  const ro = new ResizeObserver(() => adjustPlaceholders());
5050
5023
  ro.observe(grid);
@@ -5075,17 +5048,9 @@ function renderResourcePills(opts) {
5075
5048
  }
5076
5049
  }
5077
5050
  });
5078
- if (element) {
5079
- const metaLine = buildMetaLine(
5080
- state,
5081
- element,
5082
- ridList.length,
5083
- effectiveMax,
5084
- Boolean(onClearAll),
5085
- onClearAll ?? (() => {
5086
- })
5087
- );
5088
- container.appendChild(metaLine);
5051
+ if (onClearAll) {
5052
+ const row = buildClearAllRow(state, ridList.length, onClearAll);
5053
+ if (row) container.appendChild(row);
5089
5054
  }
5090
5055
  }
5091
5056
  function renderFileElementEdit(element, ctx, wrapper, pathKey) {
@@ -5309,7 +5274,6 @@ function setupMultiFileEditMode(element, ctx, wrapper, pathKey, maxFiles) {
5309
5274
  maxCount: maxFiles < Infinity ? maxFiles : void 0,
5310
5275
  isReadonly: currentlyReadonly,
5311
5276
  onLibraryPick: currentlyReadonly ? null : onLibraryPick,
5312
- element,
5313
5277
  onClearAll: currentlyReadonly ? void 0 : () => {
5314
5278
  for (const rid of initialFiles) {
5315
5279
  releaseLocalFileUrl(state.resourceIndex.get(rid)?.file);
@@ -6827,17 +6791,13 @@ function mountRemoveButton(item, onRemove, state) {
6827
6791
  `;
6828
6792
  rem.innerHTML = BIN_ICON_SVG;
6829
6793
  rem.onclick = onRemove;
6830
- const labelRow = item.querySelector("[data-fb-label-row]");
6831
- if (labelRow) {
6832
- rem.style.marginLeft = "auto";
6833
- labelRow.appendChild(rem);
6834
- return;
6835
- }
6836
6794
  rem.style.position = "absolute";
6837
- rem.style.top = "8px";
6838
- rem.style.right = "8px";
6795
+ rem.style.top = "var(--fb-row-remove-inset, 8px)";
6796
+ rem.style.right = "var(--fb-row-remove-inset, 8px)";
6797
+ rem.style.zIndex = "1";
6839
6798
  item.style.position = "relative";
6840
- item.appendChild(rem);
6799
+ item.classList.add("fb-row-removable");
6800
+ item.insertBefore(rem, item.firstChild);
6841
6801
  }
6842
6802
  function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6843
6803
  const state = ctx.state;
@@ -6862,24 +6822,29 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6862
6822
  const max = element.maxCount ?? Infinity;
6863
6823
  const pre = Array.isArray(ctx.prefill?.[element.key]) ? ctx.prefill[element.key] : null;
6864
6824
  const childDefaults = extractChildDefaults(element.elements);
6865
- const countItems = () => itemsWrap.querySelectorAll(":scope > .containerItem").length;
6866
- const handleAddItem = () => {
6867
- if (countItems() >= max) return;
6868
- const idx = countItems();
6869
- const currentFormData = state.formRoot ? extractRootFormData(state.formRoot) : {};
6825
+ let nextRowIndex = 0;
6826
+ const takeRowIndex = () => nextRowIndex++;
6827
+ const directRows = () => Array.from(itemsWrap.children).filter(
6828
+ (el) => el.classList.contains("containerItem")
6829
+ );
6830
+ const countItems = () => directRows().length;
6831
+ const handleRemoveItem = (item) => {
6832
+ if (countItems() <= min) return;
6833
+ item.remove();
6834
+ updateAddButton();
6835
+ };
6836
+ const createContainerItem = (idx, rowPrefill, formData) => {
6870
6837
  const subCtx = {
6871
- state: ctx.state,
6838
+ state,
6872
6839
  instance: ctx.instance,
6873
6840
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6874
- prefill: childDefaults,
6875
- // Defaults for enableIf evaluation
6876
- formData: currentFormData,
6877
- // Current root data from DOM for enableIf
6841
+ prefill: mergeWithDefaults(rowPrefill ?? {}, childDefaults),
6842
+ formData,
6878
6843
  inheritedReadonly: childInheritedReadonly
6879
6844
  };
6880
6845
  const item = document.createElement("div");
6881
6846
  item.className = "containerItem border border-gray-300 rounded-lg p-2 bg-white";
6882
- item.setAttribute("data-container-item", `${element.key}[${idx}]`);
6847
+ item.setAttribute("data-container-item", subCtx.path);
6883
6848
  if (isSlides) {
6884
6849
  item.setAttribute("data-fb-slide-card", "");
6885
6850
  }
@@ -6889,11 +6854,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6889
6854
  );
6890
6855
  element.elements.forEach((child) => {
6891
6856
  if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
6857
+ const hiddenValue = rowPrefill?.[child.key] ?? ("default" in child ? child.default : null) ?? null;
6892
6858
  childWrapper.appendChild(
6893
- createHiddenInput(
6894
- pathJoin(subCtx.path, child.key),
6895
- ("default" in child ? child.default : null) ?? null
6896
- )
6859
+ createHiddenInput(pathJoin(subCtx.path, child.key), hiddenValue)
6897
6860
  );
6898
6861
  } else {
6899
6862
  childWrapper.appendChild(renderElement(child, subCtx));
@@ -6903,6 +6866,17 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6903
6866
  if (!containerIsReadonly) {
6904
6867
  mountRemoveButton(item, () => handleRemoveItem(item), state);
6905
6868
  }
6869
+ return item;
6870
+ };
6871
+ const handleAddItem = () => {
6872
+ if (countItems() >= max) return;
6873
+ const item = createContainerItem(
6874
+ takeRowIndex(),
6875
+ null,
6876
+ // Current root data read back from the DOM, so enableIf sees what the
6877
+ // user has actually typed rather than the original prefill.
6878
+ state.formRoot ? extractRootFormData(state.formRoot) : {}
6879
+ );
6906
6880
  if (slideAddTile && slideAddTile.parentElement === itemsWrap) {
6907
6881
  itemsWrap.insertBefore(item, slideAddTile);
6908
6882
  } else {
@@ -6915,109 +6889,43 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6915
6889
  let pillAddUpdate = null;
6916
6890
  const syncSlideTileSize = () => {
6917
6891
  if (!slideAddTile) return;
6918
- const firstSlide = itemsWrap.querySelector(
6919
- ":scope > .containerItem"
6920
- );
6892
+ const firstSlide = directRows()[0];
6921
6893
  if (firstSlide && firstSlide.offsetHeight > 0) {
6922
6894
  slideAddTile.style.minHeight = `${firstSlide.offsetHeight}px`;
6923
6895
  }
6924
6896
  };
6897
+ const syncRemoveButtons = () => {
6898
+ const atFloor = countItems() <= min;
6899
+ directRows().forEach((row) => {
6900
+ const btn = Array.from(row.children).find(
6901
+ (el) => el.classList.contains("fb-item-remove")
6902
+ );
6903
+ if (btn) btn.disabled = atFloor;
6904
+ });
6905
+ };
6925
6906
  const updateAddButton = () => {
6926
6907
  const currentCount = countItems();
6927
6908
  if (slideAddUpdate) slideAddUpdate(currentCount, max);
6928
6909
  if (pillAddUpdate) pillAddUpdate(currentCount, max);
6929
6910
  if (slideAddTile) syncSlideTileSize();
6911
+ syncRemoveButtons();
6930
6912
  };
6931
- const handleRemoveItem = (item) => {
6932
- item.remove();
6933
- updateAddButton();
6934
- };
6935
- if (pre && Array.isArray(pre)) {
6936
- pre.forEach((prefillObj, idx) => {
6937
- const mergedPrefill = mergeWithDefaults(prefillObj || {}, childDefaults);
6938
- const subCtx = {
6939
- state: ctx.state,
6940
- instance: ctx.instance,
6941
- path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6942
- prefill: mergedPrefill,
6943
- // Merged prefill with defaults for enableIf
6944
- formData: ctx.formData ?? ctx.prefill,
6945
- // Complete root data for enableIf
6946
- inheritedReadonly: childInheritedReadonly
6947
- };
6948
- const item = document.createElement("div");
6949
- item.className = "containerItem border border-gray-300 rounded-lg p-2 bg-white";
6950
- item.setAttribute("data-container-item", `${element.key}[${idx}]`);
6951
- if (isSlides) {
6952
- item.setAttribute("data-fb-slide-card", "");
6953
- }
6954
- const childWrapper = document.createElement("div");
6955
- childWrapper.className = getChildWrapperClass(
6956
- isSlides ? void 0 : element.columns
6913
+ if (pre) {
6914
+ pre.forEach((prefillObj) => {
6915
+ itemsWrap.appendChild(
6916
+ createContainerItem(
6917
+ takeRowIndex(),
6918
+ prefillObj ?? {},
6919
+ ctx.formData ?? ctx.prefill
6920
+ )
6957
6921
  );
6958
- element.elements.forEach((child) => {
6959
- if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
6960
- const prefillVal = prefillObj?.[child.key] ?? ("default" in child ? child.default : null) ?? null;
6961
- childWrapper.appendChild(
6962
- createHiddenInput(pathJoin(subCtx.path, child.key), prefillVal)
6963
- );
6964
- } else {
6965
- childWrapper.appendChild(renderElement(child, subCtx));
6966
- }
6967
- });
6968
- item.appendChild(childWrapper);
6969
- if (!containerIsReadonly) {
6970
- mountRemoveButton(item, () => handleRemoveItem(item), ctx.state);
6971
- }
6972
- itemsWrap.appendChild(item);
6973
6922
  });
6974
6923
  }
6975
6924
  if (!containerIsReadonly) {
6976
6925
  while (countItems() < min) {
6977
- const idx = countItems();
6978
- const subCtx = {
6979
- state: ctx.state,
6980
- instance: ctx.instance,
6981
- path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6982
- prefill: childDefaults,
6983
- // Defaults for enableIf evaluation
6984
- formData: ctx.formData ?? ctx.prefill,
6985
- // Complete root data for enableIf
6986
- inheritedReadonly: childInheritedReadonly
6987
- };
6988
- const item = document.createElement("div");
6989
- item.className = "containerItem border border-gray-300 rounded-lg p-2 bg-white";
6990
- item.setAttribute("data-container-item", `${element.key}[${idx}]`);
6991
- if (isSlides) {
6992
- item.setAttribute("data-fb-slide-card", "");
6993
- }
6994
- const childWrapper = document.createElement("div");
6995
- childWrapper.className = getChildWrapperClass(
6996
- isSlides ? void 0 : element.columns
6997
- );
6998
- element.elements.forEach((child) => {
6999
- if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
7000
- childWrapper.appendChild(
7001
- createHiddenInput(
7002
- pathJoin(subCtx.path, child.key),
7003
- ("default" in child ? child.default : null) ?? null
7004
- )
7005
- );
7006
- } else {
7007
- childWrapper.appendChild(renderElement(child, subCtx));
7008
- }
7009
- });
7010
- item.appendChild(childWrapper);
7011
- mountRemoveButton(
7012
- item,
7013
- () => {
7014
- if (countItems() > min) {
7015
- handleRemoveItem(item);
7016
- }
7017
- },
7018
- ctx.state
6926
+ itemsWrap.appendChild(
6927
+ createContainerItem(takeRowIndex(), null, ctx.formData ?? ctx.prefill)
7019
6928
  );
7020
- itemsWrap.appendChild(item);
7021
6929
  }
7022
6930
  }
7023
6931
  containerWrap.appendChild(itemsWrap);
@@ -7084,15 +6992,7 @@ function validateContainerElement(element, key, context) {
7084
6992
  };
7085
6993
  if ("multiple" in element && element.multiple) {
7086
6994
  const items = [];
7087
- const allContainerWrappers = scopeRoot.querySelectorAll(
7088
- "[data-container-item]"
7089
- );
7090
- const containerWrappers = Array.from(allContainerWrappers).filter((el) => {
7091
- const attr = el.getAttribute("data-container-item") || "";
7092
- if (!attr.startsWith(`${key}[`)) return false;
7093
- const suffix = attr.slice(key.length);
7094
- return /^\[\d+\]$/.test(suffix);
7095
- });
6995
+ const containerWrappers = findDirectContainerRows(scopeRoot, key);
7096
6996
  containerWrappers.forEach((itemContainer) => {
7097
6997
  const itemData = {};
7098
6998
  const containerAttr = itemContainer.getAttribute("data-container-item") || "";
@@ -7215,9 +7115,7 @@ function updateContainerField(element, fieldPath, value, context) {
7215
7115
  });
7216
7116
  }
7217
7117
  });
7218
- const existingContainers = scopeRoot.querySelectorAll(
7219
- `[data-container-item^="${fieldPath}["]`
7220
- );
7118
+ const existingContainers = findDirectContainerRows(scopeRoot, fieldPath);
7221
7119
  if (value.length !== existingContainers.length) {
7222
7120
  console.warn(
7223
7121
  `updateContainerField: Multiple container field "${fieldPath}" item count mismatch. Consider re-rendering for add/remove.`
@@ -10737,9 +10635,6 @@ var defaultConfig = {
10737
10635
  hintRequired: "Required",
10738
10636
  hintOptional: "Optional",
10739
10637
  hintPattern: "Format: {pattern}",
10740
- fileCountSingle: "{count} file",
10741
- fileCountPlural: "{count} files",
10742
- fileCountWithMax: "{count} / {max} files",
10743
10638
  fileCountRange: "({min}-{max})",
10744
10639
  uploadingFile: "Uploading\u2026",
10745
10640
  filesCounter: "{count}/{max}",
@@ -10813,9 +10708,6 @@ var defaultConfig = {
10813
10708
  hintRequired: "\u041E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435",
10814
10709
  hintOptional: "\u041D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435",
10815
10710
  hintPattern: "\u0424\u043E\u0440\u043C\u0430\u0442: {pattern}",
10816
- fileCountSingle: "{count} \u0444\u0430\u0439\u043B",
10817
- fileCountPlural: "{count} \u0444\u0430\u0439\u043B\u043E\u0432",
10818
- fileCountWithMax: "{count} / {max} \u0444\u0430\u0439\u043B\u043E\u0432",
10819
10711
  fileCountRange: "({min}-{max})",
10820
10712
  uploadingFile: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\u2026",
10821
10713
  filesCounter: "{count}/{max}",
@@ -11982,17 +11874,12 @@ var FormBuilderInstance = class {
11982
11874
  }
11983
11875
  }
11984
11876
  if ((element.type === "container" || element.type === "group") && "elements" in element && element.elements) {
11985
- const containerData = element.key ? formData?.[element.key] : void 0;
11877
+ const containerData = element.key ? getValueByPath(formData, fullPath) : void 0;
11986
11878
  if (Array.isArray(containerData)) {
11987
- const containerItems = this.state.formRoot.querySelectorAll(
11988
- `[data-container-item]`
11879
+ const directItems = findDirectContainerRows(
11880
+ this.state.formRoot,
11881
+ fullPath
11989
11882
  );
11990
- const directItems = fullPath ? Array.from(containerItems).filter((el) => {
11991
- const attr = el.getAttribute("data-container-item") || "";
11992
- if (!attr.startsWith(`${fullPath}[`)) return false;
11993
- const suffix = attr.slice(fullPath.length);
11994
- return /^\[\d+\]$/.test(suffix);
11995
- }) : [];
11996
11883
  directItems.forEach((el) => {
11997
11884
  const attr = el.getAttribute("data-container-item") || "";
11998
11885
  checkElements(element.elements, attr);