@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.
package/dist/esm/index.js CHANGED
@@ -484,6 +484,20 @@ function applyAutoExpand(textarea) {
484
484
  setTimeout(() => {
485
485
  if (textarea.isConnected) resize();
486
486
  }, 0);
487
+ if (typeof ResizeObserver === "undefined") return;
488
+ let lastWidth = -1;
489
+ const ro = new ResizeObserver((entries) => {
490
+ if (!textarea.isConnected) {
491
+ ro.disconnect();
492
+ return;
493
+ }
494
+ const entry = entries[0];
495
+ const w = entry?.contentBoxSize?.[0]?.inlineSize ?? entry?.contentRect?.width ?? 0;
496
+ if (w === lastWidth) return;
497
+ lastWidth = w;
498
+ resize();
499
+ });
500
+ ro.observe(textarea);
487
501
  }
488
502
  function applySingleLineMode(textarea) {
489
503
  textarea.addEventListener("keydown", (e) => {
@@ -6711,6 +6725,7 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
6711
6725
  formData: ctx.formData ?? ctx.prefill,
6712
6726
  // Complete root data for enableIf evaluation
6713
6727
  state: ctx.state,
6728
+ instance: ctx.instance,
6714
6729
  inheritedReadonly: containerIsReadonly || ctx.inheritedReadonly
6715
6730
  };
6716
6731
  element.elements.forEach((child) => {
@@ -6797,6 +6812,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6797
6812
  const currentFormData = state.formRoot ? extractRootFormData(state.formRoot) : {};
6798
6813
  const subCtx = {
6799
6814
  state: ctx.state,
6815
+ instance: ctx.instance,
6800
6816
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6801
6817
  prefill: childDefaults,
6802
6818
  // Defaults for enableIf evaluation
@@ -6862,6 +6878,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6862
6878
  const mergedPrefill = mergeWithDefaults(prefillObj || {}, childDefaults);
6863
6879
  const subCtx = {
6864
6880
  state: ctx.state,
6881
+ instance: ctx.instance,
6865
6882
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6866
6883
  prefill: mergedPrefill,
6867
6884
  // Merged prefill with defaults for enableIf
@@ -6908,6 +6925,7 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
6908
6925
  const idx = countItems();
6909
6926
  const subCtx = {
6910
6927
  state: ctx.state,
6928
+ instance: ctx.instance,
6911
6929
  path: pathJoin(ctx.path, `${element.key}[${idx}]`),
6912
6930
  prefill: childDefaults,
6913
6931
  // Defaults for enableIf evaluation
@@ -8550,6 +8568,20 @@ function applyAutoExpand2(textarea, backdrop) {
8550
8568
  setTimeout(() => {
8551
8569
  if (textarea.isConnected) resize();
8552
8570
  }, 0);
8571
+ if (typeof ResizeObserver === "undefined") return;
8572
+ let lastWidth = -1;
8573
+ const ro = new ResizeObserver((entries) => {
8574
+ if (!textarea.isConnected) {
8575
+ ro.disconnect();
8576
+ return;
8577
+ }
8578
+ const entry = entries[0];
8579
+ const w = entry?.contentBoxSize?.[0]?.inlineSize ?? entry?.contentRect?.width ?? 0;
8580
+ if (w === lastWidth) return;
8581
+ lastWidth = w;
8582
+ resize();
8583
+ });
8584
+ ro.observe(textarea);
8553
8585
  }
8554
8586
  function buildFileLabels(files, state) {
8555
8587
  const labels = /* @__PURE__ */ new Map();
@@ -10315,6 +10347,33 @@ function extractDOMValue(fieldPath, formRoot) {
10315
10347
  }
10316
10348
  return void 0;
10317
10349
  }
10350
+ function buildScopedDataAtPath(path, value) {
10351
+ const segments = path.match(/[^.[\]]+|\[\d+\]/g);
10352
+ if (!segments || segments.length === 0) {
10353
+ return {};
10354
+ }
10355
+ const root = {};
10356
+ let current = root;
10357
+ for (let i = 0; i < segments.length - 1; i++) {
10358
+ const seg = segments[i];
10359
+ const next = segments[i + 1];
10360
+ const placeholder = next.startsWith("[") && next.endsWith("]") ? [] : {};
10361
+ if (seg.startsWith("[") && seg.endsWith("]")) {
10362
+ const idx = parseInt(seg.slice(1, -1), 10);
10363
+ current[idx] = placeholder;
10364
+ } else {
10365
+ current[seg] = placeholder;
10366
+ }
10367
+ current = placeholder;
10368
+ }
10369
+ const last = segments[segments.length - 1];
10370
+ if (last.startsWith("[") && last.endsWith("]")) {
10371
+ current[parseInt(last.slice(1, -1), 10)] = value;
10372
+ } else {
10373
+ current[last] = value;
10374
+ }
10375
+ return root;
10376
+ }
10318
10377
  function reevaluateEnableIf(wrapper, element, ctx) {
10319
10378
  if (!element.enableIf) {
10320
10379
  return;
@@ -10326,54 +10385,13 @@ function reevaluateEnableIf(wrapper, element, ctx) {
10326
10385
  }
10327
10386
  const condition = element.enableIf;
10328
10387
  const scope = condition.scope ?? "relative";
10329
- let rootFormData = {};
10330
- const containerData = {};
10331
10388
  const effectiveScope = !ctx.path || ctx.path === "" ? "absolute" : scope;
10332
- if (effectiveScope === "relative" && ctx.path) {
10333
- const containerMatch = ctx.path.match(/^(.+)\[(\d+)\]$/);
10334
- if (containerMatch) {
10335
- const containerKey = containerMatch[1];
10336
- const containerIndex = parseInt(containerMatch[2], 10);
10337
- const containerItemElement = formRoot.querySelector(
10338
- `[data-container-item="${containerKey}[${containerIndex}]"]`
10339
- );
10340
- if (containerItemElement) {
10341
- const inputs = containerItemElement.querySelectorAll("input, select, textarea");
10342
- inputs.forEach((input) => {
10343
- const fieldName = input.getAttribute("name");
10344
- if (fieldName) {
10345
- const fieldKeyMatch = fieldName.match(/\.([^.[\]]+)$/);
10346
- if (fieldKeyMatch) {
10347
- const fieldKey = fieldKeyMatch[1];
10348
- if (input instanceof HTMLSelectElement) {
10349
- containerData[fieldKey] = input.value;
10350
- } else if (input instanceof HTMLInputElement) {
10351
- if (input.type === "checkbox") {
10352
- containerData[fieldKey] = input.checked;
10353
- } else if (input.type === "radio") {
10354
- if (input.checked) {
10355
- containerData[fieldKey] = input.value;
10356
- }
10357
- } else {
10358
- containerData[fieldKey] = input.value;
10359
- }
10360
- } else if (input instanceof HTMLTextAreaElement) {
10361
- containerData[fieldKey] = input.value;
10362
- }
10363
- }
10364
- }
10365
- });
10366
- }
10367
- }
10368
- } else {
10369
- const dependencyKey = condition.key;
10370
- const dependencyValue = extractDOMValue(dependencyKey, formRoot);
10371
- if (dependencyValue !== void 0) {
10372
- rootFormData[dependencyKey] = dependencyValue;
10373
- } else {
10374
- rootFormData = ctx.formData ?? ctx.prefill;
10375
- }
10376
- }
10389
+ const dependencyKey = condition.key;
10390
+ const dependencyFieldPath = effectiveScope === "relative" && ctx.path ? `${ctx.path}.${dependencyKey}` : dependencyKey;
10391
+ const dependencyValue = extractDOMValue(dependencyFieldPath, formRoot);
10392
+ const scopedData = buildScopedDataAtPath(dependencyKey, dependencyValue);
10393
+ const rootFormData = effectiveScope === "relative" ? {} : scopedData;
10394
+ const containerData = effectiveScope === "relative" ? scopedData : void 0;
10377
10395
  try {
10378
10396
  const shouldEnable = evaluateEnableCondition(
10379
10397
  condition,
@@ -10426,8 +10444,10 @@ function setupEnableIfListeners(wrapper, element, ctx) {
10426
10444
  reevaluateEnableIf(wrapper, element, ctx);
10427
10445
  });
10428
10446
  observer.disconnect();
10447
+ ctx.state.enableIfObservers.delete(observer);
10429
10448
  }
10430
10449
  });
10450
+ ctx.state.enableIfObservers.add(observer);
10431
10451
  observer.observe(formRoot, {
10432
10452
  childList: true,
10433
10453
  subtree: true
@@ -10824,7 +10844,8 @@ function createInstanceState(config) {
10824
10844
  debounceTimer: null,
10825
10845
  prefill: {},
10826
10846
  syntheticElementIds: /* @__PURE__ */ new WeakMap(),
10827
- syntheticElementIdCounter: 0
10847
+ syntheticElementIdCounter: 0,
10848
+ enableIfObservers: /* @__PURE__ */ new Set()
10828
10849
  };
10829
10850
  }
10830
10851
  function generateInstanceId() {
@@ -11506,6 +11527,7 @@ var FormBuilderInstance = class {
11506
11527
  console.error("Schema validation errors:", errors);
11507
11528
  return;
11508
11529
  }
11530
+ this.disconnectEnableIfObservers();
11509
11531
  this.state.formRoot = root;
11510
11532
  this.state.schema = schema;
11511
11533
  this.state.externalActions = actions || null;
@@ -11936,6 +11958,7 @@ var FormBuilderInstance = class {
11936
11958
  clearTimeout(this.state.debounceTimer);
11937
11959
  this.state.debounceTimer = null;
11938
11960
  }
11961
+ this.disconnectEnableIfObservers();
11939
11962
  this.state.resourceIndex.clear();
11940
11963
  if (this.state.formRoot) {
11941
11964
  clear(this.state.formRoot);
@@ -11947,6 +11970,12 @@ var FormBuilderInstance = class {
11947
11970
  globalThis.__formBuilderInstances?.delete(this.instanceId);
11948
11971
  }
11949
11972
  }
11973
+ disconnectEnableIfObservers() {
11974
+ for (const observer of this.state.enableIfObservers) {
11975
+ observer.disconnect();
11976
+ }
11977
+ this.state.enableIfObservers.clear();
11978
+ }
11950
11979
  };
11951
11980
 
11952
11981
  // src/index.ts