@allhailai/formfoundry-core 1.2.0 → 1.2.1

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/index.cjs CHANGED
@@ -117,13 +117,28 @@ function createHookDispatcher() {
117
117
  };
118
118
  return next(payload);
119
119
  },
120
- // BUG-34 fix: async dispatch that awaits each middleware result
120
+ // BUG-34 + E1 fix: async dispatch that processes middleware sequentially.
121
+ // Unlike dispatch() (recursive chain with wrapping), dispatchAsync uses
122
+ // a sequential pipeline: each middleware receives the output of the
123
+ // previous one. Short-circuiting works by not calling next().
124
+ // This is intentionally different from dispatch() because sync middleware
125
+ // cannot await async next() calls, so wrapping patterns don't compose.
121
126
  async dispatchAsync(payload) {
122
127
  if (middlewares.length === 0) return payload;
123
128
  let current = payload;
124
129
  for (const middleware of middlewares) {
125
- const result = middleware(current, (p) => p);
126
- current = result instanceof Promise ? await result : result;
130
+ let called = false;
131
+ const next = (p) => {
132
+ called = true;
133
+ current = p;
134
+ return p;
135
+ };
136
+ const result = middleware(current, next);
137
+ if (result instanceof Promise) {
138
+ current = await result;
139
+ } else if (!called) {
140
+ return result;
141
+ } else ;
127
142
  }
128
143
  return current;
129
144
  }
@@ -545,13 +560,20 @@ function createNode(options = {}) {
545
560
  if (node.type === "group" && node.children.length > 0) {
546
561
  const obj = typeof resetValue === "object" && resetValue !== null && !Array.isArray(resetValue) ? resetValue : void 0;
547
562
  for (const child of node.children) {
563
+ const savedParent = child.parent;
564
+ child.parent = null;
548
565
  child.reset(obj?.[child.name]);
566
+ child.parent = savedParent;
549
567
  }
550
568
  recomputeValue(node);
551
569
  } else if (node.type === "list" && node.children.length > 0) {
552
570
  const arr = Array.isArray(resetValue) ? resetValue : void 0;
553
571
  for (let i = 0; i < node.children.length; i++) {
554
- node.children[i].reset(arr?.[i]);
572
+ const child = node.children[i];
573
+ const savedParent = child.parent;
574
+ child.parent = null;
575
+ child.reset(arr?.[i]);
576
+ child.parent = savedParent;
555
577
  }
556
578
  recomputeValue(node);
557
579
  } else {
@@ -577,10 +599,14 @@ function createNode(options = {}) {
577
599
  * before settlement completes.
578
600
  */
579
601
  async settle() {
580
- if (pendingCount <= 0) return;
581
- return new Promise((resolve) => {
582
- settleResolvers.push(resolve);
583
- });
602
+ if (pendingCount > 0) {
603
+ await new Promise((resolve) => {
604
+ settleResolvers.push(resolve);
605
+ });
606
+ }
607
+ for (const child of node.children) {
608
+ await child.settle();
609
+ }
584
610
  },
585
611
  async submit() {
586
612
  }
@@ -1375,8 +1401,13 @@ function useFormFoundryField(options) {
1375
1401
  }, [validationBehavior, validate, node]);
1376
1402
  const depsKey = dependsOn?.join(",") ?? "";
1377
1403
  const depsValues = dependsOn?.map((dep) => JSON.stringify(getValue(dep))).join("|") ?? "";
1404
+ const depsInitializedRef = React4.useRef(false);
1378
1405
  React4.useEffect(() => {
1379
1406
  if (!dependsOn || dependsOn.length === 0) return;
1407
+ if (!depsInitializedRef.current) {
1408
+ depsInitializedRef.current = true;
1409
+ return;
1410
+ }
1380
1411
  if (touched || hasBlurredRef.current) {
1381
1412
  void validate();
1382
1413
  }
@@ -1471,7 +1502,7 @@ function useFormNode(id) {
1471
1502
  return id ? getNode(id) : void 0;
1472
1503
  }
1473
1504
  function useFormNodes(ids) {
1474
- const [, forceRender] = React4.useState(0);
1505
+ const [renderCount, forceRender] = React4.useState(0);
1475
1506
  const nodeUnsubsRef = React4.useRef(/* @__PURE__ */ new Map());
1476
1507
  const triggerRender = React4.useCallback(() => {
1477
1508
  forceRender((n) => n + 1);
@@ -1512,11 +1543,13 @@ function useFormNodes(ids) {
1512
1543
  nodeUnsubsRef.current.clear();
1513
1544
  };
1514
1545
  }, [idsKey, triggerRender]);
1515
- const result = /* @__PURE__ */ new Map();
1516
- for (const id of ids) {
1517
- result.set(id, getNode(id));
1518
- }
1519
- return result;
1546
+ return React4.useMemo(() => {
1547
+ const result = /* @__PURE__ */ new Map();
1548
+ for (const id of ids) {
1549
+ result.set(id, getNode(id));
1550
+ }
1551
+ return result;
1552
+ }, [idsKey, renderCount]);
1520
1553
  }
1521
1554
  function useFormPrint(defaultOptions) {
1522
1555
  const { values } = useFormValues();