@dmitryvim/form-builder 0.2.9 → 0.2.11

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.
@@ -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.displayIf) {
79
- const displayIf = element.displayIf;
80
- if (!displayIf.key || typeof displayIf.key !== "string") {
113
+ if (element.enableIf) {
114
+ const enableIf = element.enableIf;
115
+ if (!enableIf.key || typeof enableIf.key !== "string") {
81
116
  errors.push(
82
- `${elementPath}: displayIf must have a 'key' property of type string`
117
+ `${elementPath}: enableIf must have a 'key' property of type string`
83
118
  );
84
119
  }
85
- const hasOperator = "equals" in displayIf;
120
+ const hasOperator = "equals" in enableIf;
86
121
  if (!hasOperator) {
87
122
  errors.push(
88
- `${elementPath}: displayIf must have at least one operator (equals, etc.)`
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/display-conditions.ts
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 evaluateDisplayCondition(condition, formData) {
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
- "Invalid displayIf condition: must have a 'key' property"
240
+ `Invalid enableIf scope: must be "relative" or "absolute" (got "${scope}")`
196
241
  );
197
242
  }
198
- const actualValue = getValueByPath(formData, condition.key);
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 displayIf condition: no recognized operator (equals, etc.)`
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 displayIf comparison, using reference equality"
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
- ctx.instance.triggerOnChange(pathKey, textInput.value);
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
- ctx.instance.triggerOnChange(textInput.name, textInput.value);
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);
@@ -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
- values.push(val);
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 = values.filter((v) => v.trim() !== "");
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: "", errors };
594
+ return { value: null, errors };
550
595
  }
551
- validateTextInput(input, val, key);
552
- return { value: val, errors };
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
- ctx.instance.triggerOnChange(pathKey, textareaInput.value);
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
- ctx.instance.triggerOnChange(textareaInput.name, textareaInput.value);
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);
@@ -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(".change-file-btn");
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(".delete-file-btn");
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(document.createTextNode("Your browser does not support the video tag."));
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(container, resourceId, fileName, meta, state);
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(document.createTextNode(` ${t("dragDropText", state)}`));
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(files[0], fileContainer, pathKey, state, deps, ctx.instance);
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(picker.files[0], fileContainer, pathKey, state, deps, ctx.instance);
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(filesContainer, initialFiles, state, updateFilesList2, pathKey, ctx.instance);
2195
- setupFilesPickerHandler(filesPicker, initialFiles, state, updateFilesList2, pathKey, ctx.instance);
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(filesContainer, initialFiles, state, updateFilesDisplay, pathKey, ctx.instance);
2259
- setupFilesPickerHandler(filesPicker, initialFiles, state, updateFilesDisplay, pathKey, ctx.instance);
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
  }
@@ -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(".colour-picker-hidden");
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(".colour-picker-hidden");
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(
@@ -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(errorElement, sliderContainer.nextSibling);
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 displayIf evaluation
3547
+ // Complete root data for enableIf evaluation
3425
3548
  state: ctx.state
3426
3549
  };
3427
3550
  element.elements.forEach((child) => {
@@ -3475,15 +3598,15 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3475
3598
  add.style.backgroundColor = "transparent";
3476
3599
  });
3477
3600
  add.onclick = () => {
3478
- var _a2;
3479
3601
  if (countItems() < max) {
3480
3602
  const idx = countItems();
3603
+ const currentFormData = state.formRoot ? extractRootFormData(state.formRoot) : {};
3481
3604
  const subCtx = {
3482
3605
  state: ctx.state,
3483
3606
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3484
3607
  prefill: {},
3485
- formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill
3486
- // Complete root data for displayIf
3608
+ formData: currentFormData
3609
+ // Current root data from DOM for enableIf
3487
3610
  };
3488
3611
  const item = document.createElement("div");
3489
3612
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -3532,7 +3655,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3532
3655
  };
3533
3656
  const updateAddButton = () => {
3534
3657
  const currentCount = countItems();
3535
- const existingAddBtn = containerWrap.querySelector(".add-container-btn");
3658
+ const existingAddBtn = containerWrap.querySelector(
3659
+ ".add-container-btn"
3660
+ );
3536
3661
  if (existingAddBtn) {
3537
3662
  existingAddBtn.disabled = currentCount >= max;
3538
3663
  existingAddBtn.style.opacity = currentCount >= max ? "0.5" : "1";
@@ -3548,7 +3673,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3548
3673
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3549
3674
  prefill: prefillObj || {},
3550
3675
  formData: (_a2 = ctx.formData) != null ? _a2 : ctx.prefill
3551
- // Complete root data for displayIf
3676
+ // Complete root data for enableIf
3552
3677
  };
3553
3678
  const item = document.createElement("div");
3554
3679
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -3600,7 +3725,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3600
3725
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3601
3726
  prefill: {},
3602
3727
  formData: (_d = ctx.formData) != null ? _d : ctx.prefill
3603
- // Complete root data for displayIf
3728
+ // Complete root data for enableIf
3604
3729
  };
3605
3730
  const item = document.createElement("div");
3606
3731
  item.className = "containerItem border border-gray-300 rounded-lg p-4 bg-white";
@@ -3700,6 +3825,27 @@ function validateContainerElement(element, key, context) {
3700
3825
  `[data-container-item="${key}[${i}]"]`
3701
3826
  ) || scopeRoot;
3702
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
+ }
3703
3849
  if (child.hidden || child.type === "hidden") {
3704
3850
  itemData[child.key] = child.default !== void 0 ? child.default : null;
3705
3851
  } else {
@@ -3719,6 +3865,27 @@ function validateContainerElement(element, key, context) {
3719
3865
  const containerData = {};
3720
3866
  const containerContainer = scopeRoot.querySelector(`[data-container="${key}"]`) || scopeRoot;
3721
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
+ }
3722
3889
  if (child.hidden || child.type === "hidden") {
3723
3890
  containerData[child.key] = child.default !== void 0 ? child.default : null;
3724
3891
  } else {
@@ -3905,32 +4072,183 @@ if (typeof document !== "undefined") {
3905
4072
  }
3906
4073
  });
3907
4074
  }
3908
- function checkDisplayCondition(element, ctx) {
3909
- var _a;
3910
- if (!element.displayIf) {
3911
- return null;
4075
+ function shouldDisableElement(element, ctx) {
4076
+ var _a, _b;
4077
+ if (!element.enableIf) {
4078
+ return false;
3912
4079
  }
3913
4080
  try {
3914
- const dataForCondition = (_a = ctx.formData) != null ? _a : ctx.prefill;
3915
- const shouldDisplay = evaluateDisplayCondition(
3916
- element.displayIf,
3917
- dataForCondition
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
3918
4087
  );
3919
- if (!shouldDisplay) {
3920
- const hiddenWrapper = document.createElement("div");
3921
- hiddenWrapper.className = "fb-field-wrapper-hidden";
3922
- hiddenWrapper.style.display = "none";
3923
- hiddenWrapper.setAttribute("data-field-key", element.key);
3924
- hiddenWrapper.setAttribute("data-conditionally-hidden", "true");
3925
- return hiddenWrapper;
3926
- }
4088
+ return !shouldEnable;
3927
4089
  } catch (error) {
3928
4090
  console.error(
3929
- `Error evaluating displayIf for field "${element.key}":`,
4091
+ `Error evaluating enableIf for field "${element.key}":`,
3930
4092
  error
3931
4093
  );
3932
4094
  }
3933
- return null;
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
+ });
3934
4252
  }
3935
4253
  function createFieldLabel(element) {
3936
4254
  const title = document.createElement("label");
@@ -4048,10 +4366,7 @@ function dispatchToRenderer(element, ctx, wrapper, pathKey) {
4048
4366
  }
4049
4367
  }
4050
4368
  function renderElement2(element, ctx) {
4051
- const hiddenElement = checkDisplayCondition(element, ctx);
4052
- if (hiddenElement) {
4053
- return hiddenElement;
4054
- }
4369
+ const initiallyDisabled = shouldDisableElement(element, ctx);
4055
4370
  const wrapper = document.createElement("div");
4056
4371
  wrapper.className = "mb-6 fb-field-wrapper";
4057
4372
  wrapper.setAttribute("data-field-key", element.key);
@@ -4059,6 +4374,12 @@ function renderElement2(element, ctx) {
4059
4374
  wrapper.appendChild(label);
4060
4375
  const pathKey = pathJoin(ctx.path, element.key);
4061
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);
4062
4383
  return wrapper;
4063
4384
  }
4064
4385
  setRenderElement(renderElement2);
@@ -4717,15 +5038,16 @@ var FormBuilderInstance = class {
4717
5038
  event.preventDefault();
4718
5039
  event.stopPropagation();
4719
5040
  const hintValuesJson = target.getAttribute("data-hint-values");
5041
+ const isRootHint = target.getAttribute("data-root-hint") === "true";
4720
5042
  const containerKey = target.getAttribute("data-container-key");
4721
- if (!hintValuesJson || !containerKey) {
5043
+ if (!hintValuesJson || !isRootHint && !containerKey) {
4722
5044
  console.warn("Prefill hint missing required data attributes");
4723
5045
  return;
4724
5046
  }
4725
5047
  try {
4726
5048
  const hintValues = JSON.parse(hintValuesJson);
4727
5049
  for (const fieldKey in hintValues) {
4728
- const fullPath = `${containerKey}.${fieldKey}`;
5050
+ const fullPath = isRootHint ? fieldKey : `${containerKey}.${fieldKey}`;
4729
5051
  const value = hintValues[fieldKey];
4730
5052
  this.updateField(fullPath, value);
4731
5053
  }
@@ -4733,6 +5055,27 @@ var FormBuilderInstance = class {
4733
5055
  console.error("Error parsing prefill hint values:", error);
4734
5056
  }
4735
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
+ }
4736
5079
  /**
4737
5080
  * Render form from schema
4738
5081
  */
@@ -4748,8 +5091,19 @@ var FormBuilderInstance = class {
4748
5091
  clear(root);
4749
5092
  root.setAttribute("data-fb-root", "true");
4750
5093
  injectThemeVariables(root, this.state.config.theme);
4751
- const formEl = document.createElement("div");
4752
- formEl.className = "space-y-6";
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
+ }
4753
5107
  schema.elements.forEach((element) => {
4754
5108
  if (element.hidden) {
4755
5109
  return;
@@ -4758,13 +5112,14 @@ var FormBuilderInstance = class {
4758
5112
  path: "",
4759
5113
  prefill: prefill || {},
4760
5114
  formData: prefill || {},
4761
- // Pass complete root data for displayIf evaluation
5115
+ // Pass complete root data for enableIf evaluation
4762
5116
  state: this.state,
4763
5117
  instance: this
4764
5118
  });
4765
- formEl.appendChild(block);
5119
+ fieldsWrapper.appendChild(block);
4766
5120
  });
4767
- root.appendChild(formEl);
5121
+ rootContainer.appendChild(fieldsWrapper);
5122
+ root.appendChild(rootContainer);
4768
5123
  if (!this.state.config.readonly) {
4769
5124
  root.addEventListener("click", this.handlePrefillHintClick.bind(this));
4770
5125
  }
@@ -4806,15 +5161,18 @@ var FormBuilderInstance = class {
4806
5161
  };
4807
5162
  setValidateElement(validateElement2);
4808
5163
  this.state.schema.elements.forEach((element) => {
4809
- if (element.displayIf) {
5164
+ if (element.enableIf) {
4810
5165
  try {
4811
- const shouldDisplay = evaluateDisplayCondition(element.displayIf, data);
4812
- if (!shouldDisplay) {
5166
+ const shouldEnable = evaluateEnableCondition(
5167
+ element.enableIf,
5168
+ data
5169
+ );
5170
+ if (!shouldEnable) {
4813
5171
  return;
4814
5172
  }
4815
5173
  } catch (error) {
4816
5174
  console.error(
4817
- `Error evaluating displayIf for field "${element.key}" during validation:`,
5175
+ `Error evaluating enableIf for field "${element.key}" during validation:`,
4818
5176
  error
4819
5177
  );
4820
5178
  }
@@ -4902,7 +5260,9 @@ var FormBuilderInstance = class {
4902
5260
  }
4903
5261
  if (element.type === "container" || element.type === "group") {
4904
5262
  const containerElement = element;
4905
- const nestedData = this.buildHiddenFieldsData(containerElement.elements);
5263
+ const nestedData = this.buildHiddenFieldsData(
5264
+ containerElement.elements
5265
+ );
4906
5266
  if (Object.keys(nestedData).length > 0) {
4907
5267
  if (!(key in data)) {
4908
5268
  data[key] = nestedData;
@@ -4920,7 +5280,9 @@ var FormBuilderInstance = class {
4920
5280
  */
4921
5281
  setFormData(data) {
4922
5282
  if (!this.state.schema || !this.state.formRoot) {
4923
- console.warn("setFormData: Form not initialized. Call renderForm() first.");
5283
+ console.warn(
5284
+ "setFormData: Form not initialized. Call renderForm() first."
5285
+ );
4924
5286
  return;
4925
5287
  }
4926
5288
  for (const fieldPath in data) {
@@ -4934,20 +5296,27 @@ var FormBuilderInstance = class {
4934
5296
  */
4935
5297
  updateField(fieldPath, value) {
4936
5298
  if (!this.state.schema || !this.state.formRoot) {
4937
- console.warn("updateField: Form not initialized. Call renderForm() first.");
5299
+ console.warn(
5300
+ "updateField: Form not initialized. Call renderForm() first."
5301
+ );
4938
5302
  return;
4939
5303
  }
4940
5304
  const schemaElement = this.findSchemaElement(fieldPath);
4941
5305
  if (!schemaElement) {
4942
- console.warn(`updateField: Schema element not found for path "${fieldPath}"`);
5306
+ console.warn(
5307
+ `updateField: Schema element not found for path "${fieldPath}"`
5308
+ );
4943
5309
  return;
4944
5310
  }
4945
5311
  const domElement = this.findFormElementByFieldPath(fieldPath);
4946
5312
  if (!domElement) {
4947
- console.warn(`updateField: DOM element not found for path "${fieldPath}"`);
5313
+ console.warn(
5314
+ `updateField: DOM element not found for path "${fieldPath}"`
5315
+ );
4948
5316
  return;
4949
5317
  }
4950
5318
  this.updateFieldValue(domElement, schemaElement, fieldPath, value);
5319
+ this.reevaluateConditionalFields();
4951
5320
  if (this.state.config.onChange || this.state.config.onFieldChange) {
4952
5321
  this.triggerOnChange(fieldPath, value);
4953
5322
  }
@@ -4976,7 +5345,7 @@ var FormBuilderInstance = class {
4976
5345
  }
4977
5346
  }
4978
5347
  /**
4979
- * Re-evaluate all conditional fields (displayIf) based on current form data
5348
+ * Re-evaluate all conditional fields (enableIf) based on current form data
4980
5349
  * This is called automatically when form data changes (via onChange events)
4981
5350
  */
4982
5351
  reevaluateConditionalFields() {
@@ -4984,47 +5353,82 @@ var FormBuilderInstance = class {
4984
5353
  const formData = this.validateForm(true).data;
4985
5354
  const checkElements = (elements, currentPath) => {
4986
5355
  elements.forEach((element) => {
5356
+ var _a, _b, _c;
4987
5357
  const fullPath = currentPath ? `${currentPath}.${element.key}` : element.key;
4988
- if (element.displayIf) {
4989
- const fieldWrappers = this.state.formRoot.querySelectorAll(
4990
- `[data-field-key="${element.key}"]`
4991
- );
4992
- fieldWrappers.forEach((wrapper) => {
4993
- var _a, _b;
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;
4994
5390
  try {
4995
- const shouldDisplay = evaluateDisplayCondition(
4996
- element.displayIf,
4997
- formData
4998
- // Use complete formData for condition evaluation
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
4999
5402
  );
5000
- const isCurrentlyHidden = wrapper.getAttribute("data-conditionally-hidden") === "true";
5001
- if (shouldDisplay && isCurrentlyHidden) {
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 : {};
5002
5407
  const newWrapper = renderElement2(element, {
5003
- path: fullPath,
5004
- // Use accumulated path
5005
- prefill: formData,
5006
- // Use complete formData for root-level elements
5408
+ path: currentPath,
5409
+ // Use container path (empty string for root-level)
5410
+ prefill: prefillContext,
5007
5411
  formData,
5008
- // Pass complete formData for displayIf evaluation
5412
+ // Pass complete formData for enableIf evaluation
5009
5413
  state: this.state,
5010
5414
  instance: this
5011
5415
  });
5012
- (_a = wrapper.parentNode) == null ? void 0 : _a.replaceChild(newWrapper, wrapper);
5013
- } else if (!shouldDisplay && !isCurrentlyHidden) {
5014
- const hiddenWrapper = document.createElement("div");
5015
- hiddenWrapper.className = "fb-field-wrapper-hidden";
5016
- hiddenWrapper.style.display = "none";
5017
- hiddenWrapper.setAttribute("data-field-key", element.key);
5018
- hiddenWrapper.setAttribute("data-conditionally-hidden", "true");
5019
- (_b = wrapper.parentNode) == null ? void 0 : _b.replaceChild(hiddenWrapper, wrapper);
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);
5020
5424
  }
5021
5425
  } catch (error) {
5022
5426
  console.error(
5023
- `Error re-evaluating displayIf for field "${element.key}":`,
5427
+ `Error re-evaluating enableIf for field "${element.key}" at path "${fullPath}":`,
5024
5428
  error
5025
5429
  );
5026
5430
  }
5027
- });
5431
+ }
5028
5432
  }
5029
5433
  if ((element.type === "container" || element.type === "group") && "elements" in element && element.elements) {
5030
5434
  const containerData = formData == null ? void 0 : formData[element.key];