@opentrace/components 0.1.1-rc.11 → 0.1.1-rc.30

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.
Files changed (39) hide show
  1. package/dist/opentrace-components.cjs +159 -47
  2. package/dist/opentrace-components.cjs.map +1 -1
  3. package/dist/opentrace-components.js +160 -48
  4. package/dist/opentrace-components.js.map +1 -1
  5. package/dist/src/GraphCanvas.d.ts +22 -1
  6. package/dist/src/GraphCanvas.d.ts.map +1 -1
  7. package/dist/src/colors/linkColors.d.ts.map +1 -1
  8. package/dist/src/colors/nodeColors.d.ts.map +1 -1
  9. package/dist/src/config/graphLayout.d.ts +3 -2
  10. package/dist/src/config/graphLayout.d.ts.map +1 -1
  11. package/dist/src/graph/LayoutPipeline.d.ts.map +1 -1
  12. package/dist/src/graph/__tests__/optimizeWorker.test.d.ts +2 -0
  13. package/dist/src/graph/__tests__/optimizeWorker.test.d.ts.map +1 -0
  14. package/dist/src/graph/__tests__/spacingWorker.test.d.ts +2 -0
  15. package/dist/src/graph/__tests__/spacingWorker.test.d.ts.map +1 -0
  16. package/dist/src/graph/__tests__/useCommunities.test.d.ts +2 -0
  17. package/dist/src/graph/__tests__/useCommunities.test.d.ts.map +1 -0
  18. package/dist/src/graph/__tests__/useGraphFilters.test.d.ts +2 -0
  19. package/dist/src/graph/__tests__/useGraphFilters.test.d.ts.map +1 -0
  20. package/dist/src/graph/__tests__/useHighlights.test.d.ts +2 -0
  21. package/dist/src/graph/__tests__/useHighlights.test.d.ts.map +1 -0
  22. package/dist/src/graph/types.d.ts +2 -0
  23. package/dist/src/graph/types.d.ts.map +1 -1
  24. package/dist/src/graph/useGraphFilters.d.ts.map +1 -1
  25. package/dist/src/graph/useGraphInstance.d.ts.map +1 -1
  26. package/dist/src/graph/useGraphVisuals.d.ts.map +1 -1
  27. package/dist/src/index.d.ts +2 -1
  28. package/dist/src/index.d.ts.map +1 -1
  29. package/dist/src/sigma/zoomToNodes.d.ts +7 -2
  30. package/dist/src/sigma/zoomToNodes.d.ts.map +1 -1
  31. package/dist/{useHighlights-BHlafcBH.js → useHighlights-DbMfb0-p.js} +122 -74
  32. package/dist/useHighlights-DbMfb0-p.js.map +1 -0
  33. package/dist/{useHighlights-D6Jl6Woe.cjs → useHighlights-fRWg-A_c.cjs} +122 -74
  34. package/dist/useHighlights-fRWg-A_c.cjs.map +1 -0
  35. package/dist/utils.cjs +1 -1
  36. package/dist/utils.js +1 -1
  37. package/package.json +1 -1
  38. package/dist/useHighlights-BHlafcBH.js.map +0 -1
  39. package/dist/useHighlights-D6Jl6Woe.cjs.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-D6Jl6Woe.cjs");
5
+ const useHighlights = require("./useHighlights-fRWg-A_c.cjs");
6
6
  var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
