@almadar/ui 5.118.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 +166 -100
- package/dist/avl/index.js +166 -100
- package/dist/components/index.cjs +166 -100
- package/dist/components/index.d.cts +9 -7
- package/dist/components/index.d.ts +9 -7
- package/dist/components/index.js +166 -100
- package/dist/providers/index.cjs +166 -100
- package/dist/providers/index.js +166 -100
- package/dist/runtime/index.cjs +166 -100
- package/dist/runtime/index.js +166 -100
- package/package.json +1 -1
|
@@ -36626,11 +36626,11 @@ var init_DocumentViewer = __esm({
|
|
|
36626
36626
|
exports.DocumentViewer.displayName = "DocumentViewer";
|
|
36627
36627
|
}
|
|
36628
36628
|
});
|
|
36629
|
-
function measureLabelWidth(text) {
|
|
36629
|
+
function measureLabelWidth(text, fontFamily = "system-ui") {
|
|
36630
36630
|
if (typeof document === "undefined") return text.length * 6;
|
|
36631
36631
|
if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
|
|
36632
36632
|
if (!labelMeasureCtx) return text.length * 6;
|
|
36633
|
-
labelMeasureCtx.font =
|
|
36633
|
+
labelMeasureCtx.font = `12px ${fontFamily}`;
|
|
36634
36634
|
return labelMeasureCtx.measureText(text).width + 4;
|
|
36635
36635
|
}
|
|
36636
36636
|
function getGroupColor(group, groups) {
|
|
@@ -36655,6 +36655,9 @@ function mulberry32(a) {
|
|
|
36655
36655
|
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
36656
36656
|
};
|
|
36657
36657
|
}
|
|
36658
|
+
function edgeKeyOf(a, b) {
|
|
36659
|
+
return a < b ? `${a}\0${b}` : `${b}\0${a}`;
|
|
36660
|
+
}
|
|
36658
36661
|
function resolveColor3(color, el) {
|
|
36659
36662
|
const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
|
|
36660
36663
|
if (!m) return color;
|
|
@@ -36786,8 +36789,12 @@ var init_GraphCanvas = __esm({
|
|
|
36786
36789
|
React73.useEffect(() => {
|
|
36787
36790
|
const canvas = canvasRef.current;
|
|
36788
36791
|
if (!canvas || propNodes.length === 0) return;
|
|
36789
|
-
const
|
|
36790
|
-
const
|
|
36792
|
+
const viewW = logicalW;
|
|
36793
|
+
const viewH = height;
|
|
36794
|
+
const layoutScale = Math.max(1, Math.min(3, Math.sqrt(propNodes.length / 12)));
|
|
36795
|
+
const w = viewW * layoutScale;
|
|
36796
|
+
const h = viewH * layoutScale;
|
|
36797
|
+
const labelFont = resolveColor3("var(--font-family)", canvas) || "system-ui";
|
|
36791
36798
|
const prevPos = /* @__PURE__ */ new Map();
|
|
36792
36799
|
for (const pn of nodesRef.current) if (pn.x != null && pn.y != null) prevPos.set(pn.id, { x: pn.x, y: pn.y });
|
|
36793
36800
|
const simNodes = propNodes.map((n, idx) => {
|
|
@@ -36822,133 +36829,192 @@ var init_GraphCanvas = __esm({
|
|
|
36822
36829
|
const fullRelayout = !laidOutRef.current || overlap < 0.5;
|
|
36823
36830
|
if (layout === "force") {
|
|
36824
36831
|
const maxIterations = 300;
|
|
36825
|
-
const
|
|
36832
|
+
const COOL = 0.12;
|
|
36833
|
+
const COLLIDE_PASSES = 6;
|
|
36834
|
+
const LABEL_GAP = 12;
|
|
36835
|
+
const LABEL_H = 16;
|
|
36836
|
+
const SIMILARITY_NEIGHBORS = 5;
|
|
36837
|
+
const SIMILARITY_MIN_WEIGHT = 0.25;
|
|
36838
|
+
const drawnPairs = /* @__PURE__ */ new Set();
|
|
36839
|
+
for (const edge of propEdges) drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
36840
|
+
const similarityNeighbors = /* @__PURE__ */ new Map();
|
|
36841
|
+
{
|
|
36842
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
36843
|
+
for (const pair of propSimilarity) {
|
|
36844
|
+
if (pair.weight < SIMILARITY_MIN_WEIGHT) continue;
|
|
36845
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) continue;
|
|
36846
|
+
const arr = bySource.get(pair.source) ?? [];
|
|
36847
|
+
arr.push(pair);
|
|
36848
|
+
bySource.set(pair.source, arr);
|
|
36849
|
+
}
|
|
36850
|
+
for (const [id, arr] of bySource) {
|
|
36851
|
+
arr.sort((a, b) => b.weight - a.weight);
|
|
36852
|
+
const keep = new Set(arr.slice(0, SIMILARITY_NEIGHBORS).map((p) => p.target));
|
|
36853
|
+
similarityNeighbors.set(id, keep);
|
|
36854
|
+
}
|
|
36855
|
+
}
|
|
36856
|
+
const activeSimilarity = propSimilarity.filter((pair) => {
|
|
36857
|
+
if (drawnPairs.has(edgeKeyOf(pair.source, pair.target))) return false;
|
|
36858
|
+
const a = similarityNeighbors.get(pair.source);
|
|
36859
|
+
const b = similarityNeighbors.get(pair.target);
|
|
36860
|
+
return (a?.has(pair.target) ?? false) || (b?.has(pair.source) ?? false);
|
|
36861
|
+
});
|
|
36862
|
+
const tick = (iter, options) => {
|
|
36863
|
+
const skipForces = options?.skipForces ?? false;
|
|
36826
36864
|
const nodes = nodesRef.current;
|
|
36827
36865
|
const centerX = w / 2;
|
|
36828
36866
|
const centerY = h / 2;
|
|
36867
|
+
const temp = skipForces ? 0 : Math.max(COOL, 1 - iter / maxIterations);
|
|
36829
36868
|
for (const node of nodes) {
|
|
36830
36869
|
node.fx = 0;
|
|
36831
36870
|
node.fy = 0;
|
|
36832
36871
|
}
|
|
36833
|
-
|
|
36834
|
-
for (let
|
|
36835
|
-
|
|
36836
|
-
|
|
36837
|
-
|
|
36838
|
-
|
|
36839
|
-
|
|
36840
|
-
|
|
36841
|
-
|
|
36842
|
-
|
|
36843
|
-
|
|
36844
|
-
|
|
36872
|
+
if (!skipForces) {
|
|
36873
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
36874
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
36875
|
+
const dx = nodes[j].x - nodes[i].x;
|
|
36876
|
+
const dy = nodes[j].y - nodes[i].y;
|
|
36877
|
+
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
36878
|
+
const force = repulsion / (dist * dist) * temp;
|
|
36879
|
+
const fx = dx / dist * force;
|
|
36880
|
+
const fy = dy / dist * force;
|
|
36881
|
+
nodes[i].fx -= fx;
|
|
36882
|
+
nodes[i].fy -= fy;
|
|
36883
|
+
nodes[j].fx += fx;
|
|
36884
|
+
nodes[j].fy += fy;
|
|
36885
|
+
}
|
|
36845
36886
|
}
|
|
36846
|
-
|
|
36847
|
-
|
|
36848
|
-
|
|
36849
|
-
|
|
36850
|
-
const source = nodeById.get(pair.source);
|
|
36851
|
-
const target = nodeById.get(pair.target);
|
|
36852
|
-
if (!source || !target) continue;
|
|
36853
|
-
const dx = target.x - source.x;
|
|
36854
|
-
const dy = target.y - source.y;
|
|
36887
|
+
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
36888
|
+
const spring = (a, b, rest, k) => {
|
|
36889
|
+
const dx = b.x - a.x;
|
|
36890
|
+
const dy = b.y - a.y;
|
|
36855
36891
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
36856
|
-
const
|
|
36857
|
-
const linkTarget = linkDistance * (1 - w2);
|
|
36858
|
-
const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
|
|
36892
|
+
const force = (dist - rest) * k * temp;
|
|
36859
36893
|
const fx = dx / dist * force;
|
|
36860
36894
|
const fy = dy / dist * force;
|
|
36861
|
-
|
|
36862
|
-
|
|
36863
|
-
|
|
36864
|
-
|
|
36865
|
-
}
|
|
36866
|
-
} else {
|
|
36895
|
+
a.fx += fx;
|
|
36896
|
+
a.fy += fy;
|
|
36897
|
+
b.fx -= fx;
|
|
36898
|
+
b.fy -= fy;
|
|
36899
|
+
};
|
|
36867
36900
|
for (const edge of propEdges) {
|
|
36868
36901
|
const source = nodeById.get(edge.source);
|
|
36869
36902
|
const target = nodeById.get(edge.target);
|
|
36870
36903
|
if (!source || !target) continue;
|
|
36871
|
-
|
|
36872
|
-
const dy = target.y - source.y;
|
|
36873
|
-
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
36904
|
+
drawnPairs.add(edgeKeyOf(edge.source, edge.target));
|
|
36874
36905
|
const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
|
|
36875
|
-
|
|
36876
|
-
const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
|
|
36877
|
-
const fx = dx / dist * force;
|
|
36878
|
-
const fy = dy / dist * force;
|
|
36879
|
-
source.fx += fx;
|
|
36880
|
-
source.fy += fy;
|
|
36881
|
-
target.fx -= fx;
|
|
36882
|
-
target.fy -= fy;
|
|
36906
|
+
spring(source, target, linkDistance * (0.35 + (1 - w2) * 0.3), 0.14);
|
|
36883
36907
|
}
|
|
36884
|
-
|
|
36885
|
-
|
|
36886
|
-
|
|
36887
|
-
|
|
36888
|
-
|
|
36889
|
-
|
|
36890
|
-
c = { x: 0, y: 0, n: 0 };
|
|
36891
|
-
centroids.set(g, c);
|
|
36908
|
+
for (const pair of activeSimilarity) {
|
|
36909
|
+
const source = nodeById.get(pair.source);
|
|
36910
|
+
const target = nodeById.get(pair.target);
|
|
36911
|
+
if (!source || !target) continue;
|
|
36912
|
+
const w2 = Math.min(1, Math.max(0, pair.weight));
|
|
36913
|
+
spring(source, target, linkDistance * (1.35 - 0.55 * w2), 0.015);
|
|
36892
36914
|
}
|
|
36893
|
-
|
|
36894
|
-
|
|
36895
|
-
|
|
36896
|
-
|
|
36897
|
-
|
|
36898
|
-
|
|
36899
|
-
|
|
36900
|
-
|
|
36901
|
-
|
|
36902
|
-
|
|
36903
|
-
|
|
36904
|
-
|
|
36915
|
+
const centroids = /* @__PURE__ */ new Map();
|
|
36916
|
+
for (const node of nodes) {
|
|
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 multiCluster = centroids.size > 1;
|
|
36928
|
+
for (const node of nodes) {
|
|
36929
|
+
if (multiCluster) {
|
|
36930
|
+
const c = centroids.get(node.group ?? "__none__");
|
|
36931
|
+
if (c && c.n > 1) {
|
|
36932
|
+
node.fx += (c.x / c.n - node.x) * 0.06 * temp;
|
|
36933
|
+
node.fy += (c.y / c.n - node.y) * 0.06 * temp;
|
|
36934
|
+
} else {
|
|
36935
|
+
node.fx += (centerX - node.x) * 0.01 * temp;
|
|
36936
|
+
node.fy += (centerY - node.y) * 0.01 * temp;
|
|
36937
|
+
}
|
|
36938
|
+
} else {
|
|
36939
|
+
node.fx += (centerX - node.x) * 8e-3 * temp;
|
|
36940
|
+
node.fy += (centerY - node.y) * 8e-3 * temp;
|
|
36941
|
+
}
|
|
36942
|
+
}
|
|
36943
|
+
const damping = 0.9;
|
|
36944
|
+
for (const node of nodes) {
|
|
36945
|
+
node.vx = (node.vx + node.fx) * damping;
|
|
36946
|
+
node.vy = (node.vy + node.fy) * damping;
|
|
36947
|
+
node.x += node.vx;
|
|
36948
|
+
node.y += node.vy;
|
|
36905
36949
|
}
|
|
36906
36950
|
}
|
|
36907
|
-
const damping = 0.9;
|
|
36908
36951
|
for (const node of nodes) {
|
|
36909
|
-
node.vx = (node.vx + node.fx) * damping;
|
|
36910
|
-
node.vy = (node.vy + node.fy) * damping;
|
|
36911
|
-
node.x += node.vx;
|
|
36912
|
-
node.y += node.vy;
|
|
36913
36952
|
node.x = Math.max(30, Math.min(w - 30, node.x));
|
|
36914
36953
|
node.y = Math.max(30, Math.min(h - 30, node.y));
|
|
36915
36954
|
}
|
|
36916
|
-
const LABEL_GAP = 12;
|
|
36917
|
-
const LABEL_H = 16;
|
|
36918
36955
|
const pad = nodeSpacing / 2;
|
|
36919
|
-
|
|
36920
|
-
|
|
36921
|
-
|
|
36922
|
-
|
|
36923
|
-
|
|
36924
|
-
|
|
36925
|
-
|
|
36926
|
-
|
|
36927
|
-
|
|
36928
|
-
|
|
36929
|
-
|
|
36930
|
-
|
|
36931
|
-
|
|
36932
|
-
|
|
36933
|
-
|
|
36934
|
-
|
|
36935
|
-
|
|
36936
|
-
|
|
36937
|
-
|
|
36938
|
-
|
|
36939
|
-
|
|
36940
|
-
|
|
36941
|
-
|
|
36942
|
-
const
|
|
36943
|
-
|
|
36944
|
-
|
|
36956
|
+
const rectsOf = (n) => {
|
|
36957
|
+
const r = n.size || 8;
|
|
36958
|
+
const lw = showLabels ? n.labelW ?? (n.labelW = n.label ? measureLabelWidth(n.label, labelFont) : 0) : 0;
|
|
36959
|
+
return {
|
|
36960
|
+
circle: [n.x - r - pad, n.y - r - pad, n.x + r + pad, n.y + r + pad],
|
|
36961
|
+
label: [n.x - lw / 2 - pad, n.y + r + LABEL_GAP - 8, n.x + lw / 2 + pad, n.y + r + LABEL_GAP + LABEL_H]
|
|
36962
|
+
};
|
|
36963
|
+
};
|
|
36964
|
+
const sep = (r1, r2) => {
|
|
36965
|
+
const ox = Math.min(r1[2], r2[2]) - Math.max(r1[0], r2[0]);
|
|
36966
|
+
const oy = Math.min(r1[3], r2[3]) - Math.max(r1[1], r2[1]);
|
|
36967
|
+
if (ox <= 0 || oy <= 0) return null;
|
|
36968
|
+
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 };
|
|
36969
|
+
};
|
|
36970
|
+
for (let pass = 0; pass < COLLIDE_PASSES; pass++) {
|
|
36971
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
36972
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
36973
|
+
const a = nodes[i];
|
|
36974
|
+
const b = nodes[j];
|
|
36975
|
+
const ra = rectsOf(a);
|
|
36976
|
+
const rb = rectsOf(b);
|
|
36977
|
+
let best = null;
|
|
36978
|
+
for (const [r1, r2] of [[ra.circle, rb.circle], [ra.circle, rb.label], [ra.label, rb.circle], [ra.label, rb.label]]) {
|
|
36979
|
+
const s = sep(r1, r2);
|
|
36980
|
+
if (s && (!best || s.depth < best.depth)) best = s;
|
|
36981
|
+
}
|
|
36982
|
+
if (best) {
|
|
36983
|
+
const push = best.depth / 2;
|
|
36984
|
+
if (best.axis === "x") {
|
|
36985
|
+
a.x = Math.max(30, Math.min(w - 30, a.x - push * best.sign));
|
|
36986
|
+
b.x = Math.max(30, Math.min(w - 30, b.x + push * best.sign));
|
|
36987
|
+
a.vx = 0;
|
|
36988
|
+
b.vx = 0;
|
|
36989
|
+
} else {
|
|
36990
|
+
a.y = Math.max(30, Math.min(h - 30, a.y - push * best.sign));
|
|
36991
|
+
b.y = Math.max(30, Math.min(h - 30, b.y + push * best.sign));
|
|
36992
|
+
a.vy = 0;
|
|
36993
|
+
b.vy = 0;
|
|
36994
|
+
}
|
|
36945
36995
|
}
|
|
36946
36996
|
}
|
|
36947
36997
|
}
|
|
36948
36998
|
}
|
|
36949
36999
|
};
|
|
36950
37000
|
if (fullRelayout) {
|
|
36951
|
-
for (let i = 0; i < maxIterations; i++) tick();
|
|
37001
|
+
for (let i = 0; i < maxIterations; i++) tick(i);
|
|
37002
|
+
for (let i = 0; i < 4; i++) tick(maxIterations, { skipForces: true });
|
|
37003
|
+
const fitPad = 40;
|
|
37004
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
37005
|
+
for (const node of nodesRef.current) {
|
|
37006
|
+
const r = node.size || 8;
|
|
37007
|
+
const lw = showLabels ? node.labelW ?? (node.labelW = node.label ? measureLabelWidth(node.label, labelFont) : 0) : 0;
|
|
37008
|
+
minX = Math.min(minX, node.x - r, node.x - lw / 2);
|
|
37009
|
+
minY = Math.min(minY, node.y - r);
|
|
37010
|
+
maxX = Math.max(maxX, node.x + r, node.x + lw / 2);
|
|
37011
|
+
maxY = Math.max(maxY, node.y + r + LABEL_GAP + LABEL_H);
|
|
37012
|
+
}
|
|
37013
|
+
const bboxW = Math.max(1, maxX - minX + fitPad * 2);
|
|
37014
|
+
const bboxH = Math.max(1, maxY - minY + fitPad * 2);
|
|
37015
|
+
const nextZoom = Math.min(1, viewW / bboxW, viewH / bboxH);
|
|
37016
|
+
setZoom(nextZoom);
|
|
37017
|
+
setOffset({ x: fitPad - minX * nextZoom, y: fitPad - minY * nextZoom });
|
|
36952
37018
|
laidOutRef.current = true;
|
|
36953
37019
|
} else {
|
|
36954
37020
|
const centroids = /* @__PURE__ */ new Map();
|
|
@@ -8832,10 +8832,11 @@ interface GraphEdge {
|
|
|
8832
8832
|
color?: string;
|
|
8833
8833
|
}
|
|
8834
8834
|
/**
|
|
8835
|
-
* All-pairs similarity (cosine 0–1) used ONLY for layout
|
|
8836
|
-
*
|
|
8837
|
-
*
|
|
8838
|
-
*
|
|
8835
|
+
* All-pairs similarity (cosine 0–1) used ONLY for layout, never drawn — `edges`
|
|
8836
|
+
* remain the only rendered links. It is the SECONDARY macro-layout: pairs that are
|
|
8837
|
+
* NOT directly connected get a weak spring (higher cosine ⇒ closer) so clusters
|
|
8838
|
+
* arrange relative to each other, while drawn `edges` stay the primary tight
|
|
8839
|
+
* structure. When omitted, edges alone drive the layout.
|
|
8839
8840
|
*/
|
|
8840
8841
|
interface GraphSimilarity {
|
|
8841
8842
|
source: string;
|
|
@@ -8857,9 +8858,10 @@ interface GraphCanvasProps {
|
|
|
8857
8858
|
/** Graph edges (the only rendered links) */
|
|
8858
8859
|
edges?: readonly GraphEdge[];
|
|
8859
8860
|
/**
|
|
8860
|
-
* All-pairs similarity (cosine 0–1) used ONLY for layout
|
|
8861
|
-
*
|
|
8862
|
-
*
|
|
8861
|
+
* All-pairs similarity (cosine 0–1) used ONLY for layout, never drawn. It is the
|
|
8862
|
+
* secondary macro-layout: non-connected pairs get a weak spring (higher cosine ⇒
|
|
8863
|
+
* closer) so clusters arrange relative to each other; drawn `edges` stay the
|
|
8864
|
+
* primary tight structure. When omitted, edges alone drive the layout.
|
|
8863
8865
|
*/
|
|
8864
8866
|
similarity?: readonly GraphSimilarity[];
|
|
8865
8867
|
/** Canvas height */
|
|
@@ -8832,10 +8832,11 @@ interface GraphEdge {
|
|
|
8832
8832
|
color?: string;
|
|
8833
8833
|
}
|
|
8834
8834
|
/**
|
|
8835
|
-
* All-pairs similarity (cosine 0–1) used ONLY for layout
|
|
8836
|
-
*
|
|
8837
|
-
*
|
|
8838
|
-
*
|
|
8835
|
+
* All-pairs similarity (cosine 0–1) used ONLY for layout, never drawn — `edges`
|
|
8836
|
+
* remain the only rendered links. It is the SECONDARY macro-layout: pairs that are
|
|
8837
|
+
* NOT directly connected get a weak spring (higher cosine ⇒ closer) so clusters
|
|
8838
|
+
* arrange relative to each other, while drawn `edges` stay the primary tight
|
|
8839
|
+
* structure. When omitted, edges alone drive the layout.
|
|
8839
8840
|
*/
|
|
8840
8841
|
interface GraphSimilarity {
|
|
8841
8842
|
source: string;
|
|
@@ -8857,9 +8858,10 @@ interface GraphCanvasProps {
|
|
|
8857
8858
|
/** Graph edges (the only rendered links) */
|
|
8858
8859
|
edges?: readonly GraphEdge[];
|
|
8859
8860
|
/**
|
|
8860
|
-
* All-pairs similarity (cosine 0–1) used ONLY for layout
|
|
8861
|
-
*
|
|
8862
|
-
*
|
|
8861
|
+
* All-pairs similarity (cosine 0–1) used ONLY for layout, never drawn. It is the
|
|
8862
|
+
* secondary macro-layout: non-connected pairs get a weak spring (higher cosine ⇒
|
|
8863
|
+
* closer) so clusters arrange relative to each other; drawn `edges` stay the
|
|
8864
|
+
* primary tight structure. When omitted, edges alone drive the layout.
|
|
8863
8865
|
*/
|
|
8864
8866
|
similarity?: readonly GraphSimilarity[];
|
|
8865
8867
|
/** Canvas height */
|