@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/browser/formbuilder.min.js +117 -126
- package/dist/browser/{formbuilder.v0.5.0.min.js → formbuilder.v0.5.2.min.js} +117 -126
- package/dist/cjs/index.cjs +117 -232
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +116 -229
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +117 -126
- package/dist/types/components/file/render-edit.d.ts +0 -4
- package/dist/types/types/config.d.ts +6 -3
- package/dist/types/utils/helpers.d.ts +8 -0
- package/package.json +1 -1
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
|
|
3047
|
-
.fb-
|
|
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:
|
|
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
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
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 (
|
|
5079
|
-
const
|
|
5080
|
-
|
|
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.
|
|
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
|
-
|
|
6866
|
-
const
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
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
|
|
6838
|
+
state,
|
|
6872
6839
|
instance: ctx.instance,
|
|
6873
6840
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
6874
|
-
prefill: childDefaults,
|
|
6875
|
-
|
|
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",
|
|
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 =
|
|
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
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
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
|
-
|
|
6978
|
-
|
|
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
|
|
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
|
|
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
|
|
11877
|
+
const containerData = element.key ? getValueByPath(formData, fullPath) : void 0;
|
|
11986
11878
|
if (Array.isArray(containerData)) {
|
|
11987
|
-
const
|
|
11988
|
-
|
|
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);
|