@dmitryvim/form-builder 0.3.1 → 0.3.3

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.
@@ -492,6 +492,21 @@ function applyAutoExpand(textarea) {
492
492
  setTimeout(() => {
493
493
  if (textarea.isConnected) resize();
494
494
  }, 0);
495
+ if (typeof ResizeObserver === "undefined") return;
496
+ let lastWidth = -1;
497
+ const ro = new ResizeObserver((entries) => {
498
+ var _a, _b, _c, _d, _e;
499
+ if (!textarea.isConnected) {
500
+ ro.disconnect();
501
+ return;
502
+ }
503
+ const entry = entries[0];
504
+ const w = (_e = (_d = (_b = (_a = entry == null ? void 0 : entry.contentBoxSize) == null ? void 0 : _a[0]) == null ? void 0 : _b.inlineSize) != null ? _d : (_c = entry == null ? void 0 : entry.contentRect) == null ? void 0 : _c.width) != null ? _e : 0;
505
+ if (w === lastWidth) return;
506
+ lastWidth = w;
507
+ resize();
508
+ });
509
+ ro.observe(textarea);
495
510
  }
496
511
  function applySingleLineMode(textarea) {
497
512
  textarea.addEventListener("keydown", (e) => {
@@ -6811,6 +6826,7 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
6811
6826
  formData: (_b = ctx.formData) != null ? _b : ctx.prefill,
6812
6827
  // Complete root data for enableIf evaluation
6813
6828
  state: ctx.state,
6829
+ instance: ctx.instance,
6814
6830
  inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
6815
6831
  };
6816
6832
  element.elements.forEach((child) => {
@@ -6899,6 +6915,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6899
6915
  const currentFormData = state.formRoot ? extractRootFormData(state.formRoot) : {};
6900
6916
  const subCtx = {
6901
6917
  state: ctx.state,
6918
+ instance: ctx.instance,
6902
6919
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6903
6920
  prefill: childDefaults,
6904
6921
  // Defaults for enableIf evaluation
@@ -6966,6 +6983,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6966
6983
  const mergedPrefill = mergeWithDefaults(prefillObj || {}, childDefaults);
6967
6984
  const subCtx = {
6968
6985
  state: ctx.state,
6986
+ instance: ctx.instance,
6969
6987
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6970
6988
  prefill: mergedPrefill,
6971
6989
  // Merged prefill with defaults for enableIf
@@ -7013,6 +7031,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
7013
7031
  const idx = countItems();
7014
7032
  const subCtx = {
7015
7033
  state: ctx.state,
7034
+ instance: ctx.instance,
7016
7035
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
7017
7036
  prefill: childDefaults,
7018
7037
  // Defaults for enableIf evaluation
@@ -8688,6 +8707,21 @@ function applyAutoExpand2(textarea, backdrop) {
8688
8707
  setTimeout(() => {
8689
8708
  if (textarea.isConnected) resize();
8690
8709
  }, 0);
8710
+ if (typeof ResizeObserver === "undefined") return;
8711
+ let lastWidth = -1;
8712
+ const ro = new ResizeObserver((entries) => {
8713
+ var _a, _b, _c, _d, _e;
8714
+ if (!textarea.isConnected) {
8715
+ ro.disconnect();
8716
+ return;
8717
+ }
8718
+ const entry = entries[0];
8719
+ const w = (_e = (_d = (_b = (_a = entry == null ? void 0 : entry.contentBoxSize) == null ? void 0 : _a[0]) == null ? void 0 : _b.inlineSize) != null ? _d : (_c = entry == null ? void 0 : entry.contentRect) == null ? void 0 : _c.width) != null ? _e : 0;
8720
+ if (w === lastWidth) return;
8721
+ lastWidth = w;
8722
+ resize();
8723
+ });
8724
+ ro.observe(textarea);
8691
8725
  }
8692
8726
  function buildFileLabels(files, state) {
8693
8727
  var _a, _b, _c, _d;
@@ -10498,8 +10532,35 @@ function extractDOMValue(fieldPath, formRoot) {
10498
10532
  }
10499
10533
  return void 0;
10500
10534
  }
10535
+ function buildScopedDataAtPath(path, value) {
10536
+ const segments = path.match(/[^.[\]]+|\[\d+\]/g);
10537
+ if (!segments || segments.length === 0) {
10538
+ return {};
10539
+ }
10540
+ const root = {};
10541
+ let current = root;
10542
+ for (let i = 0; i < segments.length - 1; i++) {
10543
+ const seg = segments[i];
10544
+ const next = segments[i + 1];
10545
+ const placeholder = next.startsWith("[") && next.endsWith("]") ? [] : {};
10546
+ if (seg.startsWith("[") && seg.endsWith("]")) {
10547
+ const idx = parseInt(seg.slice(1, -1), 10);
10548
+ current[idx] = placeholder;
10549
+ } else {
10550
+ current[seg] = placeholder;
10551
+ }
10552
+ current = placeholder;
10553
+ }
10554
+ const last = segments[segments.length - 1];
10555
+ if (last.startsWith("[") && last.endsWith("]")) {
10556
+ current[parseInt(last.slice(1, -1), 10)] = value;
10557
+ } else {
10558
+ current[last] = value;
10559
+ }
10560
+ return root;
10561
+ }
10501
10562
  function reevaluateEnableIf(wrapper, element, ctx) {
10502
- var _a, _b;
10563
+ var _a;
10503
10564
  if (!element.enableIf) {
10504
10565
  return;
10505
10566
  }
@@ -10510,54 +10571,13 @@ function reevaluateEnableIf(wrapper, element, ctx) {
10510
10571
  }
10511
10572
  const condition = element.enableIf;
10512
10573
  const scope = (_a = condition.scope) != null ? _a : "relative";
10513
- let rootFormData = {};
10514
- const containerData = {};
10515
10574
  const effectiveScope = !ctx.path || ctx.path === "" ? "absolute" : scope;
10516
- if (effectiveScope === "relative" && ctx.path) {
10517
- const containerMatch = ctx.path.match(/^(.+)\[(\d+)\]$/);
10518
- if (containerMatch) {
10519
- const containerKey = containerMatch[1];
10520
- const containerIndex = parseInt(containerMatch[2], 10);
10521
- const containerItemElement = formRoot.querySelector(
10522
- `[data-container-item="${containerKey}[${containerIndex}]"]`
10523
- );
10524
- if (containerItemElement) {
10525
- const inputs = containerItemElement.querySelectorAll("input, select, textarea");
10526
- inputs.forEach((input) => {
10527
- const fieldName = input.getAttribute("name");
10528
- if (fieldName) {
10529
- const fieldKeyMatch = fieldName.match(/\.([^.[\]]+)$/);
10530
- if (fieldKeyMatch) {
10531
- const fieldKey = fieldKeyMatch[1];
10532
- if (input instanceof HTMLSelectElement) {
10533
- containerData[fieldKey] = input.value;
10534
- } else if (input instanceof HTMLInputElement) {
10535
- if (input.type === "checkbox") {
10536
- containerData[fieldKey] = input.checked;
10537
- } else if (input.type === "radio") {
10538
- if (input.checked) {
10539
- containerData[fieldKey] = input.value;
10540
- }
10541
- } else {
10542
- containerData[fieldKey] = input.value;
10543
- }
10544
- } else if (input instanceof HTMLTextAreaElement) {
10545
- containerData[fieldKey] = input.value;
10546
- }
10547
- }
10548
- }
10549
- });
10550
- }
10551
- }
10552
- } else {
10553
- const dependencyKey = condition.key;
10554
- const dependencyValue = extractDOMValue(dependencyKey, formRoot);
10555
- if (dependencyValue !== void 0) {
10556
- rootFormData[dependencyKey] = dependencyValue;
10557
- } else {
10558
- rootFormData = (_b = ctx.formData) != null ? _b : ctx.prefill;
10559
- }
10560
- }
10575
+ const dependencyKey = condition.key;
10576
+ const dependencyFieldPath = effectiveScope === "relative" && ctx.path ? `${ctx.path}.${dependencyKey}` : dependencyKey;
10577
+ const dependencyValue = extractDOMValue(dependencyFieldPath, formRoot);
10578
+ const scopedData = buildScopedDataAtPath(dependencyKey, dependencyValue);
10579
+ const rootFormData = effectiveScope === "relative" ? {} : scopedData;
10580
+ const containerData = effectiveScope === "relative" ? scopedData : void 0;
10561
10581
  try {
10562
10582
  const shouldEnable = evaluateEnableCondition(
10563
10583
  condition,
@@ -10611,8 +10631,10 @@ function setupEnableIfListeners(wrapper, element, ctx) {
10611
10631
  reevaluateEnableIf(wrapper, element, ctx);
10612
10632
  });
10613
10633
  observer.disconnect();
10634
+ ctx.state.enableIfObservers.delete(observer);
10614
10635
  }
10615
10636
  });
10637
+ ctx.state.enableIfObservers.add(observer);
10616
10638
  observer.observe(formRoot, {
10617
10639
  childList: true,
10618
10640
  subtree: true
@@ -11010,7 +11032,8 @@ function createInstanceState(config) {
11010
11032
  debounceTimer: null,
11011
11033
  prefill: {},
11012
11034
  syntheticElementIds: /* @__PURE__ */ new WeakMap(),
11013
- syntheticElementIdCounter: 0
11035
+ syntheticElementIdCounter: 0,
11036
+ enableIfObservers: /* @__PURE__ */ new Set()
11014
11037
  };
11015
11038
  }
11016
11039
  function generateInstanceId() {
@@ -11692,6 +11715,7 @@ var FormBuilderInstance = class {
11692
11715
  console.error("Schema validation errors:", errors);
11693
11716
  return;
11694
11717
  }
11718
+ this.disconnectEnableIfObservers();
11695
11719
  this.state.formRoot = root;
11696
11720
  this.state.schema = schema;
11697
11721
  this.state.externalActions = actions || null;
@@ -12129,6 +12153,7 @@ var FormBuilderInstance = class {
12129
12153
  clearTimeout(this.state.debounceTimer);
12130
12154
  this.state.debounceTimer = null;
12131
12155
  }
12156
+ this.disconnectEnableIfObservers();
12132
12157
  this.state.resourceIndex.clear();
12133
12158
  if (this.state.formRoot) {
12134
12159
  clear(this.state.formRoot);
@@ -12140,6 +12165,12 @@ var FormBuilderInstance = class {
12140
12165
  (_a = globalThis.__formBuilderInstances) == null ? void 0 : _a.delete(this.instanceId);
12141
12166
  }
12142
12167
  }
12168
+ disconnectEnableIfObservers() {
12169
+ for (const observer of this.state.enableIfObservers) {
12170
+ observer.disconnect();
12171
+ }
12172
+ this.state.enableIfObservers.clear();
12173
+ }
12143
12174
  };
12144
12175
 
12145
12176
  // src/index.ts