@opentrace/components 0.1.1-rc.62 → 0.1.1-rc.77
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 +184 -56
- package/dist/opentrace-components.cjs.map +1 -1
- package/dist/opentrace-components.js +184 -56
- package/dist/opentrace-components.js.map +1 -1
- package/dist/src/GraphCanvas.d.ts.map +1 -1
- package/dist/src/graph/drawNodeHover.d.ts +9 -3
- package/dist/src/graph/drawNodeHover.d.ts.map +1 -1
- package/dist/src/graph/drawNodeLabel.d.ts +23 -0
- package/dist/src/graph/drawNodeLabel.d.ts.map +1 -0
- package/dist/src/graph/types.d.ts +2 -0
- package/dist/src/graph/types.d.ts.map +1 -1
- package/dist/src/graph/useGraphInstance.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5605,9 +5605,10 @@ function useGraphInstance({
|
|
|
5605
5605
|
const unmountedRef = t.useRef(false);
|
|
5606
5606
|
const requestIdRef = t.useRef(0);
|
|
5607
5607
|
const [layoutReady, setLayoutReady] = t.useState(false);
|
|
5608
|
+
const flatMode = layoutConfig.flatMode ?? false;
|
|
5608
5609
|
const structuralTypes = t.useMemo(
|
|
5609
|
-
() => new Set(layoutConfig.structuralTypes),
|
|
5610
|
-
[layoutConfig.structuralTypes]
|
|
5610
|
+
() => flatMode ? /* @__PURE__ */ new Set() : new Set(layoutConfig.structuralTypes),
|
|
5611
|
+
[layoutConfig.structuralTypes, flatMode]
|
|
5611
5612
|
);
|
|
5612
5613
|
t.useEffect(() => {
|
|
5613
5614
|
graph.clear();
|
|
@@ -5671,7 +5672,7 @@ function useGraphInstance({
|
|
|
5671
5672
|
});
|
|
5672
5673
|
}
|
|
5673
5674
|
const { assignments: communityAssignments } = communityData;
|
|
5674
|
-
if (communityAssignments) {
|
|
5675
|
+
if (communityAssignments && !flatMode) {
|
|
5675
5676
|
const communityGroups = /* @__PURE__ */ new Map();
|
|
5676
5677
|
for (const node of allNodes) {
|
|
5677
5678
|
const cid = communityAssignments[node.id];
|
|
@@ -5719,7 +5720,7 @@ function useGraphInstance({
|
|
|
5719
5720
|
const nodeIds = allNodes.map((n2) => n2.id);
|
|
5720
5721
|
const simLinks = [];
|
|
5721
5722
|
for (const link of allLinks) {
|
|
5722
|
-
if (link.label !== layoutConfig.layoutEdgeType) continue;
|
|
5723
|
+
if (!flatMode && link.label !== layoutConfig.layoutEdgeType) continue;
|
|
5723
5724
|
const source = endpointId(link.source);
|
|
5724
5725
|
const target = endpointId(link.target);
|
|
5725
5726
|
if (nodeIdSet.has(source) && nodeIdSet.has(target)) {
|
|
@@ -5760,7 +5761,7 @@ function useGraphInstance({
|
|
|
5760
5761
|
console.log(`[graph] layout computed for ${pos.size} nodes`);
|
|
5761
5762
|
}
|
|
5762
5763
|
const { assignments: assignments2 } = communityData;
|
|
5763
|
-
if (assignments2 && Object.keys(assignments2).length > 0) {
|
|
5764
|
+
if (!flatMode && assignments2 && Object.keys(assignments2).length > 0) {
|
|
5764
5765
|
applySpacing(pos, assignments2, 40, 100, 50, 0.5);
|
|
5765
5766
|
const sizeMap = /* @__PURE__ */ new Map();
|
|
5766
5767
|
for (const sn of serializedNodes) {
|
|
@@ -7195,6 +7196,68 @@ function LayoutPipeline({
|
|
|
7195
7196
|
}, [layoutReady, optimizeTick, layoutConfig, start, stop, sigma]);
|
|
7196
7197
|
return null;
|
|
7197
7198
|
}
|
|
7199
|
+
let cached$1 = null;
|
|
7200
|
+
function resolveLabelColor() {
|
|
7201
|
+
const root = document.documentElement;
|
|
7202
|
+
const key = `${root.dataset.theme ?? ""}_${root.dataset.mode ?? ""}`;
|
|
7203
|
+
if (cached$1 && cached$1.key === key) return cached$1.fg;
|
|
7204
|
+
const style = getComputedStyle(root);
|
|
7205
|
+
const fg = style.getPropertyValue("--foreground").trim() || "#e2e8f0";
|
|
7206
|
+
cached$1 = { fg, key };
|
|
7207
|
+
return fg;
|
|
7208
|
+
}
|
|
7209
|
+
let renderedBoxes = [];
|
|
7210
|
+
let hoverBoxes = [];
|
|
7211
|
+
function resetLabelGrid() {
|
|
7212
|
+
renderedBoxes = [];
|
|
7213
|
+
}
|
|
7214
|
+
function resetHoverGrid() {
|
|
7215
|
+
hoverBoxes = [];
|
|
7216
|
+
}
|
|
7217
|
+
function overlaps(boxes, x, y, w2, h2) {
|
|
7218
|
+
for (const box of boxes) {
|
|
7219
|
+
if (x < box.x + box.w && x + w2 > box.x && y < box.y + box.h && y + h2 > box.y) {
|
|
7220
|
+
return true;
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
return false;
|
|
7224
|
+
}
|
|
7225
|
+
function overlapsExistingHover(x, y, w2, h2) {
|
|
7226
|
+
return overlaps(hoverBoxes, x, y, w2, h2);
|
|
7227
|
+
}
|
|
7228
|
+
function pushHoverBox(x, y, w2, h2) {
|
|
7229
|
+
hoverBoxes.push({ x, y, w: w2, h: h2 });
|
|
7230
|
+
}
|
|
7231
|
+
function drawNodeLabel(context, data, settings) {
|
|
7232
|
+
if (!data.label) return;
|
|
7233
|
+
const extras = data;
|
|
7234
|
+
if (extras.highlighted) return;
|
|
7235
|
+
const size = settings.labelSize;
|
|
7236
|
+
const font = settings.labelFont;
|
|
7237
|
+
const weight = settings.labelWeight;
|
|
7238
|
+
const fg = resolveLabelColor();
|
|
7239
|
+
context.font = `${weight} ${size}px ${font}`;
|
|
7240
|
+
const textWidth = context.measureText(data.label).width;
|
|
7241
|
+
const x = data.x + data.size + 3;
|
|
7242
|
+
const y = data.y + size / 3;
|
|
7243
|
+
const boxX = x - 1;
|
|
7244
|
+
const boxY = y - size;
|
|
7245
|
+
const boxW = textWidth + 2;
|
|
7246
|
+
const boxH = size + 4;
|
|
7247
|
+
if (overlaps(renderedBoxes, boxX, boxY, boxW, boxH)) {
|
|
7248
|
+
return;
|
|
7249
|
+
}
|
|
7250
|
+
renderedBoxes.push({ x: boxX, y: boxY, w: boxW, h: boxH });
|
|
7251
|
+
context.save();
|
|
7252
|
+
context.strokeStyle = "rgba(0,0,0,0.7)";
|
|
7253
|
+
context.lineWidth = 3;
|
|
7254
|
+
context.lineJoin = "round";
|
|
7255
|
+
context.strokeText(data.label, x, y);
|
|
7256
|
+
context.restore();
|
|
7257
|
+
context.font = `${weight} ${size}px ${font}`;
|
|
7258
|
+
context.fillStyle = fg;
|
|
7259
|
+
context.fillText(data.label, x, y);
|
|
7260
|
+
}
|
|
7198
7261
|
let _hoveredNodeKey = null;
|
|
7199
7262
|
function setHoveredNodeKey(key) {
|
|
7200
7263
|
_hoveredNodeKey = key;
|
|
@@ -7213,15 +7276,73 @@ function resolveThemeColors() {
|
|
|
7213
7276
|
};
|
|
7214
7277
|
return cached;
|
|
7215
7278
|
}
|
|
7279
|
+
let tooltipBuffer = [];
|
|
7280
|
+
let tooltipContext = null;
|
|
7281
|
+
let flushScheduled = false;
|
|
7282
|
+
function flushTooltips() {
|
|
7283
|
+
const ctx = tooltipContext;
|
|
7284
|
+
if (!ctx || tooltipBuffer.length === 0) return;
|
|
7285
|
+
const colors = resolveThemeColors();
|
|
7286
|
+
for (const cmd of tooltipBuffer) {
|
|
7287
|
+
const radius = 4;
|
|
7288
|
+
ctx.fillStyle = colors.bg;
|
|
7289
|
+
ctx.shadowOffsetX = 0;
|
|
7290
|
+
ctx.shadowOffsetY = 2;
|
|
7291
|
+
ctx.shadowBlur = 8;
|
|
7292
|
+
ctx.shadowColor = "rgba(0,0,0,0.5)";
|
|
7293
|
+
ctx.beginPath();
|
|
7294
|
+
ctx.roundRect(cmd.x, cmd.y, cmd.w, cmd.h, radius);
|
|
7295
|
+
ctx.fill();
|
|
7296
|
+
if (cmd.isHovered) {
|
|
7297
|
+
ctx.shadowBlur = 0;
|
|
7298
|
+
ctx.strokeStyle = cmd.color;
|
|
7299
|
+
ctx.lineWidth = 2;
|
|
7300
|
+
ctx.stroke();
|
|
7301
|
+
}
|
|
7302
|
+
ctx.shadowOffsetX = 0;
|
|
7303
|
+
ctx.shadowOffsetY = 0;
|
|
7304
|
+
ctx.shadowBlur = 0;
|
|
7305
|
+
const textX = cmd.x + 4;
|
|
7306
|
+
const centerY = cmd.y + cmd.h / 2;
|
|
7307
|
+
if (cmd.label) {
|
|
7308
|
+
ctx.fillStyle = colors.fg;
|
|
7309
|
+
ctx.font = `${cmd.weight} ${cmd.labelSize}px ${cmd.font}`;
|
|
7310
|
+
ctx.fillText(
|
|
7311
|
+
cmd.label,
|
|
7312
|
+
textX,
|
|
7313
|
+
centerY + (cmd.subtitle ? -cmd.lineHeight / 2 + cmd.labelSize * 0.35 : cmd.labelSize / 3)
|
|
7314
|
+
);
|
|
7315
|
+
}
|
|
7316
|
+
if (cmd.subtitle) {
|
|
7317
|
+
ctx.fillStyle = colors.muted;
|
|
7318
|
+
ctx.font = `${cmd.smallSize}px ${cmd.font}`;
|
|
7319
|
+
ctx.fillText(
|
|
7320
|
+
cmd.subtitle,
|
|
7321
|
+
textX,
|
|
7322
|
+
centerY + cmd.lineHeight / 2
|
|
7323
|
+
);
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
tooltipBuffer = [];
|
|
7327
|
+
tooltipContext = null;
|
|
7328
|
+
}
|
|
7329
|
+
let lastHoverFrameTime = 0;
|
|
7216
7330
|
function drawNodeHover(context, data, settings) {
|
|
7217
|
-
const
|
|
7218
|
-
if (
|
|
7331
|
+
const now = performance.now();
|
|
7332
|
+
if (now - lastHoverFrameTime > 8) {
|
|
7333
|
+
resetHoverGrid();
|
|
7334
|
+
tooltipBuffer = [];
|
|
7335
|
+
lastHoverFrameTime = now;
|
|
7336
|
+
}
|
|
7337
|
+
tooltipContext = context;
|
|
7338
|
+
const extras = data;
|
|
7339
|
+
const key = extras.key;
|
|
7340
|
+
const isActuallyHovered = key != null && _hoveredNodeKey != null && key === _hoveredNodeKey;
|
|
7341
|
+
const isSelected = extras.borderSize != null && extras.borderSize > 0;
|
|
7219
7342
|
const size = settings.labelSize;
|
|
7220
7343
|
const font = settings.labelFont;
|
|
7221
7344
|
const weight = settings.labelWeight;
|
|
7222
|
-
const colors = resolveThemeColors();
|
|
7223
7345
|
const PADDING = 4;
|
|
7224
|
-
const extras = data;
|
|
7225
7346
|
const label = typeof data.label === "string" ? data.label : typeof extras._originalLabel === "string" ? extras._originalLabel : "";
|
|
7226
7347
|
const nodeType = extras.nodeType;
|
|
7227
7348
|
const communityName = extras._communityName;
|
|
@@ -7235,63 +7356,58 @@ function drawNodeHover(context, data, settings) {
|
|
|
7235
7356
|
subtitleWidth = context.measureText(subtitle).width;
|
|
7236
7357
|
}
|
|
7237
7358
|
const textWidth = Math.max(labelWidth, subtitleWidth);
|
|
7238
|
-
if (textWidth === 0 && !subtitle) {
|
|
7239
|
-
context.beginPath();
|
|
7240
|
-
context.arc(data.x, data.y, data.size + PADDING, 0, Math.PI * 2);
|
|
7241
|
-
context.closePath();
|
|
7242
|
-
context.fillStyle = colors.bg;
|
|
7243
|
-
context.shadowBlur = 10;
|
|
7244
|
-
context.shadowColor = "rgba(0,0,0,0.5)";
|
|
7245
|
-
context.fill();
|
|
7246
|
-
context.shadowBlur = 0;
|
|
7247
|
-
context.beginPath();
|
|
7248
|
-
context.arc(data.x, data.y, data.size, 0, Math.PI * 2);
|
|
7249
|
-
context.closePath();
|
|
7250
|
-
context.fillStyle = data.color;
|
|
7251
|
-
context.fill();
|
|
7252
|
-
return;
|
|
7253
|
-
}
|
|
7254
7359
|
const boxWidth = Math.round(textWidth + 8);
|
|
7255
7360
|
const lineHeight = size + 2;
|
|
7256
7361
|
const lines = subtitle ? 2 : 1;
|
|
7257
7362
|
const boxHeight = Math.round(lineHeight * lines + PADDING * 2);
|
|
7258
|
-
const
|
|
7259
|
-
const
|
|
7260
|
-
const
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
context.shadowOffsetX = 0;
|
|
7277
|
-
context.shadowOffsetY = 0;
|
|
7278
|
-
context.shadowBlur = 0;
|
|
7279
|
-
const textX = data.x + nodeRadius + 4;
|
|
7280
|
-
if (label) {
|
|
7281
|
-
context.fillStyle = colors.fg;
|
|
7282
|
-
context.font = `${weight} ${size}px ${font}`;
|
|
7283
|
-
context.fillText(label, textX, data.y + (subtitle ? -1 : size / 3));
|
|
7284
|
-
}
|
|
7285
|
-
if (subtitle) {
|
|
7286
|
-
context.fillStyle = colors.muted;
|
|
7287
|
-
context.font = `${smallSize}px ${font}`;
|
|
7288
|
-
context.fillText(subtitle, textX, data.y + lineHeight - 2);
|
|
7363
|
+
const tooltipGap = 4;
|
|
7364
|
+
const tx = data.x + data.size + tooltipGap;
|
|
7365
|
+
const ty = data.y - boxHeight / 2;
|
|
7366
|
+
const hasTooltip = textWidth > 0 || subtitle;
|
|
7367
|
+
let drawTooltip = hasTooltip;
|
|
7368
|
+
const pad = 8;
|
|
7369
|
+
const cullX = data.x - data.size - pad;
|
|
7370
|
+
const cullY = data.y - Math.max(boxHeight / 2, data.size) - pad;
|
|
7371
|
+
const cullW = data.size * 2 + boxWidth + tooltipGap + pad * 2;
|
|
7372
|
+
const cullH = Math.max(boxHeight, data.size * 2) + pad * 2;
|
|
7373
|
+
if (hasTooltip && !isActuallyHovered && !isSelected) {
|
|
7374
|
+
if (overlapsExistingHover(cullX, cullY, cullW, cullH)) {
|
|
7375
|
+
drawTooltip = false;
|
|
7376
|
+
} else {
|
|
7377
|
+
pushHoverBox(cullX, cullY, cullW, cullH);
|
|
7378
|
+
}
|
|
7379
|
+
} else if (hasTooltip) {
|
|
7380
|
+
pushHoverBox(cullX, cullY, cullW, cullH);
|
|
7289
7381
|
}
|
|
7290
7382
|
context.beginPath();
|
|
7291
7383
|
context.arc(data.x, data.y, data.size, 0, Math.PI * 2);
|
|
7292
7384
|
context.closePath();
|
|
7293
7385
|
context.fillStyle = data.color;
|
|
7294
7386
|
context.fill();
|
|
7387
|
+
if (drawTooltip) {
|
|
7388
|
+
tooltipBuffer.push({
|
|
7389
|
+
x: tx,
|
|
7390
|
+
y: ty,
|
|
7391
|
+
w: boxWidth,
|
|
7392
|
+
h: boxHeight,
|
|
7393
|
+
label,
|
|
7394
|
+
subtitle,
|
|
7395
|
+
labelSize: size,
|
|
7396
|
+
smallSize,
|
|
7397
|
+
font,
|
|
7398
|
+
weight,
|
|
7399
|
+
lineHeight,
|
|
7400
|
+
color: data.color,
|
|
7401
|
+
isHovered: isActuallyHovered
|
|
7402
|
+
});
|
|
7403
|
+
}
|
|
7404
|
+
if (!flushScheduled) {
|
|
7405
|
+
flushScheduled = true;
|
|
7406
|
+
queueMicrotask(() => {
|
|
7407
|
+
flushScheduled = false;
|
|
7408
|
+
flushTooltips();
|
|
7409
|
+
});
|
|
7410
|
+
}
|
|
7295
7411
|
}
|
|
7296
7412
|
function SigmaRefCapture({
|
|
7297
7413
|
onReady
|
|
@@ -7304,6 +7420,14 @@ function SigmaRefCapture({
|
|
|
7304
7420
|
onReady(sigma);
|
|
7305
7421
|
}
|
|
7306
7422
|
}, [sigma, onReady]);
|
|
7423
|
+
t.useEffect(() => {
|
|
7424
|
+
const s = sigma;
|
|
7425
|
+
const handler = () => resetLabelGrid();
|
|
7426
|
+
s.on("beforeRender", handler);
|
|
7427
|
+
return () => {
|
|
7428
|
+
s.off("beforeRender", handler);
|
|
7429
|
+
};
|
|
7430
|
+
}, [sigma]);
|
|
7307
7431
|
return null;
|
|
7308
7432
|
}
|
|
7309
7433
|
function GraphEventHandler({
|
|
@@ -7557,6 +7681,7 @@ const GraphCanvas = t.memo(
|
|
|
7557
7681
|
labelFont: LABEL_FONT,
|
|
7558
7682
|
labelColor: { color: LABEL_COLOR },
|
|
7559
7683
|
labelSize: LABEL_SIZE,
|
|
7684
|
+
defaultDrawNodeLabel: drawNodeLabel,
|
|
7560
7685
|
defaultDrawNodeHover: drawNodeHover,
|
|
7561
7686
|
allowInvalidContainer: true,
|
|
7562
7687
|
zIndex: zIndexEnabled,
|
|
@@ -9119,6 +9244,9 @@ exports.NODE_SIZE_MIN = NODE_SIZE_MIN;
|
|
|
9119
9244
|
exports.NODE_SIZE_MULTIPLIERS = NODE_SIZE_MULTIPLIERS;
|
|
9120
9245
|
exports.ZOOM_SIZE_EXPONENT = ZOOM_SIZE_EXPONENT;
|
|
9121
9246
|
exports.drawNodeHover = drawNodeHover;
|
|
9247
|
+
exports.drawNodeLabel = drawNodeLabel;
|
|
9248
|
+
exports.flushTooltips = flushTooltips;
|
|
9249
|
+
exports.resetLabelGrid = resetLabelGrid;
|
|
9122
9250
|
exports.setHoveredNodeKey = setHoveredNodeKey;
|
|
9123
9251
|
exports.useGraphInstance = useGraphInstance;
|
|
9124
9252
|
exports.useGraphVisuals = useGraphVisuals;
|