@almadar/ui 5.118.0 → 5.119.0

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.
@@ -34732,11 +34732,11 @@ var init_DocumentViewer = __esm({
34732
34732
  DocumentViewer.displayName = "DocumentViewer";
34733
34733
  }
34734
34734
  });
34735
- function measureLabelWidth(text) {
34735
+ function measureLabelWidth(text, fontFamily = "system-ui") {
34736
34736
  if (typeof document === "undefined") return text.length * 6;
34737
34737
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
34738
34738
  if (!labelMeasureCtx) return text.length * 6;
34739
- labelMeasureCtx.font = "12px system-ui";
34739
+ labelMeasureCtx.font = `12px ${fontFamily}`;
34740
34740
  return labelMeasureCtx.measureText(text).width + 4;
34741
34741
  }
34742
34742
  function getGroupColor(group, groups) {
@@ -34761,6 +34761,9 @@ function mulberry32(a) {
34761
34761
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
34762
34762
  };
34763
34763
  }
34764
+ function edgeKeyOf(a, b) {
34765
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
34766
+ }
34764
34767
  function resolveColor3(color, el) {
34765
34768
  const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
34766
34769
  if (!m) return color;
@@ -34894,6 +34897,7 @@ var init_GraphCanvas = __esm({
34894
34897
  if (!canvas || propNodes.length === 0) return;
34895
34898
  const w = logicalW;
34896
34899
  const h = height;
34900
+ const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
34897
34901
  const prevPos = /* @__PURE__ */ new Map();
34898
34902
  for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
34899
34903
  const simNodes = propNodes.map((n, idx) => {
@@ -34928,10 +34932,15 @@ var init_GraphCanvas = __esm({
34928
34932
  const fullRelayout = !laidOutRef.current || overlap < 0.5;
34929
34933
  if (layout === "force") {
34930
34934
  const maxIterations = 300;
34931
- const tick = () => {
34935
+ const COOL = 0.12;
34936
+ const COLLIDE_PASSES = 6;
34937
+ const LABEL_GAP = 12;
34938
+ const LABEL_H = 16;
34939
+ const tick = (iter) => {
34932
34940
  const nodes = nodesRef.current;
34933
34941
  const centerX = w / 2;
34934
34942
  const centerY = h / 2;
34943
+ const temp = Math.max(COOL, 1 - iter / maxIterations);
34935
34944
  for (const node of nodes) {
34936
34945
  node.fx = 0;
34937
34946
  node.fy = 0;
@@ -34941,7 +34950,7 @@ var init_GraphCanvas = __esm({
34941
34950
  const dx = nodes[j].x - nodes[i].x;
34942
34951
  const dy = nodes[j].y - nodes[i].y;
34943
34952
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34944
- const force = repulsion / (dist * dist);
34953
+ const force = repulsion / (dist * dist) * temp;
34945
34954
  const fx = dx / dist * force;
34946
34955
  const fy = dy / dist * force;
34947
34956
  nodes[i].fx -= fx;
@@ -34951,42 +34960,34 @@ var init_GraphCanvas = __esm({
34951
34960
  }
34952
34961
  }
34953
34962
  const nodeById = new Map(nodes.map((n) => [n.id, n]));
34954
- if (propSimilarity.length > 0) {
34955
- for (const pair of propSimilarity) {
34956
- const source = nodeById.get(pair.source);
34957
- const target = nodeById.get(pair.target);
34958
- if (!source || !target) continue;
34959
- const dx = target.x - source.x;
34960
- const dy = target.y - source.y;
34961
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34962
- const w2 = Math.min(1, Math.max(0, pair.weight));
34963
- const linkTarget = linkDistance * (1 - w2);
34964
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
34965
- const fx = dx / dist * force;
34966
- const fy = dy / dist * force;
34967
- source.fx += fx;
34968
- source.fy += fy;
34969
- target.fx -= fx;
34970
- target.fy -= fy;
34971
- }
34972
- } else {
34973
- for (const edge of propEdges) {
34974
- const source = nodeById.get(edge.source);
34975
- const target = nodeById.get(edge.target);
34976
- if (!source || !target) continue;
34977
- const dx = target.x - source.x;
34978
- const dy = target.y - source.y;
34979
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34980
- const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
34981
- const linkTarget = linkDistance * (0.5 + (1 - w2) * 1.5);
34982
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
34983
- const fx = dx / dist * force;
34984
- const fy = dy / dist * force;
34985
- source.fx += fx;
34986
- source.fy += fy;
34987
- target.fx -= fx;
34988
- target.fy -= fy;
34989
- }
34963
+ const spring = (a, b, rest, k) => {
34964
+ const dx = b.x - a.x;
34965
+ const dy = b.y - a.y;
34966
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34967
+ const force = (dist - rest) * k * temp;
34968
+ const fx = dx / dist * force;
34969
+ const fy = dy / dist * force;
34970
+ a.fx += fx;
34971
+ a.fy += fy;
34972
+ b.fx -= fx;
34973
+ b.fy -= fy;
34974
+ };
34975
+ const drawnPairs = /* @__PURE__ */ new Set();
34976
+ for (const edge of propEdges) {
34977
+ const source = nodeById.get(edge.source);
34978
+ const target = nodeById.get(edge.target);
34979
+ if (!source || !target) continue;
34980
+ drawnPairs.add(edgeKeyOf(edge.source, edge.target));
34981
+ const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
34982
+ spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
34983
+ }
34984
+ for (const pair of propSimilarity) {
34985
+ if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
34986
+ const source = nodeById.get(pair.source);
34987
+ const target = nodeById.get(pair.target);
34988
+ if (!source || !target) continue;
34989
+ const w2 = Math.min(1, Math.max(0, pair.weight));
34990
+ spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
34990
34991
  }
34991
34992
  const centroids = /* @__PURE__ */ new Map();
34992
34993
  for (const node of nodes) {
@@ -35000,14 +35001,20 @@ var init_GraphCanvas = __esm({
35000
35001
  c.y += node.y;
35001
35002
  c.n += 1;
35002
35003
  }
35004
+ const multiCluster = centroids.size > 1;
35003
35005
  for (const node of nodes) {
35004
- const c = centroids.get(node.group ?? "__none__");
35005
- if (c && c.n > 1) {
35006
- node.fx += (c.x / c.n - node.x) * 0.04;
35007
- node.fy += (c.y / c.n - node.y) * 0.04;
35006
+ if (multiCluster) {
35007
+ const c = centroids.get(node.group ?? "__none__");
35008
+ if (c && c.n > 1) {
35009
+ node.fx += (c.x / c.n - node.x) * 0.04 * temp;
35010
+ node.fy += (c.y / c.n - node.y) * 0.04 * temp;
35011
+ } else {
35012
+ node.fx += (centerX - node.x) * 0.01 * temp;
35013
+ node.fy += (centerY - node.y) * 0.01 * temp;
35014
+ }
35008
35015
  } else {
35009
- node.fx += (centerX - node.x) * 0.01;
35010
- node.fy += (centerY - node.y) * 0.01;
35016
+ node.fx += (centerX - node.x) * 8e-3 * temp;
35017
+ node.fy += (centerY - node.y) * 8e-3 * temp;
35011
35018
  }
35012
35019
  }
35013
35020
  const damping = 0.9;
@@ -35019,42 +35026,53 @@ var init_GraphCanvas = __esm({
35019
35026
  node.x = Math.max(30, Math.min(w - 30, node.x));
35020
35027
  node.y = Math.max(30, Math.min(h - 30, node.y));
35021
35028
  }
35022
- const LABEL_GAP = 12;
35023
- const LABEL_H = 16;
35024
35029
  const pad = nodeSpacing / 2;
35025
- for (let i = 0; i < nodes.length; i++) {
35026
- for (let j = i + 1; j < nodes.length; j++) {
35027
- const a = nodes[i];
35028
- const b = nodes[j];
35029
- const ar = a.size || 8;
35030
- const br = b.size || 8;
35031
- if (showLabels) {
35032
- if (a.labelW === void 0) a.labelW = a.label ? measureLabelWidth(a.label) : 0;
35033
- if (b.labelW === void 0) b.labelW = b.label ? measureLabelWidth(b.label) : 0;
35034
- }
35035
- const labelBelow = showLabels ? LABEL_GAP + LABEL_H : 0;
35036
- const aHalfW = Math.max(ar, (a.labelW ?? 0) / 2) + pad;
35037
- const bHalfW = Math.max(br, (b.labelW ?? 0) / 2) + pad;
35038
- const aTop = a.y - ar - pad, aBot = a.y + ar + labelBelow + pad;
35039
- const bTop = b.y - br - pad, bBot = b.y + br + labelBelow + pad;
35040
- const overlapX = Math.min(a.x + aHalfW, b.x + bHalfW) - Math.max(a.x - aHalfW, b.x - bHalfW);
35041
- const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
35042
- if (overlapX > 0 && overlapY > 0) {
35043
- if (overlapX <= overlapY) {
35044
- const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
35045
- a.x = Math.max(30, Math.min(w - 30, a.x - push));
35046
- b.x = Math.max(30, Math.min(w - 30, b.x + push));
35047
- } else {
35048
- const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
35049
- a.y = Math.max(30, Math.min(h - 30, a.y - push));
35050
- b.y = Math.max(30, Math.min(h - 30, b.y + push));
35030
+ const rectsOf = (n) => {
35031
+ const r = n.size || 8;
35032
+ const lw = showLabels ? n.labelW ?? (n.labelW = n.label ? measureLabelWidth(n.label, labelFont) : 0) : 0;
35033
+ return {
35034
+ circle: [n.x - r - pad, n.y - r - pad, n.x + r + pad, n.y + r + pad],
35035
+ label: [n.x - lw / 2 - pad, n.y + r + LABEL_GAP - 8, n.x + lw / 2 + pad, n.y + r + LABEL_GAP + LABEL_H]
35036
+ };
35037
+ };
35038
+ const sep = (r1, r2) => {
35039
+ const ox = Math.min(r1[2], r2[2]) - Math.max(r1[0], r2[0]);
35040
+ const oy = Math.min(r1[3], r2[3]) - Math.max(r1[1], r2[1]);
35041
+ if (ox <= 0 || oy <= 0) return null;
35042
+ return ox <= oy ? { axis: "x", depth: ox, sign: r1[0] + r1[2] < r2[0] + r2[2] ? 1 : -1 } : { axis: "y", depth: oy, sign: r1[1] + r1[3] < r2[1] + r2[3] ? 1 : -1 };
35043
+ };
35044
+ for (let pass = 0; pass < COLLIDE_PASSES; pass++) {
35045
+ for (let i = 0; i < nodes.length; i++) {
35046
+ for (let j = i + 1; j < nodes.length; j++) {
35047
+ const a = nodes[i];
35048
+ const b = nodes[j];
35049
+ const ra = rectsOf(a);
35050
+ const rb = rectsOf(b);
35051
+ let best = null;
35052
+ for (const [r1, r2] of [[ra.circle, rb.circle], [ra.circle, rb.label], [ra.label, rb.circle], [ra.label, rb.label]]) {
35053
+ const s = sep(r1, r2);
35054
+ if (s && (!best || s.depth < best.depth)) best = s;
35055
+ }
35056
+ if (best) {
35057
+ const push = best.depth / 2;
35058
+ if (best.axis === "x") {
35059
+ a.x = Math.max(30, Math.min(w - 30, a.x - push * best.sign));
35060
+ b.x = Math.max(30, Math.min(w - 30, b.x + push * best.sign));
35061
+ a.vx = 0;
35062
+ b.vx = 0;
35063
+ } else {
35064
+ a.y = Math.max(30, Math.min(h - 30, a.y - push * best.sign));
35065
+ b.y = Math.max(30, Math.min(h - 30, b.y + push * best.sign));
35066
+ a.vy = 0;
35067
+ b.vy = 0;
35068
+ }
35051
35069
  }
35052
35070
  }
35053
35071
  }
35054
35072
  }
35055
35073
  };
35056
35074
  if (fullRelayout) {
35057
- for (let i = 0; i < maxIterations; i++) tick();
35075
+ for (let i = 0; i < maxIterations; i++) tick(i);
35058
35076
  laidOutRef.current = true;
35059
35077
  } else {
35060
35078
  const centroids = /* @__PURE__ */ new Map();
@@ -34688,11 +34688,11 @@ var init_DocumentViewer = __esm({
34688
34688
  DocumentViewer.displayName = "DocumentViewer";
34689
34689
  }
34690
34690
  });
34691
- function measureLabelWidth(text) {
34691
+ function measureLabelWidth(text, fontFamily = "system-ui") {
34692
34692
  if (typeof document === "undefined") return text.length * 6;
34693
34693
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
34694
34694
  if (!labelMeasureCtx) return text.length * 6;
34695
- labelMeasureCtx.font = "12px system-ui";
34695
+ labelMeasureCtx.font = `12px ${fontFamily}`;
34696
34696
  return labelMeasureCtx.measureText(text).width + 4;
34697
34697
  }
34698
34698
  function getGroupColor(group, groups) {
@@ -34717,6 +34717,9 @@ function mulberry32(a) {
34717
34717
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
34718
34718
  };
34719
34719
  }
34720
+ function edgeKeyOf(a, b) {
34721
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
34722
+ }
34720
34723
  function resolveColor3(color, el) {
34721
34724
  const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
34722
34725
  if (!m) return color;
@@ -34850,6 +34853,7 @@ var init_GraphCanvas = __esm({
34850
34853
  if (!canvas || propNodes.length === 0) return;
34851
34854
  const w = logicalW;
34852
34855
  const h = height;
34856
+ const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
34853
34857
  const prevPos = /* @__PURE__ */ new Map();
34854
34858
  for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
34855
34859
  const simNodes = propNodes.map((n, idx) => {
@@ -34884,10 +34888,15 @@ var init_GraphCanvas = __esm({
34884
34888
  const fullRelayout = !laidOutRef.current || overlap < 0.5;
34885
34889
  if (layout === "force") {
34886
34890
  const maxIterations = 300;
34887
- const tick = () => {
34891
+ const COOL = 0.12;
34892
+ const COLLIDE_PASSES = 6;
34893
+ const LABEL_GAP = 12;
34894
+ const LABEL_H = 16;
34895
+ const tick = (iter) => {
34888
34896
  const nodes = nodesRef.current;
34889
34897
  const centerX = w / 2;
34890
34898
  const centerY = h / 2;
34899
+ const temp = Math.max(COOL, 1 - iter / maxIterations);
34891
34900
  for (const node of nodes) {
34892
34901
  node.fx = 0;
34893
34902
  node.fy = 0;
@@ -34897,7 +34906,7 @@ var init_GraphCanvas = __esm({
34897
34906
  const dx = nodes[j].x - nodes[i].x;
34898
34907
  const dy = nodes[j].y - nodes[i].y;
34899
34908
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34900
- const force = repulsion / (dist * dist);
34909
+ const force = repulsion / (dist * dist) * temp;
34901
34910
  const fx = dx / dist * force;
34902
34911
  const fy = dy / dist * force;
34903
34912
  nodes[i].fx -= fx;
@@ -34907,42 +34916,34 @@ var init_GraphCanvas = __esm({
34907
34916
  }
34908
34917
  }
34909
34918
  const nodeById = new Map(nodes.map((n) => [n.id, n]));
34910
- if (propSimilarity.length > 0) {
34911
- for (const pair of propSimilarity) {
34912
- const source = nodeById.get(pair.source);
34913
- const target = nodeById.get(pair.target);
34914
- if (!source || !target) continue;
34915
- const dx = target.x - source.x;
34916
- const dy = target.y - source.y;
34917
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34918
- const w2 = Math.min(1, Math.max(0, pair.weight));
34919
- const linkTarget = linkDistance * (1 - w2);
34920
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
34921
- const fx = dx / dist * force;
34922
- const fy = dy / dist * force;
34923
- source.fx += fx;
34924
- source.fy += fy;
34925
- target.fx -= fx;
34926
- target.fy -= fy;
34927
- }
34928
- } else {
34929
- for (const edge of propEdges) {
34930
- const source = nodeById.get(edge.source);
34931
- const target = nodeById.get(edge.target);
34932
- if (!source || !target) continue;
34933
- const dx = target.x - source.x;
34934
- const dy = target.y - source.y;
34935
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34936
- const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
34937
- const linkTarget = linkDistance * (0.5 + (1 - w2) * 1.5);
34938
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
34939
- const fx = dx / dist * force;
34940
- const fy = dy / dist * force;
34941
- source.fx += fx;
34942
- source.fy += fy;
34943
- target.fx -= fx;
34944
- target.fy -= fy;
34945
- }
34919
+ const spring = (a, b, rest, k) => {
34920
+ const dx = b.x - a.x;
34921
+ const dy = b.y - a.y;
34922
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
34923
+ const force = (dist - rest) * k * temp;
34924
+ const fx = dx / dist * force;
34925
+ const fy = dy / dist * force;
34926
+ a.fx += fx;
34927
+ a.fy += fy;
34928
+ b.fx -= fx;
34929
+ b.fy -= fy;
34930
+ };
34931
+ const drawnPairs = /* @__PURE__ */ new Set();
34932
+ for (const edge of propEdges) {
34933
+ const source = nodeById.get(edge.source);
34934
+ const target = nodeById.get(edge.target);
34935
+ if (!source || !target) continue;
34936
+ drawnPairs.add(edgeKeyOf(edge.source, edge.target));
34937
+ const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
34938
+ spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
34939
+ }
34940
+ for (const pair of propSimilarity) {
34941
+ if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
34942
+ const source = nodeById.get(pair.source);
34943
+ const target = nodeById.get(pair.target);
34944
+ if (!source || !target) continue;
34945
+ const w2 = Math.min(1, Math.max(0, pair.weight));
34946
+ spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
34946
34947
  }
34947
34948
  const centroids = /* @__PURE__ */ new Map();
34948
34949
  for (const node of nodes) {
@@ -34956,14 +34957,20 @@ var init_GraphCanvas = __esm({
34956
34957
  c.y += node.y;
34957
34958
  c.n += 1;
34958
34959
  }
34960
+ const multiCluster = centroids.size > 1;
34959
34961
  for (const node of nodes) {
34960
- const c = centroids.get(node.group ?? "__none__");
34961
- if (c && c.n > 1) {
34962
- node.fx += (c.x / c.n - node.x) * 0.04;
34963
- node.fy += (c.y / c.n - node.y) * 0.04;
34962
+ if (multiCluster) {
34963
+ const c = centroids.get(node.group ?? "__none__");
34964
+ if (c && c.n > 1) {
34965
+ node.fx += (c.x / c.n - node.x) * 0.04 * temp;
34966
+ node.fy += (c.y / c.n - node.y) * 0.04 * temp;
34967
+ } else {
34968
+ node.fx += (centerX - node.x) * 0.01 * temp;
34969
+ node.fy += (centerY - node.y) * 0.01 * temp;
34970
+ }
34964
34971
  } else {
34965
- node.fx += (centerX - node.x) * 0.01;
34966
- node.fy += (centerY - node.y) * 0.01;
34972
+ node.fx += (centerX - node.x) * 8e-3 * temp;
34973
+ node.fy += (centerY - node.y) * 8e-3 * temp;
34967
34974
  }
34968
34975
  }
34969
34976
  const damping = 0.9;
@@ -34975,42 +34982,53 @@ var init_GraphCanvas = __esm({
34975
34982
  node.x = Math.max(30, Math.min(w - 30, node.x));
34976
34983
  node.y = Math.max(30, Math.min(h - 30, node.y));
34977
34984
  }
34978
- const LABEL_GAP = 12;
34979
- const LABEL_H = 16;
34980
34985
  const pad = nodeSpacing / 2;
34981
- for (let i = 0; i < nodes.length; i++) {
34982
- for (let j = i + 1; j < nodes.length; j++) {
34983
- const a = nodes[i];
34984
- const b = nodes[j];
34985
- const ar = a.size || 8;
34986
- const br = b.size || 8;
34987
- if (showLabels) {
34988
- if (a.labelW === void 0) a.labelW = a.label ? measureLabelWidth(a.label) : 0;
34989
- if (b.labelW === void 0) b.labelW = b.label ? measureLabelWidth(b.label) : 0;
34990
- }
34991
- const labelBelow = showLabels ? LABEL_GAP + LABEL_H : 0;
34992
- const aHalfW = Math.max(ar, (a.labelW ?? 0) / 2) + pad;
34993
- const bHalfW = Math.max(br, (b.labelW ?? 0) / 2) + pad;
34994
- const aTop = a.y - ar - pad, aBot = a.y + ar + labelBelow + pad;
34995
- const bTop = b.y - br - pad, bBot = b.y + br + labelBelow + pad;
34996
- const overlapX = Math.min(a.x + aHalfW, b.x + bHalfW) - Math.max(a.x - aHalfW, b.x - bHalfW);
34997
- const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
34998
- if (overlapX > 0 && overlapY > 0) {
34999
- if (overlapX <= overlapY) {
35000
- const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
35001
- a.x = Math.max(30, Math.min(w - 30, a.x - push));
35002
- b.x = Math.max(30, Math.min(w - 30, b.x + push));
35003
- } else {
35004
- const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
35005
- a.y = Math.max(30, Math.min(h - 30, a.y - push));
35006
- b.y = Math.max(30, Math.min(h - 30, b.y + push));
34986
+ const rectsOf = (n) => {
34987
+ const r = n.size || 8;
34988
+ const lw = showLabels ? n.labelW ?? (n.labelW = n.label ? measureLabelWidth(n.label, labelFont) : 0) : 0;
34989
+ return {
34990
+ circle: [n.x - r - pad, n.y - r - pad, n.x + r + pad, n.y + r + pad],
34991
+ label: [n.x - lw / 2 - pad, n.y + r + LABEL_GAP - 8, n.x + lw / 2 + pad, n.y + r + LABEL_GAP + LABEL_H]
34992
+ };
34993
+ };
34994
+ const sep = (r1, r2) => {
34995
+ const ox = Math.min(r1[2], r2[2]) - Math.max(r1[0], r2[0]);
34996
+ const oy = Math.min(r1[3], r2[3]) - Math.max(r1[1], r2[1]);
34997
+ if (ox <= 0 || oy <= 0) return null;
34998
+ return ox <= oy ? { axis: "x", depth: ox, sign: r1[0] + r1[2] < r2[0] + r2[2] ? 1 : -1 } : { axis: "y", depth: oy, sign: r1[1] + r1[3] < r2[1] + r2[3] ? 1 : -1 };
34999
+ };
35000
+ for (let pass = 0; pass < COLLIDE_PASSES; pass++) {
35001
+ for (let i = 0; i < nodes.length; i++) {
35002
+ for (let j = i + 1; j < nodes.length; j++) {
35003
+ const a = nodes[i];
35004
+ const b = nodes[j];
35005
+ const ra = rectsOf(a);
35006
+ const rb = rectsOf(b);
35007
+ let best = null;
35008
+ for (const [r1, r2] of [[ra.circle, rb.circle], [ra.circle, rb.label], [ra.label, rb.circle], [ra.label, rb.label]]) {
35009
+ const s = sep(r1, r2);
35010
+ if (s && (!best || s.depth < best.depth)) best = s;
35011
+ }
35012
+ if (best) {
35013
+ const push = best.depth / 2;
35014
+ if (best.axis === "x") {
35015
+ a.x = Math.max(30, Math.min(w - 30, a.x - push * best.sign));
35016
+ b.x = Math.max(30, Math.min(w - 30, b.x + push * best.sign));
35017
+ a.vx = 0;
35018
+ b.vx = 0;
35019
+ } else {
35020
+ a.y = Math.max(30, Math.min(h - 30, a.y - push * best.sign));
35021
+ b.y = Math.max(30, Math.min(h - 30, b.y + push * best.sign));
35022
+ a.vy = 0;
35023
+ b.vy = 0;
35024
+ }
35007
35025
  }
35008
35026
  }
35009
35027
  }
35010
35028
  }
35011
35029
  };
35012
35030
  if (fullRelayout) {
35013
- for (let i = 0; i < maxIterations; i++) tick();
35031
+ for (let i = 0; i < maxIterations; i++) tick(i);
35014
35032
  laidOutRef.current = true;
35015
35033
  } else {
35016
35034
  const centroids = /* @__PURE__ */ new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.118.0",
3
+ "version": "5.119.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [