@almadar/ui 5.119.0 → 5.120.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.
- package/dist/avl/index.cjs +120 -72
- package/dist/avl/index.js +120 -72
- package/dist/components/index.cjs +120 -72
- package/dist/components/index.js +120 -72
- package/dist/providers/index.cjs +120 -72
- package/dist/providers/index.js +120 -72
- package/dist/runtime/index.cjs +120 -72
- package/dist/runtime/index.js +120 -72
- package/package.json +1 -1
package/dist/runtime/index.cjs
CHANGED
|
@@ -34895,8 +34895,11 @@ var init_GraphCanvas = __esm({
|
|
|
34895
34895
|
React81.useEffect(() => {
|
|
34896
34896
|
const canvas = canvasRef.current;
|
|
34897
34897
|
if (!canvas || propNodes.length === 0) return;
|
|
34898
|
-
const
|
|
34899
|
-
const
|
|
34898
|
+
const viewW = logicalW;
|
|
34899
|
+
const viewH = height;
|
|
34900
|
+
const layoutScale = Math.max(1, Math.min(3, Math.sqrt(propNodes.length / 12)));
|
|
34901
|
+
const w = viewW * layoutScale;
|
|
34902
|
+
const h = viewH * layoutScale;
|
|
34900
34903
|
const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
|
|
34901
34904
|
const prevPos = /* @__PURE__ */ new Map();
|
|
34902
34905
|
for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
|
|
@@ -34936,93 +34939,122 @@ var init_GraphCanvas = __esm({
|
|
|
34936
34939
|
const COLLIDE_PASSES = 6;
|
|
34937
34940
|
const LABEL_GAP = 12;
|
|
34938
34941
|
const LABEL_H = 16;
|
|
34939
|
-
const
|
|
34942
|
+
const SIMILARITY_NEIGHBORS = 5;
|
|
34943
|
+
const SIMILARITY_MIN_WEIGHT = 0.25;
|
|
34944
|
+
const drawnPairs = /* @__PURE__ */ new Set();
|
|
34945
|
+
for (const edge of propEdges) drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
34946
|
+
const similarityNeighbors = /* @__PURE__ */ new Map();
|
|
34947
|
+
{
|
|
34948
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
34949
|
+
for (const pair of propSimilarity) {
|
|
34950
|
+
if (pair.weight < SIMILARITY_MIN_WEIGHT) continue;
|
|
34951
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
|
|
34952
|
+
const arr = bySource.get(pair.source) ?? [];
|
|
34953
|
+
arr.push(pair);
|
|
34954
|
+
bySource.set(pair.source, arr);
|
|
34955
|
+
}
|
|
34956
|
+
for (const [id, arr] of bySource) {
|
|
34957
|
+
arr.sort((a, b) => b.weight - a.weight);
|
|
34958
|
+
const keep = new Set(arr.slice(0, SIMILARITY_NEIGHBORS).map((p) => p.target));
|
|
34959
|
+
similarityNeighbors.set(id, keep);
|
|
34960
|
+
}
|
|
34961
|
+
}
|
|
34962
|
+
const activeSimilarity = propSimilarity.filter((pair) => {
|
|
34963
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) return false;
|
|
34964
|
+
const a = similarityNeighbors.get(pair.source);
|
|
34965
|
+
const b = similarityNeighbors.get(pair.target);
|
|
34966
|
+
return (a?.has(pair.target) ?? false) || (b?.has(pair.source) ?? false);
|
|
34967
|
+
});
|
|
34968
|
+
const tick = (iter, options) => {
|
|
34969
|
+
const skipForces = options?.skipForces ?? false;
|
|
34940
34970
|
const nodes = nodesRef.current;
|
|
34941
34971
|
const centerX = w / 2;
|
|
34942
34972
|
const centerY = h / 2;
|
|
34943
|
-
const temp = Math.max(COOL, 1 - iter / maxIterations);
|
|
34973
|
+
const temp = skipForces ? 0 : Math.max(COOL, 1 - iter / maxIterations);
|
|
34944
34974
|
for (const node of nodes) {
|
|
34945
34975
|
node.fx = 0;
|
|
34946
34976
|
node.fy = 0;
|
|
34947
34977
|
}
|
|
34948
|
-
|
|
34949
|
-
for (let
|
|
34950
|
-
|
|
34951
|
-
|
|
34978
|
+
if (!skipForces) {
|
|
34979
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
34980
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
34981
|
+
const dx = nodes[j].x - nodes[i].x;
|
|
34982
|
+
const dy = nodes[j].y - nodes[i].y;
|
|
34983
|
+
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
34984
|
+
const force = repulsion / (dist * dist) * temp;
|
|
34985
|
+
const fx = dx / dist * force;
|
|
34986
|
+
const fy = dy / dist * force;
|
|
34987
|
+
nodes[i].fx -= fx;
|
|
34988
|
+
nodes[i].fy -= fy;
|
|
34989
|
+
nodes[j].fx += fx;
|
|
34990
|
+
nodes[j].fy += fy;
|
|
34991
|
+
}
|
|
34992
|
+
}
|
|
34993
|
+
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
34994
|
+
const spring = (a, b, rest, k) => {
|
|
34995
|
+
const dx = b.x - a.x;
|
|
34996
|
+
const dy = b.y - a.y;
|
|
34952
34997
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
34953
|
-
const force =
|
|
34998
|
+
const force = (dist - rest) * k * temp;
|
|
34954
34999
|
const fx = dx / dist * force;
|
|
34955
35000
|
const fy = dy / dist * force;
|
|
34956
|
-
|
|
34957
|
-
|
|
34958
|
-
|
|
34959
|
-
|
|
35001
|
+
a.fx += fx;
|
|
35002
|
+
a.fy += fy;
|
|
35003
|
+
b.fx -= fx;
|
|
35004
|
+
b.fy -= fy;
|
|
35005
|
+
};
|
|
35006
|
+
for (const edge of propEdges) {
|
|
35007
|
+
const source = nodeById.get(edge.source);
|
|
35008
|
+
const target = nodeById.get(edge.target);
|
|
35009
|
+
if (!source || !target) continue;
|
|
35010
|
+
drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
35011
|
+
const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
|
|
35012
|
+
spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
|
|
34960
35013
|
}
|
|
34961
|
-
|
|
34962
|
-
|
|
34963
|
-
|
|
34964
|
-
|
|
34965
|
-
|
|
34966
|
-
|
|
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);
|
|
34991
|
-
}
|
|
34992
|
-
const centroids = /* @__PURE__ */ new Map();
|
|
34993
|
-
for (const node of nodes) {
|
|
34994
|
-
const g = node.group ?? "__none__";
|
|
34995
|
-
let c = centroids.get(g);
|
|
34996
|
-
if (!c) {
|
|
34997
|
-
c = { x: 0, y: 0, n: 0 };
|
|
34998
|
-
centroids.set(g, c);
|
|
35014
|
+
for (const pair of activeSimilarity) {
|
|
35015
|
+
const source = nodeById.get(pair.source);
|
|
35016
|
+
const target = nodeById.get(pair.target);
|
|
35017
|
+
if (!source || !target) continue;
|
|
35018
|
+
const w2 = Math.min(1, Math.max(0, pair.weight));
|
|
35019
|
+
spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
|
|
34999
35020
|
}
|
|
35000
|
-
|
|
35001
|
-
|
|
35002
|
-
|
|
35003
|
-
|
|
35004
|
-
|
|
35005
|
-
|
|
35006
|
-
|
|
35007
|
-
|
|
35008
|
-
|
|
35009
|
-
|
|
35010
|
-
|
|
35021
|
+
const centroids = /* @__PURE__ */ new Map();
|
|
35022
|
+
for (const node of nodes) {
|
|
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 multiCluster = centroids.size > 1;
|
|
35034
|
+
for (const node of nodes) {
|
|
35035
|
+
if (multiCluster) {
|
|
35036
|
+
const c = centroids.get(node.group ?? "__none__");
|
|
35037
|
+
if (c && c.n > 1) {
|
|
35038
|
+
node.fx += (c.x / c.n - node.x) * 0.06 * temp;
|
|
35039
|
+
node.fy += (c.y / c.n - node.y) * 0.06 * temp;
|
|
35040
|
+
} else {
|
|
35041
|
+
node.fx += (centerX - node.x) * 0.01 * temp;
|
|
35042
|
+
node.fy += (centerY - node.y) * 0.01 * temp;
|
|
35043
|
+
}
|
|
35011
35044
|
} else {
|
|
35012
|
-
node.fx += (centerX - node.x) *
|
|
35013
|
-
node.fy += (centerY - node.y) *
|
|
35045
|
+
node.fx += (centerX - node.x) * 8e-3 * temp;
|
|
35046
|
+
node.fy += (centerY - node.y) * 8e-3 * temp;
|
|
35014
35047
|
}
|
|
35015
|
-
}
|
|
35016
|
-
|
|
35017
|
-
|
|
35048
|
+
}
|
|
35049
|
+
const damping = 0.9;
|
|
35050
|
+
for (const node of nodes) {
|
|
35051
|
+
node.vx = (node.vx + node.fx) * damping;
|
|
35052
|
+
node.vy = (node.vy + node.fy) * damping;
|
|
35053
|
+
node.x += node.vx;
|
|
35054
|
+
node.y += node.vy;
|
|
35018
35055
|
}
|
|
35019
35056
|
}
|
|
35020
|
-
const damping = 0.9;
|
|
35021
35057
|
for (const node of nodes) {
|
|
35022
|
-
node.vx = (node.vx + node.fx) * damping;
|
|
35023
|
-
node.vy = (node.vy + node.fy) * damping;
|
|
35024
|
-
node.x += node.vx;
|
|
35025
|
-
node.y += node.vy;
|
|
35026
35058
|
node.x = Math.max(30, Math.min(w - 30, node.x));
|
|
35027
35059
|
node.y = Math.max(30, Math.min(h - 30, node.y));
|
|
35028
35060
|
}
|
|
@@ -35073,6 +35105,22 @@ var init_GraphCanvas = __esm({
|
|
|
35073
35105
|
};
|
|
35074
35106
|
if (fullRelayout) {
|
|
35075
35107
|
for (let i = 0; i < maxIterations; i++) tick(i);
|
|
35108
|
+
for (let i = 0; i < 4; i++) tick(maxIterations, { skipForces: true });
|
|
35109
|
+
const fitPad = 40;
|
|
35110
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
35111
|
+
for (const node of nodesRef.current) {
|
|
35112
|
+
const r = node.size || 8;
|
|
35113
|
+
const lw = showLabels ? node.labelW ?? (node.labelW = node.label ? measureLabelWidth(node.label, labelFont) : 0) : 0;
|
|
35114
|
+
minX = Math.min(minX, node.x - r, node.x - lw / 2);
|
|
35115
|
+
minY = Math.min(minY, node.y - r);
|
|
35116
|
+
maxX = Math.max(maxX, node.x + r, node.x + lw / 2);
|
|
35117
|
+
maxY = Math.max(maxY, node.y + r + LABEL_GAP + LABEL_H);
|
|
35118
|
+
}
|
|
35119
|
+
const bboxW = Math.max(1, maxX - minX + fitPad * 2);
|
|
35120
|
+
const bboxH = Math.max(1, maxY - minY + fitPad * 2);
|
|
35121
|
+
const nextZoom = Math.min(1, viewW / bboxW, viewH / bboxH);
|
|
35122
|
+
setZoom(nextZoom);
|
|
35123
|
+
setOffset({ x: fitPad - minX * nextZoom, y: fitPad - minY * nextZoom });
|
|
35076
35124
|
laidOutRef.current = true;
|
|
35077
35125
|
} else {
|
|
35078
35126
|
const centroids = /* @__PURE__ */ new Map();
|
package/dist/runtime/index.js
CHANGED
|
@@ -34851,8 +34851,11 @@ var init_GraphCanvas = __esm({
|
|
|
34851
34851
|
useEffect(() => {
|
|
34852
34852
|
const canvas = canvasRef.current;
|
|
34853
34853
|
if (!canvas || propNodes.length === 0) return;
|
|
34854
|
-
const
|
|
34855
|
-
const
|
|
34854
|
+
const viewW = logicalW;
|
|
34855
|
+
const viewH = height;
|
|
34856
|
+
const layoutScale = Math.max(1, Math.min(3, Math.sqrt(propNodes.length / 12)));
|
|
34857
|
+
const w = viewW * layoutScale;
|
|
34858
|
+
const h = viewH * layoutScale;
|
|
34856
34859
|
const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
|
|
34857
34860
|
const prevPos = /* @__PURE__ */ new Map();
|
|
34858
34861
|
for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
|
|
@@ -34892,93 +34895,122 @@ var init_GraphCanvas = __esm({
|
|
|
34892
34895
|
const COLLIDE_PASSES = 6;
|
|
34893
34896
|
const LABEL_GAP = 12;
|
|
34894
34897
|
const LABEL_H = 16;
|
|
34895
|
-
const
|
|
34898
|
+
const SIMILARITY_NEIGHBORS = 5;
|
|
34899
|
+
const SIMILARITY_MIN_WEIGHT = 0.25;
|
|
34900
|
+
const drawnPairs = /* @__PURE__ */ new Set();
|
|
34901
|
+
for (const edge of propEdges) drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
34902
|
+
const similarityNeighbors = /* @__PURE__ */ new Map();
|
|
34903
|
+
{
|
|
34904
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
34905
|
+
for (const pair of propSimilarity) {
|
|
34906
|
+
if (pair.weight < SIMILARITY_MIN_WEIGHT) continue;
|
|
34907
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
|
|
34908
|
+
const arr = bySource.get(pair.source) ?? [];
|
|
34909
|
+
arr.push(pair);
|
|
34910
|
+
bySource.set(pair.source, arr);
|
|
34911
|
+
}
|
|
34912
|
+
for (const [id, arr] of bySource) {
|
|
34913
|
+
arr.sort((a, b) => b.weight - a.weight);
|
|
34914
|
+
const keep = new Set(arr.slice(0, SIMILARITY_NEIGHBORS).map((p) => p.target));
|
|
34915
|
+
similarityNeighbors.set(id, keep);
|
|
34916
|
+
}
|
|
34917
|
+
}
|
|
34918
|
+
const activeSimilarity = propSimilarity.filter((pair) => {
|
|
34919
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) return false;
|
|
34920
|
+
const a = similarityNeighbors.get(pair.source);
|
|
34921
|
+
const b = similarityNeighbors.get(pair.target);
|
|
34922
|
+
return (a?.has(pair.target) ?? false) || (b?.has(pair.source) ?? false);
|
|
34923
|
+
});
|
|
34924
|
+
const tick = (iter, options) => {
|
|
34925
|
+
const skipForces = options?.skipForces ?? false;
|
|
34896
34926
|
const nodes = nodesRef.current;
|
|
34897
34927
|
const centerX = w / 2;
|
|
34898
34928
|
const centerY = h / 2;
|
|
34899
|
-
const temp = Math.max(COOL, 1 - iter / maxIterations);
|
|
34929
|
+
const temp = skipForces ? 0 : Math.max(COOL, 1 - iter / maxIterations);
|
|
34900
34930
|
for (const node of nodes) {
|
|
34901
34931
|
node.fx = 0;
|
|
34902
34932
|
node.fy = 0;
|
|
34903
34933
|
}
|
|
34904
|
-
|
|
34905
|
-
for (let
|
|
34906
|
-
|
|
34907
|
-
|
|
34934
|
+
if (!skipForces) {
|
|
34935
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
34936
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
34937
|
+
const dx = nodes[j].x - nodes[i].x;
|
|
34938
|
+
const dy = nodes[j].y - nodes[i].y;
|
|
34939
|
+
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
34940
|
+
const force = repulsion / (dist * dist) * temp;
|
|
34941
|
+
const fx = dx / dist * force;
|
|
34942
|
+
const fy = dy / dist * force;
|
|
34943
|
+
nodes[i].fx -= fx;
|
|
34944
|
+
nodes[i].fy -= fy;
|
|
34945
|
+
nodes[j].fx += fx;
|
|
34946
|
+
nodes[j].fy += fy;
|
|
34947
|
+
}
|
|
34948
|
+
}
|
|
34949
|
+
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
34950
|
+
const spring = (a, b, rest, k) => {
|
|
34951
|
+
const dx = b.x - a.x;
|
|
34952
|
+
const dy = b.y - a.y;
|
|
34908
34953
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
34909
|
-
const force =
|
|
34954
|
+
const force = (dist - rest) * k * temp;
|
|
34910
34955
|
const fx = dx / dist * force;
|
|
34911
34956
|
const fy = dy / dist * force;
|
|
34912
|
-
|
|
34913
|
-
|
|
34914
|
-
|
|
34915
|
-
|
|
34957
|
+
a.fx += fx;
|
|
34958
|
+
a.fy += fy;
|
|
34959
|
+
b.fx -= fx;
|
|
34960
|
+
b.fy -= fy;
|
|
34961
|
+
};
|
|
34962
|
+
for (const edge of propEdges) {
|
|
34963
|
+
const source = nodeById.get(edge.source);
|
|
34964
|
+
const target = nodeById.get(edge.target);
|
|
34965
|
+
if (!source || !target) continue;
|
|
34966
|
+
drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
34967
|
+
const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
|
|
34968
|
+
spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
|
|
34916
34969
|
}
|
|
34917
|
-
|
|
34918
|
-
|
|
34919
|
-
|
|
34920
|
-
|
|
34921
|
-
|
|
34922
|
-
|
|
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);
|
|
34947
|
-
}
|
|
34948
|
-
const centroids = /* @__PURE__ */ new Map();
|
|
34949
|
-
for (const node of nodes) {
|
|
34950
|
-
const g = node.group ?? "__none__";
|
|
34951
|
-
let c = centroids.get(g);
|
|
34952
|
-
if (!c) {
|
|
34953
|
-
c = { x: 0, y: 0, n: 0 };
|
|
34954
|
-
centroids.set(g, c);
|
|
34970
|
+
for (const pair of activeSimilarity) {
|
|
34971
|
+
const source = nodeById.get(pair.source);
|
|
34972
|
+
const target = nodeById.get(pair.target);
|
|
34973
|
+
if (!source || !target) continue;
|
|
34974
|
+
const w2 = Math.min(1, Math.max(0, pair.weight));
|
|
34975
|
+
spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
|
|
34955
34976
|
}
|
|
34956
|
-
|
|
34957
|
-
|
|
34958
|
-
|
|
34959
|
-
|
|
34960
|
-
|
|
34961
|
-
|
|
34962
|
-
|
|
34963
|
-
|
|
34964
|
-
|
|
34965
|
-
|
|
34966
|
-
|
|
34977
|
+
const centroids = /* @__PURE__ */ new Map();
|
|
34978
|
+
for (const node of nodes) {
|
|
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 multiCluster = centroids.size > 1;
|
|
34990
|
+
for (const node of nodes) {
|
|
34991
|
+
if (multiCluster) {
|
|
34992
|
+
const c = centroids.get(node.group ?? "__none__");
|
|
34993
|
+
if (c && c.n > 1) {
|
|
34994
|
+
node.fx += (c.x / c.n - node.x) * 0.06 * temp;
|
|
34995
|
+
node.fy += (c.y / c.n - node.y) * 0.06 * temp;
|
|
34996
|
+
} else {
|
|
34997
|
+
node.fx += (centerX - node.x) * 0.01 * temp;
|
|
34998
|
+
node.fy += (centerY - node.y) * 0.01 * temp;
|
|
34999
|
+
}
|
|
34967
35000
|
} else {
|
|
34968
|
-
node.fx += (centerX - node.x) *
|
|
34969
|
-
node.fy += (centerY - node.y) *
|
|
35001
|
+
node.fx += (centerX - node.x) * 8e-3 * temp;
|
|
35002
|
+
node.fy += (centerY - node.y) * 8e-3 * temp;
|
|
34970
35003
|
}
|
|
34971
|
-
}
|
|
34972
|
-
|
|
34973
|
-
|
|
35004
|
+
}
|
|
35005
|
+
const damping = 0.9;
|
|
35006
|
+
for (const node of nodes) {
|
|
35007
|
+
node.vx = (node.vx + node.fx) * damping;
|
|
35008
|
+
node.vy = (node.vy + node.fy) * damping;
|
|
35009
|
+
node.x += node.vx;
|
|
35010
|
+
node.y += node.vy;
|
|
34974
35011
|
}
|
|
34975
35012
|
}
|
|
34976
|
-
const damping = 0.9;
|
|
34977
35013
|
for (const node of nodes) {
|
|
34978
|
-
node.vx = (node.vx + node.fx) * damping;
|
|
34979
|
-
node.vy = (node.vy + node.fy) * damping;
|
|
34980
|
-
node.x += node.vx;
|
|
34981
|
-
node.y += node.vy;
|
|
34982
35014
|
node.x = Math.max(30, Math.min(w - 30, node.x));
|
|
34983
35015
|
node.y = Math.max(30, Math.min(h - 30, node.y));
|
|
34984
35016
|
}
|
|
@@ -35029,6 +35061,22 @@ var init_GraphCanvas = __esm({
|
|
|
35029
35061
|
};
|
|
35030
35062
|
if (fullRelayout) {
|
|
35031
35063
|
for (let i = 0; i < maxIterations; i++) tick(i);
|
|
35064
|
+
for (let i = 0; i < 4; i++) tick(maxIterations, { skipForces: true });
|
|
35065
|
+
const fitPad = 40;
|
|
35066
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
35067
|
+
for (const node of nodesRef.current) {
|
|
35068
|
+
const r = node.size || 8;
|
|
35069
|
+
const lw = showLabels ? node.labelW ?? (node.labelW = node.label ? measureLabelWidth(node.label, labelFont) : 0) : 0;
|
|
35070
|
+
minX = Math.min(minX, node.x - r, node.x - lw / 2);
|
|
35071
|
+
minY = Math.min(minY, node.y - r);
|
|
35072
|
+
maxX = Math.max(maxX, node.x + r, node.x + lw / 2);
|
|
35073
|
+
maxY = Math.max(maxY, node.y + r + LABEL_GAP + LABEL_H);
|
|
35074
|
+
}
|
|
35075
|
+
const bboxW = Math.max(1, maxX - minX + fitPad * 2);
|
|
35076
|
+
const bboxH = Math.max(1, maxY - minY + fitPad * 2);
|
|
35077
|
+
const nextZoom = Math.min(1, viewW / bboxW, viewH / bboxH);
|
|
35078
|
+
setZoom(nextZoom);
|
|
35079
|
+
setOffset({ x: fitPad - minX * nextZoom, y: fitPad - minY * nextZoom });
|
|
35032
35080
|
laidOutRef.current = true;
|
|
35033
35081
|
} else {
|
|
35034
35082
|
const centroids = /* @__PURE__ */ new Map();
|