@almadar/ui 5.116.1 → 5.117.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.
@@ -37311,6 +37311,7 @@ var init_GraphCanvas = __esm({
37311
37311
  offsetRef.current = offset;
37312
37312
  const [hoveredNode, setHoveredNode] = React90.useState(null);
37313
37313
  const nodesRef = React90.useRef([]);
37314
+ const laidOutRef = React90.useRef(false);
37314
37315
  const [, forceUpdate] = React90.useState(0);
37315
37316
  const [logicalW, setLogicalW] = React90.useState(800);
37316
37317
  React90.useEffect(() => {
@@ -37406,6 +37407,11 @@ var init_GraphCanvas = __esm({
37406
37407
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
37407
37408
  });
37408
37409
  nodesRef.current = simNodes;
37410
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
37411
+ const newIdList = simNodes.map((n) => n.id);
37412
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
37413
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
37414
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
37409
37415
  if (layout === "force") {
37410
37416
  const maxIterations = 300;
37411
37417
  const tick = () => {
@@ -37512,7 +37518,38 @@ var init_GraphCanvas = __esm({
37512
37518
  }
37513
37519
  }
37514
37520
  };
37515
- for (let i = 0; i < maxIterations; i++) tick();
37521
+ if (fullRelayout) {
37522
+ for (let i = 0; i < maxIterations; i++) tick();
37523
+ laidOutRef.current = true;
37524
+ } else {
37525
+ const centroids = /* @__PURE__ */ new Map();
37526
+ for (const node of simNodes) {
37527
+ if (!prevPos.has(node.id)) continue;
37528
+ const g = node.group ?? "__none__";
37529
+ let c = centroids.get(g);
37530
+ if (!c) {
37531
+ c = { x: 0, y: 0, n: 0 };
37532
+ centroids.set(g, c);
37533
+ }
37534
+ c.x += node.x;
37535
+ c.y += node.y;
37536
+ c.n += 1;
37537
+ }
37538
+ const ringCount = /* @__PURE__ */ new Map();
37539
+ for (const node of simNodes) {
37540
+ if (prevPos.has(node.id)) continue;
37541
+ const g = node.group ?? "__none__";
37542
+ const c = centroids.get(g);
37543
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
37544
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
37545
+ const k = ringCount.get(g) ?? 0;
37546
+ ringCount.set(g, k + 1);
37547
+ const angle = k * 2.399963;
37548
+ const r2 = 22 + k * 8;
37549
+ node.x = Math.max(30, Math.min(w - 30, cx + r2 * Math.cos(angle)));
37550
+ node.y = Math.max(30, Math.min(h - 30, cy + r2 * Math.sin(angle)));
37551
+ }
37552
+ }
37516
37553
  forceUpdate((n) => n + 1);
37517
37554
  } else {
37518
37555
  forceUpdate((n) => n + 1);
@@ -37520,7 +37557,7 @@ var init_GraphCanvas = __esm({
37520
37557
  return () => {
37521
37558
  cancelAnimationFrame(animRef.current);
37522
37559
  };
37523
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
37560
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37524
37561
  React90.useEffect(() => {
37525
37562
  const canvas = canvasRef.current;
37526
37563
  if (!canvas) return;
package/dist/avl/index.js CHANGED
@@ -37265,6 +37265,7 @@ var init_GraphCanvas = __esm({
37265
37265
  offsetRef.current = offset;
37266
37266
  const [hoveredNode, setHoveredNode] = useState(null);
37267
37267
  const nodesRef = useRef([]);
37268
+ const laidOutRef = useRef(false);
37268
37269
  const [, forceUpdate] = useState(0);
37269
37270
  const [logicalW, setLogicalW] = useState(800);
37270
37271
  useEffect(() => {
@@ -37360,6 +37361,11 @@ var init_GraphCanvas = __esm({
37360
37361
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
37361
37362
  });
37362
37363
  nodesRef.current = simNodes;
37364
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
37365
+ const newIdList = simNodes.map((n) => n.id);
37366
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
37367
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
37368
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
37363
37369
  if (layout === "force") {
37364
37370
  const maxIterations = 300;
37365
37371
  const tick = () => {
@@ -37466,7 +37472,38 @@ var init_GraphCanvas = __esm({
37466
37472
  }
37467
37473
  }
37468
37474
  };
37469
- for (let i = 0; i < maxIterations; i++) tick();
37475
+ if (fullRelayout) {
37476
+ for (let i = 0; i < maxIterations; i++) tick();
37477
+ laidOutRef.current = true;
37478
+ } else {
37479
+ const centroids = /* @__PURE__ */ new Map();
37480
+ for (const node of simNodes) {
37481
+ if (!prevPos.has(node.id)) continue;
37482
+ const g = node.group ?? "__none__";
37483
+ let c = centroids.get(g);
37484
+ if (!c) {
37485
+ c = { x: 0, y: 0, n: 0 };
37486
+ centroids.set(g, c);
37487
+ }
37488
+ c.x += node.x;
37489
+ c.y += node.y;
37490
+ c.n += 1;
37491
+ }
37492
+ const ringCount = /* @__PURE__ */ new Map();
37493
+ for (const node of simNodes) {
37494
+ if (prevPos.has(node.id)) continue;
37495
+ const g = node.group ?? "__none__";
37496
+ const c = centroids.get(g);
37497
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
37498
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
37499
+ const k = ringCount.get(g) ?? 0;
37500
+ ringCount.set(g, k + 1);
37501
+ const angle = k * 2.399963;
37502
+ const r2 = 22 + k * 8;
37503
+ node.x = Math.max(30, Math.min(w - 30, cx + r2 * Math.cos(angle)));
37504
+ node.y = Math.max(30, Math.min(h - 30, cy + r2 * Math.sin(angle)));
37505
+ }
37506
+ }
37470
37507
  forceUpdate((n) => n + 1);
37471
37508
  } else {
37472
37509
  forceUpdate((n) => n + 1);
@@ -37474,7 +37511,7 @@ var init_GraphCanvas = __esm({
37474
37511
  return () => {
37475
37512
  cancelAnimationFrame(animRef.current);
37476
37513
  };
37477
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
37514
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37478
37515
  useEffect(() => {
37479
37516
  const canvas = canvasRef.current;
37480
37517
  if (!canvas) return;
@@ -36700,6 +36700,7 @@ var init_GraphCanvas = __esm({
36700
36700
  offsetRef.current = offset;
36701
36701
  const [hoveredNode, setHoveredNode] = React73.useState(null);
36702
36702
  const nodesRef = React73.useRef([]);
36703
+ const laidOutRef = React73.useRef(false);
36703
36704
  const [, forceUpdate] = React73.useState(0);
36704
36705
  const [logicalW, setLogicalW] = React73.useState(800);
36705
36706
  React73.useEffect(() => {
@@ -36795,6 +36796,11 @@ var init_GraphCanvas = __esm({
36795
36796
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
36796
36797
  });
36797
36798
  nodesRef.current = simNodes;
36799
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
36800
+ const newIdList = simNodes.map((n) => n.id);
36801
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
36802
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
36803
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
36798
36804
  if (layout === "force") {
36799
36805
  const maxIterations = 300;
36800
36806
  const tick = () => {
@@ -36901,7 +36907,38 @@ var init_GraphCanvas = __esm({
36901
36907
  }
36902
36908
  }
36903
36909
  };
36904
- for (let i = 0; i < maxIterations; i++) tick();
36910
+ if (fullRelayout) {
36911
+ for (let i = 0; i < maxIterations; i++) tick();
36912
+ laidOutRef.current = true;
36913
+ } else {
36914
+ const centroids = /* @__PURE__ */ new Map();
36915
+ for (const node of simNodes) {
36916
+ if (!prevPos.has(node.id)) continue;
36917
+ const g = node.group ?? "__none__";
36918
+ let c = centroids.get(g);
36919
+ if (!c) {
36920
+ c = { x: 0, y: 0, n: 0 };
36921
+ centroids.set(g, c);
36922
+ }
36923
+ c.x += node.x;
36924
+ c.y += node.y;
36925
+ c.n += 1;
36926
+ }
36927
+ const ringCount = /* @__PURE__ */ new Map();
36928
+ for (const node of simNodes) {
36929
+ if (prevPos.has(node.id)) continue;
36930
+ const g = node.group ?? "__none__";
36931
+ const c = centroids.get(g);
36932
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
36933
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
36934
+ const k = ringCount.get(g) ?? 0;
36935
+ ringCount.set(g, k + 1);
36936
+ const angle = k * 2.399963;
36937
+ const r = 22 + k * 8;
36938
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
36939
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
36940
+ }
36941
+ }
36905
36942
  forceUpdate((n) => n + 1);
36906
36943
  } else {
36907
36944
  forceUpdate((n) => n + 1);
@@ -36909,7 +36946,7 @@ var init_GraphCanvas = __esm({
36909
36946
  return () => {
36910
36947
  cancelAnimationFrame(animRef.current);
36911
36948
  };
36912
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
36949
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
36913
36950
  React73.useEffect(() => {
36914
36951
  const canvas = canvasRef.current;
36915
36952
  if (!canvas) return;
@@ -36655,6 +36655,7 @@ var init_GraphCanvas = __esm({
36655
36655
  offsetRef.current = offset;
36656
36656
  const [hoveredNode, setHoveredNode] = useState(null);
36657
36657
  const nodesRef = useRef([]);
36658
+ const laidOutRef = useRef(false);
36658
36659
  const [, forceUpdate] = useState(0);
36659
36660
  const [logicalW, setLogicalW] = useState(800);
36660
36661
  useEffect(() => {
@@ -36750,6 +36751,11 @@ var init_GraphCanvas = __esm({
36750
36751
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
36751
36752
  });
36752
36753
  nodesRef.current = simNodes;
36754
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
36755
+ const newIdList = simNodes.map((n) => n.id);
36756
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
36757
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
36758
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
36753
36759
  if (layout === "force") {
36754
36760
  const maxIterations = 300;
36755
36761
  const tick = () => {
@@ -36856,7 +36862,38 @@ var init_GraphCanvas = __esm({
36856
36862
  }
36857
36863
  }
36858
36864
  };
36859
- for (let i = 0; i < maxIterations; i++) tick();
36865
+ if (fullRelayout) {
36866
+ for (let i = 0; i < maxIterations; i++) tick();
36867
+ laidOutRef.current = true;
36868
+ } else {
36869
+ const centroids = /* @__PURE__ */ new Map();
36870
+ for (const node of simNodes) {
36871
+ if (!prevPos.has(node.id)) continue;
36872
+ const g = node.group ?? "__none__";
36873
+ let c = centroids.get(g);
36874
+ if (!c) {
36875
+ c = { x: 0, y: 0, n: 0 };
36876
+ centroids.set(g, c);
36877
+ }
36878
+ c.x += node.x;
36879
+ c.y += node.y;
36880
+ c.n += 1;
36881
+ }
36882
+ const ringCount = /* @__PURE__ */ new Map();
36883
+ for (const node of simNodes) {
36884
+ if (prevPos.has(node.id)) continue;
36885
+ const g = node.group ?? "__none__";
36886
+ const c = centroids.get(g);
36887
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
36888
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
36889
+ const k = ringCount.get(g) ?? 0;
36890
+ ringCount.set(g, k + 1);
36891
+ const angle = k * 2.399963;
36892
+ const r = 22 + k * 8;
36893
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
36894
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
36895
+ }
36896
+ }
36860
36897
  forceUpdate((n) => n + 1);
36861
36898
  } else {
36862
36899
  forceUpdate((n) => n + 1);
@@ -36864,7 +36901,7 @@ var init_GraphCanvas = __esm({
36864
36901
  return () => {
36865
36902
  cancelAnimationFrame(animRef.current);
36866
36903
  };
36867
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
36904
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
36868
36905
  useEffect(() => {
36869
36906
  const canvas = canvasRef.current;
36870
36907
  if (!canvas) return;
@@ -35441,6 +35441,7 @@ var init_GraphCanvas = __esm({
35441
35441
  offsetRef.current = offset;
35442
35442
  const [hoveredNode, setHoveredNode] = React83.useState(null);
35443
35443
  const nodesRef = React83.useRef([]);
35444
+ const laidOutRef = React83.useRef(false);
35444
35445
  const [, forceUpdate] = React83.useState(0);
35445
35446
  const [logicalW, setLogicalW] = React83.useState(800);
35446
35447
  React83.useEffect(() => {
@@ -35536,6 +35537,11 @@ var init_GraphCanvas = __esm({
35536
35537
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
35537
35538
  });
35538
35539
  nodesRef.current = simNodes;
35540
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
35541
+ const newIdList = simNodes.map((n) => n.id);
35542
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
35543
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
35544
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
35539
35545
  if (layout === "force") {
35540
35546
  const maxIterations = 300;
35541
35547
  const tick = () => {
@@ -35642,7 +35648,38 @@ var init_GraphCanvas = __esm({
35642
35648
  }
35643
35649
  }
35644
35650
  };
35645
- for (let i = 0; i < maxIterations; i++) tick();
35651
+ if (fullRelayout) {
35652
+ for (let i = 0; i < maxIterations; i++) tick();
35653
+ laidOutRef.current = true;
35654
+ } else {
35655
+ const centroids = /* @__PURE__ */ new Map();
35656
+ for (const node of simNodes) {
35657
+ if (!prevPos.has(node.id)) continue;
35658
+ const g = node.group ?? "__none__";
35659
+ let c = centroids.get(g);
35660
+ if (!c) {
35661
+ c = { x: 0, y: 0, n: 0 };
35662
+ centroids.set(g, c);
35663
+ }
35664
+ c.x += node.x;
35665
+ c.y += node.y;
35666
+ c.n += 1;
35667
+ }
35668
+ const ringCount = /* @__PURE__ */ new Map();
35669
+ for (const node of simNodes) {
35670
+ if (prevPos.has(node.id)) continue;
35671
+ const g = node.group ?? "__none__";
35672
+ const c = centroids.get(g);
35673
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
35674
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
35675
+ const k = ringCount.get(g) ?? 0;
35676
+ ringCount.set(g, k + 1);
35677
+ const angle = k * 2.399963;
35678
+ const r = 22 + k * 8;
35679
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
35680
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
35681
+ }
35682
+ }
35646
35683
  forceUpdate((n) => n + 1);
35647
35684
  } else {
35648
35685
  forceUpdate((n) => n + 1);
@@ -35650,7 +35687,7 @@ var init_GraphCanvas = __esm({
35650
35687
  return () => {
35651
35688
  cancelAnimationFrame(animRef.current);
35652
35689
  };
35653
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
35690
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
35654
35691
  React83.useEffect(() => {
35655
35692
  const canvas = canvasRef.current;
35656
35693
  if (!canvas) return;
@@ -35396,6 +35396,7 @@ var init_GraphCanvas = __esm({
35396
35396
  offsetRef.current = offset;
35397
35397
  const [hoveredNode, setHoveredNode] = useState(null);
35398
35398
  const nodesRef = useRef([]);
35399
+ const laidOutRef = useRef(false);
35399
35400
  const [, forceUpdate] = useState(0);
35400
35401
  const [logicalW, setLogicalW] = useState(800);
35401
35402
  useEffect(() => {
@@ -35491,6 +35492,11 @@ var init_GraphCanvas = __esm({
35491
35492
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
35492
35493
  });
35493
35494
  nodesRef.current = simNodes;
35495
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
35496
+ const newIdList = simNodes.map((n) => n.id);
35497
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
35498
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
35499
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
35494
35500
  if (layout === "force") {
35495
35501
  const maxIterations = 300;
35496
35502
  const tick = () => {
@@ -35597,7 +35603,38 @@ var init_GraphCanvas = __esm({
35597
35603
  }
35598
35604
  }
35599
35605
  };
35600
- for (let i = 0; i < maxIterations; i++) tick();
35606
+ if (fullRelayout) {
35607
+ for (let i = 0; i < maxIterations; i++) tick();
35608
+ laidOutRef.current = true;
35609
+ } else {
35610
+ const centroids = /* @__PURE__ */ new Map();
35611
+ for (const node of simNodes) {
35612
+ if (!prevPos.has(node.id)) continue;
35613
+ const g = node.group ?? "__none__";
35614
+ let c = centroids.get(g);
35615
+ if (!c) {
35616
+ c = { x: 0, y: 0, n: 0 };
35617
+ centroids.set(g, c);
35618
+ }
35619
+ c.x += node.x;
35620
+ c.y += node.y;
35621
+ c.n += 1;
35622
+ }
35623
+ const ringCount = /* @__PURE__ */ new Map();
35624
+ for (const node of simNodes) {
35625
+ if (prevPos.has(node.id)) continue;
35626
+ const g = node.group ?? "__none__";
35627
+ const c = centroids.get(g);
35628
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
35629
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
35630
+ const k = ringCount.get(g) ?? 0;
35631
+ ringCount.set(g, k + 1);
35632
+ const angle = k * 2.399963;
35633
+ const r = 22 + k * 8;
35634
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
35635
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
35636
+ }
35637
+ }
35601
35638
  forceUpdate((n) => n + 1);
35602
35639
  } else {
35603
35640
  forceUpdate((n) => n + 1);
@@ -35605,7 +35642,7 @@ var init_GraphCanvas = __esm({
35605
35642
  return () => {
35606
35643
  cancelAnimationFrame(animRef.current);
35607
35644
  };
35608
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
35645
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
35609
35646
  useEffect(() => {
35610
35647
  const canvas = canvasRef.current;
35611
35648
  if (!canvas) return;
@@ -34806,6 +34806,7 @@ var init_GraphCanvas = __esm({
34806
34806
  offsetRef.current = offset;
34807
34807
  const [hoveredNode, setHoveredNode] = React81.useState(null);
34808
34808
  const nodesRef = React81.useRef([]);
34809
+ const laidOutRef = React81.useRef(false);
34809
34810
  const [, forceUpdate] = React81.useState(0);
34810
34811
  const [logicalW, setLogicalW] = React81.useState(800);
34811
34812
  React81.useEffect(() => {
@@ -34901,6 +34902,11 @@ var init_GraphCanvas = __esm({
34901
34902
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
34902
34903
  });
34903
34904
  nodesRef.current = simNodes;
34905
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
34906
+ const newIdList = simNodes.map((n) => n.id);
34907
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
34908
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
34909
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
34904
34910
  if (layout === "force") {
34905
34911
  const maxIterations = 300;
34906
34912
  const tick = () => {
@@ -35007,7 +35013,38 @@ var init_GraphCanvas = __esm({
35007
35013
  }
35008
35014
  }
35009
35015
  };
35010
- for (let i = 0; i < maxIterations; i++) tick();
35016
+ if (fullRelayout) {
35017
+ for (let i = 0; i < maxIterations; i++) tick();
35018
+ laidOutRef.current = true;
35019
+ } else {
35020
+ const centroids = /* @__PURE__ */ new Map();
35021
+ for (const node of simNodes) {
35022
+ if (!prevPos.has(node.id)) continue;
35023
+ const g = node.group ?? "__none__";
35024
+ let c = centroids.get(g);
35025
+ if (!c) {
35026
+ c = { x: 0, y: 0, n: 0 };
35027
+ centroids.set(g, c);
35028
+ }
35029
+ c.x += node.x;
35030
+ c.y += node.y;
35031
+ c.n += 1;
35032
+ }
35033
+ const ringCount = /* @__PURE__ */ new Map();
35034
+ for (const node of simNodes) {
35035
+ if (prevPos.has(node.id)) continue;
35036
+ const g = node.group ?? "__none__";
35037
+ const c = centroids.get(g);
35038
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
35039
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
35040
+ const k = ringCount.get(g) ?? 0;
35041
+ ringCount.set(g, k + 1);
35042
+ const angle = k * 2.399963;
35043
+ const r = 22 + k * 8;
35044
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
35045
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
35046
+ }
35047
+ }
35011
35048
  forceUpdate((n) => n + 1);
35012
35049
  } else {
35013
35050
  forceUpdate((n) => n + 1);
@@ -35015,7 +35052,7 @@ var init_GraphCanvas = __esm({
35015
35052
  return () => {
35016
35053
  cancelAnimationFrame(animRef.current);
35017
35054
  };
35018
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
35055
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
35019
35056
  React81.useEffect(() => {
35020
35057
  const canvas = canvasRef.current;
35021
35058
  if (!canvas) return;
@@ -34762,6 +34762,7 @@ var init_GraphCanvas = __esm({
34762
34762
  offsetRef.current = offset;
34763
34763
  const [hoveredNode, setHoveredNode] = useState(null);
34764
34764
  const nodesRef = useRef([]);
34765
+ const laidOutRef = useRef(false);
34765
34766
  const [, forceUpdate] = useState(0);
34766
34767
  const [logicalW, setLogicalW] = useState(800);
34767
34768
  useEffect(() => {
@@ -34857,6 +34858,11 @@ var init_GraphCanvas = __esm({
34857
34858
  return { ...n, x, y, vx: 0, vy: 0, fx: 0, fy: 0 };
34858
34859
  });
34859
34860
  nodesRef.current = simNodes;
34861
+ const prevIds = /* @__PURE__ */ new Set([...prevPos.keys()]);
34862
+ const newIdList = simNodes.map((n) => n.id);
34863
+ const kept = newIdList.filter((id) => prevIds.has(id)).length;
34864
+ const overlap = prevIds.size === 0 ? 0 : kept / Math.max(prevIds.size, newIdList.length);
34865
+ const fullRelayout = !laidOutRef.current || overlap < 0.5;
34860
34866
  if (layout === "force") {
34861
34867
  const maxIterations = 300;
34862
34868
  const tick = () => {
@@ -34963,7 +34969,38 @@ var init_GraphCanvas = __esm({
34963
34969
  }
34964
34970
  }
34965
34971
  };
34966
- for (let i = 0; i < maxIterations; i++) tick();
34972
+ if (fullRelayout) {
34973
+ for (let i = 0; i < maxIterations; i++) tick();
34974
+ laidOutRef.current = true;
34975
+ } else {
34976
+ const centroids = /* @__PURE__ */ new Map();
34977
+ for (const node of simNodes) {
34978
+ if (!prevPos.has(node.id)) continue;
34979
+ const g = node.group ?? "__none__";
34980
+ let c = centroids.get(g);
34981
+ if (!c) {
34982
+ c = { x: 0, y: 0, n: 0 };
34983
+ centroids.set(g, c);
34984
+ }
34985
+ c.x += node.x;
34986
+ c.y += node.y;
34987
+ c.n += 1;
34988
+ }
34989
+ const ringCount = /* @__PURE__ */ new Map();
34990
+ for (const node of simNodes) {
34991
+ if (prevPos.has(node.id)) continue;
34992
+ const g = node.group ?? "__none__";
34993
+ const c = centroids.get(g);
34994
+ const cx = c && c.n > 0 ? c.x / c.n : w / 2;
34995
+ const cy = c && c.n > 0 ? c.y / c.n : h / 2;
34996
+ const k = ringCount.get(g) ?? 0;
34997
+ ringCount.set(g, k + 1);
34998
+ const angle = k * 2.399963;
34999
+ const r = 22 + k * 8;
35000
+ node.x = Math.max(30, Math.min(w - 30, cx + r * Math.cos(angle)));
35001
+ node.y = Math.max(30, Math.min(h - 30, cy + r * Math.sin(angle)));
35002
+ }
35003
+ }
34967
35004
  forceUpdate((n) => n + 1);
34968
35005
  } else {
34969
35006
  forceUpdate((n) => n + 1);
@@ -34971,7 +35008,7 @@ var init_GraphCanvas = __esm({
34971
35008
  return () => {
34972
35009
  cancelAnimationFrame(animRef.current);
34973
35010
  };
34974
- }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels, logicalW, height]);
35011
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
34975
35012
  useEffect(() => {
34976
35013
  const canvas = canvasRef.current;
34977
35014
  if (!canvas) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.116.1",
3
+ "version": "5.117.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [