@opentrace/components 0.1.1-rc.54 → 0.1.1-rc.66
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/opentrace-components.cjs +358 -249
- package/dist/opentrace-components.cjs.map +1 -1
- package/dist/opentrace-components.js +359 -250
- package/dist/opentrace-components.js.map +1 -1
- package/dist/src/GraphCanvas.d.ts +5 -0
- package/dist/src/GraphCanvas.d.ts.map +1 -1
- package/dist/src/colors/communityColors.d.ts.map +1 -1
- package/dist/src/config/graphLayout.d.ts +9 -9
- package/dist/src/config/graphLayout.d.ts.map +1 -1
- package/dist/src/graph/LayoutPipeline.d.ts +4 -6
- package/dist/src/graph/LayoutPipeline.d.ts.map +1 -1
- package/dist/src/graph/spacingWorker.d.ts +4 -0
- package/dist/src/graph/spacingWorker.d.ts.map +1 -1
- package/dist/src/graph/types.d.ts +2 -0
- package/dist/src/graph/types.d.ts.map +1 -1
- package/dist/src/graph/useGraphFilters.d.ts.map +1 -1
- package/dist/src/graph/useGraphInstance.d.ts.map +1 -1
- package/dist/src/graph/useGraphVisuals.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/sigma/useSelectionPulse.d.ts +3 -0
- package/dist/src/sigma/useSelectionPulse.d.ts.map +1 -0
- package/dist/{useHighlights-DbMfb0-p.js → useHighlights-CmOAWaLE.js} +60 -53
- package/dist/{useHighlights-DbMfb0-p.js.map → useHighlights-CmOAWaLE.js.map} +1 -1
- package/dist/{useHighlights-fRWg-A_c.cjs → useHighlights-zx7DM4V0.cjs} +60 -53
- package/dist/{useHighlights-fRWg-A_c.cjs.map → useHighlights-zx7DM4V0.cjs.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/dist/assets/spacingWorker-hXLGHyRg.js +0 -123
- package/dist/assets/spacingWorker-hXLGHyRg.js.map +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const t = require("react");
|
|
5
|
-
const useHighlights = require("./useHighlights-
|
|
5
|
+
const useHighlights = require("./useHighlights-zx7DM4V0.cjs");
|
|
6
6
|
const urlNormalize = require("./urlNormalize-DL0SAEQS.cjs");
|
|
7
7
|
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
8
8
|
function _toPrimitive$1(t2, r) {
|
|
@@ -5252,8 +5252,112 @@ createEdgeCurveProgram({
|
|
|
5252
5252
|
extremity: "both"
|
|
5253
5253
|
})
|
|
5254
5254
|
});
|
|
5255
|
-
const
|
|
5256
|
-
const
|
|
5255
|
+
const PING_DURATION = 400;
|
|
5256
|
+
const PING_MAX_SCALE = 2;
|
|
5257
|
+
const PING_ALPHA = 0.5;
|
|
5258
|
+
const HALO_SCALE = 1.05;
|
|
5259
|
+
const HALO_ALPHA = 0.35;
|
|
5260
|
+
const HALO_LINE_WIDTH = 5;
|
|
5261
|
+
function useSelectionPulse(sigma, selectedNodeId, enabled) {
|
|
5262
|
+
const startTimeRef = t.useRef(0);
|
|
5263
|
+
const pingRafRef = t.useRef(null);
|
|
5264
|
+
t.useEffect(() => {
|
|
5265
|
+
if (!sigma || !selectedNodeId || !enabled) {
|
|
5266
|
+
if (pingRafRef.current !== null) {
|
|
5267
|
+
cancelAnimationFrame(pingRafRef.current);
|
|
5268
|
+
pingRafRef.current = null;
|
|
5269
|
+
}
|
|
5270
|
+
return;
|
|
5271
|
+
}
|
|
5272
|
+
const graph = sigma.getGraph();
|
|
5273
|
+
if (!graph.hasNode(selectedNodeId)) return;
|
|
5274
|
+
startTimeRef.current = performance.now();
|
|
5275
|
+
function safeRefresh() {
|
|
5276
|
+
try {
|
|
5277
|
+
sigma?.refresh();
|
|
5278
|
+
} catch {
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
function pingLoop() {
|
|
5282
|
+
if (!sigma || !selectedNodeId) return;
|
|
5283
|
+
const elapsed = performance.now() - startTimeRef.current;
|
|
5284
|
+
if (elapsed < PING_DURATION) {
|
|
5285
|
+
safeRefresh();
|
|
5286
|
+
pingRafRef.current = requestAnimationFrame(pingLoop);
|
|
5287
|
+
} else {
|
|
5288
|
+
pingRafRef.current = null;
|
|
5289
|
+
safeRefresh();
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
pingRafRef.current = requestAnimationFrame(pingLoop);
|
|
5293
|
+
const handler = () => {
|
|
5294
|
+
if (!sigma || !selectedNodeId) return;
|
|
5295
|
+
const graph2 = sigma.getGraph();
|
|
5296
|
+
if (!graph2.hasNode(selectedNodeId)) return;
|
|
5297
|
+
const attrs = graph2.getNodeAttributes(selectedNodeId);
|
|
5298
|
+
const nodePosition = sigma.graphToViewport({
|
|
5299
|
+
x: attrs.x,
|
|
5300
|
+
y: attrs.y
|
|
5301
|
+
});
|
|
5302
|
+
const camera = sigma.getCamera();
|
|
5303
|
+
const baseSize = attrs.size ?? 5;
|
|
5304
|
+
const screenSize = baseSize / camera.ratio;
|
|
5305
|
+
const container = sigma.getContainer();
|
|
5306
|
+
const canvas = container.querySelector(
|
|
5307
|
+
".sigma-hovers"
|
|
5308
|
+
);
|
|
5309
|
+
if (!canvas) return;
|
|
5310
|
+
const ctx = canvas.getContext("2d");
|
|
5311
|
+
if (!ctx) return;
|
|
5312
|
+
const color = attrs.color ?? "#ffffff";
|
|
5313
|
+
const elapsed = performance.now() - startTimeRef.current;
|
|
5314
|
+
if (elapsed < PING_DURATION) {
|
|
5315
|
+
const t2 = elapsed / PING_DURATION;
|
|
5316
|
+
const scale2 = 1 + (PING_MAX_SCALE - 1) * t2;
|
|
5317
|
+
const alpha = PING_ALPHA * (1 - t2);
|
|
5318
|
+
ctx.save();
|
|
5319
|
+
ctx.globalAlpha = alpha;
|
|
5320
|
+
ctx.strokeStyle = color;
|
|
5321
|
+
ctx.lineWidth = 2;
|
|
5322
|
+
ctx.beginPath();
|
|
5323
|
+
ctx.arc(
|
|
5324
|
+
nodePosition.x,
|
|
5325
|
+
nodePosition.y,
|
|
5326
|
+
screenSize * scale2,
|
|
5327
|
+
0,
|
|
5328
|
+
Math.PI * 2
|
|
5329
|
+
);
|
|
5330
|
+
ctx.stroke();
|
|
5331
|
+
ctx.restore();
|
|
5332
|
+
}
|
|
5333
|
+
ctx.save();
|
|
5334
|
+
ctx.globalAlpha = HALO_ALPHA;
|
|
5335
|
+
ctx.strokeStyle = color;
|
|
5336
|
+
ctx.lineWidth = HALO_LINE_WIDTH;
|
|
5337
|
+
ctx.beginPath();
|
|
5338
|
+
ctx.arc(
|
|
5339
|
+
nodePosition.x,
|
|
5340
|
+
nodePosition.y,
|
|
5341
|
+
screenSize * HALO_SCALE,
|
|
5342
|
+
0,
|
|
5343
|
+
Math.PI * 2
|
|
5344
|
+
);
|
|
5345
|
+
ctx.stroke();
|
|
5346
|
+
ctx.restore();
|
|
5347
|
+
};
|
|
5348
|
+
sigma.on("afterRender", handler);
|
|
5349
|
+
safeRefresh();
|
|
5350
|
+
return () => {
|
|
5351
|
+
sigma.off("afterRender", handler);
|
|
5352
|
+
if (pingRafRef.current !== null) {
|
|
5353
|
+
cancelAnimationFrame(pingRafRef.current);
|
|
5354
|
+
pingRafRef.current = null;
|
|
5355
|
+
}
|
|
5356
|
+
};
|
|
5357
|
+
}, [sigma, selectedNodeId, enabled]);
|
|
5358
|
+
}
|
|
5359
|
+
const NODE_SIZE_MIN = 3;
|
|
5360
|
+
const NODE_SIZE_MAX = 12;
|
|
5257
5361
|
const NODE_SIZE_DEGREE_SCALE = 1;
|
|
5258
5362
|
const NODE_SIZE_MULTIPLIERS = {
|
|
5259
5363
|
Repository: 1,
|
|
@@ -5265,12 +5369,12 @@ const EDGE_SIZE_DEFAULT = 1;
|
|
|
5265
5369
|
const EDGE_SIZE_DEFAULT_LINE = 2;
|
|
5266
5370
|
const EDGE_SIZE_HIGHLIGHTED = 1.25;
|
|
5267
5371
|
const EDGE_SIZE_DIMMED = 0.5;
|
|
5268
|
-
const EDGE_OPACITY_DEFAULT = 0.
|
|
5372
|
+
const EDGE_OPACITY_DEFAULT = 0.78;
|
|
5269
5373
|
const EDGE_OPACITY_HIGHLIGHTED = 1;
|
|
5270
|
-
const EDGE_OPACITY_DIMMED = 0.
|
|
5271
|
-
const NODE_OPACITY_DIMMED = 0.
|
|
5374
|
+
const EDGE_OPACITY_DIMMED = 0.08;
|
|
5375
|
+
const NODE_OPACITY_DIMMED = 0.22;
|
|
5272
5376
|
const NODE_SIZE_DIMMED_SCALE = 0.35;
|
|
5273
|
-
const ZOOM_SIZE_EXPONENT = 0.
|
|
5377
|
+
const ZOOM_SIZE_EXPONENT = 0.7;
|
|
5274
5378
|
const FORCE_LINK_DISTANCE = 200;
|
|
5275
5379
|
const FORCE_CHARGE_STRENGTH = -200;
|
|
5276
5380
|
const FORCE_SIMULATION_TICKS = 80;
|
|
@@ -5278,15 +5382,15 @@ const FORCE_CLUSTER_STRENGTH = 0.3;
|
|
|
5278
5382
|
const FORCE_CLUSTER_TICKS = 40;
|
|
5279
5383
|
const FA2_ENABLED = true;
|
|
5280
5384
|
const FA2_GRAVITY = 0.1;
|
|
5281
|
-
const FA2_SCALING_RATIO =
|
|
5282
|
-
const FA2_SLOW_DOWN =
|
|
5385
|
+
const FA2_SCALING_RATIO = 120;
|
|
5386
|
+
const FA2_SLOW_DOWN = 0.5;
|
|
5283
5387
|
const FA2_BARNES_HUT_THRESHOLD = 300;
|
|
5284
5388
|
const FA2_BARNES_HUT_THETA = 0.5;
|
|
5285
5389
|
const FA2_STRONG_GRAVITY = false;
|
|
5286
5390
|
const FA2_LIN_LOG_MODE = true;
|
|
5287
5391
|
const FA2_OUTBOUND_ATTRACTION = true;
|
|
5288
5392
|
const FA2_ADJUST_SIZES = true;
|
|
5289
|
-
const FA2_DURATION =
|
|
5393
|
+
const FA2_DURATION = 2e4;
|
|
5290
5394
|
const NOVERLAP_MAX_ITERATIONS = 50;
|
|
5291
5395
|
const NOVERLAP_RATIO = 1.5;
|
|
5292
5396
|
const NOVERLAP_MARGIN = 25;
|
|
@@ -5351,6 +5455,145 @@ function endpointId(endpoint) {
|
|
|
5351
5455
|
return endpoint.id;
|
|
5352
5456
|
return String(endpoint);
|
|
5353
5457
|
}
|
|
5458
|
+
function applySpacing(pos, assignments, radiusScale, gap, maxIterations, pushFactor) {
|
|
5459
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5460
|
+
for (const [id] of pos) {
|
|
5461
|
+
const cid = assignments[id];
|
|
5462
|
+
if (cid === void 0) continue;
|
|
5463
|
+
let list = groups.get(cid);
|
|
5464
|
+
if (!list) {
|
|
5465
|
+
list = [];
|
|
5466
|
+
groups.set(cid, list);
|
|
5467
|
+
}
|
|
5468
|
+
list.push(id);
|
|
5469
|
+
}
|
|
5470
|
+
if (groups.size < 2) return;
|
|
5471
|
+
const comms = [];
|
|
5472
|
+
for (const [, ids] of groups) {
|
|
5473
|
+
let cx = 0, cy = 0;
|
|
5474
|
+
for (const id of ids) {
|
|
5475
|
+
const p = pos.get(id);
|
|
5476
|
+
cx += p.x;
|
|
5477
|
+
cy += p.y;
|
|
5478
|
+
}
|
|
5479
|
+
cx /= ids.length;
|
|
5480
|
+
cy /= ids.length;
|
|
5481
|
+
comms.push({
|
|
5482
|
+
nodeIds: ids,
|
|
5483
|
+
cx,
|
|
5484
|
+
cy,
|
|
5485
|
+
radius: Math.sqrt(ids.length) * radiusScale
|
|
5486
|
+
});
|
|
5487
|
+
}
|
|
5488
|
+
for (let iter = 0; iter < maxIterations; iter++) {
|
|
5489
|
+
const pushX = new Float64Array(comms.length);
|
|
5490
|
+
const pushY = new Float64Array(comms.length);
|
|
5491
|
+
let maxOverlap = 0;
|
|
5492
|
+
for (let i = 0; i < comms.length; i++) {
|
|
5493
|
+
for (let j2 = i + 1; j2 < comms.length; j2++) {
|
|
5494
|
+
const a = comms[i];
|
|
5495
|
+
const b = comms[j2];
|
|
5496
|
+
const dx = b.cx - a.cx;
|
|
5497
|
+
const dy = b.cy - a.cy;
|
|
5498
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
5499
|
+
const minDist = a.radius + b.radius + gap;
|
|
5500
|
+
if (dist < minDist) {
|
|
5501
|
+
const overlap = (minDist - dist) / minDist;
|
|
5502
|
+
if (overlap > maxOverlap) maxOverlap = overlap;
|
|
5503
|
+
const push = (minDist - dist) * pushFactor;
|
|
5504
|
+
if (dist > 1e-3) {
|
|
5505
|
+
const nx = dx / dist;
|
|
5506
|
+
const ny = dy / dist;
|
|
5507
|
+
const totalSize = a.nodeIds.length + b.nodeIds.length;
|
|
5508
|
+
const aRatio = b.nodeIds.length / totalSize;
|
|
5509
|
+
const bRatio = a.nodeIds.length / totalSize;
|
|
5510
|
+
pushX[i] -= nx * push * aRatio;
|
|
5511
|
+
pushY[i] -= ny * push * aRatio;
|
|
5512
|
+
pushX[j2] += nx * push * bRatio;
|
|
5513
|
+
pushY[j2] += ny * push * bRatio;
|
|
5514
|
+
} else {
|
|
5515
|
+
const angle = Math.random() * Math.PI * 2;
|
|
5516
|
+
pushX[i] -= Math.cos(angle) * minDist * 0.5;
|
|
5517
|
+
pushY[i] -= Math.sin(angle) * minDist * 0.5;
|
|
5518
|
+
pushX[j2] += Math.cos(angle) * minDist * 0.5;
|
|
5519
|
+
pushY[j2] += Math.sin(angle) * minDist * 0.5;
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
if (maxOverlap <= 0.05) break;
|
|
5525
|
+
for (let i = 0; i < comms.length; i++) {
|
|
5526
|
+
const ox = pushX[i];
|
|
5527
|
+
const oy = pushY[i];
|
|
5528
|
+
if (Math.abs(ox) < 0.01 && Math.abs(oy) < 0.01) continue;
|
|
5529
|
+
comms[i].cx += ox;
|
|
5530
|
+
comms[i].cy += oy;
|
|
5531
|
+
for (const id of comms[i].nodeIds) {
|
|
5532
|
+
const p = pos.get(id);
|
|
5533
|
+
p.x += ox;
|
|
5534
|
+
p.y += oy;
|
|
5535
|
+
}
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
function applyNoverlap(pos, sizes, assignments, margin, iterations) {
|
|
5540
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5541
|
+
for (const [id] of pos) {
|
|
5542
|
+
const cid = assignments[id];
|
|
5543
|
+
if (cid === void 0) continue;
|
|
5544
|
+
let list = groups.get(cid);
|
|
5545
|
+
if (!list) {
|
|
5546
|
+
list = [];
|
|
5547
|
+
groups.set(cid, list);
|
|
5548
|
+
}
|
|
5549
|
+
list.push(id);
|
|
5550
|
+
}
|
|
5551
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
5552
|
+
for (const [, p] of pos) {
|
|
5553
|
+
if (p.x < minX) minX = p.x;
|
|
5554
|
+
if (p.x > maxX) maxX = p.x;
|
|
5555
|
+
if (p.y < minY) minY = p.y;
|
|
5556
|
+
if (p.y > maxY) maxY = p.y;
|
|
5557
|
+
}
|
|
5558
|
+
const scale2 = Math.max(maxX - minX, maxY - minY, 1) / 4e3;
|
|
5559
|
+
const scaledMargin = margin * scale2;
|
|
5560
|
+
const MAX_INLINE = 500;
|
|
5561
|
+
for (const [, ids] of groups) {
|
|
5562
|
+
if (ids.length < 3 || ids.length > MAX_INLINE) continue;
|
|
5563
|
+
const nodes = ids.map((id) => ({
|
|
5564
|
+
id,
|
|
5565
|
+
x: pos.get(id).x,
|
|
5566
|
+
y: pos.get(id).y,
|
|
5567
|
+
size: (sizes.get(id) ?? 3) * scale2
|
|
5568
|
+
}));
|
|
5569
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
5570
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
5571
|
+
const a = nodes[i];
|
|
5572
|
+
for (let j2 = i + 1; j2 < nodes.length; j2++) {
|
|
5573
|
+
const b = nodes[j2];
|
|
5574
|
+
const dx = b.x - a.x;
|
|
5575
|
+
const dy = b.y - a.y;
|
|
5576
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
5577
|
+
const minDist = a.size + b.size + scaledMargin;
|
|
5578
|
+
if (dist < minDist && dist > 1e-3) {
|
|
5579
|
+
const push = (minDist - dist) * 0.5;
|
|
5580
|
+
const nx = dx / dist;
|
|
5581
|
+
const ny = dy / dist;
|
|
5582
|
+
a.x -= nx * push;
|
|
5583
|
+
a.y -= ny * push;
|
|
5584
|
+
b.x += nx * push;
|
|
5585
|
+
b.y += ny * push;
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
}
|
|
5590
|
+
for (const n2 of nodes) {
|
|
5591
|
+
const p = pos.get(n2.id);
|
|
5592
|
+
p.x = n2.x;
|
|
5593
|
+
p.y = n2.y;
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5354
5597
|
function useGraphInstance({
|
|
5355
5598
|
allNodes,
|
|
5356
5599
|
allLinks,
|
|
@@ -5362,9 +5605,10 @@ function useGraphInstance({
|
|
|
5362
5605
|
const unmountedRef = t.useRef(false);
|
|
5363
5606
|
const requestIdRef = t.useRef(0);
|
|
5364
5607
|
const [layoutReady, setLayoutReady] = t.useState(false);
|
|
5608
|
+
const flatMode = layoutConfig.flatMode ?? false;
|
|
5365
5609
|
const structuralTypes = t.useMemo(
|
|
5366
|
-
() => new Set(layoutConfig.structuralTypes),
|
|
5367
|
-
[layoutConfig.structuralTypes]
|
|
5610
|
+
() => flatMode ? /* @__PURE__ */ new Set() : new Set(layoutConfig.structuralTypes),
|
|
5611
|
+
[layoutConfig.structuralTypes, flatMode]
|
|
5368
5612
|
);
|
|
5369
5613
|
t.useEffect(() => {
|
|
5370
5614
|
graph.clear();
|
|
@@ -5427,6 +5671,48 @@ function useGraphInstance({
|
|
|
5427
5671
|
}
|
|
5428
5672
|
});
|
|
5429
5673
|
}
|
|
5674
|
+
const { assignments: communityAssignments } = communityData;
|
|
5675
|
+
if (communityAssignments && !flatMode) {
|
|
5676
|
+
const communityGroups = /* @__PURE__ */ new Map();
|
|
5677
|
+
for (const node of allNodes) {
|
|
5678
|
+
const cid = communityAssignments[node.id];
|
|
5679
|
+
if (cid === void 0) continue;
|
|
5680
|
+
let list = communityGroups.get(cid);
|
|
5681
|
+
if (!list) {
|
|
5682
|
+
list = [];
|
|
5683
|
+
communityGroups.set(cid, list);
|
|
5684
|
+
}
|
|
5685
|
+
list.push(node.id);
|
|
5686
|
+
}
|
|
5687
|
+
let vcIdx = 0;
|
|
5688
|
+
for (const [, members] of communityGroups) {
|
|
5689
|
+
if (members.length < 2) continue;
|
|
5690
|
+
const baseTies = members.length >= 10 ? 3 : 2;
|
|
5691
|
+
for (const nodeId of members) {
|
|
5692
|
+
const count = Math.min(baseTies, members.length - 1);
|
|
5693
|
+
for (let c2 = 0; c2 < count; c2++) {
|
|
5694
|
+
const targetIdx = (members.indexOf(nodeId) + c2 + 1) % members.length;
|
|
5695
|
+
const targetId = members[targetIdx];
|
|
5696
|
+
if (targetId === nodeId) continue;
|
|
5697
|
+
const vcKey = `_vc_${vcIdx++}`;
|
|
5698
|
+
if (seenEdges.has(`${nodeId}-_COMMUNITY_-${targetId}`)) continue;
|
|
5699
|
+
seenEdges.add(`${nodeId}-_COMMUNITY_-${targetId}`);
|
|
5700
|
+
serializedEdges.push({
|
|
5701
|
+
key: vcKey,
|
|
5702
|
+
source: nodeId,
|
|
5703
|
+
target: targetId,
|
|
5704
|
+
attributes: {
|
|
5705
|
+
label: "_COMMUNITY_",
|
|
5706
|
+
color: "transparent",
|
|
5707
|
+
size: 0,
|
|
5708
|
+
hidden: true,
|
|
5709
|
+
_virtual: true
|
|
5710
|
+
}
|
|
5711
|
+
});
|
|
5712
|
+
}
|
|
5713
|
+
}
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5430
5716
|
graph.import({
|
|
5431
5717
|
nodes: serializedNodes,
|
|
5432
5718
|
edges: serializedEdges
|
|
@@ -5434,7 +5720,7 @@ function useGraphInstance({
|
|
|
5434
5720
|
const nodeIds = allNodes.map((n2) => n2.id);
|
|
5435
5721
|
const simLinks = [];
|
|
5436
5722
|
for (const link of allLinks) {
|
|
5437
|
-
if (link.label !== layoutConfig.layoutEdgeType) continue;
|
|
5723
|
+
if (!flatMode && link.label !== layoutConfig.layoutEdgeType) continue;
|
|
5438
5724
|
const source = endpointId(link.source);
|
|
5439
5725
|
const target = endpointId(link.target);
|
|
5440
5726
|
if (nodeIdSet.has(source) && nodeIdSet.has(target)) {
|
|
@@ -5474,6 +5760,15 @@ function useGraphInstance({
|
|
|
5474
5760
|
console.timeEnd("[graph] d3-force worker layout");
|
|
5475
5761
|
console.log(`[graph] layout computed for ${pos.size} nodes`);
|
|
5476
5762
|
}
|
|
5763
|
+
const { assignments: assignments2 } = communityData;
|
|
5764
|
+
if (!flatMode && assignments2 && Object.keys(assignments2).length > 0) {
|
|
5765
|
+
applySpacing(pos, assignments2, 40, 100, 50, 0.5);
|
|
5766
|
+
const sizeMap = /* @__PURE__ */ new Map();
|
|
5767
|
+
for (const sn of serializedNodes) {
|
|
5768
|
+
sizeMap.set(sn.key, sn.attributes.size);
|
|
5769
|
+
}
|
|
5770
|
+
applyNoverlap(pos, sizeMap, assignments2, layoutConfig.noverlapMargin, layoutConfig.noverlapCommunityIterations ?? 20);
|
|
5771
|
+
}
|
|
5477
5772
|
graph.updateEachNodeAttributes((_id, attrs) => {
|
|
5478
5773
|
const p = pos.get(_id);
|
|
5479
5774
|
if (p) {
|
|
@@ -5563,6 +5858,10 @@ function useGraphVisuals(graph, layoutReady, visualState, layoutConfig, _degreeM
|
|
|
5563
5858
|
const defaultEdgeSize = isLargeGraph ? EDGE_SIZE_DEFAULT_LINE : EDGE_SIZE_DEFAULT;
|
|
5564
5859
|
graph.updateEachEdgeAttributes(
|
|
5565
5860
|
(_id, attrs, source, target) => {
|
|
5861
|
+
if (attrs._virtual) {
|
|
5862
|
+
attrs.hidden = true;
|
|
5863
|
+
return attrs;
|
|
5864
|
+
}
|
|
5566
5865
|
const linkKey = `${source}-${target}`;
|
|
5567
5866
|
const isHighlighted = highlightLinks.has(linkKey);
|
|
5568
5867
|
const baseColor = getLinkColor(attrs.label);
|
|
@@ -6853,13 +7152,10 @@ function LayoutPipeline({
|
|
|
6853
7152
|
layoutReady,
|
|
6854
7153
|
layoutConfig,
|
|
6855
7154
|
optimizeTick,
|
|
6856
|
-
communityAssignments,
|
|
6857
7155
|
onOptimizeStatus
|
|
6858
7156
|
}) {
|
|
6859
7157
|
const sigma = v();
|
|
6860
7158
|
const timerRef = t.useRef(null);
|
|
6861
|
-
const spacingWorkerRef = t.useRef(null);
|
|
6862
|
-
const perCommunityNoverlapCancel = t.useRef(null);
|
|
6863
7159
|
const { start, stop } = n({
|
|
6864
7160
|
settings: {
|
|
6865
7161
|
gravity: layoutConfig.fa2Gravity,
|
|
@@ -6878,245 +7174,24 @@ function LayoutPipeline({
|
|
|
6878
7174
|
clearTimeout(timerRef.current);
|
|
6879
7175
|
timerRef.current = null;
|
|
6880
7176
|
}
|
|
6881
|
-
if (spacingWorkerRef.current) {
|
|
6882
|
-
spacingWorkerRef.current.terminate();
|
|
6883
|
-
spacingWorkerRef.current = null;
|
|
6884
|
-
}
|
|
6885
|
-
perCommunityNoverlapCancel.current?.();
|
|
6886
|
-
perCommunityNoverlapCancel.current = null;
|
|
6887
7177
|
stop();
|
|
6888
7178
|
}
|
|
6889
|
-
function runSpacing(onDone) {
|
|
6890
|
-
const graph = sigma.getGraph();
|
|
6891
|
-
if (graph.order === 0 || !communityAssignments) {
|
|
6892
|
-
onDone();
|
|
6893
|
-
return;
|
|
6894
|
-
}
|
|
6895
|
-
onOptimizeStatus?.({ phase: "spacing" });
|
|
6896
|
-
const nodes = [];
|
|
6897
|
-
graph.forEachNode((id, attrs) => {
|
|
6898
|
-
const cid = communityAssignments[id];
|
|
6899
|
-
if (cid === void 0) return;
|
|
6900
|
-
nodes.push({
|
|
6901
|
-
id,
|
|
6902
|
-
x: attrs.x,
|
|
6903
|
-
y: attrs.y,
|
|
6904
|
-
communityId: cid
|
|
6905
|
-
});
|
|
6906
|
-
});
|
|
6907
|
-
const worker2 = new Worker(new URL(
|
|
6908
|
-
/* @vite-ignore */
|
|
6909
|
-
"/assets/spacingWorker-hXLGHyRg.js",
|
|
6910
|
-
typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("opentrace-components.cjs", document.baseURI).href
|
|
6911
|
-
), {
|
|
6912
|
-
type: "module"
|
|
6913
|
-
});
|
|
6914
|
-
spacingWorkerRef.current = worker2;
|
|
6915
|
-
worker2.onmessage = (e2) => {
|
|
6916
|
-
const msg = e2.data;
|
|
6917
|
-
if (msg.type === "progress") {
|
|
6918
|
-
if (msg.updates.length > 0) {
|
|
6919
|
-
const posMap = /* @__PURE__ */ new Map();
|
|
6920
|
-
for (const u of msg.updates) posMap.set(u.id, { x: u.x, y: u.y });
|
|
6921
|
-
graph.updateEachNodeAttributes((id, attrs) => {
|
|
6922
|
-
const pos = posMap.get(id);
|
|
6923
|
-
if (pos) {
|
|
6924
|
-
attrs.x = pos.x;
|
|
6925
|
-
attrs.y = pos.y;
|
|
6926
|
-
}
|
|
6927
|
-
return attrs;
|
|
6928
|
-
});
|
|
6929
|
-
}
|
|
6930
|
-
onOptimizeStatus?.({
|
|
6931
|
-
phase: "spacing",
|
|
6932
|
-
iteration: msg.iteration,
|
|
6933
|
-
cleanRatio: 1 - msg.maxOverlap
|
|
6934
|
-
});
|
|
6935
|
-
if (process.env.NODE_ENV === "development") {
|
|
6936
|
-
console.log(
|
|
6937
|
-
`%c[spacing]%c iter ${msg.iteration}: overlap ${(msg.maxOverlap * 100).toFixed(0)}%, ${msg.updates.length} nodes moved`,
|
|
6938
|
-
"color: #fbbf24; font-weight: bold",
|
|
6939
|
-
"color: inherit"
|
|
6940
|
-
);
|
|
6941
|
-
}
|
|
6942
|
-
} else if (msg.type === "done") {
|
|
6943
|
-
if (process.env.NODE_ENV === "development") {
|
|
6944
|
-
console.log(
|
|
6945
|
-
`%c[spacing]%c done: ${msg.iterations} iters, ${(msg.maxOverlap * 100).toFixed(0)}% max overlap in ${msg.totalMs.toFixed(0)}ms`,
|
|
6946
|
-
"color: #fbbf24; font-weight: bold",
|
|
6947
|
-
"color: inherit"
|
|
6948
|
-
);
|
|
6949
|
-
}
|
|
6950
|
-
worker2.terminate();
|
|
6951
|
-
spacingWorkerRef.current = null;
|
|
6952
|
-
onDone();
|
|
6953
|
-
}
|
|
6954
|
-
};
|
|
6955
|
-
worker2.onerror = () => {
|
|
6956
|
-
worker2.terminate();
|
|
6957
|
-
spacingWorkerRef.current = null;
|
|
6958
|
-
onDone();
|
|
6959
|
-
};
|
|
6960
|
-
worker2.postMessage({
|
|
6961
|
-
nodes,
|
|
6962
|
-
radiusScale: 40,
|
|
6963
|
-
gap: 100,
|
|
6964
|
-
maxIterations: 50,
|
|
6965
|
-
overlapThreshold: 0.05
|
|
6966
|
-
});
|
|
6967
|
-
}
|
|
6968
|
-
function getGraphScaleFactor() {
|
|
6969
|
-
const graph = sigma.getGraph();
|
|
6970
|
-
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
6971
|
-
graph.forEachNode((_, attrs) => {
|
|
6972
|
-
const x = attrs.x;
|
|
6973
|
-
const y = attrs.y;
|
|
6974
|
-
if (x < minX) minX = x;
|
|
6975
|
-
if (x > maxX) maxX = x;
|
|
6976
|
-
if (y < minY) minY = y;
|
|
6977
|
-
if (y > maxY) maxY = y;
|
|
6978
|
-
});
|
|
6979
|
-
return Math.max(maxX - minX, maxY - minY, 1) / 4e3;
|
|
6980
|
-
}
|
|
6981
|
-
function runPerCommunityNoverlap(onDone) {
|
|
6982
|
-
const graph = sigma.getGraph();
|
|
6983
|
-
if (graph.order === 0 || !communityAssignments) {
|
|
6984
|
-
onDone();
|
|
6985
|
-
return;
|
|
6986
|
-
}
|
|
6987
|
-
const scale2 = getGraphScaleFactor();
|
|
6988
|
-
const groups = /* @__PURE__ */ new Map();
|
|
6989
|
-
graph.forEachNode((id) => {
|
|
6990
|
-
const cid = communityAssignments[id];
|
|
6991
|
-
if (cid === void 0) return;
|
|
6992
|
-
let list = groups.get(cid);
|
|
6993
|
-
if (!list) {
|
|
6994
|
-
list = [];
|
|
6995
|
-
groups.set(cid, list);
|
|
6996
|
-
}
|
|
6997
|
-
list.push(id);
|
|
6998
|
-
});
|
|
6999
|
-
const sorted = [...groups.entries()].sort(
|
|
7000
|
-
(a, b) => b[1].length - a[1].length
|
|
7001
|
-
);
|
|
7002
|
-
const MAX_INLINE = 500;
|
|
7003
|
-
let idx = 0;
|
|
7004
|
-
let totalMoved = 0;
|
|
7005
|
-
let cancelled = false;
|
|
7006
|
-
let pendingCallbackId = null;
|
|
7007
|
-
perCommunityNoverlapCancel.current = () => {
|
|
7008
|
-
cancelled = true;
|
|
7009
|
-
if (pendingCallbackId !== null) {
|
|
7010
|
-
if (typeof cancelIdleCallback === "function") {
|
|
7011
|
-
cancelIdleCallback(pendingCallbackId);
|
|
7012
|
-
} else {
|
|
7013
|
-
clearTimeout(pendingCallbackId);
|
|
7014
|
-
}
|
|
7015
|
-
pendingCallbackId = null;
|
|
7016
|
-
}
|
|
7017
|
-
};
|
|
7018
|
-
function processNext() {
|
|
7019
|
-
if (cancelled || idx >= sorted.length) {
|
|
7020
|
-
if (process.env.NODE_ENV === "development") {
|
|
7021
|
-
console.log(
|
|
7022
|
-
`%c[noverlap]%c per-community done: ${sorted.length} communities, ${totalMoved} nodes moved${cancelled ? " (cancelled)" : ""}`,
|
|
7023
|
-
"color: #4ade80; font-weight: bold",
|
|
7024
|
-
"color: inherit"
|
|
7025
|
-
);
|
|
7026
|
-
}
|
|
7027
|
-
perCommunityNoverlapCancel.current = null;
|
|
7028
|
-
if (!cancelled) onDone();
|
|
7029
|
-
return;
|
|
7030
|
-
}
|
|
7031
|
-
const [, nodeIds] = sorted[idx++];
|
|
7032
|
-
if (nodeIds.length < 3 || nodeIds.length > MAX_INLINE) {
|
|
7033
|
-
scheduleNext();
|
|
7034
|
-
return;
|
|
7035
|
-
}
|
|
7036
|
-
const subGraph = /* @__PURE__ */ new Map();
|
|
7037
|
-
for (const nid of nodeIds) {
|
|
7038
|
-
const attrs = graph.getNodeAttributes(nid);
|
|
7039
|
-
subGraph.set(nid, {
|
|
7040
|
-
x: attrs.x,
|
|
7041
|
-
y: attrs.y,
|
|
7042
|
-
size: (attrs.size ?? 3) * scale2
|
|
7043
|
-
});
|
|
7044
|
-
}
|
|
7045
|
-
const margin = layoutConfig.noverlapMargin * scale2;
|
|
7046
|
-
const iters = layoutConfig.noverlapCommunityIterations ?? 20;
|
|
7047
|
-
const nodeArr = [...subGraph.entries()];
|
|
7048
|
-
for (let iter = 0; iter < iters; iter++) {
|
|
7049
|
-
for (let i = 0; i < nodeArr.length; i++) {
|
|
7050
|
-
const [, a] = nodeArr[i];
|
|
7051
|
-
for (let j2 = i + 1; j2 < nodeArr.length; j2++) {
|
|
7052
|
-
const [, b] = nodeArr[j2];
|
|
7053
|
-
const dx = b.x - a.x;
|
|
7054
|
-
const dy = b.y - a.y;
|
|
7055
|
-
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
7056
|
-
const minDist = a.size + b.size + margin;
|
|
7057
|
-
if (dist < minDist && dist > 1e-3) {
|
|
7058
|
-
const push = (minDist - dist) * 0.5;
|
|
7059
|
-
const nx = dx / dist;
|
|
7060
|
-
const ny = dy / dist;
|
|
7061
|
-
a.x -= nx * push;
|
|
7062
|
-
a.y -= ny * push;
|
|
7063
|
-
b.x += nx * push;
|
|
7064
|
-
b.y += ny * push;
|
|
7065
|
-
}
|
|
7066
|
-
}
|
|
7067
|
-
}
|
|
7068
|
-
}
|
|
7069
|
-
let moved = 0;
|
|
7070
|
-
for (const [nid, pos] of subGraph) {
|
|
7071
|
-
const attrs = graph.getNodeAttributes(nid);
|
|
7072
|
-
if (Math.abs(pos.x - attrs.x) > 0.1 || Math.abs(pos.y - attrs.y) > 0.1) {
|
|
7073
|
-
graph.mergeNodeAttributes(nid, { x: pos.x, y: pos.y });
|
|
7074
|
-
moved++;
|
|
7075
|
-
}
|
|
7076
|
-
}
|
|
7077
|
-
totalMoved += moved;
|
|
7078
|
-
scheduleNext();
|
|
7079
|
-
}
|
|
7080
|
-
function scheduleNext() {
|
|
7081
|
-
if (typeof requestIdleCallback === "function") {
|
|
7082
|
-
pendingCallbackId = requestIdleCallback(processNext, { timeout: 50 });
|
|
7083
|
-
} else {
|
|
7084
|
-
pendingCallbackId = setTimeout(processNext, 0);
|
|
7085
|
-
}
|
|
7086
|
-
}
|
|
7087
|
-
processNext();
|
|
7088
|
-
}
|
|
7089
7179
|
t.useEffect(() => {
|
|
7090
7180
|
if (!layoutReady) return;
|
|
7091
7181
|
cleanup();
|
|
7092
7182
|
const sigmaInstance = sigma;
|
|
7093
7183
|
const graph = sigma.getGraph();
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
onDone();
|
|
7106
|
-
}
|
|
7107
|
-
};
|
|
7108
|
-
runFA2(layoutConfig.fa2Duration, () => {
|
|
7109
|
-
onOptimizeStatus?.({ phase: "noverlap" });
|
|
7110
|
-
runPerCommunityNoverlap(() => {
|
|
7111
|
-
runSpacing(() => {
|
|
7112
|
-
runFA2(Math.min(layoutConfig.fa2Duration, 1500), () => {
|
|
7113
|
-
zoomToFit(sigmaInstance, 600);
|
|
7114
|
-
onOptimizeStatus?.(null);
|
|
7115
|
-
});
|
|
7116
|
-
});
|
|
7117
|
-
});
|
|
7118
|
-
});
|
|
7119
|
-
});
|
|
7184
|
+
zoomToFit(sigmaInstance, 0);
|
|
7185
|
+
if (layoutConfig.fa2Enabled && graph.order > 0) {
|
|
7186
|
+
onOptimizeStatus?.({ phase: "fa2" });
|
|
7187
|
+
start();
|
|
7188
|
+
timerRef.current = setTimeout(() => {
|
|
7189
|
+
stop();
|
|
7190
|
+
onOptimizeStatus?.(null);
|
|
7191
|
+
}, layoutConfig.fa2Duration);
|
|
7192
|
+
} else {
|
|
7193
|
+
onOptimizeStatus?.(null);
|
|
7194
|
+
}
|
|
7120
7195
|
return cleanup;
|
|
7121
7196
|
}, [layoutReady, optimizeTick, layoutConfig, start, stop, sigma]);
|
|
7122
7197
|
return null;
|
|
@@ -7316,10 +7391,25 @@ function GraphEventHandler({
|
|
|
7316
7391
|
}, [sigma, onNodeClick, onEdgeClick, onStageClick]);
|
|
7317
7392
|
return null;
|
|
7318
7393
|
}
|
|
7394
|
+
function AnimationEffects({
|
|
7395
|
+
selectedNodeId,
|
|
7396
|
+
animationSettings
|
|
7397
|
+
}) {
|
|
7398
|
+
const sigma = v();
|
|
7399
|
+
useSelectionPulse(
|
|
7400
|
+
sigma,
|
|
7401
|
+
selectedNodeId,
|
|
7402
|
+
animationSettings.selectionPulse
|
|
7403
|
+
);
|
|
7404
|
+
return null;
|
|
7405
|
+
}
|
|
7319
7406
|
const defaultGetSubType = () => null;
|
|
7320
7407
|
const EMPTY_STRING_SET = /* @__PURE__ */ new Set();
|
|
7321
7408
|
const EMPTY_NUMBER_SET = /* @__PURE__ */ new Set();
|
|
7322
7409
|
const EMPTY_SUB_TYPES = /* @__PURE__ */ new Map();
|
|
7410
|
+
const DEFAULT_ANIMATION = {
|
|
7411
|
+
selectionPulse: true
|
|
7412
|
+
};
|
|
7323
7413
|
const GraphCanvas = t.memo(
|
|
7324
7414
|
t.forwardRef(
|
|
7325
7415
|
function GraphCanvas2(props, ref) {
|
|
@@ -7344,6 +7434,7 @@ const GraphCanvas = t.memo(
|
|
|
7344
7434
|
availableSubTypes = EMPTY_SUB_TYPES,
|
|
7345
7435
|
zIndex: zIndexEnabled = false,
|
|
7346
7436
|
communityData: communityDataProp,
|
|
7437
|
+
animationSettings = DEFAULT_ANIMATION,
|
|
7347
7438
|
onNodeClick,
|
|
7348
7439
|
onEdgeClick,
|
|
7349
7440
|
onStageClick,
|
|
@@ -7474,9 +7565,21 @@ const GraphCanvas = t.memo(
|
|
|
7474
7565
|
}),
|
|
7475
7566
|
[isLargeGraph, zIndexEnabled]
|
|
7476
7567
|
);
|
|
7568
|
+
const edgeReducer = t.useCallback(
|
|
7569
|
+
(_edge, data) => {
|
|
7570
|
+
if (!sigmaRef.current) return data;
|
|
7571
|
+
const ratio = sigmaRef.current.getCamera().ratio;
|
|
7572
|
+
return { ...data, size: (data.size || 1) * ratio };
|
|
7573
|
+
},
|
|
7574
|
+
[]
|
|
7575
|
+
);
|
|
7477
7576
|
const handleSigmaReady = t.useCallback(
|
|
7478
7577
|
(sigma) => {
|
|
7479
7578
|
sigmaRef.current = sigma;
|
|
7579
|
+
sigma.setSetting(
|
|
7580
|
+
"edgeReducer",
|
|
7581
|
+
edgeReducer
|
|
7582
|
+
);
|
|
7480
7583
|
},
|
|
7481
7584
|
[]
|
|
7482
7585
|
);
|
|
@@ -7620,10 +7723,16 @@ const GraphCanvas = t.memo(
|
|
|
7620
7723
|
layoutReady,
|
|
7621
7724
|
layoutConfig,
|
|
7622
7725
|
optimizeTick,
|
|
7623
|
-
communityAssignments: communityData.assignments,
|
|
7624
7726
|
onOptimizeStatus
|
|
7625
7727
|
}
|
|
7626
7728
|
),
|
|
7729
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7730
|
+
AnimationEffects,
|
|
7731
|
+
{
|
|
7732
|
+
selectedNodeId: selectedNodeId ?? null,
|
|
7733
|
+
animationSettings
|
|
7734
|
+
}
|
|
7735
|
+
),
|
|
7627
7736
|
/* @__PURE__ */ jsxRuntime.jsx(SigmaRefCapture, { onReady: handleSigmaReady })
|
|
7628
7737
|
]
|
|
7629
7738
|
}
|