@almadar/ui 5.117.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.
@@ -37237,11 +37237,11 @@ var init_DocumentViewer = __esm({
37237
37237
  DocumentViewer.displayName = "DocumentViewer";
37238
37238
  }
37239
37239
  });
37240
- function measureLabelWidth(text) {
37240
+ function measureLabelWidth(text, fontFamily = "system-ui") {
37241
37241
  if (typeof document === "undefined") return text.length * 6;
37242
37242
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
37243
37243
  if (!labelMeasureCtx) return text.length * 6;
37244
- labelMeasureCtx.font = "12px system-ui";
37244
+ labelMeasureCtx.font = `12px ${fontFamily}`;
37245
37245
  return labelMeasureCtx.measureText(text).width + 4;
37246
37246
  }
37247
37247
  function getGroupColor(group, groups) {
@@ -37249,6 +37249,26 @@ function getGroupColor(group, groups) {
37249
37249
  const idx = groups.indexOf(group);
37250
37250
  return GROUP_COLORS2[idx % GROUP_COLORS2.length];
37251
37251
  }
37252
+ function hashSeed(str) {
37253
+ let h = 1779033703 ^ str.length;
37254
+ for (let i = 0; i < str.length; i++) {
37255
+ h = Math.imul(h ^ str.charCodeAt(i), 3432918353);
37256
+ h = h << 13 | h >>> 19;
37257
+ }
37258
+ return (h ^= h >>> 16) >>> 0;
37259
+ }
37260
+ function mulberry32(a) {
37261
+ return function() {
37262
+ a |= 0;
37263
+ a = a + 1831565813 | 0;
37264
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
37265
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
37266
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
37267
+ };
37268
+ }
37269
+ function edgeKeyOf(a, b) {
37270
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
37271
+ }
37252
37272
  function resolveColor3(color, el) {
37253
37273
  const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
37254
37274
  if (!m) return color;
@@ -37280,6 +37300,7 @@ var init_GraphCanvas = __esm({
37280
37300
  title,
37281
37301
  nodes: propNodes = [],
37282
37302
  edges: propEdges = [],
37303
+ similarity: propSimilarity = [],
37283
37304
  height = 400,
37284
37305
  showLabels = true,
37285
37306
  interactive = true,
@@ -37381,6 +37402,7 @@ var init_GraphCanvas = __esm({
37381
37402
  if (!canvas || propNodes.length === 0) return;
37382
37403
  const w = logicalW;
37383
37404
  const h = height;
37405
+ const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
37384
37406
  const prevPos = /* @__PURE__ */ new Map();
37385
37407
  for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
37386
37408
  const simNodes = propNodes.map((n, idx) => {
@@ -37400,8 +37422,9 @@ var init_GraphCanvas = __esm({
37400
37422
  x = gapX * (idx % cols + 1);
37401
37423
  y = gapY * (Math.floor(idx / cols) + 1);
37402
37424
  } else {
37403
- x = w * 0.2 + Math.random() * w * 0.6;
37404
- y = h * 0.2 + Math.random() * h * 0.6;
37425
+ const rand = mulberry32(hashSeed(n.id));
37426
+ x = w * 0.2 + rand() * w * 0.6;
37427
+ y = h * 0.2 + rand() * h * 0.6;
37405
37428
  }
37406
37429
  }
37407
37430
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
@@ -37414,10 +37437,15 @@ var init_GraphCanvas = __esm({
37414
37437
  const fullRelayout = !laidOutRef.current || overlap < 0.5;
37415
37438
  if (layout === "force") {
37416
37439
  const maxIterations = 300;
37417
- const tick = () => {
37440
+ const COOL = 0.12;
37441
+ const COLLIDE_PASSES = 6;
37442
+ const LABEL_GAP = 12;
37443
+ const LABEL_H = 16;
37444
+ const tick = (iter) => {
37418
37445
  const nodes = nodesRef.current;
37419
37446
  const centerX = w / 2;
37420
37447
  const centerY = h / 2;
37448
+ const temp = Math.max(COOL, 1 - iter / maxIterations);
37421
37449
  for (const node of nodes) {
37422
37450
  node.fx = 0;
37423
37451
  node.fy = 0;
@@ -37427,7 +37455,7 @@ var init_GraphCanvas = __esm({
37427
37455
  const dx = nodes[j].x - nodes[i].x;
37428
37456
  const dy = nodes[j].y - nodes[i].y;
37429
37457
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
37430
- const force = repulsion / (dist * dist);
37458
+ const force = repulsion / (dist * dist) * temp;
37431
37459
  const fx = dx / dist * force;
37432
37460
  const fy = dy / dist * force;
37433
37461
  nodes[i].fx -= fx;
@@ -37436,22 +37464,35 @@ var init_GraphCanvas = __esm({
37436
37464
  nodes[j].fy += fy;
37437
37465
  }
37438
37466
  }
37439
- for (const edge of propEdges) {
37440
- const source = nodes.find((n) => n.id === edge.source);
37441
- const target = nodes.find((n) => n.id === edge.target);
37442
- if (!source || !target) continue;
37443
- const dx = target.x - source.x;
37444
- const dy = target.y - source.y;
37467
+ const nodeById = new Map(nodes.map((n) => [n.id, n]));
37468
+ const spring = (a, b, rest, k) => {
37469
+ const dx = b.x - a.x;
37470
+ const dy = b.y - a.y;
37445
37471
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
37446
- const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
37447
- const linkTarget = linkDistance * (0.5 + (1 - w2) * 1.5);
37448
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
37472
+ const force = (dist - rest) * k * temp;
37449
37473
  const fx = dx / dist * force;
37450
37474
  const fy = dy / dist * force;
37451
- source.fx += fx;
37452
- source.fy += fy;
37453
- target.fx -= fx;
37454
- target.fy -= fy;
37475
+ a.fx += fx;
37476
+ a.fy += fy;
37477
+ b.fx -= fx;
37478
+ b.fy -= fy;
37479
+ };
37480
+ const drawnPairs = /* @__PURE__ */ new Set();
37481
+ for (const edge of propEdges) {
37482
+ const source = nodeById.get(edge.source);
37483
+ const target = nodeById.get(edge.target);
37484
+ if (!source || !target) continue;
37485
+ drawnPairs.add(edgeKeyOf(edge.source, edge.target));
37486
+ const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
37487
+ spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
37488
+ }
37489
+ for (const pair of propSimilarity) {
37490
+ if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
37491
+ const source = nodeById.get(pair.source);
37492
+ const target = nodeById.get(pair.target);
37493
+ if (!source || !target) continue;
37494
+ const w2 = Math.min(1, Math.max(0, pair.weight));
37495
+ spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
37455
37496
  }
37456
37497
  const centroids = /* @__PURE__ */ new Map();
37457
37498
  for (const node of nodes) {
@@ -37465,14 +37506,20 @@ var init_GraphCanvas = __esm({
37465
37506
  c.y += node.y;
37466
37507
  c.n += 1;
37467
37508
  }
37509
+ const multiCluster = centroids.size > 1;
37468
37510
  for (const node of nodes) {
37469
- const c = centroids.get(node.group ?? "__none__");
37470
- if (c && c.n > 1) {
37471
- node.fx += (c.x / c.n - node.x) * 0.04;
37472
- node.fy += (c.y / c.n - node.y) * 0.04;
37511
+ if (multiCluster) {
37512
+ const c = centroids.get(node.group ?? "__none__");
37513
+ if (c && c.n > 1) {
37514
+ node.fx += (c.x / c.n - node.x) * 0.04 * temp;
37515
+ node.fy += (c.y / c.n - node.y) * 0.04 * temp;
37516
+ } else {
37517
+ node.fx += (centerX - node.x) * 0.01 * temp;
37518
+ node.fy += (centerY - node.y) * 0.01 * temp;
37519
+ }
37473
37520
  } else {
37474
- node.fx += (centerX - node.x) * 0.01;
37475
- node.fy += (centerY - node.y) * 0.01;
37521
+ node.fx += (centerX - node.x) * 8e-3 * temp;
37522
+ node.fy += (centerY - node.y) * 8e-3 * temp;
37476
37523
  }
37477
37524
  }
37478
37525
  const damping = 0.9;
@@ -37484,42 +37531,53 @@ var init_GraphCanvas = __esm({
37484
37531
  node.x = Math.max(30, Math.min(w - 30, node.x));
37485
37532
  node.y = Math.max(30, Math.min(h - 30, node.y));
37486
37533
  }
37487
- const LABEL_GAP = 12;
37488
- const LABEL_H = 16;
37489
37534
  const pad = nodeSpacing / 2;
37490
- for (let i = 0; i < nodes.length; i++) {
37491
- for (let j = i + 1; j < nodes.length; j++) {
37492
- const a = nodes[i];
37493
- const b = nodes[j];
37494
- const ar = a.size || 8;
37495
- const br = b.size || 8;
37496
- if (showLabels) {
37497
- if (a.labelW === void 0) a.labelW = a.label ? measureLabelWidth(a.label) : 0;
37498
- if (b.labelW === void 0) b.labelW = b.label ? measureLabelWidth(b.label) : 0;
37499
- }
37500
- const labelBelow = showLabels ? LABEL_GAP + LABEL_H : 0;
37501
- const aHalfW = Math.max(ar, (a.labelW ?? 0) / 2) + pad;
37502
- const bHalfW = Math.max(br, (b.labelW ?? 0) / 2) + pad;
37503
- const aTop = a.y - ar - pad, aBot = a.y + ar + labelBelow + pad;
37504
- const bTop = b.y - br - pad, bBot = b.y + br + labelBelow + pad;
37505
- const overlapX = Math.min(a.x + aHalfW, b.x + bHalfW) - Math.max(a.x - aHalfW, b.x - bHalfW);
37506
- const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
37507
- if (overlapX > 0 && overlapY > 0) {
37508
- if (overlapX <= overlapY) {
37509
- const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
37510
- a.x = Math.max(30, Math.min(w - 30, a.x - push));
37511
- b.x = Math.max(30, Math.min(w - 30, b.x + push));
37512
- } else {
37513
- const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
37514
- a.y = Math.max(30, Math.min(h - 30, a.y - push));
37515
- b.y = Math.max(30, Math.min(h - 30, b.y + push));
37535
+ const rectsOf = (n) => {
37536
+ const r2 = n.size || 8;
37537
+ const lw = showLabels ? n.labelW ?? (n.labelW = n.label ? measureLabelWidth(n.label, labelFont) : 0) : 0;
37538
+ return {
37539
+ circle: [n.x - r2 - pad, n.y - r2 - pad, n.x + r2 + pad, n.y + r2 + pad],
37540
+ label: [n.x - lw / 2 - pad, n.y + r2 + LABEL_GAP - 8, n.x + lw / 2 + pad, n.y + r2 + LABEL_GAP + LABEL_H]
37541
+ };
37542
+ };
37543
+ const sep = (r1, r2) => {
37544
+ const ox = Math.min(r1[2], r2[2]) - Math.max(r1[0], r2[0]);
37545
+ const oy = Math.min(r1[3], r2[3]) - Math.max(r1[1], r2[1]);
37546
+ if (ox <= 0 || oy <= 0) return null;
37547
+ 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 };
37548
+ };
37549
+ for (let pass = 0; pass < COLLIDE_PASSES; pass++) {
37550
+ for (let i = 0; i < nodes.length; i++) {
37551
+ for (let j = i + 1; j < nodes.length; j++) {
37552
+ const a = nodes[i];
37553
+ const b = nodes[j];
37554
+ const ra = rectsOf(a);
37555
+ const rb = rectsOf(b);
37556
+ let best = null;
37557
+ for (const [r1, r2] of [[ra.circle, rb.circle], [ra.circle, rb.label], [ra.label, rb.circle], [ra.label, rb.label]]) {
37558
+ const s = sep(r1, r2);
37559
+ if (s && (!best || s.depth < best.depth)) best = s;
37560
+ }
37561
+ if (best) {
37562
+ const push = best.depth / 2;
37563
+ if (best.axis === "x") {
37564
+ a.x = Math.max(30, Math.min(w - 30, a.x - push * best.sign));
37565
+ b.x = Math.max(30, Math.min(w - 30, b.x + push * best.sign));
37566
+ a.vx = 0;
37567
+ b.vx = 0;
37568
+ } else {
37569
+ a.y = Math.max(30, Math.min(h - 30, a.y - push * best.sign));
37570
+ b.y = Math.max(30, Math.min(h - 30, b.y + push * best.sign));
37571
+ a.vy = 0;
37572
+ b.vy = 0;
37573
+ }
37516
37574
  }
37517
37575
  }
37518
37576
  }
37519
37577
  }
37520
37578
  };
37521
37579
  if (fullRelayout) {
37522
- for (let i = 0; i < maxIterations; i++) tick();
37580
+ for (let i = 0; i < maxIterations; i++) tick(i);
37523
37581
  laidOutRef.current = true;
37524
37582
  } else {
37525
37583
  const centroids = /* @__PURE__ */ new Map();
@@ -37557,7 +37615,7 @@ var init_GraphCanvas = __esm({
37557
37615
  return () => {
37558
37616
  cancelAnimationFrame(animRef.current);
37559
37617
  };
37560
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37618
+ }, [propNodes, propEdges, propSimilarity, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37561
37619
  React90.useEffect(() => {
37562
37620
  const canvas = canvasRef.current;
37563
37621
  if (!canvas) return;
package/dist/avl/index.js CHANGED
@@ -37191,11 +37191,11 @@ var init_DocumentViewer = __esm({
37191
37191
  DocumentViewer.displayName = "DocumentViewer";
37192
37192
  }
37193
37193
  });
37194
- function measureLabelWidth(text) {
37194
+ function measureLabelWidth(text, fontFamily = "system-ui") {
37195
37195
  if (typeof document === "undefined") return text.length * 6;
37196
37196
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
37197
37197
  if (!labelMeasureCtx) return text.length * 6;
37198
- labelMeasureCtx.font = "12px system-ui";
37198
+ labelMeasureCtx.font = `12px ${fontFamily}`;
37199
37199
  return labelMeasureCtx.measureText(text).width + 4;
37200
37200
  }
37201
37201
  function getGroupColor(group, groups) {
@@ -37203,6 +37203,26 @@ function getGroupColor(group, groups) {
37203
37203
  const idx = groups.indexOf(group);
37204
37204
  return GROUP_COLORS2[idx % GROUP_COLORS2.length];
37205
37205
  }
37206
+ function hashSeed(str) {
37207
+ let h = 1779033703 ^ str.length;
37208
+ for (let i = 0; i < str.length; i++) {
37209
+ h = Math.imul(h ^ str.charCodeAt(i), 3432918353);
37210
+ h = h << 13 | h >>> 19;
37211
+ }
37212
+ return (h ^= h >>> 16) >>> 0;
37213
+ }
37214
+ function mulberry32(a) {
37215
+ return function() {
37216
+ a |= 0;
37217
+ a = a + 1831565813 | 0;
37218
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
37219
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
37220
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
37221
+ };
37222
+ }
37223
+ function edgeKeyOf(a, b) {
37224
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
37225
+ }
37206
37226
  function resolveColor3(color, el) {
37207
37227
  const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
37208
37228
  if (!m) return color;
@@ -37234,6 +37254,7 @@ var init_GraphCanvas = __esm({
37234
37254
  title,
37235
37255
  nodes: propNodes = [],
37236
37256
  edges: propEdges = [],
37257
+ similarity: propSimilarity = [],
37237
37258
  height = 400,
37238
37259
  showLabels = true,
37239
37260
  interactive = true,
@@ -37335,6 +37356,7 @@ var init_GraphCanvas = __esm({
37335
37356
  if (!canvas || propNodes.length === 0) return;
37336
37357
  const w = logicalW;
37337
37358
  const h = height;
37359
+ const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
37338
37360
  const prevPos = /* @__PURE__ */ new Map();
37339
37361
  for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
37340
37362
  const simNodes = propNodes.map((n, idx) => {
@@ -37354,8 +37376,9 @@ var init_GraphCanvas = __esm({
37354
37376
  x = gapX * (idx % cols + 1);
37355
37377
  y = gapY * (Math.floor(idx / cols) + 1);
37356
37378
  } else {
37357
- x = w * 0.2 + Math.random() * w * 0.6;
37358
- y = h * 0.2 + Math.random() * h * 0.6;
37379
+ const rand = mulberry32(hashSeed(n.id));
37380
+ x = w * 0.2 + rand() * w * 0.6;
37381
+ y = h * 0.2 + rand() * h * 0.6;
37359
37382
  }
37360
37383
  }
37361
37384
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
@@ -37368,10 +37391,15 @@ var init_GraphCanvas = __esm({
37368
37391
  const fullRelayout = !laidOutRef.current || overlap < 0.5;
37369
37392
  if (layout === "force") {
37370
37393
  const maxIterations = 300;
37371
- const tick = () => {
37394
+ const COOL = 0.12;
37395
+ const COLLIDE_PASSES = 6;
37396
+ const LABEL_GAP = 12;
37397
+ const LABEL_H = 16;
37398
+ const tick = (iter) => {
37372
37399
  const nodes = nodesRef.current;
37373
37400
  const centerX = w / 2;
37374
37401
  const centerY = h / 2;
37402
+ const temp = Math.max(COOL, 1 - iter / maxIterations);
37375
37403
  for (const node of nodes) {
37376
37404
  node.fx = 0;
37377
37405
  node.fy = 0;
@@ -37381,7 +37409,7 @@ var init_GraphCanvas = __esm({
37381
37409
  const dx = nodes[j].x - nodes[i].x;
37382
37410
  const dy = nodes[j].y - nodes[i].y;
37383
37411
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
37384
- const force = repulsion / (dist * dist);
37412
+ const force = repulsion / (dist * dist) * temp;
37385
37413
  const fx = dx / dist * force;
37386
37414
  const fy = dy / dist * force;
37387
37415
  nodes[i].fx -= fx;
@@ -37390,22 +37418,35 @@ var init_GraphCanvas = __esm({
37390
37418
  nodes[j].fy += fy;
37391
37419
  }
37392
37420
  }
37393
- for (const edge of propEdges) {
37394
- const source = nodes.find((n) => n.id === edge.source);
37395
- const target = nodes.find((n) => n.id === edge.target);
37396
- if (!source || !target) continue;
37397
- const dx = target.x - source.x;
37398
- const dy = target.y - source.y;
37421
+ const nodeById = new Map(nodes.map((n) => [n.id, n]));
37422
+ const spring = (a, b, rest, k) => {
37423
+ const dx = b.x - a.x;
37424
+ const dy = b.y - a.y;
37399
37425
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
37400
- const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
37401
- const linkTarget = linkDistance * (0.5 + (1 - w2) * 1.5);
37402
- const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
37426
+ const force = (dist - rest) * k * temp;
37403
37427
  const fx = dx / dist * force;
37404
37428
  const fy = dy / dist * force;
37405
- source.fx += fx;
37406
- source.fy += fy;
37407
- target.fx -= fx;
37408
- target.fy -= fy;
37429
+ a.fx += fx;
37430
+ a.fy += fy;
37431
+ b.fx -= fx;
37432
+ b.fy -= fy;
37433
+ };
37434
+ const drawnPairs = /* @__PURE__ */ new Set();
37435
+ for (const edge of propEdges) {
37436
+ const source = nodeById.get(edge.source);
37437
+ const target = nodeById.get(edge.target);
37438
+ if (!source || !target) continue;
37439
+ drawnPairs.add(edgeKeyOf(edge.source, edge.target));
37440
+ const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
37441
+ spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
37442
+ }
37443
+ for (const pair of propSimilarity) {
37444
+ if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
37445
+ const source = nodeById.get(pair.source);
37446
+ const target = nodeById.get(pair.target);
37447
+ if (!source || !target) continue;
37448
+ const w2 = Math.min(1, Math.max(0, pair.weight));
37449
+ spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
37409
37450
  }
37410
37451
  const centroids = /* @__PURE__ */ new Map();
37411
37452
  for (const node of nodes) {
@@ -37419,14 +37460,20 @@ var init_GraphCanvas = __esm({
37419
37460
  c.y += node.y;
37420
37461
  c.n += 1;
37421
37462
  }
37463
+ const multiCluster = centroids.size > 1;
37422
37464
  for (const node of nodes) {
37423
- const c = centroids.get(node.group ?? "__none__");
37424
- if (c && c.n > 1) {
37425
- node.fx += (c.x / c.n - node.x) * 0.04;
37426
- node.fy += (c.y / c.n - node.y) * 0.04;
37465
+ if (multiCluster) {
37466
+ const c = centroids.get(node.group ?? "__none__");
37467
+ if (c && c.n > 1) {
37468
+ node.fx += (c.x / c.n - node.x) * 0.04 * temp;
37469
+ node.fy += (c.y / c.n - node.y) * 0.04 * temp;
37470
+ } else {
37471
+ node.fx += (centerX - node.x) * 0.01 * temp;
37472
+ node.fy += (centerY - node.y) * 0.01 * temp;
37473
+ }
37427
37474
  } else {
37428
- node.fx += (centerX - node.x) * 0.01;
37429
- node.fy += (centerY - node.y) * 0.01;
37475
+ node.fx += (centerX - node.x) * 8e-3 * temp;
37476
+ node.fy += (centerY - node.y) * 8e-3 * temp;
37430
37477
  }
37431
37478
  }
37432
37479
  const damping = 0.9;
@@ -37438,42 +37485,53 @@ var init_GraphCanvas = __esm({
37438
37485
  node.x = Math.max(30, Math.min(w - 30, node.x));
37439
37486
  node.y = Math.max(30, Math.min(h - 30, node.y));
37440
37487
  }
37441
- const LABEL_GAP = 12;
37442
- const LABEL_H = 16;
37443
37488
  const pad = nodeSpacing / 2;
37444
- for (let i = 0; i < nodes.length; i++) {
37445
- for (let j = i + 1; j < nodes.length; j++) {
37446
- const a = nodes[i];
37447
- const b = nodes[j];
37448
- const ar = a.size || 8;
37449
- const br = b.size || 8;
37450
- if (showLabels) {
37451
- if (a.labelW === void 0) a.labelW = a.label ? measureLabelWidth(a.label) : 0;
37452
- if (b.labelW === void 0) b.labelW = b.label ? measureLabelWidth(b.label) : 0;
37453
- }
37454
- const labelBelow = showLabels ? LABEL_GAP + LABEL_H : 0;
37455
- const aHalfW = Math.max(ar, (a.labelW ?? 0) / 2) + pad;
37456
- const bHalfW = Math.max(br, (b.labelW ?? 0) / 2) + pad;
37457
- const aTop = a.y - ar - pad, aBot = a.y + ar + labelBelow + pad;
37458
- const bTop = b.y - br - pad, bBot = b.y + br + labelBelow + pad;
37459
- const overlapX = Math.min(a.x + aHalfW, b.x + bHalfW) - Math.max(a.x - aHalfW, b.x - bHalfW);
37460
- const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
37461
- if (overlapX > 0 && overlapY > 0) {
37462
- if (overlapX <= overlapY) {
37463
- const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
37464
- a.x = Math.max(30, Math.min(w - 30, a.x - push));
37465
- b.x = Math.max(30, Math.min(w - 30, b.x + push));
37466
- } else {
37467
- const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
37468
- a.y = Math.max(30, Math.min(h - 30, a.y - push));
37469
- b.y = Math.max(30, Math.min(h - 30, b.y + push));
37489
+ const rectsOf = (n) => {
37490
+ const r2 = n.size || 8;
37491
+ const lw = showLabels ? n.labelW ?? (n.labelW = n.label ? measureLabelWidth(n.label, labelFont) : 0) : 0;
37492
+ return {
37493
+ circle: [n.x - r2 - pad, n.y - r2 - pad, n.x + r2 + pad, n.y + r2 + pad],
37494
+ label: [n.x - lw / 2 - pad, n.y + r2 + LABEL_GAP - 8, n.x + lw / 2 + pad, n.y + r2 + LABEL_GAP + LABEL_H]
37495
+ };
37496
+ };
37497
+ const sep = (r1, r2) => {
37498
+ const ox = Math.min(r1[2], r2[2]) - Math.max(r1[0], r2[0]);
37499
+ const oy = Math.min(r1[3], r2[3]) - Math.max(r1[1], r2[1]);
37500
+ if (ox <= 0 || oy <= 0) return null;
37501
+ 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 };
37502
+ };
37503
+ for (let pass = 0; pass < COLLIDE_PASSES; pass++) {
37504
+ for (let i = 0; i < nodes.length; i++) {
37505
+ for (let j = i + 1; j < nodes.length; j++) {
37506
+ const a = nodes[i];
37507
+ const b = nodes[j];
37508
+ const ra = rectsOf(a);
37509
+ const rb = rectsOf(b);
37510
+ let best = null;
37511
+ for (const [r1, r2] of [[ra.circle, rb.circle], [ra.circle, rb.label], [ra.label, rb.circle], [ra.label, rb.label]]) {
37512
+ const s = sep(r1, r2);
37513
+ if (s && (!best || s.depth < best.depth)) best = s;
37514
+ }
37515
+ if (best) {
37516
+ const push = best.depth / 2;
37517
+ if (best.axis === "x") {
37518
+ a.x = Math.max(30, Math.min(w - 30, a.x - push * best.sign));
37519
+ b.x = Math.max(30, Math.min(w - 30, b.x + push * best.sign));
37520
+ a.vx = 0;
37521
+ b.vx = 0;
37522
+ } else {
37523
+ a.y = Math.max(30, Math.min(h - 30, a.y - push * best.sign));
37524
+ b.y = Math.max(30, Math.min(h - 30, b.y + push * best.sign));
37525
+ a.vy = 0;
37526
+ b.vy = 0;
37527
+ }
37470
37528
  }
37471
37529
  }
37472
37530
  }
37473
37531
  }
37474
37532
  };
37475
37533
  if (fullRelayout) {
37476
- for (let i = 0; i < maxIterations; i++) tick();
37534
+ for (let i = 0; i < maxIterations; i++) tick(i);
37477
37535
  laidOutRef.current = true;
37478
37536
  } else {
37479
37537
  const centroids = /* @__PURE__ */ new Map();
@@ -37511,7 +37569,7 @@ var init_GraphCanvas = __esm({
37511
37569
  return () => {
37512
37570
  cancelAnimationFrame(animRef.current);
37513
37571
  };
37514
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37572
+ }, [propNodes, propEdges, propSimilarity, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37515
37573
  useEffect(() => {
37516
37574
  const canvas = canvasRef.current;
37517
37575
  if (!canvas) return;