@deck.gl-community/graph-layers 9.2.0-beta.2 → 9.2.0-beta.3

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 (232) hide show
  1. package/dist/core/graph-engine.d.ts +63 -21
  2. package/dist/core/graph-engine.d.ts.map +1 -1
  3. package/dist/core/graph-engine.js +155 -75
  4. package/dist/core/graph-engine.js.map +1 -1
  5. package/dist/core/graph-layout.d.ts +22 -18
  6. package/dist/core/graph-layout.d.ts.map +1 -1
  7. package/dist/core/graph-layout.js +33 -18
  8. package/dist/core/graph-layout.js.map +1 -1
  9. package/dist/core/interaction-manager.d.ts +2 -2
  10. package/dist/core/interaction-manager.d.ts.map +1 -1
  11. package/dist/core/interaction-manager.js +7 -5
  12. package/dist/core/interaction-manager.js.map +1 -1
  13. package/dist/graph/arrow-graph.d.ts +69 -0
  14. package/dist/graph/arrow-graph.d.ts.map +1 -0
  15. package/dist/graph/arrow-graph.js +513 -0
  16. package/dist/graph/arrow-graph.js.map +1 -0
  17. package/dist/graph/classic-graph.d.ts +169 -0
  18. package/dist/graph/classic-graph.d.ts.map +1 -0
  19. package/dist/graph/classic-graph.js +390 -0
  20. package/dist/graph/classic-graph.js.map +1 -0
  21. package/dist/graph/edge.d.ts +6 -6
  22. package/dist/graph/edge.d.ts.map +1 -1
  23. package/dist/graph/edge.js.map +1 -1
  24. package/dist/graph/functions/arrow-utils.d.ts +6 -0
  25. package/dist/graph/functions/arrow-utils.d.ts.map +1 -0
  26. package/dist/graph/functions/arrow-utils.js +67 -0
  27. package/dist/graph/functions/arrow-utils.js.map +1 -0
  28. package/dist/graph/functions/create-graph-from-data.d.ts +3 -0
  29. package/dist/graph/functions/create-graph-from-data.d.ts.map +1 -0
  30. package/dist/graph/functions/create-graph-from-data.js +12 -0
  31. package/dist/graph/functions/create-graph-from-data.js.map +1 -0
  32. package/dist/graph/graph-normalization.d.ts +10 -0
  33. package/dist/graph/graph-normalization.d.ts.map +1 -0
  34. package/dist/graph/graph-normalization.js +65 -0
  35. package/dist/graph/graph-normalization.js.map +1 -0
  36. package/dist/graph/graph.d.ts +62 -155
  37. package/dist/graph/graph.d.ts.map +1 -1
  38. package/dist/graph/graph.js +11 -300
  39. package/dist/graph/graph.js.map +1 -1
  40. package/dist/graph/node.d.ts +6 -6
  41. package/dist/graph/node.d.ts.map +1 -1
  42. package/dist/graph/node.js +2 -2
  43. package/dist/graph/node.js.map +1 -1
  44. package/dist/graph-data/arrow-graph-data-builder.d.ts +21 -0
  45. package/dist/graph-data/arrow-graph-data-builder.d.ts.map +1 -0
  46. package/dist/graph-data/arrow-graph-data-builder.js +105 -0
  47. package/dist/graph-data/arrow-graph-data-builder.js.map +1 -0
  48. package/dist/graph-data/graph-data-builder.d.ts +6 -0
  49. package/dist/graph-data/graph-data-builder.d.ts.map +1 -0
  50. package/dist/graph-data/graph-data-builder.js +1 -0
  51. package/dist/graph-data/graph-data-builder.js.map +1 -0
  52. package/dist/graph-data/graph-data.d.ts +40 -0
  53. package/dist/graph-data/graph-data.d.ts.map +1 -0
  54. package/dist/graph-data/graph-data.js +11 -0
  55. package/dist/graph-data/graph-data.js.map +1 -0
  56. package/dist/graph-data/plain-graph-data-builder.d.ts +20 -0
  57. package/dist/graph-data/plain-graph-data-builder.d.ts.map +1 -0
  58. package/dist/graph-data/plain-graph-data-builder.js +105 -0
  59. package/dist/graph-data/plain-graph-data-builder.js.map +1 -0
  60. package/dist/graph-style-schema.cdn.js +1 -1
  61. package/dist/graph-style-schema.json +1 -1
  62. package/dist/index.cjs +6905 -4576
  63. package/dist/index.cjs.map +4 -4
  64. package/dist/index.d.ts +14 -7
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +24 -11
  67. package/dist/index.js.map +1 -1
  68. package/dist/layers/common-layers/flow-path-layer/flow-path-layer.d.ts.map +1 -1
  69. package/dist/layers/common-layers/flow-path-layer/flow-path-layer.js +1 -2
  70. package/dist/layers/common-layers/flow-path-layer/flow-path-layer.js.map +1 -1
  71. package/dist/layers/common-layers/grid-layer/grid-layer.d.ts +83 -0
  72. package/dist/layers/common-layers/grid-layer/grid-layer.d.ts.map +1 -0
  73. package/dist/layers/common-layers/grid-layer/grid-layer.js +133 -0
  74. package/dist/layers/common-layers/grid-layer/grid-layer.js.map +1 -0
  75. package/dist/layers/edge-attachment-helper.d.ts.map +1 -1
  76. package/dist/layers/edge-attachment-helper.js +1 -2
  77. package/dist/layers/edge-attachment-helper.js.map +1 -1
  78. package/dist/layers/graph-layer.d.ts +68 -11
  79. package/dist/layers/graph-layer.d.ts.map +1 -1
  80. package/dist/layers/graph-layer.js +435 -50
  81. package/dist/layers/graph-layer.js.map +1 -1
  82. package/dist/layouts/d3-dag/collapsable-d3-dag-layout.d.ts +24 -0
  83. package/dist/layouts/d3-dag/collapsable-d3-dag-layout.d.ts.map +1 -0
  84. package/dist/layouts/d3-dag/collapsable-d3-dag-layout.js +251 -0
  85. package/dist/layouts/d3-dag/collapsable-d3-dag-layout.js.map +1 -0
  86. package/dist/layouts/d3-dag/d3-dag-layout.d.ts +46 -61
  87. package/dist/layouts/d3-dag/d3-dag-layout.d.ts.map +1 -1
  88. package/dist/layouts/d3-dag/d3-dag-layout.js +85 -270
  89. package/dist/layouts/d3-dag/d3-dag-layout.js.map +1 -1
  90. package/dist/layouts/d3-force/d3-force-layout.d.ts +20 -8
  91. package/dist/layouts/d3-force/d3-force-layout.d.ts.map +1 -1
  92. package/dist/layouts/d3-force/d3-force-layout.js +39 -20
  93. package/dist/layouts/d3-force/d3-force-layout.js.map +1 -1
  94. package/dist/layouts/experimental/force-multi-graph-layout.d.ts +19 -15
  95. package/dist/layouts/experimental/force-multi-graph-layout.d.ts.map +1 -1
  96. package/dist/layouts/experimental/force-multi-graph-layout.js +47 -38
  97. package/dist/layouts/experimental/force-multi-graph-layout.js.map +1 -1
  98. package/dist/layouts/experimental/hive-plot-layout.d.ts +18 -15
  99. package/dist/layouts/experimental/hive-plot-layout.d.ts.map +1 -1
  100. package/dist/layouts/experimental/hive-plot-layout.js +33 -34
  101. package/dist/layouts/experimental/hive-plot-layout.js.map +1 -1
  102. package/dist/layouts/experimental/radial-layout.d.ts +12 -7
  103. package/dist/layouts/experimental/radial-layout.d.ts.map +1 -1
  104. package/dist/layouts/experimental/radial-layout.js +31 -14
  105. package/dist/layouts/experimental/radial-layout.js.map +1 -1
  106. package/dist/layouts/gpu-force/gpu-force-layout.d.ts +11 -8
  107. package/dist/layouts/gpu-force/gpu-force-layout.d.ts.map +1 -1
  108. package/dist/layouts/gpu-force/gpu-force-layout.js +59 -56
  109. package/dist/layouts/gpu-force/gpu-force-layout.js.map +1 -1
  110. package/dist/layouts/simple-layout.d.ts +8 -25
  111. package/dist/layouts/simple-layout.d.ts.map +1 -1
  112. package/dist/layouts/simple-layout.js +13 -17
  113. package/dist/layouts/simple-layout.js.map +1 -1
  114. package/dist/loaders/dot-graph-loader.d.ts +25 -0
  115. package/dist/loaders/dot-graph-loader.d.ts.map +1 -0
  116. package/dist/loaders/dot-graph-loader.js +668 -0
  117. package/dist/loaders/dot-graph-loader.js.map +1 -0
  118. package/dist/loaders/json-graph-loader.d.ts +6 -0
  119. package/dist/loaders/json-graph-loader.d.ts.map +1 -0
  120. package/dist/loaders/json-graph-loader.js +31 -0
  121. package/dist/loaders/json-graph-loader.js.map +1 -0
  122. package/dist/loaders/{edge-parsers.d.ts → parsers/edge-parsers.d.ts} +1 -1
  123. package/dist/loaders/parsers/edge-parsers.d.ts.map +1 -0
  124. package/dist/loaders/{edge-parsers.js → parsers/edge-parsers.js} +1 -1
  125. package/dist/loaders/parsers/edge-parsers.js.map +1 -0
  126. package/dist/loaders/{node-parsers.d.ts → parsers/node-parsers.d.ts} +1 -1
  127. package/dist/loaders/parsers/node-parsers.d.ts.map +1 -0
  128. package/dist/loaders/{node-parsers.js → parsers/node-parsers.js} +1 -1
  129. package/dist/loaders/parsers/node-parsers.js.map +1 -0
  130. package/dist/loaders/parsers/parse-json-graph.d.ts +29 -0
  131. package/dist/loaders/parsers/parse-json-graph.d.ts.map +1 -0
  132. package/dist/loaders/parsers/parse-json-graph.js +78 -0
  133. package/dist/loaders/parsers/parse-json-graph.js.map +1 -0
  134. package/dist/style/graph-style-engine.d.ts +4 -2
  135. package/dist/style/graph-style-engine.d.ts.map +1 -1
  136. package/dist/style/graph-style-engine.js +3 -2
  137. package/dist/style/graph-style-engine.js.map +1 -1
  138. package/dist/style/{style-engine.d.ts → stylesheet-engine.d.ts} +3 -3
  139. package/dist/style/stylesheet-engine.d.ts.map +1 -0
  140. package/dist/style/{style-engine.js → stylesheet-engine.js} +1 -1
  141. package/dist/style/stylesheet-engine.js.map +1 -0
  142. package/dist/utils/collapsed-chains.d.ts +8 -8
  143. package/dist/utils/collapsed-chains.d.ts.map +1 -1
  144. package/dist/utils/collapsed-chains.js +1 -6
  145. package/dist/utils/collapsed-chains.js.map +1 -1
  146. package/dist/utils/rank-grid.d.ts +30 -0
  147. package/dist/utils/rank-grid.d.ts.map +1 -0
  148. package/dist/utils/rank-grid.js +306 -0
  149. package/dist/utils/rank-grid.js.map +1 -0
  150. package/package.json +4 -8
  151. package/src/_disabled/arrow-graph-data.ts.disabled +18 -0
  152. package/src/_disabled/columnar-graph-data-builder.ts.disabled +250 -0
  153. package/src/_disabled/graph-runtime-layout.ts.disabled +29 -0
  154. package/src/core/graph-engine.ts +201 -84
  155. package/src/core/graph-layout.ts +52 -29
  156. package/src/core/interaction-manager.ts +20 -20
  157. package/src/graph/arrow-graph.ts +648 -0
  158. package/src/graph/classic-graph.ts +447 -0
  159. package/src/graph/edge.ts +7 -7
  160. package/src/graph/functions/arrow-utils.ts +72 -0
  161. package/src/graph/functions/convert-arrow-graph-to-classic-graph.ts.disabled +47 -0
  162. package/src/graph/functions/convert-plain-graph-to-arrow-graph.ts.disabled +119 -0
  163. package/src/graph/functions/create-graph-from-data.ts +16 -0
  164. package/src/graph/functions/create-plain-graph-from-data.ts.disabled +176 -0
  165. package/src/graph/graph-normalization.ts +87 -0
  166. package/src/graph/graph.ts +68 -339
  167. package/src/graph/node.ts +9 -9
  168. package/src/graph/tabular-graph.ts.disabled +761 -0
  169. package/src/graph-data/arrow-graph-data-builder.ts +165 -0
  170. package/src/graph-data/graph-data-builder.ts +7 -0
  171. package/src/graph-data/graph-data.ts +57 -0
  172. package/src/graph-data/plain-graph-data-builder.ts +132 -0
  173. package/src/index.ts +53 -13
  174. package/src/layers/common-layers/flow-path-layer/flow-path-layer.ts +1 -2
  175. package/src/layers/common-layers/grid-layer/grid-layer.ts +237 -0
  176. package/src/layers/edge-attachment-helper.ts +22 -16
  177. package/src/layers/graph-layer.ts +642 -62
  178. package/src/layouts/d3-dag/collapsable-d3-dag-layout.ts +330 -0
  179. package/src/layouts/d3-dag/d3-dag-layout.ts +166 -396
  180. package/src/layouts/d3-force/d3-force-layout.ts +52 -30
  181. package/src/layouts/experimental/force-multi-graph-layout.ts +55 -49
  182. package/src/layouts/experimental/hive-plot-layout.ts +41 -42
  183. package/src/layouts/experimental/radial-layout.ts +39 -20
  184. package/src/layouts/gpu-force/gpu-force-layout.ts +72 -70
  185. package/src/layouts/simple-layout.ts +20 -44
  186. package/src/loaders/{create-graph.ts → deprecated/create-graph.ts.disabled} +6 -6
  187. package/src/loaders/deprecated/json-classic-graph-loader.ts.disabled +33 -0
  188. package/src/loaders/{simple-json-graph-loader.ts → deprecated/simple-json-graph-loader.ts.disabled} +3 -3
  189. package/src/loaders/{table-graph-loader.ts → deprecated/table-graph-loader.ts.disabled} +8 -8
  190. package/src/loaders/dot-graph-loader.ts +860 -0
  191. package/src/loaders/json-graph-loader.ts +48 -0
  192. package/src/loaders/parsers/create-graph-data.ts.disabled +45 -0
  193. package/src/loaders/{edge-parsers.ts → parsers/edge-parsers.ts} +2 -2
  194. package/src/loaders/{node-parsers.ts → parsers/node-parsers.ts} +2 -2
  195. package/src/loaders/parsers/parse-json-graph.ts +134 -0
  196. package/src/style/graph-style-engine.ts +5 -2
  197. package/src/style/{style-engine.ts → stylesheet-engine.ts} +3 -3
  198. package/src/utils/collapsed-chains.ts +11 -17
  199. package/src/utils/rank-grid.ts +426 -0
  200. package/dist/loaders/create-graph.d.ts +0 -12
  201. package/dist/loaders/create-graph.d.ts.map +0 -1
  202. package/dist/loaders/create-graph.js +0 -38
  203. package/dist/loaders/create-graph.js.map +0 -1
  204. package/dist/loaders/edge-parsers.d.ts.map +0 -1
  205. package/dist/loaders/edge-parsers.js.map +0 -1
  206. package/dist/loaders/json-loader.d.ts +0 -7
  207. package/dist/loaders/json-loader.d.ts.map +0 -1
  208. package/dist/loaders/json-loader.js +0 -16
  209. package/dist/loaders/json-loader.js.map +0 -1
  210. package/dist/loaders/node-parsers.d.ts.map +0 -1
  211. package/dist/loaders/node-parsers.js.map +0 -1
  212. package/dist/loaders/simple-json-graph-loader.d.ts +0 -11
  213. package/dist/loaders/simple-json-graph-loader.d.ts.map +0 -1
  214. package/dist/loaders/simple-json-graph-loader.js +0 -20
  215. package/dist/loaders/simple-json-graph-loader.js.map +0 -1
  216. package/dist/loaders/table-graph-loader.d.ts +0 -16
  217. package/dist/loaders/table-graph-loader.d.ts.map +0 -1
  218. package/dist/loaders/table-graph-loader.js +0 -91
  219. package/dist/loaders/table-graph-loader.js.map +0 -1
  220. package/dist/style/style-engine.d.ts.map +0 -1
  221. package/dist/style/style-engine.js.map +0 -1
  222. package/dist/widgets/long-press-button.d.ts +0 -12
  223. package/dist/widgets/long-press-button.d.ts.map +0 -1
  224. package/dist/widgets/long-press-button.js +0 -31
  225. package/dist/widgets/long-press-button.js.map +0 -1
  226. package/dist/widgets/view-control-widget.d.ts +0 -77
  227. package/dist/widgets/view-control-widget.d.ts.map +0 -1
  228. package/dist/widgets/view-control-widget.js +0 -197
  229. package/dist/widgets/view-control-widget.js.map +0 -1
  230. package/src/loaders/json-loader.ts +0 -19
  231. package/src/widgets/long-press-button.tsx +0 -50
  232. package/src/widgets/view-control-widget.tsx +0 -339
