footprint-explainable-ui 0.25.2 → 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.
@@ -2066,6 +2066,18 @@ function centerForkParents(graph, options = {}) {
2066
2066
  }
2067
2067
  return minX <= maxX ? Math.max(minX, Math.min(maxX, desiredX)) : x0;
2068
2068
  };
2069
+ const evenFanKids = (forkCenter, kids) => {
2070
+ if (kids.length < 2) return;
2071
+ const sorted = [...kids].sort((a, b) => centerX(a) - centerX(b));
2072
+ let gap = 0;
2073
+ for (let i = 0; i < sorted.length - 1; i++) {
2074
+ gap = Math.max(gap, width.get(sorted[i]) / 2 + nodeSep + width.get(sorted[i + 1]) / 2);
2075
+ }
2076
+ const mid = (sorted.length - 1) / 2;
2077
+ for (let i = 0; i < sorted.length; i++) {
2078
+ workingX.set(sorted[i], forkCenter + (i - mid) * gap - width.get(sorted[i]) / 2);
2079
+ }
2080
+ };
2069
2081
  const order = [...graph.nodes].sort(
2070
2082
  (a, b) => b.position.y - a.position.y || a.position.x - b.position.x || a.id.localeCompare(b.id)
2071
2083
  );
@@ -2084,6 +2096,11 @@ function centerForkParents(graph, options = {}) {
2084
2096
  const wN = width.get(n.id);
2085
2097
  const span = (Math.min(...centers) + Math.max(...centers)) / 2;
2086
2098
  workingX.set(n.id, clampX(n.id, span - wN / 2));
2099
+ if (isFork) {
2100
+ const succSets = kin.map((k) => childrenOf.get(k) ?? []);
2101
+ const isDiamond = kin.length >= 2 && succSets[0].some((s) => succSets.every((ss) => ss.includes(s)));
2102
+ if (isDiamond) evenFanKids(centerX(n.id), kin);
2103
+ }
2087
2104
  const stepOf = isFork ? predsOf : childrenOf;
2088
2105
  let curId = n.id;
2089
2106
  const walked = /* @__PURE__ */ new Set([curId]);
@@ -2100,6 +2117,28 @@ function centerForkParents(graph, options = {}) {
2100
2117
  curId = m;
2101
2118
  }
2102
2119
  }
2120
+ for (const n of order) {
2121
+ const outD = outDegree.get(n.id) ?? 0;
2122
+ const inD = inDegree.get(n.id) ?? 0;
2123
+ if (!(outD >= 2 && inD <= 1)) continue;
2124
+ const kids = (childrenOf.get(n.id) ?? []).filter(
2125
+ (k) => byId.get(k)?.parentId === n.parentId
2126
+ );
2127
+ if (kids.length < 2) continue;
2128
+ const succSets = kids.map((k) => childrenOf.get(k) ?? []);
2129
+ const isDiamond = succSets[0].some((s) => succSets.every((ss) => ss.includes(s)));
2130
+ if (isDiamond) continue;
2131
+ const ps = predsOf.get(n.id);
2132
+ if (!ps || ps.length !== 1) continue;
2133
+ const pred = ps[0];
2134
+ if ((outDegree.get(pred) ?? 0) !== 1) continue;
2135
+ if (byId.get(pred)?.parentId !== byId.get(n.id)?.parentId) continue;
2136
+ const before = centerX(n.id);
2137
+ workingX.set(n.id, clampX(n.id, centerX(pred) - width.get(n.id) / 2));
2138
+ const delta = centerX(n.id) - before;
2139
+ if (delta === 0) continue;
2140
+ for (const k of kids) workingX.set(k, clampX(k, workingX.get(k) + delta));
2141
+ }
2103
2142
  const nodes = graph.nodes.map(
2104
2143
  (n) => workingX.get(n.id) === n.position.x ? n : { ...n, position: { x: workingX.get(n.id), y: n.position.y } }
2105
2144
  );