footprint-explainable-ui 0.25.1 → 0.25.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/flowchart.js CHANGED
@@ -1875,7 +1875,7 @@ function TraceFlow(props) {
1875
1875
  }
1876
1876
 
1877
1877
  // src/components/FlowchartView/TracedFlow.tsx
1878
- import { useCallback as useCallback3, useMemo as useMemo5, useRef as useRef5, useState as useState4 } from "react";
1878
+ import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState4 } from "react";
1879
1879
  import {
1880
1880
  ReactFlow as ReactFlow2,
1881
1881
  Background as Background2,
@@ -1883,6 +1883,16 @@ import {
1883
1883
  MarkerType as MarkerType2
1884
1884
  } from "@xyflow/react";
1885
1885
 
1886
+ // src/components/FlowchartView/_internal/devWarn.ts
1887
+ function isDevModeEnv() {
1888
+ const proc = globalThis.process;
1889
+ return proc?.env?.NODE_ENV !== "production";
1890
+ }
1891
+ function devWarn(messageFn, ...extras) {
1892
+ if (!isDevModeEnv()) return;
1893
+ console.warn(messageFn(), ...extras);
1894
+ }
1895
+
1886
1896
  // src/components/FlowchartView/_internal/snapLinearSuccessors.ts
1887
1897
  function snapLinearSuccessors(graph, options = {}) {
1888
1898
  if (graph.nodes.length === 0) return graph;
@@ -1984,36 +1994,79 @@ function centerForkParents(graph, options = {}) {
1984
1994
  }
1985
1995
  return minX <= maxX ? Math.max(minX, Math.min(maxX, desiredX)) : x0;
1986
1996
  };
1997
+ const evenFanKids = (forkCenter, kids) => {
1998
+ if (kids.length < 2) return;
1999
+ const sorted = [...kids].sort((a, b) => centerX(a) - centerX(b));
2000
+ let gap = 0;
2001
+ for (let i = 0; i < sorted.length - 1; i++) {
2002
+ gap = Math.max(gap, width.get(sorted[i]) / 2 + nodeSep + width.get(sorted[i + 1]) / 2);
2003
+ }
2004
+ const mid = (sorted.length - 1) / 2;
2005
+ for (let i = 0; i < sorted.length; i++) {
2006
+ workingX.set(sorted[i], forkCenter + (i - mid) * gap - width.get(sorted[i]) / 2);
2007
+ }
2008
+ };
1987
2009
  const order = [...graph.nodes].sort(
1988
2010
  (a, b) => b.position.y - a.position.y || a.position.x - b.position.x || a.id.localeCompare(b.id)
1989
2011
  );
1990
2012
  for (const n of order) {
1991
- if ((outDegree.get(n.id) ?? 0) < 2) continue;
1992
- if ((inDegree.get(n.id) ?? 0) > 1) continue;
1993
- const kids = (childrenOf.get(n.id) ?? []).filter(
2013
+ const outD = outDegree.get(n.id) ?? 0;
2014
+ const inD = inDegree.get(n.id) ?? 0;
2015
+ const isFork = outD >= 2 && inD <= 1;
2016
+ const isMerge = inD >= 2 && outD <= 1;
2017
+ if (!isFork && !isMerge) continue;
2018
+ const kin = ((isFork ? childrenOf.get(n.id) : predsOf.get(n.id)) ?? []).filter(
1994
2019
  (k) => byId.get(k)?.parentId === n.parentId
1995
2020
  // same compound only
1996
2021
  );
1997
- if (kids.length < 2) continue;
1998
- const centers = kids.map(centerX);
2022
+ if (kin.length < 2) continue;
2023
+ const centers = kin.map(centerX);
1999
2024
  const wN = width.get(n.id);
2000
2025
  const span = (Math.min(...centers) + Math.max(...centers)) / 2;
2001
2026
  workingX.set(n.id, clampX(n.id, span - wN / 2));
2027
+ if (isFork) {
2028
+ const succSets = kin.map((k) => childrenOf.get(k) ?? []);
2029
+ const isDiamond = kin.length >= 2 && succSets[0].some((s) => succSets.every((ss) => ss.includes(s)));
2030
+ if (isDiamond) evenFanKids(centerX(n.id), kin);
2031
+ }
2032
+ const stepOf = isFork ? predsOf : childrenOf;
2002
2033
  let curId = n.id;
2003
2034
  const walked = /* @__PURE__ */ new Set([curId]);
2004
2035
  for (; ; ) {
2005
- const ps = predsOf.get(curId);
2006
- if (!ps || ps.length !== 1) break;
2007
- const p = ps[0];
2008
- if (walked.has(p)) break;
2009
- if ((outDegree.get(p) ?? 0) !== 1) break;
2010
- if ((inDegree.get(p) ?? 0) > 1) break;
2011
- if (byId.get(p)?.parentId !== byId.get(curId)?.parentId) break;
2012
- workingX.set(p, clampX(p, centerX(curId) - width.get(p) / 2));
2013
- walked.add(p);
2014
- curId = p;
2036
+ const nexts = stepOf.get(curId);
2037
+ if (!nexts || nexts.length !== 1) break;
2038
+ const m = nexts[0];
2039
+ if (walked.has(m)) break;
2040
+ if ((outDegree.get(m) ?? 0) > 1) break;
2041
+ if ((inDegree.get(m) ?? 0) > 1) break;
2042
+ if (byId.get(m)?.parentId !== byId.get(curId)?.parentId) break;
2043
+ workingX.set(m, clampX(m, centerX(curId) - width.get(m) / 2));
2044
+ walked.add(m);
2045
+ curId = m;
2015
2046
  }
2016
2047
  }
2048
+ for (const n of order) {
2049
+ const outD = outDegree.get(n.id) ?? 0;
2050
+ const inD = inDegree.get(n.id) ?? 0;
2051
+ if (!(outD >= 2 && inD <= 1)) continue;
2052
+ const kids = (childrenOf.get(n.id) ?? []).filter(
2053
+ (k) => byId.get(k)?.parentId === n.parentId
2054
+ );
2055
+ if (kids.length < 2) continue;
2056
+ const succSets = kids.map((k) => childrenOf.get(k) ?? []);
2057
+ const isDiamond = succSets[0].some((s) => succSets.every((ss) => ss.includes(s)));
2058
+ if (isDiamond) continue;
2059
+ const ps = predsOf.get(n.id);
2060
+ if (!ps || ps.length !== 1) continue;
2061
+ const pred = ps[0];
2062
+ if ((outDegree.get(pred) ?? 0) !== 1) continue;
2063
+ if (byId.get(pred)?.parentId !== byId.get(n.id)?.parentId) continue;
2064
+ const before = centerX(n.id);
2065
+ workingX.set(n.id, clampX(n.id, centerX(pred) - width.get(n.id) / 2));
2066
+ const delta = centerX(n.id) - before;
2067
+ if (delta === 0) continue;
2068
+ for (const k of kids) workingX.set(k, clampX(k, workingX.get(k) + delta));
2069
+ }
2017
2070
  const nodes = graph.nodes.map(
2018
2071
  (n) => workingX.get(n.id) === n.position.x ? n : { ...n, position: { x: workingX.get(n.id), y: n.position.y } }
2019
2072
  );
@@ -2023,16 +2076,6 @@ function withForkCentering(base, options = {}) {
2023
2076
  return (graph) => centerForkParents(base(graph), options);
2024
2077
  }
2025
2078
 
2026
- // src/components/FlowchartView/_internal/devWarn.ts
2027
- function isDevModeEnv() {
2028
- const proc = globalThis.process;
2029
- return proc?.env?.NODE_ENV !== "production";
2030
- }
2031
- function devWarn(messageFn, ...extras) {
2032
- if (!isDevModeEnv()) return;
2033
- console.warn(messageFn(), ...extras);
2034
- }
2035
-
2036
2079
  // src/components/FlowchartView/_internal/notifyChange.ts
2037
2080
  function createNotifier(label = "notifier") {
2038
2081
  const listeners = /* @__PURE__ */ new Set();
@@ -2572,6 +2615,13 @@ function TracedFlow({
2572
2615
  style
2573
2616
  }) {
2574
2617
  const layout = layoutProp ?? dagreTraceLayout;
2618
+ useEffect7(() => {
2619
+ if (layoutProp === dagreTraceLayout) {
2620
+ devWarn(
2621
+ () => "[footprint-explainable-ui] <TracedFlow layout={dagreTraceLayout}> bypasses the built-in measure-then-layout pipeline (content-exact sizing, fork/merge centering, straight spines). OMIT the `layout` prop to use it \u2014 passing the raw dagreTraceLayout silently forfeits every layout improvement eui ships."
2622
+ );
2623
+ }
2624
+ }, [layoutProp]);
2575
2625
  const colors = useMemo5(
2576
2626
  () => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
2577
2627
  [colorOverrides]