@@ -3,6 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {GraphLayout, GraphLayoutProps} from '../../core/graph-layout';
6
+ import type {Graph, NodeInterface, EdgeInterface} from '../../graph/graph';
6
7
  import {log} from '../../utils/log';
7
8
 
8
9
  export type D3ForceLayoutOptions = GraphLayoutProps & {
@@ -15,39 +16,38 @@ export type D3ForceLayoutOptions = GraphLayoutProps & {
15
16
  };
16
17
 
17
18
  export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
18
- static defaultProps: Required<D3ForceLayoutOptions> = {
19
+ static defaultProps = {
20
+ ...GraphLayout.defaultProps,
19
21
  alpha: 0.3,
20
22
  resumeAlpha: 0.1,
21
23
  nBodyStrength: -900,
22
24
  nBodyDistanceMin: 100,
23
25
  nBodyDistanceMax: 400,
24
26
  getCollisionRadius: 0
25
- };
27
+ } as const satisfies Readonly<Required<D3ForceLayoutOptions>>;
26
28
 
27
29
  protected readonly _name = 'D3';
28
- private _positionsByNodeId = new Map();
29
- private _graph: any;
30
- private _worker: any;
31
-
32
- constructor(options?: D3ForceLayoutOptions) {
33
- super(options);
30
+ private _positionsByNodeId = new Map<string | number, any>();
31
+ private _graph: Graph | null = null;
32
+ private _worker: Worker | null = null;
34
33
 
35
- this._options = {
36
- ...D3ForceLayout.defaultProps,
37
- ...options
38
- };
34
+ constructor(props?: D3ForceLayoutOptions) {
35
+ super(props, D3ForceLayout.defaultProps);
39
36
  }
40
37
 
41
- initializeGraph(graph) {
38
+ initializeGraph(graph: Graph) {
42
39
  this._graph = graph;
43
40
  }
44
41
 
45
42
  // for streaming new data on the same graph
46
- updateGraph(graph) {
43
+ updateGraph(graph: Graph) {
47
44
  this._graph = graph;
48
45
 
49
46
  this._positionsByNodeId = new Map(
50
- this._graph.getNodes().map((node) => [node.id, this._positionsByNodeId.get(node.id)])
47
+ Array.from(this._graph.getNodes(), (node) => {
48
+ const id = node.getId();
49
+ return [id, this._positionsByNodeId.get(id)];
50
+ })
51
51
  );
52
52
  }
53
53
 
@@ -69,17 +69,30 @@ export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
69
69
 
70
70
  this._worker = new Worker(new URL('./worker.js', import.meta.url).href);
71
71
 
72
+ if (!this._graph) {
73
+ return;
74
+ }
75
+
76
+ const options = {...this.props};
77
+ delete options.onLayoutStart;
78
+ delete options.onLayoutChange;
79
+ delete options.onLayoutDone;
80
+ delete options.onLayoutError;
81
+
72
82
  this._worker.postMessage({
73
- nodes: this._graph.getNodes().map((node) => ({
74
- id: node.id,
75
- ...this._positionsByNodeId.get(node.id)
76
- })),
77
- edges: this._graph.getEdges().map((edge) => ({
78
- id: edge.id,
83
+ nodes: Array.from(this._graph.getNodes(), (node) => {
84
+ const id = node.getId();
85
+ return {
86
+ id,
87
+ ...this._positionsByNodeId.get(id)
88
+ };
89
+ }),
90
+ edges: Array.from(this._graph.getEdges(), (edge) => ({
91
+ id: edge.getId(),
79
92
  source: edge.getSourceNodeId(),
80
93
  target: edge.getTargetNodeId()
81
94
  })),
82
- options: this._options
95
+ options
83
96
  });
84
97
 
85
98
  this._worker.onmessage = (event) => {
@@ -112,7 +125,11 @@ export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
112
125
  }
113
126
  }
114
127
 
115
- getEdgePosition = (edge) => {
128
+ getEdgePosition = (edge: EdgeInterface) => {
129
+ if (!this._graph) {
130
+ return null;
131
+ }
132
+
116
133
  const sourceNode = this._graph.findNode(edge.getSourceNodeId());
117
134
  const targetNode = this._graph.findNode(edge.getTargetNodeId());
118
135
  if (!sourceNode || !targetNode) {
@@ -134,12 +151,12 @@ export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
134
151
  };
135
152
  };
136
153
 
137
- getNodePosition = (node) => {
154
+ getNodePosition = (node: NodeInterface | null) => {
138
155
  if (!node) {
139
156
  return null;
140
157
  }
141
158
 
142
- const d3Node = this._positionsByNodeId.get(node.id);
159
+ const d3Node = this._positionsByNodeId.get(node.getId());
143
160
  if (d3Node) {
144
161
  return d3Node.coordinates;
145
162
  }
@@ -147,9 +164,10 @@ export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
147
164
  return null;
148
165
  };
149
166
 
150
- lockNodePosition = (node, x, y) => {
151
- const d3Node = this._positionsByNodeId.get(node.id);
152
- this._positionsByNodeId.set(node.id, {
167
+ lockNodePosition = (node: NodeInterface, x: number, y: number) => {
168
+ const id = node.getId();
169
+ const d3Node = this._positionsByNodeId.get(id);
170
+ this._positionsByNodeId.set(id, {
153
171
  ...d3Node,
154
172
  x,
155
173
  y,
@@ -161,8 +179,12 @@ export class D3ForceLayout extends GraphLayout<D3ForceLayoutOptions> {
161
179
  this._onLayoutDone();
162
180
  };
163
181
 
164
- unlockNodePosition = (node) => {
165
- const d3Node = this._positionsByNodeId.get(node.id);
182
+ unlockNodePosition = (node: NodeInterface) => {
183
+ const id = node.getId();
184
+ const d3Node = this._positionsByNodeId.get(id);
185
+ if (!d3Node) {
186
+ return;
187
+ }
166
188
  d3Node.fx = null;
167
189
  d3Node.fy = null;
168
190
  };
@@ -3,8 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {GraphLayout, GraphLayoutProps} from '../../core/graph-layout';
6
- import {Node} from '../../graph/node';
7
- import {Graph} from '../../graph/graph';
6
+ import type {Graph, NodeInterface, EdgeInterface} from '../../graph/graph';
8
7
  import * as d3 from 'd3-force';
9
8
 
10
9
  export type ForceMultiGraphLayoutProps = GraphLayoutProps & {
@@ -16,28 +15,25 @@ export type ForceMultiGraphLayoutProps = GraphLayoutProps & {
16
15
 
17
16
  export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProps> {
18
17
  static defaultProps = {
18
+ ...GraphLayout.defaultProps,
19
19
  alpha: 3,
20
20
  nBodyStrength: -1200,
21
21
  nBodyDistanceMin: 100,
22
22
  nBodyDistanceMax: 1400
23
- };
23
+ } as const satisfies Readonly<Required<ForceMultiGraphLayoutProps>>;
24
24
 
25
25
  _name = 'ForceMultiGraphLayout';
26
- _graph: Graph;
26
+ _graph: Graph | null = null;
27
27
 
28
28
  // d3 part
29
29
  // custom graph data
30
- _d3Graph = {nodes: [], edges: []};
31
- _nodeMap = {};
32
- _edgeMap = {};
33
- _simulator;
30
+ _d3Graph: {nodes: any[]; edges: any[]} = {nodes: [], edges: []};
31
+ _nodeMap = new Map<string | number, any>();
32
+ _edgeMap = new Map<string | number, any>();
33
+ _simulator: d3.Simulation<any, undefined> | null = null;
34
34
 
35
- constructor(options: ForceMultiGraphLayoutProps = {}) {
36
- super(options);
37
- this._options = {
38
- ...ForceMultiGraphLayout.defaultProps,
39
- ...options
40
- };
35
+ constructor(props: ForceMultiGraphLayoutProps = {}) {
36
+ super(props, ForceMultiGraphLayout.defaultProps);
41
37
  }
42
38
 
43
39
  initializeGraph(graph: Graph): void {
@@ -48,8 +44,10 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
48
44
  if (d3Edge.isVirtual) {
49
45
  return 1 / d3Edge.edgeCount;
50
46
  }
51
- const sourceDegree = this._graph.getDegree(d3Edge.source.id);
52
- const targetDegree = this._graph.getDegree(d3Edge.target.id);
47
+ const sourceNode = this._graph?.findNode(d3Edge.source.id);
48
+ const targetNode = this._graph?.findNode(d3Edge.target.id);
49
+ const sourceDegree = sourceNode?.getDegree() ?? 0;
50
+ const targetDegree = targetNode?.getDegree() ?? 0;
53
51
  return 1 / Math.min(sourceDegree, targetDegree);
54
52
  };
55
53
 
@@ -58,7 +56,7 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
58
56
  this._simulator.on('tick', null).on('end', null);
59
57
  this._simulator = null;
60
58
  }
61
- const {alpha, nBodyStrength, nBodyDistanceMin, nBodyDistanceMax} = this._options;
59
+ const {alpha, nBodyStrength, nBodyDistanceMin, nBodyDistanceMax} = this.props;
62
60
 
63
61
  const g = this._d3Graph;
64
62
  this._simulator = d3
@@ -100,25 +98,28 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
100
98
 
101
99
  update(): void {}
102
100
 
103
- updateGraph(graph) {
101
+ updateGraph(graph: Graph) {
104
102
  this._graph = graph;
105
103
 
106
104
  // nodes
107
- const newNodeMap = {};
108
- const newD3Nodes = graph.getNodes().map((node) => {
109
- const oldD3Node = this._nodeMap[node.id];
110
- const newD3Node = oldD3Node ? oldD3Node : {id: node.id};
111
- newNodeMap[node.id] = newD3Node;
105
+ const newNodeMap = new Map<string | number, any>();
106
+ const nodes = Array.from(graph.getNodes());
107
+ const newD3Nodes = nodes.map((node) => {
108
+ const id = node.getId();
109
+ const oldD3Node = this._nodeMap.get(id);
110
+ const newD3Node = oldD3Node ? oldD3Node : {id};
111
+ newNodeMap.set(id, newD3Node);
112
112
  return newD3Node;
113
113
  });
114
114
 
115
115
  // edges
116
116
  // bucket edges between the same source/target node pairs.
117
- const nodePairs = graph.getEdges().reduce((res, edge) => {
118
- const nodes = [edge.getSourceNodeId(), edge.getTargetNodeId()];
117
+ const edges = Array.from(graph.getEdges());
118
+ const nodePairs = edges.reduce((res, edge) => {
119
+ const endpoints = [edge.getSourceNodeId(), edge.getTargetNodeId()];
119
120
  // sort the node ids to count the edges with the same pair
120
121
  // but different direction (a -> b or b -> a)
121
- const pairId = nodes.sort().toString();
122
+ const pairId = endpoints.sort().toString();
122
123
  // push this edge into the bucket
123
124
  if (!res[pairId]) {
124
125
  res[pairId] = [edge];
@@ -131,8 +132,8 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
131
132
  // go through each pair of edges,
132
133
  // if only one edge between two nodes, create a straight line
133
134
  // otherwise, create one virtual node and two edges for each edge
134
- const newD3Edges = [];
135
- const newEdgeMap = {};
135
+ const newD3Edges: any[] = [];
136
+ const newEdgeMap = new Map<string | number, any>();
136
137
 
137
138
  Object.keys(nodePairs).forEach((pairId) => {
138
139
  const betweenEdges = nodePairs[pairId];
@@ -142,11 +143,11 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
142
143
  const newD3Edge = {
143
144
  type: 'line',
144
145
  id: firstEdge.getId(),
145
- source: newNodeMap[firstEdge.getSourceNodeId()],
146
- target: newNodeMap[firstEdge.getTargetNodeId()],
146
+ source: newNodeMap.get(firstEdge.getSourceNodeId()),
147
+ target: newNodeMap.get(firstEdge.getTargetNodeId()),
147
148
  isVirtual: false
148
149
  };
149
- newEdgeMap[firstEdge.getId()] = newD3Edge;
150
+ newEdgeMap.set(firstEdge.getId(), newD3Edge);
150
151
  newD3Edges.push(newD3Edge);
151
152
  return;
152
153
  }
@@ -155,24 +156,25 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
155
156
  const newD3Edge = {
156
157
  type: 'line',
157
158
  id: pairId,
158
- source: newNodeMap[firstEdge.getSourceNodeId()],
159
- target: newNodeMap[firstEdge.getTargetNodeId()],
159
+ source: newNodeMap.get(firstEdge.getSourceNodeId()),
160
+ target: newNodeMap.get(firstEdge.getTargetNodeId()),
160
161
  isVirtual: true,
161
162
  edgeCount: betweenEdges.length
162
163
  };
163
- newEdgeMap[pairId] = newD3Edge;
164
+ newEdgeMap.set(pairId, newD3Edge);
164
165
  newD3Edges.push(newD3Edge);
165
166
 
166
167
  betweenEdges.forEach((e, idx) => {
167
- newEdgeMap[e.id] = {
168
+ const edgeId = e.getId();
169
+ newEdgeMap.set(edgeId, {
168
170
  type: 'spline-curve',
169
- id: e.id,
170
- source: newNodeMap[e.getSourceNodeId()],
171
- target: newNodeMap[e.getTargetNodeId()],
171
+ id: edgeId,
172
+ source: newNodeMap.get(e.getSourceNodeId()),
173
+ target: newNodeMap.get(e.getTargetNodeId()),
172
174
  virtualEdgeId: pairId,
173
175
  isVirtual: true,
174
176
  index: idx
175
- };
177
+ });
176
178
  });
177
179
  });
178
180
 
@@ -182,8 +184,8 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
182
184
  this._d3Graph.edges = newD3Edges;
183
185
  }
184
186
 
185
- getNodePosition = (node: Node): [number, number] => {
186
- const d3Node = this._nodeMap[node.id];
187
+ getNodePosition = (node: NodeInterface): [number, number] => {
188
+ const d3Node = this._nodeMap.get(node.getId());
187
189
  if (d3Node) {
188
190
  return [d3Node.x, d3Node.y];
189
191
  }
@@ -191,8 +193,8 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
191
193
  return [0, 0];
192
194
  };
193
195
 
194
- getEdgePosition = (edge) => {
195
- const d3Edge = this._edgeMap[edge.id];
196
+ getEdgePosition = (edge: EdgeInterface) => {
197
+ const d3Edge = this._edgeMap.get(edge.getId());
196
198
  if (d3Edge) {
197
199
  if (!d3Edge.isVirtual) {
198
200
  return {
@@ -203,7 +205,10 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
203
205
  };
204
206
  }
205
207
  // else, check the referenced virtual edge
206
- const virtualEdge = this._edgeMap[d3Edge.virtualEdgeId];
208
+ const virtualEdge = this._edgeMap.get(d3Edge.virtualEdgeId);
209
+ if (!virtualEdge) {
210
+ return null;
211
+ }
207
212
  const edgeCount = virtualEdge.edgeCount;
208
213
  // get the position of source and target nodes
209
214
  const sourcePosition = [virtualEdge.source.x, virtualEdge.source.y];
@@ -239,8 +244,11 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
239
244
  };
240
245
  };
241
246
 
242
- lockNodePosition = (node, x, y) => {
243
- const d3Node = this._nodeMap[node.id];
247
+ lockNodePosition = (node: NodeInterface, x: number, y: number) => {
248
+ const d3Node = this._nodeMap.get(node.getId());
249
+ if (!d3Node) {
250
+ return;
251
+ }
244
252
  d3Node.x = x;
245
253
  d3Node.y = y;
246
254
  this._onLayoutChange();
@@ -248,9 +256,7 @@ export class ForceMultiGraphLayout extends GraphLayout<ForceMultiGraphLayoutProp
248
256
  };
249
257
 
250
258
  protected override _updateBounds(): void {
251
- const positions = Object.values(this._nodeMap ?? {}).map((node) =>
252
- this._normalizePosition(node)
253
- );
259
+ const positions = Array.from(this._nodeMap.values(), (node) => this._normalizePosition(node));
254
260
  this._bounds = this._calculateBounds(positions);
255
261
  }
256
262
  }
@@ -3,52 +3,46 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {GraphLayout, GraphLayoutProps} from '../../core/graph-layout';
6
- import {Node} from '../../graph/node';
7
- import {Graph} from '../../graph/graph';
6
+ import type {Graph, NodeInterface, EdgeInterface} from '../../graph/graph';
8
7
 
9
8
  export type HivePlotLayoutProps = GraphLayoutProps & {
10
9
  innerRadius?: number;
11
10
  outerRadius?: number;
12
- getNodeAxis?: (node: Node) => any;
11
+ getNodeAxis?: (node: NodeInterface) => any;
13
12
  };
14
13
 
15
14
  export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
16
15
  static defaultProps = {
16
+ ...GraphLayout.defaultProps,
17
17
  innerRadius: 100,
18
18
  outerRadius: 500,
19
- getNodeAxis: (node: Node) => node.getPropertyValue('group')
19
+ getNodeAxis: (node: NodeInterface) => node.getPropertyValue('group')
20
20
  } as const satisfies Readonly<Required<HivePlotLayoutProps>>;
21
21
 
22
22
  _name = 'HivePlot';
23
- _graph: Graph;
24
- _totalAxis: number;
25
- _axis: Record<string, any>;
26
- _nodeMap = {};
27
- _nodePositionMap = {};
28
-
29
- constructor(options: HivePlotLayoutProps = {}) {
30
- super(options);
31
- this._options = {
32
- ...HivePlotLayout.defaultProps,
33
- ...options
34
- };
23
+ _graph: Graph | null = null;
24
+ _totalAxis: number = 0;
25
+ _axis: Record<string, NodeInterface[]> = {};
26
+ _nodeMap = new Map<string | number, NodeInterface>();
27
+ _nodePositionMap = new Map<string | number, [number, number]>();
28
+
29
+ constructor(props: HivePlotLayoutProps = {}) {
30
+ super(props, HivePlotLayout.defaultProps);
35
31
  }
36
32
 
37
33
  initializeGraph(graph: Graph) {
38
34
  this.updateGraph(graph);
39
35
  }
40
36
 
41
- updateGraph(graph) {
42
- const {getNodeAxis, innerRadius, outerRadius} = this._options;
37
+ updateGraph(graph: Graph) {
38
+ const {getNodeAxis, innerRadius, outerRadius} = this.props;
43
39
  this._graph = graph;
44
- this._nodeMap = graph.getNodes().reduce((res, node) => {
45
- res[node.getId()] = node;
46
- return res;
47
- }, {});
40
+ const nodes = Array.from(graph.getNodes());
41
+ this._nodeMap = new Map(nodes.map((node) => [node.getId(), node]));
48
42
 
49
43
  // bucket nodes into few axis
50
44
 
51
- this._axis = graph.getNodes().reduce((res, node) => {
45
+ this._axis = nodes.reduce((res, node) => {
52
46
  const axis = getNodeAxis(node);
53
47
  if (!res[axis]) {
54
48
  res[axis] = [];
@@ -77,7 +71,8 @@ export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
77
71
  const angleInterval = 360 / Object.keys(this._axis).length;
78
72
 
79
73
  // calculate positions
80
- this._nodePositionMap = Object.keys(this._axis).reduce((res, axis, axisIdx) => {
74
+ this._nodePositionMap = new Map();
75
+ Object.keys(this._axis).forEach((axis, axisIdx) => {
81
76
  const axisAngle = angleInterval * axisIdx;
82
77
  const bucketedNodes = this._axis[axis];
83
78
  const interval = (outerRadius - innerRadius) / bucketedNodes.length;
@@ -86,13 +81,13 @@ export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
86
81
  const radius = innerRadius + idx * interval;
87
82
  const x = Math.cos((axisAngle / 180) * Math.PI) * radius + center[0];
88
83
  const y = Math.sin((axisAngle / 180) * Math.PI) * radius + center[1];
89
- res[node.getId()] = [x, y];
84
+ this._nodePositionMap.set(node.getId(), [x, y]);
90
85
  });
91
- return res;
92
- }, {});
86
+ });
93
87
  }
94
88
 
95
89
  start() {
90
+ this._onLayoutStart();
96
91
  this._onLayoutChange();
97
92
  this._onLayoutDone();
98
93
  }
@@ -103,23 +98,27 @@ export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
103
98
 
104
99
  resume() {}
105
100
 
106
- getNodePosition = (node) => this._nodePositionMap[node.getId()];
101
+ getNodePosition = (node: NodeInterface) => this._nodePositionMap.get(node.getId());
107
102
 
108
- getEdgePosition = (edge) => {
109
- const {getNodeAxis} = this._options;
103
+ getEdgePosition = (edge: EdgeInterface) => {
104
+ const {getNodeAxis} = this.props;
110
105
  const sourceNodeId = edge.getSourceNodeId();
111
106
  const targetNodeId = edge.getTargetNodeId();
112
107
 
113
- const sourcePosition = this._nodePositionMap[sourceNodeId];
114
- const targetPosition = this._nodePositionMap[targetNodeId];
108
+ const sourcePosition = this._nodePositionMap.get(sourceNodeId);
109
+ const targetPosition = this._nodePositionMap.get(targetNodeId);
110
+
111
+ if (!sourcePosition || !targetPosition) {
112
+ return null;
113
+ }
115
114
 
116
- const sourceNode = this._nodeMap[sourceNodeId];
117
- const targetNode = this._nodeMap[targetNodeId];
115
+ const sourceNode = this._nodeMap.get(sourceNodeId);
116
+ const targetNode = this._nodeMap.get(targetNodeId);
118
117
 
119
- const sourceNodeAxis = getNodeAxis(sourceNode);
120
- const targetNodeAxis = getNodeAxis(targetNode);
118
+ const sourceNodeAxis = sourceNode ? getNodeAxis(sourceNode) : null;
119
+ const targetNodeAxis = targetNode ? getNodeAxis(targetNode) : null;
121
120
 
122
- if (sourceNodeAxis === targetNodeAxis) {
121
+ if (sourceNodeAxis !== null && sourceNodeAxis === targetNodeAxis) {
123
122
  return {
124
123
  type: 'line',
125
124
  sourcePosition,
@@ -130,9 +129,9 @@ export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
130
129
 
131
130
  const controlPoint = computeControlPoint({
132
131
  sourcePosition,
133
- sourceNodeAxis,
132
+ sourceNodeAxis: sourceNodeAxis ?? 0,
134
133
  targetPosition,
135
- targetNodeAxis,
134
+ targetNodeAxis: targetNodeAxis ?? 0,
136
135
  totalAxis: this._totalAxis
137
136
  });
138
137
 
@@ -144,14 +143,14 @@ export class HivePlotLayout extends GraphLayout<HivePlotLayoutProps> {
144
143
  };
145
144
  };
146
145
 
147
- lockNodePosition = (node, x, y) => {
148
- this._nodePositionMap[node.id] = [x, y];
146
+ lockNodePosition = (node: NodeInterface, x: number, y: number) => {
147
+ this._nodePositionMap.set(node.getId(), [x, y]);
149
148
  this._onLayoutChange();
150
149
  this._onLayoutDone();
151
150
  };
152
151
 
153
152
  protected override _updateBounds(): void {
154
- const positions = Object.values(this._nodePositionMap ?? {}).map((position) =>
153
+ const positions = Array.from(this._nodePositionMap.values(), (position) =>
155
154
  this._normalizePosition(position)
156
155
  );
157
156
  this._bounds = this._calculateBounds(positions);
@@ -3,21 +3,33 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {GraphLayout, GraphLayoutProps} from '../../core/graph-layout';
6
- import {Graph} from '../../graph/graph';
6
+ import type {Graph, NodeInterface, EdgeInterface} from '../../graph/graph';
7
7
 
8
8
  export type RadialLayoutProps = GraphLayoutProps & {
9
9
  radius?: number;
10
10
  tree?: any;
11
11
  };
12
12
 
13
- const traverseTree = (nodeId, nodeMap) => {
13
+ const getTreeNode = (nodeId: string, nodeMap: Record<string, {children?: string[]; isLeaf?: boolean}>) => {
14
14
  const node = nodeMap[nodeId];
15
+ if (node) {
16
+ return node;
17
+ }
18
+ return {
19
+ id: nodeId,
20
+ children: [],
21
+ isLeaf: true
22
+ };
23
+ };
24
+
25
+ const traverseTree = (nodeId, nodeMap) => {
26
+ const node = getTreeNode(nodeId, nodeMap);
15
27
  if (node.isLeaf) {
16
28
  return node;
17
29
  }
18
30
  return {
19
31
  ...node,
20
- children: node.children.map((nid) => traverseTree(nid, nodeMap))
32
+ children: (node.children ?? []).map((nid) => traverseTree(nid, nodeMap))
21
33
  };
22
34
  };
23
35
 
@@ -39,6 +51,9 @@ const getTreeDepth = (node, depth = 0) => {
39
51
  };
40
52
 
41
53
  const getPath = (node, targetId, path) => {
54
+ if (!node) {
55
+ return false;
56
+ }
42
57
  if (node.id === targetId) {
43
58
  path.push(node.id);
44
59
  return true;
@@ -53,21 +68,19 @@ const getPath = (node, targetId, path) => {
53
68
 
54
69
  export class RadialLayout extends GraphLayout<RadialLayoutProps> {
55
70
  static defaultProps = {
56
- radius: 500
57
- };
71
+ ...GraphLayout.defaultProps,
72
+ radius: 500,
73
+ tree: []
74
+ } as const satisfies Readonly<Required<RadialLayoutProps>>;
58
75
 
59
76
  _name = 'RadialLayout';
60
- _graph: Graph = null;
77
+ _graph: Graph | null = null;
61
78
  // custom layout data structure
62
79
  _hierarchicalPoints = {};
63
80
  nestedTree;
64
81
 
65
- constructor(options: RadialLayoutProps = {}) {
66
- super(options);
67
- this._options = {
68
- ...RadialLayout.defaultProps,
69
- ...options
70
- };
82
+ constructor(props: RadialLayoutProps = {}) {
83
+ super(props, RadialLayout.defaultProps);
71
84
  }
72
85
 
73
86
  initializeGraph(graph: Graph): void {
@@ -79,18 +92,24 @@ export class RadialLayout extends GraphLayout<RadialLayoutProps> {
79
92
  }
80
93
 
81
94
  start(): void {
82
- const nodeCount = this._graph.getNodes().length;
95
+ if (!this._graph) {
96
+ return;
97
+ }
98
+ const nodes = Array.from(this._graph.getNodes());
99
+ const nodeCount = nodes.length;
83
100
  if (nodeCount === 0) {
84
101
  return;
85
102
  }
86
103
 
87
- const {tree} = this._options;
104
+ const {tree} = this.props;
88
105
 
89
106
  if (!tree || tree.length === 0) {
90
107
  return;
91
108
  }
92
109
 
93
- const {radius} = this._options;
110
+ this._onLayoutStart();
111
+
112
+ const {radius} = this.props;
94
113
  const unitAngle = 360 / nodeCount;
95
114
 
96
115
  // hierarchical positions
@@ -154,12 +173,12 @@ export class RadialLayout extends GraphLayout<RadialLayoutProps> {
154
173
 
155
174
  update() {}
156
175
 
157
- getNodePosition = (node) => {
158
- return this._hierarchicalPoints[node.id];
176
+ getNodePosition = (node: NodeInterface) => {
177
+ return this._hierarchicalPoints[node.getId()];
159
178
  };
160
179
 
161
180
  // spline curve version
162
- getEdgePosition = (edge) => {
181
+ getEdgePosition = (edge: EdgeInterface) => {
163
182
  const sourceNodeId = edge.getSourceNodeId();
164
183
  const targetNodeId = edge.getTargetNodeId();
165
184
  const sourceNodePos = this._hierarchicalPoints[sourceNodeId];
@@ -197,8 +216,8 @@ export class RadialLayout extends GraphLayout<RadialLayoutProps> {
197
216
  };
198
217
  };
199
218
 
200
- lockNodePosition = (node, x, y) => {
201
- this._hierarchicalPoints[node.id] = [x, y];
219
+ lockNodePosition = (node: NodeInterface, x: number, y: number) => {
220
+ this._hierarchicalPoints[node.getId()] = [x, y];
202
221
  this._onLayoutChange();
203
222
  this._onLayoutDone();
204
223
  };