@opentrace/components 0.1.1-rc.88 → 0.1.1-rc.93

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.
@@ -7154,10 +7154,12 @@ function LayoutPipeline({
7154
7154
  layoutReady,
7155
7155
  layoutConfig,
7156
7156
  optimizeTick,
7157
- onOptimizeStatus
7157
+ onOptimizeStatus,
7158
+ onLayoutControl
7158
7159
  }) {
7159
7160
  const sigma = v();
7160
7161
  const timerRef = t.useRef(null);
7162
+ const runningRef = t.useRef(false);
7161
7163
  const { start, stop } = n({
7162
7164
  settings: {
7163
7165
  gravity: layoutConfig.fa2Gravity,
@@ -7169,14 +7171,45 @@ function LayoutPipeline({
7169
7171
  linLogMode: layoutConfig.fa2LinLogMode,
7170
7172
  outboundAttractionDistribution: layoutConfig.fa2OutboundAttraction,
7171
7173
  adjustSizes: layoutConfig.fa2AdjustSizes
7174
+ },
7175
+ outputReducer: (_key, attrs) => {
7176
+ if (attrs._pinnedX != null) {
7177
+ attrs.x = attrs._pinnedX;
7178
+ attrs.y = attrs._pinnedY;
7179
+ if (!attrs.fixed) {
7180
+ attrs._pinnedX = void 0;
7181
+ attrs._pinnedY = void 0;
7182
+ }
7183
+ }
7184
+ return attrs;
7172
7185
  }
7173
7186
  });
7187
+ t.useEffect(() => {
7188
+ onLayoutControl?.({
7189
+ stop: () => {
7190
+ if (timerRef.current) {
7191
+ clearTimeout(timerRef.current);
7192
+ timerRef.current = null;
7193
+ }
7194
+ stop();
7195
+ runningRef.current = false;
7196
+ onOptimizeStatus?.(null);
7197
+ },
7198
+ start: () => {
7199
+ start();
7200
+ runningRef.current = true;
7201
+ onOptimizeStatus?.({ phase: "fa2" });
7202
+ },
7203
+ isRunning: () => runningRef.current
7204
+ });
7205
+ }, [start, stop, onLayoutControl]);
7174
7206
  function cleanup() {
7175
7207
  if (timerRef.current) {
7176
7208
  clearTimeout(timerRef.current);
7177
7209
  timerRef.current = null;
7178
7210
  }
7179
7211
  stop();
7212
+ runningRef.current = false;
7180
7213
  }
7181
7214
  t.useEffect(() => {
7182
7215
  if (!layoutReady) return;
@@ -7187,8 +7220,10 @@ function LayoutPipeline({
7187
7220
  if (layoutConfig.fa2Enabled && graph.order > 0) {
7188
7221
  onOptimizeStatus?.({ phase: "fa2" });
7189
7222
  start();
7223
+ runningRef.current = true;
7190
7224
  timerRef.current = setTimeout(() => {
7191
7225
  stop();
7226
+ runningRef.current = false;
7192
7227
  onOptimizeStatus?.(null);
7193
7228
  }, layoutConfig.fa2Duration);
7194
7229
  } else {
@@ -7441,13 +7476,16 @@ function GraphEventHandler({
7441
7476
  t.useEffect(() => {
7442
7477
  const container = sigma.getContainer();
7443
7478
  const graph = sigma.getGraph();
7479
+ const s = sigma;
7444
7480
  const mouseCanvas = container.querySelector(
7445
7481
  ".sigma-mouse"
7446
7482
  );
7447
7483
  let overNode = false;
7448
7484
  let overEdge = false;
7485
+ let draggedNode = null;
7486
+ let isDragging = false;
7449
7487
  function updateCursor() {
7450
- const value = overNode || overEdge ? "pointer" : "grab";
7488
+ const value = isDragging ? "grabbing" : overNode || overEdge ? "pointer" : "grab";
7451
7489
  container.style.cursor = value;
7452
7490
  if (mouseCanvas) mouseCanvas.style.cursor = value;
7453
7491
  }
@@ -7471,7 +7509,21 @@ function GraphEventHandler({
7471
7509
  overEdge = false;
7472
7510
  updateCursor();
7473
7511
  },
7512
+ // Start drag on mousedown over a node
7513
+ downNode: ({ node }) => {
7514
+ draggedNode = node;
7515
+ isDragging = false;
7516
+ const attrs = graph.getNodeAttributes(node);
7517
+ graph.setNodeAttribute(node, "fixed", true);
7518
+ graph.setNodeAttribute(node, "_pinnedX", attrs.x);
7519
+ graph.setNodeAttribute(node, "_pinnedY", attrs.y);
7520
+ s.getCamera().disable();
7521
+ },
7474
7522
  clickNode: ({ node }) => {
7523
+ if (isDragging) {
7524
+ isDragging = false;
7525
+ return;
7526
+ }
7475
7527
  if (!onNodeClick) return;
7476
7528
  const attrs = graph.getNodeAttributes(node);
7477
7529
  const graphNode = attrs._graphNode;
@@ -7497,21 +7549,56 @@ function GraphEventHandler({
7497
7549
  onStageClick?.();
7498
7550
  }
7499
7551
  };
7552
+ function onMouseMove(e2) {
7553
+ if (!draggedNode) return;
7554
+ isDragging = true;
7555
+ updateCursor();
7556
+ const pos = s.viewportToGraph({
7557
+ x: e2.offsetX,
7558
+ y: e2.offsetY
7559
+ });
7560
+ graph.setNodeAttribute(draggedNode, "x", pos.x);
7561
+ graph.setNodeAttribute(draggedNode, "y", pos.y);
7562
+ graph.setNodeAttribute(draggedNode, "_pinnedX", pos.x);
7563
+ graph.setNodeAttribute(draggedNode, "_pinnedY", pos.y);
7564
+ e2.preventDefault();
7565
+ }
7566
+ function onMouseUp() {
7567
+ if (draggedNode) {
7568
+ graph.setNodeAttribute(draggedNode, "fixed", false);
7569
+ draggedNode = null;
7570
+ s.getCamera().enable();
7571
+ updateCursor();
7572
+ }
7573
+ }
7500
7574
  sigma.on("enterNode", handlers.enterNode);
7501
7575
  sigma.on("leaveNode", handlers.leaveNode);
7502
7576
  sigma.on("enterEdge", handlers.enterEdge);
7503
7577
  sigma.on("leaveEdge", handlers.leaveEdge);
7578
+ sigma.on("downNode", handlers.downNode);
7504
7579
  sigma.on("clickNode", handlers.clickNode);
7505
7580
  sigma.on("clickEdge", handlers.clickEdge);
7506
7581
  sigma.on("clickStage", handlers.clickStage);
7582
+ const mouseTarget = mouseCanvas ?? container;
7583
+ mouseTarget.addEventListener("mousemove", onMouseMove);
7584
+ mouseTarget.addEventListener("mouseup", onMouseUp);
7585
+ mouseTarget.addEventListener("mouseleave", onMouseUp);
7507
7586
  return () => {
7587
+ if (draggedNode) {
7588
+ graph.setNodeAttribute(draggedNode, "fixed", false);
7589
+ s.getCamera().enable();
7590
+ }
7508
7591
  sigma.off("enterNode", handlers.enterNode);
7509
7592
  sigma.off("leaveNode", handlers.leaveNode);
7510
7593
  sigma.off("enterEdge", handlers.enterEdge);
7511
7594
  sigma.off("leaveEdge", handlers.leaveEdge);
7595
+ sigma.off("downNode", handlers.downNode);
7512
7596
  sigma.off("clickNode", handlers.clickNode);
7513
7597
  sigma.off("clickEdge", handlers.clickEdge);
7514
7598
  sigma.off("clickStage", handlers.clickStage);
7599
+ mouseTarget.removeEventListener("mousemove", onMouseMove);
7600
+ mouseTarget.removeEventListener("mouseup", onMouseUp);
7601
+ mouseTarget.removeEventListener("mouseleave", onMouseUp);
7515
7602
  };
7516
7603
  }, [sigma, onNodeClick, onEdgeClick, onStageClick]);
7517
7604
  return null;
@@ -7559,6 +7646,7 @@ const GraphCanvas = t.memo(
7559
7646
  availableSubTypes = EMPTY_SUB_TYPES,
7560
7647
  zIndex: zIndexEnabled = false,
7561
7648
  communityData: communityDataProp,
7649
+ labelsVisible = true,
7562
7650
  animationSettings = DEFAULT_ANIMATION,
7563
7651
  onNodeClick,
7564
7652
  onEdgeClick,
@@ -7568,6 +7656,7 @@ const GraphCanvas = t.memo(
7568
7656
  style
7569
7657
  } = props;
7570
7658
  const sigmaRef = t.useRef(null);
7659
+ const layoutControlRef = t.useRef(null);
7571
7660
  const [optimizeTick, setOptimizeTick] = t.useState(0);
7572
7661
  const internalCommunityData = useHighlights.useCommunities(nodes, links, layoutConfig);
7573
7662
  const communityData = communityDataProp ?? internalCommunityData;
@@ -7679,17 +7768,18 @@ const GraphCanvas = t.memo(
7679
7768
  },
7680
7769
  renderEdgeLabels: false,
7681
7770
  enableEdgeEvents: !isLargeGraph,
7682
- labelRenderedSizeThreshold: LABEL_RENDERED_SIZE_THRESHOLD,
7771
+ labelRenderedSizeThreshold: labelsVisible ? LABEL_RENDERED_SIZE_THRESHOLD : Infinity,
7683
7772
  labelFont: LABEL_FONT,
7684
7773
  labelColor: { color: LABEL_COLOR },
7685
7774
  labelSize: LABEL_SIZE,
7686
- defaultDrawNodeLabel: drawNodeLabel,
7775
+ defaultDrawNodeLabel: labelsVisible ? drawNodeLabel : () => {
7776
+ },
7687
7777
  defaultDrawNodeHover: drawNodeHover,
7688
7778
  allowInvalidContainer: true,
7689
7779
  zIndex: zIndexEnabled,
7690
7780
  zoomToSizeRatioFunction: (ratio) => Math.pow(ratio, ZOOM_SIZE_EXPONENT)
7691
7781
  }),
7692
- [isLargeGraph, zIndexEnabled]
7782
+ [isLargeGraph, zIndexEnabled, labelsVisible]
7693
7783
  );
7694
7784
  const edgeReducer = t.useCallback(
7695
7785
  (_edge, data) => {
@@ -7699,6 +7789,9 @@ const GraphCanvas = t.memo(
7699
7789
  },
7700
7790
  []
7701
7791
  );
7792
+ const handleLayoutControl = t.useCallback((control) => {
7793
+ layoutControlRef.current = control;
7794
+ }, []);
7702
7795
  const handleSigmaReady = t.useCallback(
7703
7796
  (sigma) => {
7704
7797
  sigmaRef.current = sigma;
@@ -7786,6 +7879,15 @@ const GraphCanvas = t.memo(
7786
7879
  const camera = sigmaRef.current.getCamera();
7787
7880
  camera.animatedReset({ duration });
7788
7881
  }
7882
+ },
7883
+ stopPhysics: () => {
7884
+ layoutControlRef.current?.stop();
7885
+ },
7886
+ startPhysics: () => {
7887
+ layoutControlRef.current?.start();
7888
+ },
7889
+ isPhysicsRunning: () => {
7890
+ return layoutControlRef.current?.isRunning() ?? false;
7789
7891
  }
7790
7892
  }),
7791
7893
  [nodes, links, hops, onNodeClick]
@@ -7849,7 +7951,8 @@ const GraphCanvas = t.memo(
7849
7951
  layoutReady,
7850
7952
  layoutConfig,
7851
7953
  optimizeTick,
7852
- onOptimizeStatus
7954
+ onOptimizeStatus,
7955
+ onLayoutControl: handleLayoutControl
7853
7956
  }
7854
7957
  ),
7855
7958
  /* @__PURE__ */ jsxRuntime.jsx(