@krainovsd/graph 0.8.4 → 0.9.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.
@@ -1,9 +1,10 @@
1
- import { isBoolean, isArray } from '@krainovsd/js-helpers';
1
+ import { isBoolean, isArray, isObject } from '@krainovsd/js-helpers';
2
2
  import { greatest } from 'd3-array';
3
3
  import { drag } from 'd3-drag';
4
4
  import { forceLink, forceSimulation, forceX, forceY, forceManyBody, forceCenter, forceCollide } from 'd3-force';
5
5
  import { create, select } from 'd3-selection';
6
6
  import { zoomIdentity, zoom, ZoomTransform } from 'd3-zoom';
7
+ import { checkType } from '../../lib/check-type.js';
7
8
  import { colorToRgb } from '../../lib/color-to-rgb.js';
8
9
  import { extractRgb } from '../../lib/extract-rgb.js';
9
10
  import { fadeRgb } from '../../lib/fade-rgb.js';
@@ -22,6 +23,7 @@ import { calculateLinkPositionByRadius } from './lib/utils/calculate-link-positi
22
23
  import { animationByProgress } from './lib/utils/animation-by-progress.js';
23
24
  import { isNodeVisible } from './lib/utils/is-node-visible.js';
24
25
  import { getParticlePosition } from './lib/utils/get-particle-position.js';
26
+ import { linkByPointerGetter } from './lib/utils/link-by-pointer-getter.js';
25
27
  import { getDrawTime, setDrawTime } from '../../lib/draw-time.js';
26
28
 
