@dmitryvim/form-builder 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -40
- package/dist/browser/formbuilder.min.js +71 -53
- package/dist/browser/formbuilder.v0.2.10.min.js +322 -0
- package/dist/cjs/index.cjs +610 -164
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +602 -160
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +71 -53
- package/dist/types/instance/FormBuilderInstance.d.ts +5 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/schema.d.ts +6 -3
- package/dist/types/utils/enable-conditions.d.ts +18 -0
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.2.8.min.js +0 -304
- package/dist/types/utils/display-conditions.d.ts +0 -17
package/dist/cjs/index.cjs
CHANGED
|
@@ -66,6 +66,41 @@ function validateSchema(schema) {
|
|
|
66
66
|
errors.push("Schema missing elements array");
|
|
67
67
|
return errors;
|
|
68
68
|
}
|
|
69
|
+
if ("columns" in schema && schema.columns !== void 0) {
|
|
70
|
+
const columns = schema.columns;
|
|
71
|
+
const validColumns = [1, 2, 3, 4];
|
|
72
|
+
if (!Number.isInteger(columns) || !validColumns.includes(columns)) {
|
|
73
|
+
errors.push(`schema.columns must be 1, 2, 3, or 4 (got ${columns})`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if ("prefillHints" in schema && schema.prefillHints) {
|
|
77
|
+
const prefillHints = schema.prefillHints;
|
|
78
|
+
if (Array.isArray(prefillHints)) {
|
|
79
|
+
prefillHints.forEach((hint, hintIndex) => {
|
|
80
|
+
if (!hint.label || typeof hint.label !== "string") {
|
|
81
|
+
errors.push(
|
|
82
|
+
`schema.prefillHints[${hintIndex}] must have a 'label' property of type string`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (!hint.values || typeof hint.values !== "object") {
|
|
86
|
+
errors.push(
|
|
87
|
+
`schema.prefillHints[${hintIndex}] must have a 'values' property of type object`
|
|
88
|
+
);
|
|
89
|
+
} else {
|
|
90
|
+
for (const fieldKey in hint.values) {
|
|
91
|
+
const fieldExists = schema.elements.some(
|
|
92
|
+
(element) => element.key === fieldKey
|
|
93
|
+
);
|
|
94
|
+
if (!fieldExists) {
|
|
95
|
+
errors.push(
|
|
96
|
+
`schema.prefillHints[${hintIndex}] references non-existent field "${fieldKey}"`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
69
104
|
function validateElements(elements, path) {
|
|
70
105
|
elements.forEach((element, index) => {
|
|
71
106
|
const elementPath = `${path}[${index}]`;
|
|
@@ -75,17 +110,17 @@ function validateSchema(schema) {
|
|
|
75
110
|
if (!element.key) {
|
|
76
111
|
errors.push(`${elementPath}: missing key`);
|
|
77
112
|
}
|
|
78
|
-
if (element.
|
|
79
|
-
const
|
|
80
|
-
if (!
|
|
113
|
+
if (element.enableIf) {
|
|
114
|
+
const enableIf = element.enableIf;
|
|
115
|
+
if (!enableIf.key || typeof enableIf.key !== "string") {
|
|
81
116
|
errors.push(
|
|
82
|
-
`${elementPath}:
|
|
117
|
+
`${elementPath}: enableIf must have a 'key' property of type string`
|
|
83
118
|
);
|
|
84
119
|
}
|
|
85
|
-
const hasOperator = "equals" in
|
|
120
|
+
const hasOperator = "equals" in enableIf;
|
|
86
121
|
if (!hasOperator) {
|
|
87
122
|
errors.push(
|
|
88
|
-
`${elementPath}:
|
|
123
|
+
`${elementPath}: enableIf must have at least one operator (equals, etc.)`
|
|
89
124
|
);
|
|
90
125
|
}
|
|
91
126
|
}
|
|
@@ -163,7 +198,7 @@ function clear(node) {
|
|
|
163
198
|
while (node.firstChild) node.removeChild(node.firstChild);
|
|
164
199
|
}
|
|
165
200
|
|
|
166
|
-
// src/utils/
|
|
201
|
+
// src/utils/enable-conditions.ts
|
|
167
202
|
function getValueByPath(data, path) {
|
|
168
203
|
if (!data || typeof data !== "object") {
|
|
169
204
|
return void 0;
|
|
@@ -189,18 +224,28 @@ function getValueByPath(data, path) {
|
|
|
189
224
|
}
|
|
190
225
|
return current;
|
|
191
226
|
}
|
|
192
|
-
function
|
|
227
|
+
function evaluateEnableCondition(condition, formData, containerData) {
|
|
228
|
+
var _a;
|
|
193
229
|
if (!condition || !condition.key) {
|
|
230
|
+
throw new Error("Invalid enableIf condition: must have a 'key' property");
|
|
231
|
+
}
|
|
232
|
+
const scope = (_a = condition.scope) != null ? _a : "relative";
|
|
233
|
+
let dataSource;
|
|
234
|
+
if (scope === "relative") {
|
|
235
|
+
dataSource = containerData != null ? containerData : formData;
|
|
236
|
+
} else if (scope === "absolute") {
|
|
237
|
+
dataSource = formData;
|
|
238
|
+
} else {
|
|
194
239
|
throw new Error(
|
|
195
|
-
|
|
240
|
+
`Invalid enableIf scope: must be "relative" or "absolute" (got "${scope}")`
|
|
196
241
|
);
|
|
197
242
|
}
|
|
198
|
-
const actualValue = getValueByPath(
|
|
243
|
+
const actualValue = getValueByPath(dataSource, condition.key);
|
|
199
244
|
if ("equals" in condition) {
|
|
200
245
|
return deepEqual(actualValue, condition.equals);
|
|
201
246
|
}
|
|
202
247
|
throw new Error(
|
|
203
|
-
`Invalid
|
|
248
|
+
`Invalid enableIf condition: no recognized operator (equals, etc.)`
|
|
204
249
|
);
|
|
205
250
|
}
|
|
206
251
|
function deepEqual(a, b) {
|
|
@@ -213,7 +258,7 @@ function deepEqual(a, b) {
|
|
|
213
258
|
} catch (e) {
|
|
214
259
|
if (e instanceof TypeError && (e.message.includes("circular") || e.message.includes("cyclic"))) {
|
|
215
260
|
console.warn(
|
|
216
|
-
"deepEqual: Circular reference detected in
|
|
261
|
+
"deepEqual: Circular reference detected in enableIf comparison, using reference equality"
|
|
217
262
|
);
|
|
218
263
|
return a === b;
|
|
219
264
|
}
|
|
@@ -266,7 +311,8 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
266
311
|
}
|
|
267
312
|
if (!state.config.readonly && ctx.instance) {
|
|
268
313
|
const handleChange = () => {
|
|
269
|
-
|
|
314
|
+
const value = textInput.value === "" ? null : textInput.value;
|
|
315
|
+
ctx.instance.triggerOnChange(pathKey, value);
|
|
270
316
|
};
|
|
271
317
|
textInput.addEventListener("blur", handleChange);
|
|
272
318
|
textInput.addEventListener("input", handleChange);
|
|
@@ -345,7 +391,8 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
345
391
|
}
|
|
346
392
|
if (!state.config.readonly && ctx.instance) {
|
|
347
393
|
const handleChange = () => {
|
|
348
|
-
|
|
394
|
+
const value2 = textInput.value === "" ? null : textInput.value;
|
|
395
|
+
ctx.instance.triggerOnChange(textInput.name, value2);
|
|
349
396
|
};
|
|
350
397
|
textInput.addEventListener("blur", handleChange);
|
|
351
398
|
textInput.addEventListener("input", handleChange);
|
|
@@ -417,7 +464,7 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
417
464
|
font-size: var(--fb-font-size);
|
|
418
465
|
transition: all var(--fb-transition-duration);
|
|
419
466
|
`;
|
|
420
|
-
addBtn.textContent =
|
|
467
|
+
addBtn.textContent = "+";
|
|
421
468
|
addBtn.addEventListener("mouseenter", () => {
|
|
422
469
|
addBtn.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
423
470
|
});
|
|
@@ -513,20 +560,20 @@ function validateTextElement(element, key, context) {
|
|
|
513
560
|
}
|
|
514
561
|
};
|
|
515
562
|
if (element.multiple) {
|
|
516
|
-
const inputs = scopeRoot.querySelectorAll(
|
|
517
|
-
`[name^="${key}["]`
|
|
518
|
-
);
|
|
563
|
+
const inputs = scopeRoot.querySelectorAll(`[name^="${key}["]`);
|
|
519
564
|
const values = [];
|
|
565
|
+
const rawValues = [];
|
|
520
566
|
inputs.forEach((input, index) => {
|
|
521
567
|
var _a2;
|
|
522
568
|
const val = (_a2 = input == null ? void 0 : input.value) != null ? _a2 : "";
|
|
523
|
-
|
|
569
|
+
rawValues.push(val);
|
|
570
|
+
values.push(val === "" ? null : val);
|
|
524
571
|
validateTextInput(input, val, `${key}[${index}]`);
|
|
525
572
|
});
|
|
526
573
|
if (!skipValidation) {
|
|
527
574
|
const minCount = (_a = element.minCount) != null ? _a : 1;
|
|
528
575
|
const maxCount = (_b = element.maxCount) != null ? _b : Infinity;
|
|
529
|
-
const filteredValues =
|
|
576
|
+
const filteredValues = rawValues.filter((v) => v.trim() !== "");
|
|
530
577
|
if (element.required && filteredValues.length === 0) {
|
|
531
578
|
errors.push(`${key}: required`);
|
|
532
579
|
}
|
|
@@ -539,17 +586,17 @@ function validateTextElement(element, key, context) {
|
|
|
539
586
|
}
|
|
540
587
|
return { value: values, errors };
|
|
541
588
|
} else {
|
|
542
|
-
const input = scopeRoot.querySelector(
|
|
543
|
-
`[name$="${key}"]`
|
|
544
|
-
);
|
|
589
|
+
const input = scopeRoot.querySelector(`[name$="${key}"]`);
|
|
545
590
|
const val = (_c = input == null ? void 0 : input.value) != null ? _c : "";
|
|
546
591
|
if (!skipValidation && element.required && val === "") {
|
|
547
592
|
errors.push(`${key}: required`);
|
|
548
593
|
markValidity(input, "required");
|
|
549
|
-
return { value:
|
|
594
|
+
return { value: null, errors };
|
|
550
595
|
}
|
|
551
|
-
|
|
552
|
-
|
|
596
|
+
if (input) {
|
|
597
|
+
validateTextInput(input, val, key);
|
|
598
|
+
}
|
|
599
|
+
return { value: val === "" ? null : val, errors };
|
|
553
600
|
}
|
|
554
601
|
}
|
|
555
602
|
function updateTextField(element, fieldPath, value, context) {
|
|
@@ -561,9 +608,7 @@ function updateTextField(element, fieldPath, value, context) {
|
|
|
561
608
|
);
|
|
562
609
|
return;
|
|
563
610
|
}
|
|
564
|
-
const inputs = scopeRoot.querySelectorAll(
|
|
565
|
-
`[name^="${fieldPath}["]`
|
|
566
|
-
);
|
|
611
|
+
const inputs = scopeRoot.querySelectorAll(`[name^="${fieldPath}["]`);
|
|
567
612
|
inputs.forEach((input, index) => {
|
|
568
613
|
if (index < value.length) {
|
|
569
614
|
input.value = value[index] != null ? String(value[index]) : "";
|
|
@@ -577,9 +622,7 @@ function updateTextField(element, fieldPath, value, context) {
|
|
|
577
622
|
);
|
|
578
623
|
}
|
|
579
624
|
} else {
|
|
580
|
-
const input = scopeRoot.querySelector(
|
|
581
|
-
`[name="${fieldPath}"]`
|
|
582
|
-
);
|
|
625
|
+
const input = scopeRoot.querySelector(`[name="${fieldPath}"]`);
|
|
583
626
|
if (input) {
|
|
584
627
|
input.value = value != null ? String(value) : "";
|
|
585
628
|
input.classList.remove("invalid");
|
|
@@ -600,7 +643,8 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
600
643
|
textareaInput.readOnly = state.config.readonly;
|
|
601
644
|
if (!state.config.readonly && ctx.instance) {
|
|
602
645
|
const handleChange = () => {
|
|
603
|
-
|
|
646
|
+
const value = textareaInput.value === "" ? null : textareaInput.value;
|
|
647
|
+
ctx.instance.triggerOnChange(pathKey, value);
|
|
604
648
|
};
|
|
605
649
|
textareaInput.addEventListener("blur", handleChange);
|
|
606
650
|
textareaInput.addEventListener("input", handleChange);
|
|
@@ -644,7 +688,8 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
644
688
|
textareaInput.readOnly = state.config.readonly;
|
|
645
689
|
if (!state.config.readonly && ctx.instance) {
|
|
646
690
|
const handleChange = () => {
|
|
647
|
-
|
|
691
|
+
const value2 = textareaInput.value === "" ? null : textareaInput.value;
|
|
692
|
+
ctx.instance.triggerOnChange(textareaInput.name, value2);
|
|
648
693
|
};
|
|
649
694
|
textareaInput.addEventListener("blur", handleChange);
|
|
650
695
|
textareaInput.addEventListener("input", handleChange);
|
|
@@ -670,7 +715,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
670
715
|
removeBtn = document.createElement("button");
|
|
671
716
|
removeBtn.type = "button";
|
|
672
717
|
removeBtn.className = "remove-item-btn mt-1 px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm";
|
|
673
|
-
removeBtn.innerHTML = "\u2715
|
|
718
|
+
removeBtn.innerHTML = "\u2715";
|
|
674
719
|
removeBtn.onclick = () => {
|
|
675
720
|
const currentIndex = Array.from(container.children).indexOf(
|
|
676
721
|
item
|
|
@@ -698,7 +743,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
698
743
|
const addBtn = document.createElement("button");
|
|
699
744
|
addBtn.type = "button";
|
|
700
745
|
addBtn.className = "add-textarea-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm";
|
|
701
|
-
addBtn.textContent =
|
|
746
|
+
addBtn.textContent = "+";
|
|
702
747
|
addBtn.onclick = () => {
|
|
703
748
|
values.push(element.default || "");
|
|
704
749
|
addTextareaItem(element.default || "");
|
|
@@ -841,7 +886,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
841
886
|
const addBtn = document.createElement("button");
|
|
842
887
|
addBtn.type = "button";
|
|
843
888
|
addBtn.className = "add-number-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm";
|
|
844
|
-
addBtn.textContent =
|
|
889
|
+
addBtn.textContent = "+";
|
|
845
890
|
addBtn.onclick = () => {
|
|
846
891
|
values.push(element.default || "");
|
|
847
892
|
addNumberItem(element.default || "");
|
|
@@ -1127,7 +1172,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1127
1172
|
const addBtn = document.createElement("button");
|
|
1128
1173
|
addBtn.type = "button";
|
|
1129
1174
|
addBtn.className = "add-select-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm";
|
|
1130
|
-
addBtn.textContent =
|
|
1175
|
+
addBtn.textContent = "+";
|
|
1131
1176
|
addBtn.onclick = () => {
|
|
1132
1177
|
var _a2, _b2;
|
|
1133
1178
|
const defaultValue = element.default || ((_b2 = (_a2 = element.options) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.value) || "";
|
|
@@ -1319,7 +1364,9 @@ function renderLocalVideoPreview(container, file, videoType, resourceId, state,
|
|
|
1319
1364
|
return newContainer;
|
|
1320
1365
|
}
|
|
1321
1366
|
function attachVideoButtonHandlers(container, resourceId, state, deps) {
|
|
1322
|
-
const changeBtn = container.querySelector(
|
|
1367
|
+
const changeBtn = container.querySelector(
|
|
1368
|
+
".change-file-btn"
|
|
1369
|
+
);
|
|
1323
1370
|
if (changeBtn) {
|
|
1324
1371
|
changeBtn.onclick = (e) => {
|
|
1325
1372
|
e.stopPropagation();
|
|
@@ -1328,7 +1375,9 @@ function attachVideoButtonHandlers(container, resourceId, state, deps) {
|
|
|
1328
1375
|
}
|
|
1329
1376
|
};
|
|
1330
1377
|
}
|
|
1331
|
-
const deleteBtn = container.querySelector(
|
|
1378
|
+
const deleteBtn = container.querySelector(
|
|
1379
|
+
".delete-file-btn"
|
|
1380
|
+
);
|
|
1332
1381
|
if (deleteBtn) {
|
|
1333
1382
|
deleteBtn.onclick = (e) => {
|
|
1334
1383
|
e.stopPropagation();
|
|
@@ -1370,7 +1419,9 @@ function renderUploadedVideoPreview(container, thumbnailUrl, videoType) {
|
|
|
1370
1419
|
source.src = thumbnailUrl;
|
|
1371
1420
|
source.type = videoType;
|
|
1372
1421
|
video.appendChild(source);
|
|
1373
|
-
video.appendChild(
|
|
1422
|
+
video.appendChild(
|
|
1423
|
+
document.createTextNode("Your browser does not support the video tag.")
|
|
1424
|
+
);
|
|
1374
1425
|
container.appendChild(video);
|
|
1375
1426
|
}
|
|
1376
1427
|
function renderDeleteButton(container, resourceId, state) {
|
|
@@ -1472,7 +1523,13 @@ async function renderFilePreview(container, resourceId, state, options = {}) {
|
|
|
1472
1523
|
deps
|
|
1473
1524
|
);
|
|
1474
1525
|
} else {
|
|
1475
|
-
await renderUploadedFilePreview(
|
|
1526
|
+
await renderUploadedFilePreview(
|
|
1527
|
+
container,
|
|
1528
|
+
resourceId,
|
|
1529
|
+
fileName,
|
|
1530
|
+
meta,
|
|
1531
|
+
state
|
|
1532
|
+
);
|
|
1476
1533
|
}
|
|
1477
1534
|
}
|
|
1478
1535
|
async function renderFilePreviewReadonly(resourceId, state, fileName) {
|
|
@@ -1631,7 +1688,9 @@ function renderResourcePills(container, rids, state, onRemove) {
|
|
|
1631
1688
|
if (fileInput) fileInput.click();
|
|
1632
1689
|
};
|
|
1633
1690
|
textContainer.appendChild(uploadLink);
|
|
1634
|
-
textContainer.appendChild(
|
|
1691
|
+
textContainer.appendChild(
|
|
1692
|
+
document.createTextNode(` ${t("dragDropText", state)}`)
|
|
1693
|
+
);
|
|
1635
1694
|
container.appendChild(gridContainer);
|
|
1636
1695
|
container.appendChild(textContainer);
|
|
1637
1696
|
return;
|
|
@@ -2101,7 +2160,14 @@ function renderFileElement(element, ctx, wrapper, pathKey) {
|
|
|
2101
2160
|
const dragHandler = (files) => {
|
|
2102
2161
|
if (files.length > 0) {
|
|
2103
2162
|
const deps = { picker, fileUploadHandler, dragHandler };
|
|
2104
|
-
handleFileSelect(
|
|
2163
|
+
handleFileSelect(
|
|
2164
|
+
files[0],
|
|
2165
|
+
fileContainer,
|
|
2166
|
+
pathKey,
|
|
2167
|
+
state,
|
|
2168
|
+
deps,
|
|
2169
|
+
ctx.instance
|
|
2170
|
+
);
|
|
2105
2171
|
}
|
|
2106
2172
|
};
|
|
2107
2173
|
if (initial) {
|
|
@@ -2125,7 +2191,14 @@ function renderFileElement(element, ctx, wrapper, pathKey) {
|
|
|
2125
2191
|
picker.onchange = () => {
|
|
2126
2192
|
if (picker.files && picker.files.length > 0) {
|
|
2127
2193
|
const deps = { picker, fileUploadHandler, dragHandler };
|
|
2128
|
-
handleFileSelect(
|
|
2194
|
+
handleFileSelect(
|
|
2195
|
+
picker.files[0],
|
|
2196
|
+
fileContainer,
|
|
2197
|
+
pathKey,
|
|
2198
|
+
state,
|
|
2199
|
+
deps,
|
|
2200
|
+
ctx.instance
|
|
2201
|
+
);
|
|
2129
2202
|
}
|
|
2130
2203
|
};
|
|
2131
2204
|
fileWrapper.appendChild(fileContainer);
|
|
@@ -2191,8 +2264,22 @@ function renderFilesElement(element, ctx, wrapper, pathKey) {
|
|
|
2191
2264
|
const initialFiles = ctx.prefill[element.key] || [];
|
|
2192
2265
|
addPrefillFilesToIndex(initialFiles, state);
|
|
2193
2266
|
updateFilesList2();
|
|
2194
|
-
setupFilesDropHandler(
|
|
2195
|
-
|
|
2267
|
+
setupFilesDropHandler(
|
|
2268
|
+
filesContainer,
|
|
2269
|
+
initialFiles,
|
|
2270
|
+
state,
|
|
2271
|
+
updateFilesList2,
|
|
2272
|
+
pathKey,
|
|
2273
|
+
ctx.instance
|
|
2274
|
+
);
|
|
2275
|
+
setupFilesPickerHandler(
|
|
2276
|
+
filesPicker,
|
|
2277
|
+
initialFiles,
|
|
2278
|
+
state,
|
|
2279
|
+
updateFilesList2,
|
|
2280
|
+
pathKey,
|
|
2281
|
+
ctx.instance
|
|
2282
|
+
);
|
|
2196
2283
|
filesContainer.appendChild(list);
|
|
2197
2284
|
filesWrapper.appendChild(filesContainer);
|
|
2198
2285
|
filesWrapper.appendChild(filesPicker);
|
|
@@ -2255,8 +2342,22 @@ function renderMultipleFileElement(element, ctx, wrapper, pathKey) {
|
|
|
2255
2342
|
if (existingCount) existingCount.remove();
|
|
2256
2343
|
filesWrapper.appendChild(countInfo);
|
|
2257
2344
|
};
|
|
2258
|
-
setupFilesDropHandler(
|
|
2259
|
-
|
|
2345
|
+
setupFilesDropHandler(
|
|
2346
|
+
filesContainer,
|
|
2347
|
+
initialFiles,
|
|
2348
|
+
state,
|
|
2349
|
+
updateFilesDisplay,
|
|
2350
|
+
pathKey,
|
|
2351
|
+
ctx.instance
|
|
2352
|
+
);
|
|
2353
|
+
setupFilesPickerHandler(
|
|
2354
|
+
filesPicker,
|
|
2355
|
+
initialFiles,
|
|
2356
|
+
state,
|
|
2357
|
+
updateFilesDisplay,
|
|
2358
|
+
pathKey,
|
|
2359
|
+
ctx.instance
|
|
2360
|
+
);
|
|
2260
2361
|
updateFilesDisplay();
|
|
2261
2362
|
wrapper.appendChild(filesWrapper);
|
|
2262
2363
|
}
|
|
@@ -2660,7 +2761,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
2660
2761
|
font-size: var(--fb-font-size);
|
|
2661
2762
|
transition: all var(--fb-transition-duration);
|
|
2662
2763
|
`;
|
|
2663
|
-
addBtn.textContent =
|
|
2764
|
+
addBtn.textContent = "+";
|
|
2664
2765
|
addBtn.addEventListener("mouseenter", () => {
|
|
2665
2766
|
addBtn.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
2666
2767
|
});
|
|
@@ -2746,9 +2847,7 @@ function validateColourElement(element, key, context) {
|
|
|
2746
2847
|
return normalized;
|
|
2747
2848
|
};
|
|
2748
2849
|
if (element.multiple) {
|
|
2749
|
-
const hexInputs = scopeRoot.querySelectorAll(
|
|
2750
|
-
`.colour-hex-input`
|
|
2751
|
-
);
|
|
2850
|
+
const hexInputs = scopeRoot.querySelectorAll(`[name^="${key}["].colour-hex-input`);
|
|
2752
2851
|
const values = [];
|
|
2753
2852
|
hexInputs.forEach((input, index) => {
|
|
2754
2853
|
var _a2;
|
|
@@ -2794,9 +2893,7 @@ function updateColourField(element, fieldPath, value, context) {
|
|
|
2794
2893
|
);
|
|
2795
2894
|
return;
|
|
2796
2895
|
}
|
|
2797
|
-
const hexInputs = scopeRoot.querySelectorAll(
|
|
2798
|
-
`.colour-hex-input`
|
|
2799
|
-
);
|
|
2896
|
+
const hexInputs = scopeRoot.querySelectorAll(`[name^="${fieldPath}["].colour-hex-input`);
|
|
2800
2897
|
hexInputs.forEach((hexInput, index) => {
|
|
2801
2898
|
if (index < value.length) {
|
|
2802
2899
|
const normalized = normalizeColourValue(value[index]);
|
|
@@ -2806,7 +2903,9 @@ function updateColourField(element, fieldPath, value, context) {
|
|
|
2806
2903
|
const wrapper = hexInput.closest(".colour-picker-wrapper");
|
|
2807
2904
|
if (wrapper) {
|
|
2808
2905
|
const swatch = wrapper.querySelector(".colour-swatch");
|
|
2809
|
-
const colourInput = wrapper.querySelector(
|
|
2906
|
+
const colourInput = wrapper.querySelector(
|
|
2907
|
+
".colour-picker-hidden"
|
|
2908
|
+
);
|
|
2810
2909
|
if (swatch) {
|
|
2811
2910
|
swatch.style.backgroundColor = normalized;
|
|
2812
2911
|
}
|
|
@@ -2833,7 +2932,9 @@ function updateColourField(element, fieldPath, value, context) {
|
|
|
2833
2932
|
const wrapper = hexInput.closest(".colour-picker-wrapper");
|
|
2834
2933
|
if (wrapper) {
|
|
2835
2934
|
const swatch = wrapper.querySelector(".colour-swatch");
|
|
2836
|
-
const colourInput = wrapper.querySelector(
|
|
2935
|
+
const colourInput = wrapper.querySelector(
|
|
2936
|
+
".colour-picker-hidden"
|
|
2937
|
+
);
|
|
2837
2938
|
if (swatch) {
|
|
2838
2939
|
swatch.style.backgroundColor = normalized;
|
|
2839
2940
|
}
|
|
@@ -2973,14 +3074,10 @@ function createSliderUI(value, pathKey, element, ctx, readonly) {
|
|
|
2973
3074
|
function renderSliderElement(element, ctx, wrapper, pathKey) {
|
|
2974
3075
|
var _a;
|
|
2975
3076
|
if (element.min === void 0 || element.min === null) {
|
|
2976
|
-
throw new Error(
|
|
2977
|
-
`Slider field "${element.key}" requires "min" property`
|
|
2978
|
-
);
|
|
3077
|
+
throw new Error(`Slider field "${element.key}" requires "min" property`);
|
|
2979
3078
|
}
|
|
2980
3079
|
if (element.max === void 0 || element.max === null) {
|
|
2981
|
-
throw new Error(
|
|
2982
|
-
`Slider field "${element.key}" requires "max" property`
|
|
2983
|
-
);
|
|
3080
|
+
throw new Error(`Slider field "${element.key}" requires "max" property`);
|
|
2984
3081
|
}
|
|
2985
3082
|
if (element.min >= element.max) {
|
|
2986
3083
|
throw new Error(
|
|
@@ -3010,14 +3107,10 @@ function renderSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
3010
3107
|
function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
3011
3108
|
var _a, _b;
|
|
3012
3109
|
if (element.min === void 0 || element.min === null) {
|
|
3013
|
-
throw new Error(
|
|
3014
|
-
`Slider field "${element.key}" requires "min" property`
|
|
3015
|
-
);
|
|
3110
|
+
throw new Error(`Slider field "${element.key}" requires "min" property`);
|
|
3016
3111
|
}
|
|
3017
3112
|
if (element.max === void 0 || element.max === null) {
|
|
3018
|
-
throw new Error(
|
|
3019
|
-
`Slider field "${element.key}" requires "max" property`
|
|
3020
|
-
);
|
|
3113
|
+
throw new Error(`Slider field "${element.key}" requires "max" property`);
|
|
3021
3114
|
}
|
|
3022
3115
|
if (element.min >= element.max) {
|
|
3023
3116
|
throw new Error(
|
|
@@ -3125,7 +3218,7 @@ function renderMultipleSliderElement(element, ctx, wrapper, pathKey) {
|
|
|
3125
3218
|
font-size: var(--fb-font-size);
|
|
3126
3219
|
transition: all var(--fb-transition-duration);
|
|
3127
3220
|
`;
|
|
3128
|
-
addBtn.textContent =
|
|
3221
|
+
addBtn.textContent = "+";
|
|
3129
3222
|
addBtn.addEventListener("mouseenter", () => {
|
|
3130
3223
|
addBtn.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
3131
3224
|
});
|
|
@@ -3190,7 +3283,10 @@ function validateSliderElement(element, key, context) {
|
|
|
3190
3283
|
`;
|
|
3191
3284
|
const sliderContainer = input.closest(".slider-container");
|
|
3192
3285
|
if (sliderContainer && sliderContainer.nextSibling) {
|
|
3193
|
-
(_a2 = sliderContainer.parentNode) == null ? void 0 : _a2.insertBefore(
|
|
3286
|
+
(_a2 = sliderContainer.parentNode) == null ? void 0 : _a2.insertBefore(
|
|
3287
|
+
errorElement,
|
|
3288
|
+
sliderContainer.nextSibling
|
|
3289
|
+
);
|
|
3194
3290
|
} else if (sliderContainer) {
|
|
3195
3291
|
(_b2 = sliderContainer.parentNode) == null ? void 0 : _b2.appendChild(errorElement);
|
|
3196
3292
|
}
|
|
@@ -3362,6 +3458,33 @@ function updateSliderField(element, fieldPath, value, context) {
|
|
|
3362
3458
|
}
|
|
3363
3459
|
|
|
3364
3460
|
// src/components/container.ts
|
|
3461
|
+
function extractRootFormData(formRoot) {
|
|
3462
|
+
const data = {};
|
|
3463
|
+
const inputs = formRoot.querySelectorAll(
|
|
3464
|
+
"input, select, textarea"
|
|
3465
|
+
);
|
|
3466
|
+
inputs.forEach((input) => {
|
|
3467
|
+
const fieldName = input.getAttribute("name");
|
|
3468
|
+
if (fieldName && !fieldName.includes("[") && !fieldName.includes(".")) {
|
|
3469
|
+
if (input instanceof HTMLSelectElement) {
|
|
3470
|
+
data[fieldName] = input.value;
|
|
3471
|
+
} else if (input instanceof HTMLInputElement) {
|
|
3472
|
+
if (input.type === "checkbox") {
|
|
3473
|
+
data[fieldName] = input.checked;
|
|
3474
|
+
} else if (input.type === "radio") {
|
|
3475
|
+
if (input.checked) {
|
|
3476
|
+
data[fieldName] = input.value;
|
|
3477
|
+
}
|
|
3478
|
+
} else {
|
|
3479
|
+
data[fieldName] = input.value;
|
|
3480
|
+
}
|
|
3481
|
+
} else if (input instanceof HTMLTextAreaElement) {
|
|
3482
|
+
data[fieldName] = input.value;
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
});
|
|
3486
|
+
return data;
|
|
3487
|
+
}
|
|
3365
3488
|
var renderElementFunc = null;
|
|
3366
3489
|
function setRenderElement(fn) {
|
|
3367
3490
|
renderElementFunc = fn;
|
|
@@ -3421,7 +3544,7 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
3421
3544
|
prefill: ((_a = ctx.prefill) == null ? void 0 : _a[element.key]) || {},
|
|
3422
3545
|
// Sliced data for value population
|
|
3423
3546
|
formData: (_b = ctx.formData) != null ? _b : ctx.prefill,
|
|
3424
|
-
// Complete root data for
|
|
3547
|
+
// Complete root data for enableIf evaluation
|
|
3425
3548
|
state: ctx.state
|
|
3426
3549
|
};
|
|
3427
3550
|
element.elements.forEach((child) => {
|
|
@@ -3442,15 +3565,10 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3442
3565
|
header.className = "flex justify-between items-center mb-4";
|
|
3443
3566
|
const left = document.createElement("div");
|
|
3444
3567
|
left.className = "flex-1";
|
|
3445
|
-
const right = document.createElement("div");
|
|
3446
|
-
right.className = "flex gap-2";
|
|
3447
3568
|
const itemsWrap = document.createElement("div");
|
|
3448
3569
|
itemsWrap.className = "space-y-4";
|
|
3449
3570
|
containerWrap.appendChild(header);
|
|
3450
3571
|
header.appendChild(left);
|
|
3451
|
-
if (!state.config.readonly) {
|
|
3452
|
-
header.appendChild(right);
|
|
3453
|
-
}
|
|
3454
3572
|
if (!ctx.state.config.readonly) {
|
|
3455
3573
|
const hintsElement = createPrefillHints(element, element.key);
|
|
3456
3574
|
if (hintsElement) {
|
|
@@ -3464,18 +3582,31 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3464
3582
|
const createAddButton = () => {
|
|
3465
3583
|
const add = document.createElement("button");
|
|
3466
3584
|
add.type = "button";
|
|
3467
|
-
add.className = "
|
|
3468
|
-
add.
|
|
3585
|
+
add.className = "add-container-btn mt-2 px-3 py-1 rounded";
|
|
3586
|
+
add.style.cssText = `
|
|
3587
|
+
color: var(--fb-primary-color);
|
|
3588
|
+
border: var(--fb-border-width) solid var(--fb-primary-color);
|
|
3589
|
+
background-color: transparent;
|
|
3590
|
+
font-size: var(--fb-font-size);
|
|
3591
|
+
transition: all var(--fb-transition-duration);
|
|
3592
|
+
`;
|
|
3593
|
+
add.textContent = "+";
|
|
3594
|
+
add.addEventListener("mouseenter", () => {
|
|
3595
|
+
add.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
3596
|
+
});
|
|
3597
|
+
add.addEventListener("mouseleave", () => {
|
|
3598
|
+
add.style.backgroundColor = "transparent";
|
|
3599
|
+
});
|
|
3469
3600
|
add.onclick = () => {
|
|
3470
|
-
var _a2;
|
|
3471
3601
|
if (countItems() < max) {
|
|
3472
3602
|
const idx = countItems();
|
|
3603
|
+
const currentFormData = state.formRoot ? extractRootFormData(state.formRoot) : {};
|
|
3473
3604
|
const subCtx = {
|
|
3474
3605
|
state: ctx.state,
|
|
3475
3606
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
3476
3607
|
prefill: {},
|
|
3477
|
-
formData:
|
|
3478
|
-
//
|
|
3608
|
+
formData: currentFormData
|
|
3609
|
+
// Current root data from DOM for enableIf
|
|
3479
3610
|
};
|
|
3480
3611
|
const item = document.createElement("div");
|
|
3481
3612
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -3496,8 +3627,19 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3496
3627
|
if (!state.config.readonly) {
|
|
3497
3628
|
const rem = document.createElement("button");
|
|
3498
3629
|
rem.type = "button";
|
|
3499
|
-
rem.className = "absolute top-2 right-2
|
|
3500
|
-
rem.
|
|
3630
|
+
rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
|
|
3631
|
+
rem.style.cssText = `
|
|
3632
|
+
color: var(--fb-error-color);
|
|
3633
|
+
background-color: transparent;
|
|
3634
|
+
transition: background-color var(--fb-transition-duration);
|
|
3635
|
+
`;
|
|
3636
|
+
rem.textContent = "\u2715";
|
|
3637
|
+
rem.addEventListener("mouseenter", () => {
|
|
3638
|
+
rem.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
3639
|
+
});
|
|
3640
|
+
rem.addEventListener("mouseleave", () => {
|
|
3641
|
+
rem.style.backgroundColor = "transparent";
|
|
3642
|
+
});
|
|
3501
3643
|
rem.onclick = () => {
|
|
3502
3644
|
item.remove();
|
|
3503
3645
|
updateAddButton();
|
|
@@ -3513,16 +3655,16 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3513
3655
|
};
|
|
3514
3656
|
const updateAddButton = () => {
|
|
3515
3657
|
const currentCount = countItems();
|
|
3516
|
-
const
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3658
|
+
const existingAddBtn = containerWrap.querySelector(
|
|
3659
|
+
".add-container-btn"
|
|
3660
|
+
);
|
|
3661
|
+
if (existingAddBtn) {
|
|
3662
|
+
existingAddBtn.disabled = currentCount >= max;
|
|
3663
|
+
existingAddBtn.style.opacity = currentCount >= max ? "0.5" : "1";
|
|
3664
|
+
existingAddBtn.style.pointerEvents = currentCount >= max ? "none" : "auto";
|
|
3520
3665
|
}
|
|
3521
3666
|
left.innerHTML = `<span>${element.label || element.key}</span> <span class="text-sm text-gray-500">(${currentCount}/${max === Infinity ? "\u221E" : max})</span>`;
|
|
3522
3667
|
};
|
|
3523
|
-
if (!state.config.readonly) {
|
|
3524
|
-
right.appendChild(createAddButton());
|
|
3525
|
-
}
|
|
3526
3668
|
if (pre && Array.isArray(pre)) {
|
|
3527
3669
|
pre.forEach((prefillObj, idx) => {
|
|
3528
3670
|
var _a2;
|
|
@@ -3531,7 +3673,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3531
3673
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
3532
3674
|
prefill: prefillObj || {},
|
|
3533
3675
|
formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill
|
|
3534
|
-
// Complete root data for
|
|
3676
|
+
// Complete root data for enableIf
|
|
3535
3677
|
};
|
|
3536
3678
|
const item = document.createElement("div");
|
|
3537
3679
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -3552,8 +3694,19 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3552
3694
|
if (!state.config.readonly) {
|
|
3553
3695
|
const rem = document.createElement("button");
|
|
3554
3696
|
rem.type = "button";
|
|
3555
|
-
rem.className = "absolute top-2 right-2
|
|
3556
|
-
rem.
|
|
3697
|
+
rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
|
|
3698
|
+
rem.style.cssText = `
|
|
3699
|
+
color: var(--fb-error-color);
|
|
3700
|
+
background-color: transparent;
|
|
3701
|
+
transition: background-color var(--fb-transition-duration);
|
|
3702
|
+
`;
|
|
3703
|
+
rem.textContent = "\u2715";
|
|
3704
|
+
rem.addEventListener("mouseenter", () => {
|
|
3705
|
+
rem.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
3706
|
+
});
|
|
3707
|
+
rem.addEventListener("mouseleave", () => {
|
|
3708
|
+
rem.style.backgroundColor = "transparent";
|
|
3709
|
+
});
|
|
3557
3710
|
rem.onclick = () => {
|
|
3558
3711
|
item.remove();
|
|
3559
3712
|
updateAddButton();
|
|
@@ -3572,7 +3725,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3572
3725
|
path: pathJoin(ctx.path, `${element.key}[${idx}]`),
|
|
3573
3726
|
prefill: {},
|
|
3574
3727
|
formData: (_d = ctx.formData) != null ? _d : ctx.prefill
|
|
3575
|
-
// Complete root data for
|
|
3728
|
+
// Complete root data for enableIf
|
|
3576
3729
|
};
|
|
3577
3730
|
const item = document.createElement("div");
|
|
3578
3731
|
item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
|
|
@@ -3592,8 +3745,19 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3592
3745
|
item.appendChild(childWrapper);
|
|
3593
3746
|
const rem = document.createElement("button");
|
|
3594
3747
|
rem.type = "button";
|
|
3595
|
-
rem.className = "absolute top-2 right-2
|
|
3596
|
-
rem.
|
|
3748
|
+
rem.className = "absolute top-2 right-2 px-2 py-1 rounded";
|
|
3749
|
+
rem.style.cssText = `
|
|
3750
|
+
color: var(--fb-error-color);
|
|
3751
|
+
background-color: transparent;
|
|
3752
|
+
transition: background-color var(--fb-transition-duration);
|
|
3753
|
+
`;
|
|
3754
|
+
rem.textContent = "\u2715";
|
|
3755
|
+
rem.addEventListener("mouseenter", () => {
|
|
3756
|
+
rem.style.backgroundColor = "var(--fb-background-hover-color)";
|
|
3757
|
+
});
|
|
3758
|
+
rem.addEventListener("mouseleave", () => {
|
|
3759
|
+
rem.style.backgroundColor = "transparent";
|
|
3760
|
+
});
|
|
3597
3761
|
rem.onclick = () => {
|
|
3598
3762
|
if (countItems() > min) {
|
|
3599
3763
|
item.remove();
|
|
@@ -3606,6 +3770,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
3606
3770
|
}
|
|
3607
3771
|
}
|
|
3608
3772
|
containerWrap.appendChild(itemsWrap);
|
|
3773
|
+
if (!state.config.readonly) {
|
|
3774
|
+
containerWrap.appendChild(createAddButton());
|
|
3775
|
+
}
|
|
3609
3776
|
updateAddButton();
|
|
3610
3777
|
wrapper.appendChild(containerWrap);
|
|
3611
3778
|
}
|
|
@@ -3658,6 +3825,27 @@ function validateContainerElement(element, key, context) {
|
|
|
3658
3825
|
`[data-container-item="${key}[${i}]"]`
|
|
3659
3826
|
) || scopeRoot;
|
|
3660
3827
|
element.elements.forEach((child) => {
|
|
3828
|
+
var _a;
|
|
3829
|
+
if (child.enableIf) {
|
|
3830
|
+
try {
|
|
3831
|
+
const rootFormData = ((_a = context.instance) == null ? void 0 : _a.getState().formRoot) ? extractRootFormData(context.instance.getState().formRoot) : {};
|
|
3832
|
+
const shouldEnable = evaluateEnableCondition(
|
|
3833
|
+
child.enableIf,
|
|
3834
|
+
rootFormData,
|
|
3835
|
+
// Root form data for absolute scope
|
|
3836
|
+
itemData
|
|
3837
|
+
// Container data for relative scope
|
|
3838
|
+
);
|
|
3839
|
+
if (!shouldEnable) {
|
|
3840
|
+
return;
|
|
3841
|
+
}
|
|
3842
|
+
} catch (error) {
|
|
3843
|
+
console.error(
|
|
3844
|
+
`Error evaluating enableIf for field "${child.key}" in container "${key}[${i}]":`,
|
|
3845
|
+
error
|
|
3846
|
+
);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3661
3849
|
if (child.hidden || child.type === "hidden") {
|
|
3662
3850
|
itemData[child.key] = child.default !== void 0 ? child.default : null;
|
|
3663
3851
|
} else {
|
|
@@ -3677,6 +3865,27 @@ function validateContainerElement(element, key, context) {
|
|
|
3677
3865
|
const containerData = {};
|
|
3678
3866
|
const containerContainer = scopeRoot.querySelector(`[data-container="${key}"]`) || scopeRoot;
|
|
3679
3867
|
element.elements.forEach((child) => {
|
|
3868
|
+
var _a;
|
|
3869
|
+
if (child.enableIf) {
|
|
3870
|
+
try {
|
|
3871
|
+
const rootFormData = ((_a = context.instance) == null ? void 0 : _a.getState().formRoot) ? extractRootFormData(context.instance.getState().formRoot) : {};
|
|
3872
|
+
const shouldEnable = evaluateEnableCondition(
|
|
3873
|
+
child.enableIf,
|
|
3874
|
+
rootFormData,
|
|
3875
|
+
// Root form data for absolute scope
|
|
3876
|
+
containerData
|
|
3877
|
+
// Container data for relative scope
|
|
3878
|
+
);
|
|
3879
|
+
if (!shouldEnable) {
|
|
3880
|
+
return;
|
|
3881
|
+
}
|
|
3882
|
+
} catch (error) {
|
|
3883
|
+
console.error(
|
|
3884
|
+
`Error evaluating enableIf for field "${child.key}" in container "${key}":`,
|
|
3885
|
+
error
|
|
3886
|
+
);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3680
3889
|
if (child.hidden || child.type === "hidden") {
|
|
3681
3890
|
containerData[child.key] = child.default !== void 0 ? child.default : null;
|
|
3682
3891
|
} else {
|
|
@@ -3863,32 +4072,183 @@ if (typeof document !== "undefined") {
|
|
|
3863
4072
|
}
|
|
3864
4073
|
});
|
|
3865
4074
|
}
|
|
3866
|
-
function
|
|
3867
|
-
var _a;
|
|
3868
|
-
if (!element.
|
|
3869
|
-
return
|
|
4075
|
+
function shouldDisableElement(element, ctx) {
|
|
4076
|
+
var _a, _b;
|
|
4077
|
+
if (!element.enableIf) {
|
|
4078
|
+
return false;
|
|
3870
4079
|
}
|
|
3871
4080
|
try {
|
|
3872
|
-
const
|
|
3873
|
-
const
|
|
3874
|
-
|
|
3875
|
-
|
|
4081
|
+
const rootFormData = (_b = (_a = ctx.formData) != null ? _a : ctx.prefill) != null ? _b : {};
|
|
4082
|
+
const containerData = ctx.path ? getValueByPath(rootFormData, ctx.path) : void 0;
|
|
4083
|
+
const shouldEnable = evaluateEnableCondition(
|
|
4084
|
+
element.enableIf,
|
|
4085
|
+
rootFormData,
|
|
4086
|
+
containerData
|
|
3876
4087
|
);
|
|
3877
|
-
|
|
3878
|
-
const hiddenWrapper = document.createElement("div");
|
|
3879
|
-
hiddenWrapper.className = "fb-field-wrapper-hidden";
|
|
3880
|
-
hiddenWrapper.style.display = "none";
|
|
3881
|
-
hiddenWrapper.setAttribute("data-field-key", element.key);
|
|
3882
|
-
hiddenWrapper.setAttribute("data-conditionally-hidden", "true");
|
|
3883
|
-
return hiddenWrapper;
|
|
3884
|
-
}
|
|
4088
|
+
return !shouldEnable;
|
|
3885
4089
|
} catch (error) {
|
|
3886
4090
|
console.error(
|
|
3887
|
-
`Error evaluating
|
|
4091
|
+
`Error evaluating enableIf for field "${element.key}":`,
|
|
3888
4092
|
error
|
|
3889
4093
|
);
|
|
3890
4094
|
}
|
|
3891
|
-
return
|
|
4095
|
+
return false;
|
|
4096
|
+
}
|
|
4097
|
+
function extractDOMValue(fieldPath, formRoot) {
|
|
4098
|
+
const input = formRoot.querySelector(
|
|
4099
|
+
`[name="${fieldPath}"]`
|
|
4100
|
+
);
|
|
4101
|
+
if (!input) {
|
|
4102
|
+
return void 0;
|
|
4103
|
+
}
|
|
4104
|
+
if (input instanceof HTMLSelectElement) {
|
|
4105
|
+
return input.value;
|
|
4106
|
+
} else if (input instanceof HTMLInputElement) {
|
|
4107
|
+
if (input.type === "checkbox") {
|
|
4108
|
+
return input.checked;
|
|
4109
|
+
} else if (input.type === "radio") {
|
|
4110
|
+
const checked = formRoot.querySelector(
|
|
4111
|
+
`[name="${fieldPath}"]:checked`
|
|
4112
|
+
);
|
|
4113
|
+
return checked ? checked.value : void 0;
|
|
4114
|
+
} else {
|
|
4115
|
+
return input.value;
|
|
4116
|
+
}
|
|
4117
|
+
} else if (input instanceof HTMLTextAreaElement) {
|
|
4118
|
+
return input.value;
|
|
4119
|
+
}
|
|
4120
|
+
return void 0;
|
|
4121
|
+
}
|
|
4122
|
+
function reevaluateEnableIf(wrapper, element, ctx) {
|
|
4123
|
+
var _a, _b;
|
|
4124
|
+
if (!element.enableIf) {
|
|
4125
|
+
return;
|
|
4126
|
+
}
|
|
4127
|
+
const formRoot = ctx.state.formRoot;
|
|
4128
|
+
if (!formRoot) {
|
|
4129
|
+
console.error(`Cannot re-evaluate enableIf: formRoot is null`);
|
|
4130
|
+
return;
|
|
4131
|
+
}
|
|
4132
|
+
const condition = element.enableIf;
|
|
4133
|
+
const scope = (_a = condition.scope) != null ? _a : "relative";
|
|
4134
|
+
let rootFormData = {};
|
|
4135
|
+
const containerData = {};
|
|
4136
|
+
const effectiveScope = !ctx.path || ctx.path === "" ? "absolute" : scope;
|
|
4137
|
+
if (effectiveScope === "relative" && ctx.path) {
|
|
4138
|
+
const containerMatch = ctx.path.match(/^(.+)\[(\d+)\]$/);
|
|
4139
|
+
if (containerMatch) {
|
|
4140
|
+
const containerKey = containerMatch[1];
|
|
4141
|
+
const containerIndex = parseInt(containerMatch[2], 10);
|
|
4142
|
+
const containerItemElement = formRoot.querySelector(
|
|
4143
|
+
`[data-container-item="${containerKey}[${containerIndex}]"]`
|
|
4144
|
+
);
|
|
4145
|
+
if (containerItemElement) {
|
|
4146
|
+
const inputs = containerItemElement.querySelectorAll(
|
|
4147
|
+
"input, select, textarea"
|
|
4148
|
+
);
|
|
4149
|
+
inputs.forEach((input) => {
|
|
4150
|
+
const fieldName = input.getAttribute("name");
|
|
4151
|
+
if (fieldName) {
|
|
4152
|
+
const fieldKeyMatch = fieldName.match(/\.([^.[\]]+)$/);
|
|
4153
|
+
if (fieldKeyMatch) {
|
|
4154
|
+
const fieldKey = fieldKeyMatch[1];
|
|
4155
|
+
if (input instanceof HTMLSelectElement) {
|
|
4156
|
+
containerData[fieldKey] = input.value;
|
|
4157
|
+
} else if (input instanceof HTMLInputElement) {
|
|
4158
|
+
if (input.type === "checkbox") {
|
|
4159
|
+
containerData[fieldKey] = input.checked;
|
|
4160
|
+
} else if (input.type === "radio") {
|
|
4161
|
+
if (input.checked) {
|
|
4162
|
+
containerData[fieldKey] = input.value;
|
|
4163
|
+
}
|
|
4164
|
+
} else {
|
|
4165
|
+
containerData[fieldKey] = input.value;
|
|
4166
|
+
}
|
|
4167
|
+
} else if (input instanceof HTMLTextAreaElement) {
|
|
4168
|
+
containerData[fieldKey] = input.value;
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
});
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
} else {
|
|
4176
|
+
const dependencyKey = condition.key;
|
|
4177
|
+
const dependencyValue = extractDOMValue(dependencyKey, formRoot);
|
|
4178
|
+
if (dependencyValue !== void 0) {
|
|
4179
|
+
rootFormData[dependencyKey] = dependencyValue;
|
|
4180
|
+
} else {
|
|
4181
|
+
rootFormData = (_b = ctx.formData) != null ? _b : ctx.prefill;
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
try {
|
|
4185
|
+
const shouldEnable = evaluateEnableCondition(
|
|
4186
|
+
condition,
|
|
4187
|
+
rootFormData,
|
|
4188
|
+
containerData
|
|
4189
|
+
);
|
|
4190
|
+
if (shouldEnable) {
|
|
4191
|
+
wrapper.style.display = "";
|
|
4192
|
+
wrapper.classList.remove("fb-field-wrapper-disabled");
|
|
4193
|
+
wrapper.removeAttribute("data-conditionally-disabled");
|
|
4194
|
+
} else {
|
|
4195
|
+
wrapper.style.display = "none";
|
|
4196
|
+
wrapper.classList.add("fb-field-wrapper-disabled");
|
|
4197
|
+
wrapper.setAttribute("data-conditionally-disabled", "true");
|
|
4198
|
+
}
|
|
4199
|
+
} catch (error) {
|
|
4200
|
+
console.error(`Error re-evaluating enableIf for field "${element.key}":`, error);
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
function setupEnableIfListeners(wrapper, element, ctx) {
|
|
4204
|
+
var _a;
|
|
4205
|
+
if (!element.enableIf) {
|
|
4206
|
+
return;
|
|
4207
|
+
}
|
|
4208
|
+
const formRoot = ctx.state.formRoot;
|
|
4209
|
+
if (!formRoot) {
|
|
4210
|
+
console.error(`Cannot setup enableIf listeners: formRoot is null`);
|
|
4211
|
+
return;
|
|
4212
|
+
}
|
|
4213
|
+
const condition = element.enableIf;
|
|
4214
|
+
const scope = (_a = condition.scope) != null ? _a : "relative";
|
|
4215
|
+
const dependencyKey = condition.key;
|
|
4216
|
+
let dependencyFieldPath;
|
|
4217
|
+
if (scope === "relative" && ctx.path) {
|
|
4218
|
+
dependencyFieldPath = `${ctx.path}.${dependencyKey}`;
|
|
4219
|
+
} else {
|
|
4220
|
+
dependencyFieldPath = dependencyKey;
|
|
4221
|
+
}
|
|
4222
|
+
const dependencyInput = formRoot.querySelector(
|
|
4223
|
+
`[name="${dependencyFieldPath}"]`
|
|
4224
|
+
);
|
|
4225
|
+
if (!dependencyInput) {
|
|
4226
|
+
const observer = new MutationObserver(() => {
|
|
4227
|
+
const input = formRoot.querySelector(
|
|
4228
|
+
`[name="${dependencyFieldPath}"]`
|
|
4229
|
+
);
|
|
4230
|
+
if (input) {
|
|
4231
|
+
input.addEventListener("change", () => {
|
|
4232
|
+
reevaluateEnableIf(wrapper, element, ctx);
|
|
4233
|
+
});
|
|
4234
|
+
input.addEventListener("input", () => {
|
|
4235
|
+
reevaluateEnableIf(wrapper, element, ctx);
|
|
4236
|
+
});
|
|
4237
|
+
observer.disconnect();
|
|
4238
|
+
}
|
|
4239
|
+
});
|
|
4240
|
+
observer.observe(formRoot, {
|
|
4241
|
+
childList: true,
|
|
4242
|
+
subtree: true
|
|
4243
|
+
});
|
|
4244
|
+
return;
|
|
4245
|
+
}
|
|
4246
|
+
dependencyInput.addEventListener("change", () => {
|
|
4247
|
+
reevaluateEnableIf(wrapper, element, ctx);
|
|
4248
|
+
});
|
|
4249
|
+
dependencyInput.addEventListener("input", () => {
|
|
4250
|
+
reevaluateEnableIf(wrapper, element, ctx);
|
|
4251
|
+
});
|
|
3892
4252
|
}
|
|
3893
4253
|
function createFieldLabel(element) {
|
|
3894
4254
|
const title = document.createElement("label");
|
|
@@ -4006,10 +4366,7 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
|
|
|
4006
4366
|
}
|
|
4007
4367
|
}
|
|
4008
4368
|
function renderElement2(element, ctx) {
|
|
4009
|
-
const
|
|
4010
|
-
if (hiddenElement) {
|
|
4011
|
-
return hiddenElement;
|
|
4012
|
-
}
|
|
4369
|
+
const initiallyDisabled = shouldDisableElement(element, ctx);
|
|
4013
4370
|
const wrapper = document.createElement("div");
|
|
4014
4371
|
wrapper.className = "mb-6 fb-field-wrapper";
|
|
4015
4372
|
wrapper.setAttribute("data-field-key", element.key);
|
|
@@ -4017,6 +4374,12 @@ function renderElement2(element, ctx) {
|
|
|
4017
4374
|
wrapper.appendChild(label);
|
|
4018
4375
|
const pathKey = pathJoin(ctx.path, element.key);
|
|
4019
4376
|
dispatchToRenderer(element, ctx, wrapper, pathKey);
|
|
4377
|
+
if (initiallyDisabled) {
|
|
4378
|
+
wrapper.style.display = "none";
|
|
4379
|
+
wrapper.classList.add("fb-field-wrapper-disabled");
|
|
4380
|
+
wrapper.setAttribute("data-conditionally-disabled", "true");
|
|
4381
|
+
}
|
|
4382
|
+
setupEnableIfListeners(wrapper, element, ctx);
|
|
4020
4383
|
return wrapper;
|
|
4021
4384
|
}
|
|
4022
4385
|
setRenderElement(renderElement2);
|
|
@@ -4675,15 +5038,16 @@ var FormBuilderInstance = class {
|
|
|
4675
5038
|
event.preventDefault();
|
|
4676
5039
|
event.stopPropagation();
|
|
4677
5040
|
const hintValuesJson = target.getAttribute("data-hint-values");
|
|
5041
|
+
const isRootHint = target.getAttribute("data-root-hint") === "true";
|
|
4678
5042
|
const containerKey = target.getAttribute("data-container-key");
|
|
4679
|
-
if (!hintValuesJson || !containerKey) {
|
|
5043
|
+
if (!hintValuesJson || !isRootHint && !containerKey) {
|
|
4680
5044
|
console.warn("Prefill hint missing required data attributes");
|
|
4681
5045
|
return;
|
|
4682
5046
|
}
|
|
4683
5047
|
try {
|
|
4684
5048
|
const hintValues = JSON.parse(hintValuesJson);
|
|
4685
5049
|
for (const fieldKey in hintValues) {
|
|
4686
|
-
const fullPath = `${containerKey}.${fieldKey}`;
|
|
5050
|
+
const fullPath = isRootHint ? fieldKey : `${containerKey}.${fieldKey}`;
|
|
4687
5051
|
const value = hintValues[fieldKey];
|
|
4688
5052
|
this.updateField(fullPath, value);
|
|
4689
5053
|
}
|
|
@@ -4691,6 +5055,27 @@ var FormBuilderInstance = class {
|
|
|
4691
5055
|
console.error("Error parsing prefill hint values:", error);
|
|
4692
5056
|
}
|
|
4693
5057
|
}
|
|
5058
|
+
/**
|
|
5059
|
+
* Create root-level prefill hints UI
|
|
5060
|
+
*/
|
|
5061
|
+
createRootPrefillHints(hints) {
|
|
5062
|
+
const hintsContainer = document.createElement("div");
|
|
5063
|
+
hintsContainer.className = "fb-prefill-hints flex flex-wrap gap-2 mb-4";
|
|
5064
|
+
hints.forEach((hint) => {
|
|
5065
|
+
const hintButton = document.createElement("button");
|
|
5066
|
+
hintButton.type = "button";
|
|
5067
|
+
hintButton.className = "fb-prefill-hint";
|
|
5068
|
+
if (hint.icon) {
|
|
5069
|
+
hintButton.textContent = `${hint.icon} ${hint.label}`;
|
|
5070
|
+
} else {
|
|
5071
|
+
hintButton.textContent = hint.label;
|
|
5072
|
+
}
|
|
5073
|
+
hintButton.setAttribute("data-hint-values", JSON.stringify(hint.values));
|
|
5074
|
+
hintButton.setAttribute("data-root-hint", "true");
|
|
5075
|
+
hintsContainer.appendChild(hintButton);
|
|
5076
|
+
});
|
|
5077
|
+
return hintsContainer;
|
|
5078
|
+
}
|
|
4694
5079
|
/**
|
|
4695
5080
|
* Render form from schema
|
|
4696
5081
|
*/
|
|
@@ -4706,8 +5091,19 @@ var FormBuilderInstance = class {
|
|
|
4706
5091
|
clear(root);
|
|
4707
5092
|
root.setAttribute("data-fb-root", "true");
|
|
4708
5093
|
injectThemeVariables(root, this.state.config.theme);
|
|
4709
|
-
const
|
|
4710
|
-
|
|
5094
|
+
const rootContainer = document.createElement("div");
|
|
5095
|
+
rootContainer.className = "space-y-6";
|
|
5096
|
+
if (schema.prefillHints && !this.state.config.readonly) {
|
|
5097
|
+
const hintsContainer = this.createRootPrefillHints(schema.prefillHints);
|
|
5098
|
+
rootContainer.appendChild(hintsContainer);
|
|
5099
|
+
}
|
|
5100
|
+
const fieldsWrapper = document.createElement("div");
|
|
5101
|
+
const columns = schema.columns || 1;
|
|
5102
|
+
if (columns === 1) {
|
|
5103
|
+
fieldsWrapper.className = "space-y-4";
|
|
5104
|
+
} else {
|
|
5105
|
+
fieldsWrapper.className = `grid grid-cols-${columns} gap-4`;
|
|
5106
|
+
}
|
|
4711
5107
|
schema.elements.forEach((element) => {
|
|
4712
5108
|
if (element.hidden) {
|
|
4713
5109
|
return;
|
|
@@ -4716,13 +5112,14 @@ var FormBuilderInstance = class {
|
|
|
4716
5112
|
path: "",
|
|
4717
5113
|
prefill: prefill || {},
|
|
4718
5114
|
formData: prefill || {},
|
|
4719
|
-
// Pass complete root data for
|
|
5115
|
+
// Pass complete root data for enableIf evaluation
|
|
4720
5116
|
state: this.state,
|
|
4721
5117
|
instance: this
|
|
4722
5118
|
});
|
|
4723
|
-
|
|
5119
|
+
fieldsWrapper.appendChild(block);
|
|
4724
5120
|
});
|
|
4725
|
-
|
|
5121
|
+
rootContainer.appendChild(fieldsWrapper);
|
|
5122
|
+
root.appendChild(rootContainer);
|
|
4726
5123
|
if (!this.state.config.readonly) {
|
|
4727
5124
|
root.addEventListener("click", this.handlePrefillHintClick.bind(this));
|
|
4728
5125
|
}
|
|
@@ -4764,15 +5161,18 @@ var FormBuilderInstance = class {
|
|
|
4764
5161
|
};
|
|
4765
5162
|
setValidateElement(validateElement2);
|
|
4766
5163
|
this.state.schema.elements.forEach((element) => {
|
|
4767
|
-
if (element.
|
|
5164
|
+
if (element.enableIf) {
|
|
4768
5165
|
try {
|
|
4769
|
-
const
|
|
4770
|
-
|
|
5166
|
+
const shouldEnable = evaluateEnableCondition(
|
|
5167
|
+
element.enableIf,
|
|
5168
|
+
data
|
|
5169
|
+
);
|
|
5170
|
+
if (!shouldEnable) {
|
|
4771
5171
|
return;
|
|
4772
5172
|
}
|
|
4773
5173
|
} catch (error) {
|
|
4774
5174
|
console.error(
|
|
4775
|
-
`Error evaluating
|
|
5175
|
+
`Error evaluating enableIf for field "${element.key}" during validation:`,
|
|
4776
5176
|
error
|
|
4777
5177
|
);
|
|
4778
5178
|
}
|
|
@@ -4860,7 +5260,9 @@ var FormBuilderInstance = class {
|
|
|
4860
5260
|
}
|
|
4861
5261
|
if (element.type === "container" || element.type === "group") {
|
|
4862
5262
|
const containerElement = element;
|
|
4863
|
-
const nestedData = this.buildHiddenFieldsData(
|
|
5263
|
+
const nestedData = this.buildHiddenFieldsData(
|
|
5264
|
+
containerElement.elements
|
|
5265
|
+
);
|
|
4864
5266
|
if (Object.keys(nestedData).length > 0) {
|
|
4865
5267
|
if (!(key in data)) {
|
|
4866
5268
|
data[key] = nestedData;
|
|
@@ -4878,7 +5280,9 @@ var FormBuilderInstance = class {
|
|
|
4878
5280
|
*/
|
|
4879
5281
|
setFormData(data) {
|
|
4880
5282
|
if (!this.state.schema || !this.state.formRoot) {
|
|
4881
|
-
console.warn(
|
|
5283
|
+
console.warn(
|
|
5284
|
+
"setFormData: Form not initialized. Call renderForm() first."
|
|
5285
|
+
);
|
|
4882
5286
|
return;
|
|
4883
5287
|
}
|
|
4884
5288
|
for (const fieldPath in data) {
|
|
@@ -4892,20 +5296,27 @@ var FormBuilderInstance = class {
|
|
|
4892
5296
|
*/
|
|
4893
5297
|
updateField(fieldPath, value) {
|
|
4894
5298
|
if (!this.state.schema || !this.state.formRoot) {
|
|
4895
|
-
console.warn(
|
|
5299
|
+
console.warn(
|
|
5300
|
+
"updateField: Form not initialized. Call renderForm() first."
|
|
5301
|
+
);
|
|
4896
5302
|
return;
|
|
4897
5303
|
}
|
|
4898
5304
|
const schemaElement = this.findSchemaElement(fieldPath);
|
|
4899
5305
|
if (!schemaElement) {
|
|
4900
|
-
console.warn(
|
|
5306
|
+
console.warn(
|
|
5307
|
+
`updateField: Schema element not found for path "${fieldPath}"`
|
|
5308
|
+
);
|
|
4901
5309
|
return;
|
|
4902
5310
|
}
|
|
4903
5311
|
const domElement = this.findFormElementByFieldPath(fieldPath);
|
|
4904
5312
|
if (!domElement) {
|
|
4905
|
-
console.warn(
|
|
5313
|
+
console.warn(
|
|
5314
|
+
`updateField: DOM element not found for path "${fieldPath}"`
|
|
5315
|
+
);
|
|
4906
5316
|
return;
|
|
4907
5317
|
}
|
|
4908
5318
|
this.updateFieldValue(domElement, schemaElement, fieldPath, value);
|
|
5319
|
+
this.reevaluateConditionalFields();
|
|
4909
5320
|
if (this.state.config.onChange || this.state.config.onFieldChange) {
|
|
4910
5321
|
this.triggerOnChange(fieldPath, value);
|
|
4911
5322
|
}
|
|
@@ -4934,7 +5345,7 @@ var FormBuilderInstance = class {
|
|
|
4934
5345
|
}
|
|
4935
5346
|
}
|
|
4936
5347
|
/**
|
|
4937
|
-
* Re-evaluate all conditional fields (
|
|
5348
|
+
* Re-evaluate all conditional fields (enableIf) based on current form data
|
|
4938
5349
|
* This is called automatically when form data changes (via onChange events)
|
|
4939
5350
|
*/
|
|
4940
5351
|
reevaluateConditionalFields() {
|
|
@@ -4942,47 +5353,82 @@ var FormBuilderInstance = class {
|
|
|
4942
5353
|
const formData = this.validateForm(true).data;
|
|
4943
5354
|
const checkElements = (elements, currentPath) => {
|
|
4944
5355
|
elements.forEach((element) => {
|
|
5356
|
+
var _a, _b, _c;
|
|
4945
5357
|
const fullPath = currentPath ? `${currentPath}.${element.key}` : element.key;
|
|
4946
|
-
if (element.
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
5358
|
+
if (element.enableIf) {
|
|
5359
|
+
let fieldWrapper = null;
|
|
5360
|
+
if (currentPath) {
|
|
5361
|
+
const pathMatch = currentPath.match(/^(.+)\[(\d+)\]$/);
|
|
5362
|
+
if (pathMatch) {
|
|
5363
|
+
const containerKey = pathMatch[1];
|
|
5364
|
+
const containerIndex = pathMatch[2];
|
|
5365
|
+
const containerElement = this.state.formRoot.querySelector(
|
|
5366
|
+
`[data-container-item="${containerKey}[${containerIndex}]"]`
|
|
5367
|
+
);
|
|
5368
|
+
if (containerElement) {
|
|
5369
|
+
fieldWrapper = containerElement.querySelector(
|
|
5370
|
+
`[data-field-key="${element.key}"]`
|
|
5371
|
+
);
|
|
5372
|
+
}
|
|
5373
|
+
} else {
|
|
5374
|
+
const containerElement = this.state.formRoot.querySelector(
|
|
5375
|
+
`[data-container="${currentPath}"]`
|
|
5376
|
+
);
|
|
5377
|
+
if (containerElement) {
|
|
5378
|
+
fieldWrapper = containerElement.querySelector(
|
|
5379
|
+
`[data-field-key="${element.key}"]`
|
|
5380
|
+
);
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
} else {
|
|
5384
|
+
fieldWrapper = this.state.formRoot.querySelector(
|
|
5385
|
+
`[data-field-key="${element.key}"]`
|
|
5386
|
+
);
|
|
5387
|
+
}
|
|
5388
|
+
if (fieldWrapper) {
|
|
5389
|
+
const wrapper = fieldWrapper;
|
|
4952
5390
|
try {
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
5391
|
+
let containerData = void 0;
|
|
5392
|
+
const scope = (_a = element.enableIf.scope) != null ? _a : "relative";
|
|
5393
|
+
if (scope === "relative" && currentPath) {
|
|
5394
|
+
containerData = getValueByPath(formData, currentPath);
|
|
5395
|
+
}
|
|
5396
|
+
const shouldEnable = evaluateEnableCondition(
|
|
5397
|
+
element.enableIf,
|
|
5398
|
+
formData,
|
|
5399
|
+
// Use complete formData for absolute scope
|
|
5400
|
+
containerData
|
|
5401
|
+
// Use container-specific data for relative scope
|
|
4957
5402
|
);
|
|
4958
|
-
const
|
|
4959
|
-
if (
|
|
5403
|
+
const isCurrentlyDisabled = wrapper.getAttribute("data-conditionally-disabled") === "true";
|
|
5404
|
+
if (shouldEnable && isCurrentlyDisabled) {
|
|
5405
|
+
const containerPrefill = currentPath ? getValueByPath(formData, currentPath) : formData;
|
|
5406
|
+
const prefillContext = containerPrefill && typeof containerPrefill === "object" ? containerPrefill : {};
|
|
4960
5407
|
const newWrapper = renderElement2(element, {
|
|
4961
|
-
path:
|
|
4962
|
-
// Use
|
|
4963
|
-
prefill:
|
|
4964
|
-
// Use complete formData for root-level elements
|
|
5408
|
+
path: currentPath,
|
|
5409
|
+
// Use container path (empty string for root-level)
|
|
5410
|
+
prefill: prefillContext,
|
|
4965
5411
|
formData,
|
|
4966
|
-
// Pass complete formData for
|
|
5412
|
+
// Pass complete formData for enableIf evaluation
|
|
4967
5413
|
state: this.state,
|
|
4968
5414
|
instance: this
|
|
4969
5415
|
});
|
|
4970
|
-
(
|
|
4971
|
-
} else if (!
|
|
4972
|
-
const
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
(
|
|
5416
|
+
(_b = wrapper.parentNode) == null ? void 0 : _b.replaceChild(newWrapper, wrapper);
|
|
5417
|
+
} else if (!shouldEnable && !isCurrentlyDisabled) {
|
|
5418
|
+
const disabledWrapper = document.createElement("div");
|
|
5419
|
+
disabledWrapper.className = "fb-field-wrapper-disabled";
|
|
5420
|
+
disabledWrapper.style.display = "none";
|
|
5421
|
+
disabledWrapper.setAttribute("data-field-key", element.key);
|
|
5422
|
+
disabledWrapper.setAttribute("data-conditionally-disabled", "true");
|
|
5423
|
+
(_c = wrapper.parentNode) == null ? void 0 : _c.replaceChild(disabledWrapper, wrapper);
|
|
4978
5424
|
}
|
|
4979
5425
|
} catch (error) {
|
|
4980
5426
|
console.error(
|
|
4981
|
-
`Error re-evaluating
|
|
5427
|
+
`Error re-evaluating enableIf for field "${element.key}" at path "${fullPath}":`,
|
|
4982
5428
|
error
|
|
4983
5429
|
);
|
|
4984
5430
|
}
|
|
4985
|
-
}
|
|
5431
|
+
}
|
|
4986
5432
|
}
|
|
4987
5433
|
if ((element.type === "container" || element.type === "group") && "elements" in element && element.elements) {
|
|
4988
5434
|
const containerData = formData == null ? void 0 : formData[element.key];
|