@dmitryvim/form-builder 0.2.15 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -3691,6 +3691,18 @@ function updateSliderField(element, fieldPath, value, context) {
3691
3691
  }
3692
3692
 
3693
3693
  // src/components/container.ts
3694
+ function extractChildDefaults(elements) {
3695
+ const defaults = {};
3696
+ for (const child of elements) {
3697
+ if ("default" in child && child.default !== void 0) {
3698
+ defaults[child.key] = child.default;
3699
+ }
3700
+ }
3701
+ return defaults;
3702
+ }
3703
+ function mergeWithDefaults(prefill, defaults) {
3704
+ return { ...defaults, ...prefill };
3705
+ }
3694
3706
  function extractRootFormData(formRoot) {
3695
3707
  const data = {};
3696
3708
  const inputs = formRoot.querySelectorAll(
@@ -3765,10 +3777,13 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
3765
3777
  containerWrap.appendChild(hintsElement);
3766
3778
  }
3767
3779
  }
3780
+ const childDefaults = extractChildDefaults(element.elements);
3781
+ const containerPrefill = ctx.prefill?.[element.key] || {};
3782
+ const mergedPrefill = mergeWithDefaults(containerPrefill, childDefaults);
3768
3783
  const subCtx = {
3769
3784
  path: pathJoin(ctx.path, element.key),
3770
- prefill: ctx.prefill?.[element.key] || {},
3771
- // Sliced data for value population
3785
+ prefill: mergedPrefill,
3786
+ // Merged prefill with defaults for enableIf evaluation
3772
3787
  formData: ctx.formData ?? ctx.prefill,
3773
3788
  // Complete root data for enableIf evaluation
3774
3789
  state: ctx.state
@@ -3798,6 +3813,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3798
3813
  const min = element.minCount ?? 0;
3799
3814
  const max = element.maxCount ?? Infinity;
3800
3815
  const pre = Array.isArray(ctx.prefill?.[element.key]) ? ctx.prefill[element.key] : null;
3816
+ const childDefaults = extractChildDefaults(element.elements);
3801
3817
  const countItems = () => itemsWrap.querySelectorAll(":scope > .containerItem").length;
3802
3818
  const createAddButton = () => {
3803
3819
  const add = document.createElement("button");
@@ -3824,7 +3840,8 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3824
3840
  const subCtx = {
3825
3841
  state: ctx.state,
3826
3842
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3827
- prefill: {},
3843
+ prefill: childDefaults,
3844
+ // Defaults for enableIf evaluation
3828
3845
  formData: currentFormData
3829
3846
  // Current root data from DOM for enableIf
3830
3847
  };
@@ -3860,10 +3877,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3860
3877
  rem.addEventListener("mouseleave", () => {
3861
3878
  rem.style.backgroundColor = "transparent";
3862
3879
  });
3863
- rem.onclick = () => {
3864
- item.remove();
3865
- updateAddButton();
3866
- };
3880
+ rem.onclick = () => handleRemoveItem(item);
3867
3881
  item.style.position = "relative";
3868
3882
  item.appendChild(rem);
3869
3883
  }
@@ -3885,12 +3899,18 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3885
3899
  }
3886
3900
  countDisplay.textContent = `${currentCount}/${max === Infinity ? "\u221E" : max}`;
3887
3901
  };
3902
+ const handleRemoveItem = (item) => {
3903
+ item.remove();
3904
+ updateAddButton();
3905
+ };
3888
3906
  if (pre && Array.isArray(pre)) {
3889
3907
  pre.forEach((prefillObj, idx) => {
3908
+ const mergedPrefill = mergeWithDefaults(prefillObj || {}, childDefaults);
3890
3909
  const subCtx = {
3891
3910
  state: ctx.state,
3892
3911
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3893
- prefill: prefillObj || {},
3912
+ prefill: mergedPrefill,
3913
+ // Merged prefill with defaults for enableIf
3894
3914
  formData: ctx.formData ?? ctx.prefill
3895
3915
  // Complete root data for enableIf
3896
3916
  };
@@ -3926,10 +3946,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3926
3946
  rem.addEventListener("mouseleave", () => {
3927
3947
  rem.style.backgroundColor = "transparent";
3928
3948
  });
3929
- rem.onclick = () => {
3930
- item.remove();
3931
- updateAddButton();
3932
- };
3949
+ rem.onclick = () => handleRemoveItem(item);
3933
3950
  item.style.position = "relative";
3934
3951
  item.appendChild(rem);
3935
3952
  }
@@ -3942,7 +3959,8 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3942
3959
  const subCtx = {
3943
3960
  state: ctx.state,
3944
3961
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
3945
- prefill: {},
3962
+ prefill: childDefaults,
3963
+ // Defaults for enableIf evaluation
3946
3964
  formData: ctx.formData ?? ctx.prefill
3947
3965
  // Complete root data for enableIf
3948
3966
  };
@@ -3979,8 +3997,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
3979
3997
  });