27
29
  class GraphCanvas {
@@ -52,6 +54,7 @@ class GraphCanvas {
52
54
  nodeOptionsCache = {};
53
55
  isDragging = false;
54
56
  highlightedNode = null;
57
+ highlightedLink = null;
55
58
  highlightedNeighbors = null;
56
59
  highlightProgress = 1;
57
60
  highlightWorking = false;
@@ -73,6 +76,7 @@ class GraphCanvas {
73
76
  highlightDrawing: this.highlightDrawing,
74
77
  highlightedNeighbors: this.highlightedNeighbors,
75
78
  highlightedNode: this.highlightedNode,
79
+ highlightedLink: this.highlightedLink,
76
80
  highlightWorking: this.highlightWorking,
77
81
  isDragging: this.isDragging,
78
82
  simulation: this.simulation,
@@ -203,6 +207,7 @@ class GraphCanvas {
203
207
  clearState() {
204
208
  this.isDragging = false;
205
209
  this.highlightedNode = null;
210
+ this.highlightedLink = null;
206
211
  this.highlightedNeighbors = null;
207
212
  this.highlightProgress = 0;
208
213
  this.highlightWorking = false;
@@ -363,9 +368,10 @@ class GraphCanvas {
363
368
  return void requestAnimationFrame(() => this.draw());
364
369
  }
365
370
  if (!this.highlightWorking && this.highlightProgress <= 0) {
366
- if (this.highlightedNeighbors || this.highlightedNode) {
371
+ if (this.highlightedNeighbors || this.highlightedNode || this.highlightedLink) {
367
372
  this.highlightedNeighbors = null;
368
373
  this.highlightedNode = null;
374
+ this.highlightedLink = null;
369
375
  this.particles = {};
370
376
  if (!this.simulationWorking)
371
377
  return void requestAnimationFrame(() => this.draw());
@@ -385,6 +391,8 @@ class GraphCanvas {
385
391
  this.highlightedNeighbors = null;
386
392
  if (this.highlightedNode)
387
393
  this.highlightedNode = null;
394
+ if (this.highlightedLink)
395
+ this.highlightedLink = null;
388
396
  });
389
397
  return;
390
398
  }
@@ -433,21 +441,49 @@ class GraphCanvas {
433
441
  }
434
442
  let alpha = linkOptions.alpha;
435
443
  let arrowAlpha = linkOptions.arrowReverseAppear ? 0 : linkOptions.arrowAlpha;
444
+ /** NODE HIGHLIGHT */
436
445
  if (this.highlightedNeighbors && this.highlightedNode) {
437
446
  /** Not highlighted */
438
447
  if (this.highlightedNode.id != link.source.id &&
439
448
  this.highlightedNode.id != link.target.id) {
440
- if (linkOptions.highlightFading) {
441
- const min = this.graphSettings.highlightLinkFadingMin < alpha
442
- ? this.graphSettings.highlightLinkFadingMin
449
+ if (linkOptions.highlightByNodeLinkFading) {
450
+ const min = this.graphSettings.highlightByNodeLinkFadingMin < alpha
451
+ ? this.graphSettings.highlightByNodeLinkFadingMin
443
452
  : alpha;
444
453
  alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
445
454
  }
446
455
  if (linkOptions.arrow &&
447
- linkOptions.arrowHighlightFading &&
456
+ linkOptions.highlightByNodeArrowFading &&
448
457
  !linkOptions.arrowReverseAppear) {
449
- const min = this.graphSettings.highlightArrowFadingMin < arrowAlpha
450
- ? this.graphSettings.highlightArrowFadingMin
458
+ const min = this.graphSettings.highlightByNodeArrowFadingMin < arrowAlpha
459
+ ? this.graphSettings.highlightByNodeArrowFadingMin
460
+ : arrowAlpha;
461
+ arrowAlpha = animationByProgress(min, arrowAlpha - min, 1 - this.highlightProgress);
462
+ }
463
+ }
464
+ else {
465
+ // eslint-disable-next-line no-lonely-if
466
+ if (linkOptions.arrow && linkOptions.arrowReverseAppear) {
467
+ /** Highlighted */
468
+ arrowAlpha = animationByProgress(0, linkOptions.arrowAlpha, this.highlightProgress);
469
+ }
470
+ }
471
+ }
472
+ /** LINK HIGHLIGHT */
473
+ if (this.highlightedNeighbors && this.highlightedLink) {
474
+ /** Not highlighted */
475
+ if (this.highlightedLink !== link) {
476
+ if (linkOptions.highlightByLinkLinkFading) {
477
+ const min = this.graphSettings.highlightByLinkLinkFadingMin < alpha
478
+ ? this.graphSettings.highlightByLinkLinkFadingMin
479
+ : alpha;
480
+ alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
481
+ }
482
+ if (linkOptions.arrow &&
483
+ linkOptions.highlightByLinkArrowFading &&
484
+ !linkOptions.arrowReverseAppear) {
485
+ const min = this.graphSettings.highlightByLinkArrowFadingMin < arrowAlpha
486
+ ? this.graphSettings.highlightByLinkArrowFadingMin
451
487
  : arrowAlpha;
452
488
  arrowAlpha = animationByProgress(min, arrowAlpha - min, 1 - this.highlightProgress);
453
489
  }
@@ -487,8 +523,10 @@ class GraphCanvas {
487
523
  this.context.stroke();
488
524
  /** Particle */
489
525
  if (this.linkSettings.particles &&
490
- this.highlightedNode &&
491
- (this.highlightedNode.id === link.source.id || this.highlightedNode.id === link.target.id)) {
526
+ ((this.highlightedNode &&
527
+ (this.highlightedNode.id === link.source.id ||
528
+ this.highlightedNode.id === link.target.id)) ||
529
+ (this.highlightedLink && this.highlightedLink === link))) {
492
530
  if (!this.particles[id]) {
493
531
  const sourceId = link.source.id;
494
532
  const targetId = link.target.id;
@@ -577,42 +615,84 @@ class GraphCanvas {
577
615
  let textShiftY = nodeOptions.textShiftY;
578
616
  let textWeight = nodeOptions.textWeight;
579
617
  let textWidth = nodeOptions.textWidth;
618
+ /** Node Highlight */
580
619
  if (this.highlightedNeighbors && this.highlightedNode) {
581
620
  /** Not highlighted */
582
621
  if (!this.highlightedNeighbors.has(node.id) && this.highlightedNode.id != node.id) {
583
- if (nodeOptions.highlightFading) {
584
- const min = this.graphSettings.highlightFadingMin < alpha
585
- ? this.graphSettings.highlightFadingMin
622
+ if (nodeOptions.highlightByNodeNodeFading) {
623
+ const min = this.graphSettings.highlightByNodeNodeFadingMin < alpha
624
+ ? this.graphSettings.highlightByNodeNodeFadingMin
625
+ : alpha;
626
+ alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
627
+ }
628
+ if (nodeOptions.highlightByNodeTextFading) {
629
+ const min = this.graphSettings.highlightByNodeTextFadingMin < textAlpha
630
+ ? this.graphSettings.highlightByNodeTextFadingMin
631
+ : textAlpha;
632
+ textAlpha = animationByProgress(min, textAlpha - min, 1 - this.highlightProgress);
633
+ }
634
+ if (nodeOptions.highlightByNodeNodeColor) {
635
+ const colorRgb = extractRgb(colorToRgb(color));
636
+ if (colorRgb) {
637
+ const colorRgbFade = fadeRgb(colorRgb, this.graphSettings.highlightByNodeNodeColorFadingMin);
638
+ const colorFadeAnimation = rgbAnimationByProgress(colorRgb, colorRgbFade, this.highlightProgress);
639
+ color = `rgb(${colorFadeAnimation.r}, ${colorFadeAnimation.g}, ${colorFadeAnimation.b})`;
640
+ }
641
+ }
642
+ }
643
+ else if (!this.graphSettings.highlightByNodeOnlyRoot ||
644
+ (this.graphSettings.highlightByNodeOnlyRoot && this.highlightedNode.id === node.id)) {
645
+ /** Highlighted */
646
+ if (nodeOptions.highlightByNodeNodeSizing) {
647
+ radiusInitial = animationByProgress(radiusInitial, this.graphSettings.highlightByNodeNodeSizingAdditional, this.highlightProgress);
648
+ }
649
+ if (nodeOptions.highlightByNodeTextSizing) {
650
+ textSize = animationByProgress(textSize, this.graphSettings.highlightByNodeTextSizingAdditional, this.highlightProgress);
651
+ textShiftX = animationByProgress(textShiftX, this.graphSettings.highlightByNodeTextShiftXAdditional, this.highlightProgress);
652
+ textShiftY = animationByProgress(textShiftY, this.graphSettings.highlightByNodeTextShiftYAdditional, this.highlightProgress);
653
+ textWeight = animationByProgress(textWeight, this.graphSettings.highlightByNodeTextWeightAdditional, this.highlightProgress);
654
+ textWidth = animationByProgress(textWidth, this.graphSettings.highlightByNodeTextWidthAdditional, this.highlightProgress);
655
+ }
656
+ }
657
+ }
658
+ /** LinkHighlight */
659
+ if (this.highlightedNeighbors && this.highlightedLink) {
660
+ /** Not highlighted */
661
+ if (!this.highlightedNeighbors.has(node.id) &&
662
+ this.highlightedLink.source !== node &&
663
+ this.highlightedLink.target !== node) {
664
+ if (nodeOptions.highlightByLinkNodeFading) {
665
+ const min = this.graphSettings.highlightByLinkNodeFadingMin < alpha
666
+ ? this.graphSettings.highlightByLinkNodeFadingMin
586
667
  : alpha;
587
668
  alpha = animationByProgress(min, alpha - min, 1 - this.highlightProgress);
588
669
  }
589
- if (nodeOptions.highlightTextFading) {
590
- const min = this.graphSettings.highlightTextFadingMin < textAlpha
591
- ? this.graphSettings.highlightTextFadingMin
670
+ if (nodeOptions.highlightByLinkTextFading) {
671
+ const min = this.graphSettings.highlightByLinkTextFadingMin < textAlpha
672
+ ? this.graphSettings.highlightByLinkTextFadingMin
592
673
  : textAlpha;
593
674
  textAlpha = animationByProgress(min, textAlpha - min, 1 - this.highlightProgress);
594
675
  }
595
- if (nodeOptions.highlightColor) {
676
+ if (nodeOptions.highlightByLinkNodeColor) {
596
677
  const colorRgb = extractRgb(colorToRgb(color));
597
678
  if (colorRgb) {
598
- const colorRgbFade = fadeRgb(colorRgb, this.graphSettings.highlightColorFadingMin);
679
+ const colorRgbFade = fadeRgb(colorRgb, this.graphSettings.highlightByLinkNodeColorFadingMin);
599
680
  const colorFadeAnimation = rgbAnimationByProgress(colorRgb, colorRgbFade, this.highlightProgress);
600
681
  color = `rgb(${colorFadeAnimation.r}, ${colorFadeAnimation.g}, ${colorFadeAnimation.b})`;
601
682
  }
602
683
  }
603
684
  }
604
- else if (!this.graphSettings.highlightOnlyRoot ||
605
- (this.graphSettings.highlightOnlyRoot && this.highlightedNode.id === node.id)) {
685
+ else {
606
686
  /** Highlighted */
607
- if (nodeOptions.highlightSizing) {
608
- radiusInitial = animationByProgress(radiusInitial, this.graphSettings.highlightSizingAdditional, this.highlightProgress);
687
+ if (nodeOptions.highlightByLinkNodeSizing) {
688
+ radiusInitial = animationByProgress(radiusInitial, this.graphSettings.highlightByLinkNodeSizingAdditional, this.highlightProgress);
609
689
  }
610
- if (nodeOptions.highlightTextSizing) {
611
- textSize = animationByProgress(textSize, this.graphSettings.highlightTextSizingAdditional, this.highlightProgress);
612
- textShiftX = animationByProgress(textShiftX, this.graphSettings.highlightTextShiftXAdditional, this.highlightProgress);
613
- textShiftY = animationByProgress(textShiftY, this.graphSettings.highlightTextShiftYAdditional, this.highlightProgress);
614
- textWeight = animationByProgress(textWeight, this.graphSettings.highlightTextWeightAdditional, this.highlightProgress);
615
- textWidth = animationByProgress(textWidth, this.graphSettings.highlightTextWidthAdditional, this.highlightProgress);
690
+ if (nodeOptions.highlightByLinkTextSizing) {
691
+ textSize = animationByProgress(textSize, this.graphSettings.highlightByLinkTextSizingAdditional, this.highlightProgress);
692
+ textShiftX = animationByProgress(textShiftX, this.graphSettings.highlightByLinkTextShiftXAdditional, this.highlightProgress);
693
+ textShiftY = animationByProgress(textShiftY, this.graphSettings.highlightByLinkTextShiftYAdditional, this.highlightProgress);
694
+ textWeight = animationByProgress(textWeight, this.graphSettings.highlightByLinkTextWeightAdditional, this.highlightProgress);
695
+ textWidth = animationByProgress(textWidth, this.graphSettings.highlightByLinkTextWidthAdditional, this.highlightProgress);
616
696
  }
617
697
  }
618
698
  }
@@ -754,10 +834,14 @@ class GraphCanvas {
754
834
  initPointer() {
755
835
  if (!this.area || !this.nodes || !this.simulation)
756
836
  throw new Error("bad init data");
757
- /** hover */
758
- this.area.addEventListener("pointermove", (event) => {
837
+ function onHover(event) {
838
+ if (!this.area)
839
+ return;
759
840
  let currentNode;
760
- if (this.graphSettings.highlightByHover && !this.isDragging) {
841
+ let currentLink;
842
+ const checkHighlightNode = this.graphSettings.highlightByHoverNode && !this.isDragging;
843
+ const checkHighlightLink = this.graphSettings.highlightByHoverLink && !this.isDragging;
844
+ if (checkHighlightNode) {
761
845
  currentNode = nodeByPointerGetter({
762
846
  graphSettings: this.graphSettings,
763
847
  areaRect: this.areaRect,
@@ -765,26 +849,61 @@ class GraphCanvas {
765
849
  mouseEvent: event,
766
850
  nodes: this.nodes,
767
851
  });
768
- if (currentNode && this.highlightedNode !== currentNode) {
769
- this.highlightedNode = currentNode;
770
- this.highlightedNeighbors = new Set(this.highlightedNode?.neighbors ?? []);
771
- this.highlightWorking = true;
772
- if (!this.simulationWorking && !this.highlightDrawing)
773
- requestAnimationFrame(() => {
774
- this.draw();
775
- });
852
+ }
853
+ if (currentNode) {
854
+ this.area.style.cursor = "pointer";
855
+ }
856
+ else if (checkHighlightLink) {
857
+ currentLink = linkByPointerGetter({
858
+ graphSettings: this.graphSettings,
859
+ areaRect: this.areaRect,
860
+ areaTransform: this.areaTransform,
861
+ mouseEvent: event,
862
+ links: this.links,
863
+ });
864
+ if (currentLink) {
865
+ this.area.style.cursor = "pointer";
776
866
  }
777
- else if (!currentNode && this.highlightedNode) {
778
- this.highlightWorking = false;
779
- if (!this.simulationWorking && !this.highlightDrawing)
780
- requestAnimationFrame(() => {
781
- this.draw();
782
- });
867
+ else {
868
+ this.area.style.cursor = "default";
783
869
  }
784
870
  }
871
+ else {
872
+ this.area.style.cursor = "default";
873
+ }
874
+ if (currentNode && this.highlightedNode !== currentNode) {
875
+ this.highlightedNode = currentNode;
876
+ this.highlightedLink = null;
877
+ this.highlightedNeighbors = new Set(this.highlightedNode?.neighbors ?? []);
878
+ this.highlightWorking = true;
879
+ if (!this.simulationWorking && !this.highlightDrawing)
880
+ requestAnimationFrame(() => {
881
+ this.draw();
882
+ });
883
+ }
884
+ else if (currentLink &&
885
+ checkType(currentLink.source, isObject(currentLink.source)) &&
886
+ checkType(currentLink.target, isObject(currentLink.target)) &&
887
+ this.highlightedLink !== currentLink) {
888
+ this.highlightedLink = currentLink;
889
+ this.highlightedNode = null;
890
+ this.highlightedNeighbors = new Set([currentLink.source.id, currentLink.target.id]);
891
+ this.highlightWorking = true;
892
+ if (!this.simulationWorking && !this.highlightDrawing)
893
+ requestAnimationFrame(() => {
894
+ this.draw();
895
+ });
896
+ }
897
+ else if (!currentNode && !currentLink && (this.highlightedNode || this.highlightedLink)) {
898
+ this.highlightWorking = false;
899
+ if (!this.simulationWorking && !this.highlightDrawing)
900
+ requestAnimationFrame(() => {
901
+ this.draw();
902
+ });
903
+ }
785
904
  if (!this.listeners.onMove)
786
905
  return;
787
- if (!currentNode)
906
+ if (!currentNode && !checkHighlightNode)
788
907
  currentNode = nodeByPointerGetter({
789
908
  graphSettings: this.graphSettings,
790
909
  areaRect: this.areaRect,
@@ -792,13 +911,23 @@ class GraphCanvas {
792
911
  mouseEvent: event,
793
912
  nodes: this.nodes,
794
913
  });
795
- return void this.listeners.onMove(event, currentNode);
796
- }, {
797
- signal: this.eventAbortController.signal,
798
- });
799
- /** dblclick */
800
- this.area.addEventListener("dblclick", (event) => {
801
- if (!this.listeners.onDoubleClick)
914
+ if (!currentNode && (!checkHighlightNode || (!checkHighlightLink && !currentLink))) {
915
+ currentLink = linkByPointerGetter({
916
+ graphSettings: this.graphSettings,
917
+ areaRect: this.areaRect,
918
+ areaTransform: this.areaTransform,
919
+ mouseEvent: event,
920
+ links: this.links,
921
+ });
922
+ }
923
+ if (!currentNode)
924
+ return void this.listeners.onMove(event, currentNode, currentLink);
925
+ }
926
+ function onWheelClick(event) {
927
+ if (this.isDragging ||
928
+ !this.listeners.onWheelClick ||
929
+ !("button" in event) ||
930
+ event.button !== 1)
802
931
  return;
803
932
  const currentNode = nodeByPointerGetter({
804
933
  graphSettings: this.graphSettings,
@@ -807,11 +936,20 @@ class GraphCanvas {
807
936
  mouseEvent: event,
808
937
  nodes: this.nodes,
809
938
  });
810
- return void this.listeners.onDoubleClick(event, currentNode);
811
- });
812
- /** wheel click */
813
- this.area.addEventListener("mousedown", (event) => {
814
- if (this.isDragging || !this.listeners.onWheelClick || event.button !== 1)
939
+ if (!currentNode) {
940
+ const currentLink = linkByPointerGetter({
941
+ graphSettings: this.graphSettings,
942
+ areaRect: this.areaRect,
943
+ areaTransform: this.areaTransform,
944
+ mouseEvent: event,
945
+ links: this.links,
946
+ });
947
+ return void this.listeners.onWheelClick(event, undefined, currentLink);
948
+ }
949
+ return void this.listeners.onWheelClick(event, currentNode, undefined);
950
+ }
951
+ function onRightClick(event) {
952
+ if (!this.listeners.onContextMenu)
815
953
  return;
816
954
  const currentNode = nodeByPointerGetter({
817
955
  graphSettings: this.graphSettings,
@@ -820,13 +958,20 @@ class GraphCanvas {
820
958
  mouseEvent: event,
821
959
  nodes: this.nodes,
822
960
  });
823
- return void this.listeners.onWheelClick(event, currentNode);
824
- }, {
825
- signal: this.eventAbortController.signal,
826
- });
827
- /** click */
828
- this.area.addEventListener("click", (event) => {
829
- if (this.isDragging || !this.listeners.onClick || event.button !== 0)
961
+ if (!currentNode) {
962
+ const currentLink = linkByPointerGetter({
963
+ graphSettings: this.graphSettings,
964
+ areaRect: this.areaRect,
965
+ areaTransform: this.areaTransform,
966
+ mouseEvent: event,
967
+ links: this.links,
968
+ });
969
+ return void this.listeners.onContextMenu(event, undefined, currentLink);
970
+ }
971
+ return void this.listeners.onContextMenu(event, currentNode, undefined);
972
+ }
973
+ function onDoubleClick(event) {
974
+ if (!this.listeners.onDoubleClick)
830
975
  return;
831
976
  const currentNode = nodeByPointerGetter({
832
977
  graphSettings: this.graphSettings,
@@ -835,13 +980,20 @@ class GraphCanvas {
835
980
  mouseEvent: event,
836
981
  nodes: this.nodes,
837
982
  });
838
- return void this.listeners.onClick(event, currentNode);
839
- }, {
840
- signal: this.eventAbortController.signal,
841
- });
842
- /** right click */
843
- this.area.addEventListener("contextmenu", (event) => {
844
- if (!this.listeners.onContextMenu)
983
+ if (!currentNode) {
984
+ const currentLink = linkByPointerGetter({
985
+ graphSettings: this.graphSettings,
986
+ areaRect: this.areaRect,
987
+ areaTransform: this.areaTransform,
988
+ mouseEvent: event,
989
+ links: this.links,
990
+ });
991
+ return void this.listeners.onDoubleClick(event, undefined, currentLink);
992
+ }
993
+ return void this.listeners.onDoubleClick(event, currentNode, undefined);
994
+ }
995
+ function onClick(event) {
996
+ if (this.isDragging || !this.listeners.onClick || ("button" in event && event.button !== 0))
845
997
  return;
846
998
  const currentNode = nodeByPointerGetter({
847
999
  graphSettings: this.graphSettings,
@@ -850,15 +1002,46 @@ class GraphCanvas {
850
1002
  mouseEvent: event,
851
1003
  nodes: this.nodes,
852
1004
  });
853
- return void this.listeners.onContextMenu(event, currentNode);
854
- }, {
1005
+ if (!currentNode) {
1006
+ const currentLink = linkByPointerGetter({
1007
+ graphSettings: this.graphSettings,
1008
+ areaRect: this.areaRect,
1009
+ areaTransform: this.areaTransform,
1010
+ mouseEvent: event,
1011
+ links: this.links,
1012
+ });
1013
+ return void this.listeners.onClick(event, undefined, currentLink);
1014
+ }
1015
+ return void this.listeners.onClick(event, currentNode, undefined);
1016
+ }
1017
+ /** hover */
1018
+ this.area.addEventListener("mousemove", onHover.bind(this), {
1019
+ signal: this.eventAbortController.signal,
1020
+ });
1021
+ this.area.addEventListener("touchmove", onHover.bind(this), {
1022
+ signal: this.eventAbortController.signal,
1023
+ });
1024
+ /** dblclick */
1025
+ this.area.addEventListener("dblclick", onDoubleClick.bind(this), {
1026
+ signal: this.eventAbortController.signal,
1027
+ });
1028
+ /** wheel click */
1029
+ this.area.addEventListener("mousedown", onWheelClick.bind(this), {
1030
+ signal: this.eventAbortController.signal,
1031
+ });
1032
+ /** click */
1033
+ this.area.addEventListener("click", onClick.bind(this), {
1034
+ signal: this.eventAbortController.signal,
1035
+ });
1036
+ /** right click */
1037
+ this.area.addEventListener("contextmenu", onRightClick.bind(this), {
855
1038
  signal: this.eventAbortController.signal,
856
1039
  });
857
1040
  }
858
1041
  initDnd() {
859
1042
  if (!this.area || !this.nodes || !this.simulation)
860
1043
  throw new Error("bad init data");
861
- select(this.area).call(drag()
1044
+ const dragHandler = drag()
862
1045
  .subject((event) => {
863
1046
  if (this.listeners.onDragSubject) {
864
1047
  return this.listeners.onDragSubject(event, this.state);
@@ -920,7 +1103,8 @@ class GraphCanvas {
920
1103
  event.subject.fy = null;
921
1104
  }
922
1105
  this.listeners.onEndDragFinished?.(event, this.state);
923
- }));
1106
+ });
1107
+ select(this.area).call(dragHandler);
924
1108
  }
925
1109
  initZoom(currentZoom) {
926
1110
  if (!this.area)