7
7
  function _toPrimitive$1(t2, r) {
8
8
  if ("object" != typeof t2 || !t2) return t2;
@@ -5253,7 +5253,7 @@ createEdgeCurveProgram({
5253
5253
  });
5254
5254
  const NODE_SIZE_MIN = 2;
5255
5255
  const NODE_SIZE_MAX = 8;
5256
- const NODE_SIZE_DEGREE_SCALE = 1.1;
5256
+ const NODE_SIZE_DEGREE_SCALE = 1;
5257
5257
  const NODE_SIZE_MULTIPLIERS = {
5258
5258
  Repository: 1,
5259
5259
  // All other STRUCTURAL_TYPES default to this:
@@ -5288,8 +5288,9 @@ const FA2_ADJUST_SIZES = true;
5288
5288
  const FA2_DURATION = 3e3;
5289
5289
  const NOVERLAP_MAX_ITERATIONS = 50;
5290
5290
  const NOVERLAP_RATIO = 1.5;
5291
- const NOVERLAP_MARGIN = 10;
5291
+ const NOVERLAP_MARGIN = 25;
5292
5292
  const NOVERLAP_EXPANSION = 1.5;
5293
+ const NOVERLAP_COMMUNITY_ITERATIONS = 20;
5293
5294
  const EDGE_PROGRAM_THRESHOLD = 5e4;
5294
5295
  const LABEL_RENDERED_SIZE_THRESHOLD = 8;
5295
5296
  const LABEL_SIZE = 12;
@@ -5319,6 +5320,7 @@ const DEFAULT_LAYOUT_CONFIG = {
5319
5320
  noverlapRatio: NOVERLAP_RATIO,
5320
5321
  noverlapMargin: NOVERLAP_MARGIN,
5321
5322
  noverlapExpansion: NOVERLAP_EXPANSION,
5323
+ noverlapCommunityIterations: NOVERLAP_COMMUNITY_ITERATIONS,
5322
5324
  louvainResolution: LOUVAIN_RESOLUTION,
5323
5325
  edgeProgramThreshold: 5e4,
5324
5326
  // Graph structure
@@ -5369,6 +5371,13 @@ function useGraphInstance({
5369
5371
  if (allNodes.length === 0) return;
5370
5372
  const { assignments, colorMap, names } = communityData;
5371
5373
  const { getNodeColor, getLinkColor, getCommunityColor } = layoutConfig;
5374
+ const degreeMap = /* @__PURE__ */ new Map();
5375
+ for (const link of allLinks) {
5376
+ const s = endpointId(link.source);
5377
+ const t2 = endpointId(link.target);
5378
+ degreeMap.set(s, (degreeMap.get(s) || 0) + 1);
5379
+ degreeMap.set(t2, (degreeMap.get(t2) || 0) + 1);
5380
+ }
5372
5381
  const nodeIdSet = /* @__PURE__ */ new Set();
5373
5382
  const serializedNodes = allNodes.map((node) => {
5374
5383
  nodeIdSet.add(node.id);
@@ -5376,13 +5385,17 @@ function useGraphInstance({
5376
5385
  const commColor = getCommunityColor(assignments, colorMap, node.id);
5377
5386
  const cid = assignments[node.id];
5378
5387
  const commName = cid !== void 0 ? names.get(cid) : void 0;
5388
+ const degree = degreeMap.get(node.id) || 0;
5389
+ const size = nodeSize(degree, node.type, structuralTypes);
5379
5390
  return {
5380
5391
  key: node.id,
5381
5392
  attributes: {
5382
5393
  label: node.name || node.id,
5394
+ _originalLabel: node.name || node.id,
5383
5395
  x: 0,
5384
5396
  y: 0,
5385
- size: nodeSize(0, node.type, structuralTypes),
5397
+ size,
5398
+ _baseSize: size,
5386
5399
  nodeType: node.type,
5387
5400
  _graphNode: node,
5388
5401
  _typeColor: typeColor,
@@ -5547,21 +5560,24 @@ function useGraphVisuals(graph, layoutReady, visualState, layoutConfig, _degreeM
5547
5560
  return attrs;
5548
5561
  });
5549
5562
  const defaultEdgeSize = isLargeGraph ? EDGE_SIZE_DEFAULT_LINE : EDGE_SIZE_DEFAULT;
5550
- graph.updateEachEdgeAttributes((_id, attrs, source, target) => {
5551
- const linkKey = `${source}-${target}`;
5552
- const isHighlighted = highlightLinks.has(linkKey);
5553
- const baseColor = getLinkColor(attrs.label);
5554
- if (hasHighlight) {
5555
- attrs.color = isHighlighted ? baseColor : dimColor(baseColor, EDGE_OPACITY_DIMMED);
5556
- attrs.size = isHighlighted ? EDGE_SIZE_HIGHLIGHTED : EDGE_SIZE_DIMMED;
5557
- attrs.zIndex = isHighlighted ? 1 : 0;
5558
- } else {
5559
- attrs.color = dimColor(baseColor, EDGE_OPACITY_DEFAULT);
5560
- attrs.size = defaultEdgeSize;
5561
- attrs.zIndex = 0;
5562
- }
5563
- return attrs;
5564
- });
5563
+ graph.updateEachEdgeAttributes(
5564
+ (_id, attrs, source, target) => {
5565
+ const linkKey = `${source}-${target}`;
5566
+ const isHighlighted = highlightLinks.has(linkKey);
5567
+ const baseColor = getLinkColor(attrs.label);
5568
+ if (hasHighlight) {
5569
+ attrs.color = isHighlighted ? baseColor : dimColor(baseColor, EDGE_OPACITY_DIMMED);
5570
+ attrs.size = isHighlighted ? EDGE_SIZE_HIGHLIGHTED : EDGE_SIZE_DIMMED;
5571
+ attrs.zIndex = isHighlighted ? 1 : 0;
5572
+ } else {
5573
+ attrs.color = dimColor(baseColor, EDGE_OPACITY_DEFAULT);
5574
+ attrs.size = defaultEdgeSize;
5575
+ attrs.zIndex = 0;
5576
+ }
5577
+ return attrs;
5578
+ },
5579
+ { attributes: ["zIndex"] }
5580
+ );
5565
5581
  }, [graph, layoutReady, visualState, layoutConfig, isLargeGraph]);
5566
5582
  }
5567
5583
  function c(r, n2) {
@@ -6786,7 +6802,7 @@ const e = /* @__PURE__ */ useHighlights.getDefaultExportFromCjs(workerExports);
6786
6802
  function n(t2 = {}) {
6787
6803
  return c(e, t2);
6788
6804
  }
6789
- function zoomToNodes(sigma, nodeIds, duration = 600, padding = 0.1) {
6805
+ function zoomToNodes(sigma, nodeIds, duration = 600, padding = 0.2) {
6790
6806
  let minX = Infinity;
6791
6807
  let maxX = -Infinity;
6792
6808
  let minY = Infinity;
@@ -6803,21 +6819,29 @@ function zoomToNodes(sigma, nodeIds, duration = 600, padding = 0.1) {
6803
6819
  }
6804
6820
  if (count === 0) return;
6805
6821
  const camera = sigma.getCamera();
6806
- if (count === 1 || maxX - minX < 1 && maxY - minY < 1) {
6807
- camera.animate(
6808
- { x: (minX + maxX) / 2, y: (minY + maxY) / 2, ratio: 0.1 },
6809
- { duration }
6810
- );
6811
- return;
6812
- }
6813
6822
  const cx = (minX + maxX) / 2;
6814
6823
  const cy = (minY + maxY) / 2;
6824
+ if (count === 1 || maxX - minX < 1e-3 && maxY - minY < 1e-3) {
6825
+ camera.animate({ x: cx, y: cy, ratio: 0.1 }, { duration });
6826
+ return;
6827
+ }
6828
+ const refState = { x: 0.5, y: 0.5, ratio: 1, angle: 0 };
6815
6829
  const { width, height } = sigma.getDimensions();
6816
- const graphWidth = maxX - minX;
6817
- const graphHeight = maxY - minY;
6818
- const ratioX = graphWidth / (width * (1 - padding * 2));
6819
- const ratioY = graphHeight / (height * (1 - padding * 2));
6820
- const ratio = Math.max(ratioX, ratioY, 0.01);
6830
+ const topLeft = sigma.viewportToFramedGraph(
6831
+ { x: 0, y: 0 },
6832
+ { cameraState: refState }
6833
+ );
6834
+ const bottomRight = sigma.viewportToFramedGraph(
6835
+ { x: width, y: height },
6836
+ { cameraState: refState }
6837
+ );
6838
+ const fullW = Math.abs(bottomRight.x - topLeft.x);
6839
+ const fullH = Math.abs(topLeft.y - bottomRight.y);
6840
+ const bboxW = maxX - minX;
6841
+ const bboxH = maxY - minY;
6842
+ const scaleX = fullW > 0 ? bboxW / (fullW * (1 - 2 * padding)) : 1;
6843
+ const scaleY = fullH > 0 ? bboxH / (fullH * (1 - 2 * padding)) : 1;
6844
+ const ratio = Math.max(Math.max(scaleX, scaleY), 0.01);
6821
6845
  camera.animate({ x: cx, y: cy, ratio }, { duration });
6822
6846
  }
6823
6847
  function zoomToFit(sigma, duration = 400) {
@@ -7018,8 +7042,9 @@ function LayoutPipeline({
7018
7042
  });
7019
7043
  }
7020
7044
  const margin = layoutConfig.noverlapMargin * scale2;
7045
+ const iters = layoutConfig.noverlapCommunityIterations ?? 20;
7021
7046
  const nodeArr = [...subGraph.entries()];
7022
- for (let iter = 0; iter < 10; iter++) {
7047
+ for (let iter = 0; iter < iters; iter++) {
7023
7048
  for (let i = 0; i < nodeArr.length; i++) {
7024
7049
  const [, a] = nodeArr[i];
7025
7050
  for (let j2 = i + 1; j2 < nodeArr.length; j2++) {
@@ -7095,6 +7120,10 @@ function LayoutPipeline({
7095
7120
  }, [layoutReady, optimizeTick, layoutConfig, start, stop, sigma]);
7096
7121
  return null;
7097
7122
  }
7123
+ let _hoveredNodeKey = null;
7124
+ function setHoveredNodeKey(key) {
7125
+ _hoveredNodeKey = key;
7126
+ }
7098
7127
  let cached = null;
7099
7128
  function resolveThemeColors() {
7100
7129
  const root = document.documentElement;
@@ -7110,7 +7139,8 @@ function resolveThemeColors() {
7110
7139
  return cached;
7111
7140
  }
7112
7141
  function drawNodeHover(context, data, settings) {
7113
- data.key;
7142
+ const key = data.key;
7143
+ if (key && _hoveredNodeKey !== null && key !== _hoveredNodeKey) return;
7114
7144
  const size = settings.labelSize;
7115
7145
  const font = settings.labelFont;
7116
7146
  const weight = settings.labelWeight;
@@ -7210,18 +7240,35 @@ function GraphEventHandler({
7210
7240
  t.useEffect(() => {
7211
7241
  const container = sigma.getContainer();
7212
7242
  const graph = sigma.getGraph();
7243
+ const mouseCanvas = container.querySelector(
7244
+ ".sigma-mouse"
7245
+ );
7246
+ let overNode = false;
7247
+ let overEdge = false;
7248
+ function updateCursor() {
7249
+ const value = overNode || overEdge ? "pointer" : "grab";
7250
+ container.style.cursor = value;
7251
+ if (mouseCanvas) mouseCanvas.style.cursor = value;
7252
+ }
7253
+ updateCursor();
7213
7254
  const handlers = {
7214
- enterNode: () => {
7215
- container.style.cursor = "pointer";
7255
+ enterNode: ({ node }) => {
7256
+ setHoveredNodeKey(node);
7257
+ overNode = true;
7258
+ updateCursor();
7216
7259
  },
7217
7260
  leaveNode: () => {
7218
- container.style.cursor = "default";
7261
+ setHoveredNodeKey(null);
7262
+ overNode = false;
7263
+ updateCursor();
7219
7264
  },
7220
7265
  enterEdge: () => {
7221
- container.style.cursor = "pointer";
7266
+ overEdge = true;
7267
+ updateCursor();
7222
7268
  },
7223
7269
  leaveEdge: () => {
7224
- container.style.cursor = "default";
7270
+ overEdge = false;
7271
+ updateCursor();
7225
7272
  },
7226
7273
  clickNode: ({ node }) => {
7227
7274
  if (!onNodeClick) return;
@@ -7290,6 +7337,12 @@ const GraphCanvas = t.memo(
7290
7337
  selectedNodeId = null,
7291
7338
  hops = 2,
7292
7339
  getSubType = defaultGetSubType,
7340
+ highlightNodes: highlightNodesProp,
7341
+ highlightLinks: highlightLinksProp,
7342
+ labelNodes: labelNodesProp,
7343
+ availableSubTypes = EMPTY_SUB_TYPES,
7344
+ zIndex: zIndexEnabled = false,
7345
+ communityData: communityDataProp,
7293
7346
  onNodeClick,
7294
7347
  onEdgeClick,
7295
7348
  onStageClick,
@@ -7299,7 +7352,8 @@ const GraphCanvas = t.memo(
7299
7352
  } = props;
7300
7353
  const sigmaRef = t.useRef(null);
7301
7354
  const [optimizeTick, setOptimizeTick] = t.useState(0);
7302
- const communityData = useHighlights.useCommunities(nodes, links, layoutConfig);
7355
+ const internalCommunityData = useHighlights.useCommunities(nodes, links, layoutConfig);
7356
+ const communityData = communityDataProp ?? internalCommunityData;
7303
7357
  const filterState = t.useMemo(
7304
7358
  () => ({
7305
7359
  hiddenNodeTypes,
@@ -7320,10 +7374,10 @@ const GraphCanvas = t.memo(
7320
7374
  layoutReady,
7321
7375
  filterState,
7322
7376
  communityData.assignments,
7323
- EMPTY_SUB_TYPES,
7377
+ availableSubTypes,
7324
7378
  getSubType
7325
7379
  );
7326
- const highlights = useHighlights.useHighlights(
7380
+ const internalHighlights = useHighlights.useHighlights(
7327
7381
  graph,
7328
7382
  layoutReady,
7329
7383
  nodes,
@@ -7333,6 +7387,9 @@ const GraphCanvas = t.memo(
7333
7387
  hops,
7334
7388
  filterState
7335
7389
  );
7390
+ const effectiveHighlightNodes = highlightNodesProp ?? internalHighlights.highlightNodes;
7391
+ const effectiveHighlightLinks = highlightLinksProp ?? internalHighlights.highlightLinks;
7392
+ const effectiveLabelNodes = labelNodesProp ?? internalHighlights.labelNodes;
7336
7393
  const degreeMap = t.useMemo(() => {
7337
7394
  const map = /* @__PURE__ */ new Map();
7338
7395
  links.forEach((l) => {
@@ -7347,12 +7404,18 @@ const GraphCanvas = t.memo(
7347
7404
  const visualState = t.useMemo(
7348
7405
  () => ({
7349
7406
  colorMode,
7350
- highlightNodes: highlights.highlightNodes,
7351
- highlightLinks: highlights.highlightLinks,
7352
- labelNodes: highlights.labelNodes,
7407
+ highlightNodes: effectiveHighlightNodes,
7408
+ highlightLinks: effectiveHighlightLinks,
7409
+ labelNodes: effectiveLabelNodes,
7353
7410
  selectedNodeId: selectedNodeId ?? null
7354
7411
  }),
7355
- [colorMode, highlights, selectedNodeId]
7412
+ [
7413
+ colorMode,
7414
+ effectiveHighlightNodes,
7415
+ effectiveHighlightLinks,
7416
+ effectiveLabelNodes,
7417
+ selectedNodeId
7418
+ ]
7356
7419
  );
7357
7420
  useGraphVisuals(
7358
7421
  graph,
@@ -7362,6 +7425,34 @@ const GraphCanvas = t.memo(
7362
7425
  degreeMap,
7363
7426
  isLargeGraph
7364
7427
  );
7428
+ t.useEffect(() => {
7429
+ if (!zIndexEnabled) return;
7430
+ const container = sigmaRef.current?.getContainer?.();
7431
+ if (!container) return;
7432
+ const layers = [
7433
+ "sigma-edges",
7434
+ "sigma-edgeLabels",
7435
+ "sigma-nodes",
7436
+ "sigma-labels",
7437
+ "sigma-hovers",
7438
+ "sigma-hoverNodes",
7439
+ "sigma-mouse"
7440
+ ];
7441
+ const els = layers.map(
7442
+ (cls) => container.querySelector(`.${cls}`)
7443
+ );
7444
+ const hasSelection = effectiveHighlightNodes.size > 0;
7445
+ if (hasSelection) {
7446
+ const zMap = [2, 3, 1, 4, 6, 5, 7];
7447
+ els.forEach((el, i) => {
7448
+ if (el) el.style.zIndex = String(zMap[i]);
7449
+ });
7450
+ } else {
7451
+ els.forEach((el) => {
7452
+ if (el) el.style.zIndex = "";
7453
+ });
7454
+ }
7455
+ }, [zIndexEnabled, effectiveHighlightNodes]);
7365
7456
  const sigmaSettings = t.useMemo(
7366
7457
  () => ({
7367
7458
  defaultNodeType: "circle",
@@ -7377,9 +7468,10 @@ const GraphCanvas = t.memo(
7377
7468
  labelSize: LABEL_SIZE,
7378
7469
  defaultDrawNodeHover: drawNodeHover,
7379
7470
  allowInvalidContainer: true,
7471
+ zIndex: zIndexEnabled,
7380
7472
  zoomToSizeRatioFunction: (ratio) => Math.pow(ratio, ZOOM_SIZE_EXPONENT)
7381
7473
  }),
7382
- [isLargeGraph]
7474
+ [isLargeGraph, zIndexEnabled]
7383
7475
  );
7384
7476
  const handleSigmaReady = t.useCallback(
7385
7477
  (sigma) => {
@@ -7446,6 +7538,24 @@ const GraphCanvas = t.memo(
7446
7538
  },
7447
7539
  optimize: () => {
7448
7540
  setOptimizeTick((t2) => t2 + 1);
7541
+ },
7542
+ zoomIn: (duration = 300) => {
7543
+ if (sigmaRef.current) {
7544
+ const camera = sigmaRef.current.getCamera();
7545
+ camera.animatedZoom({ duration });
7546
+ }
7547
+ },
7548
+ zoomOut: (duration = 300) => {
7549
+ if (sigmaRef.current) {
7550
+ const camera = sigmaRef.current.getCamera();
7551
+ camera.animatedUnzoom({ duration });
7552
+ }
7553
+ },
7554
+ resetCamera: (duration = 400) => {
7555
+ if (sigmaRef.current) {
7556
+ const camera = sigmaRef.current.getCamera();
7557
+ camera.animatedReset({ duration });
7558
+ }
7449
7559
  }
7450
7560
  }),
7451
7561
  [nodes, links, hops, onNodeClick]
@@ -8686,6 +8796,7 @@ exports.FA2_ENABLED = FA2_ENABLED;
8686
8796
  exports.FA2_GRAVITY = FA2_GRAVITY;
8687
8797
  exports.FA2_SCALING_RATIO = FA2_SCALING_RATIO;
8688
8798
  exports.FilterPanel = FilterPanel;
8799
+ exports.Graph = GraphCanvas;
8689
8800
  exports.GraphBadge = GraphBadge;
8690
8801
  exports.GraphCanvas = GraphCanvas;
8691
8802
  exports.GraphLegend = GraphLegend;
@@ -8702,6 +8813,7 @@ exports.NODE_SIZE_MIN = NODE_SIZE_MIN;
8702
8813
  exports.NODE_SIZE_MULTIPLIERS = NODE_SIZE_MULTIPLIERS;
8703
8814
  exports.ZOOM_SIZE_EXPONENT = ZOOM_SIZE_EXPONENT;
8704
8815
  exports.drawNodeHover = drawNodeHover;
8816
+ exports.setHoveredNodeKey = setHoveredNodeKey;
8705
8817
  exports.useGraphInstance = useGraphInstance;
8706
8818
  exports.useGraphVisuals = useGraphVisuals;
8707
8819
  exports.zoomToFit = zoomToFit;