3980
3998
  rem.onclick = () => {
3981
3999
  if (countItems() > min) {
3982
- item.remove();
3983
- updateAddButton();
4000
+ handleRemoveItem(item);
3984
4001
  }
3985
4002
  };
3986
4003
  item.style.position = "relative";
@@ -4038,15 +4055,16 @@ function validateContainerElement(element, key, context) {
4038
4055
  "[data-container-item]"
4039
4056
  );
4040
4057
  const containerWrappers = Array.from(allContainerWrappers).filter((el) => {
4041
- const attr = el.getAttribute("data-container-item");
4042
- return attr?.startsWith(`${key}[`);
4058
+ const attr = el.getAttribute("data-container-item") || "";
4059
+ if (!attr.startsWith(`${key}[`)) return false;
4060
+ const suffix = attr.slice(key.length);
4061
+ return /^\[\d+\]$/.test(suffix);
4043
4062
  });
4044
- const itemCount = containerWrappers.length;
4045
- for (let i = 0; i < itemCount; i++) {
4063
+ containerWrappers.forEach((itemContainer) => {
4046
4064
  const itemData = {};
4047
- const itemContainer = scopeRoot.querySelector(
4048
- `[data-container-item="${key}[${i}]"]`
4049
- ) || scopeRoot;
4065
+ const containerAttr = itemContainer.getAttribute("data-container-item") || "";
4066
+ const indexMatch = containerAttr.match(/\[(\d+)\]$/);
4067
+ const domIndex = indexMatch ? parseInt(indexMatch[1], 10) : 0;
4050
4068
  element.elements.forEach((child) => {
4051
4069
  if (child.enableIf) {
4052
4070
  try {
@@ -4063,7 +4081,7 @@ function validateContainerElement(element, key, context) {
4063
4081
  }
4064
4082
  } catch (error) {
4065
4083
  console.error(
4066
- `Error evaluating enableIf for field "${child.key}" in container "${key}[${i}]":`,
4084
+ `Error evaluating enableIf for field "${child.key}" in container "${key}[${domIndex}]":`,
4067
4085
  error
4068
4086
  );
4069
4087
  }
@@ -4071,7 +4089,7 @@ function validateContainerElement(element, key, context) {
4071
4089
  if (child.hidden || child.type === "hidden") {
4072
4090
  itemData[child.key] = child.default !== void 0 ? child.default : null;
4073
4091
  } else {
4074
- const childKey = `${key}[${i}].${child.key}`;
4092
+ const childKey = `${key}[${domIndex}].${child.key}`;
4075
4093
  itemData[child.key] = validateElement(
4076
4094
  { ...child, key: childKey },
4077
4095
  { path },
@@ -4080,7 +4098,7 @@ function validateContainerElement(element, key, context) {
4080
4098
  }
4081
4099
  });
4082
4100
  items.push(itemData);
4083
- }
4101
+ });
4084
4102
  validateContainerCount(key, items, element);
4085
4103
  return { value: items, errors };
4086
4104
  } else {
@@ -4297,7 +4315,8 @@ function shouldDisableElement(element, ctx) {
4297
4315
  }
4298
4316
  try {
4299
4317
  const rootFormData = ctx.formData ?? ctx.prefill ?? {};
4300
- const containerData = ctx.path ? getValueByPath(rootFormData, ctx.path) : void 0;
4318
+ const scope = element.enableIf.scope ?? "relative";
4319
+ const containerData = scope === "relative" && ctx.path ? ctx.prefill : void 0;
4301
4320
  const shouldEnable = evaluateEnableCondition(
4302
4321
  element.enableIf,
4303
4322
  rootFormData,
@@ -5730,8 +5749,18 @@ var FormBuilderInstance = class {
5730
5749
  if ((element.type === "container" || element.type === "group") && "elements" in element && element.elements) {
5731
5750
  const containerData = formData?.[element.key];
5732
5751
  if (Array.isArray(containerData)) {
5733
- containerData.forEach((_, index) => {
5734
- checkElements(element.elements, `${fullPath}[${index}]`);
5752
+ const containerItems = this.state.formRoot.querySelectorAll(
5753
+ `[data-container-item]`
5754
+ );
5755
+ const directItems = Array.from(containerItems).filter((el) => {
5756
+ const attr = el.getAttribute("data-container-item") || "";
5757
+ if (!attr.startsWith(`${fullPath}[`)) return false;
5758
+ const suffix = attr.slice(fullPath.length);
5759
+ return /^\[\d+\]$/.test(suffix);
5760
+ });
5761
+ directItems.forEach((el) => {
5762
+ const attr = el.getAttribute("data-container-item") || "";
5763
+ checkElements(element.elements, attr);
5735
5764
  });
5736
5765
  } else {
5737
5766
  checkElements(element.elements, fullPath);