@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
@@ -4,67 +4,125 @@
4
4
 
5
5
  import type {Bounds2D} from '@math.gl/types';
6
6
 
7
- import type {Node} from '../graph/node';
8
- import {Edge} from '../graph/edge';
9
- import {Graph} from '../graph/graph';
7
+ import type {Graph, EdgeInterface, NodeInterface} from '../graph/graph';
8
+ import {ClassicGraph} from '../graph/classic-graph';
10
9
  import {GraphLayout, type GraphLayoutEventDetail} from './graph-layout';
11
10
  import {Cache} from './cache';
12
11
  import {log} from '../utils/log';
12
+ import {GraphStylesheetEngine, type GraphStylesheet} from '../style/graph-style-engine';
13
13
 
14
- export type GraphEngineProps = {
14
+ type ClassicGraphEngineProps = {
15
+ graph: ClassicGraph;
16
+ layout: GraphLayout;
17
+ onLayoutStart?: (detail?: GraphLayoutEventDetail) => void;
18
+ onLayoutChange?: (detail?: GraphLayoutEventDetail) => void;
19
+ onLayoutDone?: (detail?: GraphLayoutEventDetail) => void;
20
+ onLayoutError?: (error?: unknown) => void;
21
+ onTransactionStart?: () => void;
22
+ onTransactionEnd?: () => void;
23
+ onNodeAdded?: (node: NodeInterface) => void;
24
+ onNodeRemoved?: (node: NodeInterface) => void;
25
+ onNodeUpdated?: (node: NodeInterface) => void;
26
+ onEdgeAdded?: (edge: EdgeInterface) => void;
27
+ onEdgeRemoved?: (edge: EdgeInterface) => void;
28
+ onEdgeUpdated?: (edge: EdgeInterface) => void;
29
+ };
30
+
31
+ type InterfaceGraphEngineProps = {
15
32
  graph: Graph;
16
33
  layout: GraphLayout;
34
+ onLayoutStart?: (detail?: GraphLayoutEventDetail) => void;
35
+ onLayoutChange?: (detail?: GraphLayoutEventDetail) => void;
36
+ onLayoutDone?: (detail?: GraphLayoutEventDetail) => void;
37
+ onLayoutError?: (error?: unknown) => void;
38
+ onTransactionStart?: () => void;
39
+ onTransactionEnd?: () => void;
40
+ onNodeAdded?: (node: NodeInterface) => void;
41
+ onNodeRemoved?: (node: NodeInterface) => void;
42
+ onNodeUpdated?: (node: NodeInterface) => void;
43
+ onEdgeAdded?: (edge: EdgeInterface) => void;
44
+ onEdgeRemoved?: (edge: EdgeInterface) => void;
45
+ onEdgeUpdated?: (edge: EdgeInterface) => void;
17
46
  };
18
47
 
19
- /** Graph engine controls the graph data and layout calculation */
20
- export class GraphEngine extends EventTarget {
21
- props: Readonly<Required<GraphEngineProps>>;
48
+ export type GraphEngineProps = ClassicGraphEngineProps | InterfaceGraphEngineProps;
22
49
 
50
+ /** Graph engine controls the graph data and layout calculation */
51
+ export class GraphEngine {
52
+ private _props: GraphEngineProps;
23
53
  private readonly _graph: Graph;
24
54
  private readonly _layout: GraphLayout;
25
- private readonly _cache = new Cache<'nodes' | 'edges', Node[] | Edge[]>();
55
+ private readonly _cache = new Cache<'nodes' | 'edges', NodeInterface[] | EdgeInterface[]>();
26
56
  private _layoutDirty = false;
27
57
  private _transactionInProgress = false;
58
+ private _graphCallbacksAttached = false;
59
+ private _layoutCallbacksAttached = false;
28
60
 
29
61
  constructor(props: GraphEngineProps);
30
62
  /** @deprecated Use props constructor: new GraphEngine(props) */
31
- constructor(graph: Graph, layout: GraphLayout);
32
-
33
- constructor(props: GraphEngineProps | Graph, layout?: GraphLayout) {
34
- super();
35
- if (props instanceof Graph) {
36
- props = {
37
- graph: props,
38
- layout
39
- };
63
+ constructor(graph: ClassicGraph, layout: GraphLayout);
64
+
65
+ constructor(props: GraphEngineProps | ClassicGraph, layout?: GraphLayout) {
66
+ let normalizedProps: GraphEngineProps;
67
+ if (props instanceof ClassicGraph) {
68
+ if (!(layout instanceof GraphLayout)) {
69
+ throw new Error('GraphEngine: legacy graphs require a GraphLayout instance.');
70
+ }
71
+ normalizedProps = {graph: props, layout};
72
+ } else {
73
+ normalizedProps = props;
40
74
  }
41
75
 
42
- this.props = props;
43
- this._graph = props.graph;
44
- this._layout = props.layout;
76
+ this._props = {...normalizedProps};
77
+
78
+ this._graph = normalizedProps.graph;
79
+ this._layout = normalizedProps.layout;
80
+ }
81
+
82
+ get props(): GraphEngineProps {
83
+ return {...this._props};
84
+ }
85
+
86
+ setProps(props: Partial<Omit<GraphEngineProps, 'graph' | 'layout'>>): void {
87
+ this._props = {
88
+ ...this._props,
89
+ ...props,
90
+ graph: this._props.graph,
91
+ layout: this._props.layout
92
+ } as GraphEngineProps;
45
93
  }
46
94
 
47
95
  /** Getters */
48
96
 
49
- getNodes = (): Node[] => {
97
+ getNodes = (): NodeInterface[] => {
50
98
  this._updateCache('nodes', () =>
51
- this._graph.getNodes().filter((node) => this.getNodePosition(node))
99
+ Array.from(this._graph.getNodes()).filter((node) => {
100
+ const position = this.getNodePosition(node);
101
+ return position !== null && position !== undefined;
102
+ })
52
103
  );
53
104
 
54
- return this._cache.get('nodes') as Node[];
105
+ return (this._cache.get('nodes') as NodeInterface[]) ?? [];
55
106
  };
56
107
 
57
108
  getEdges = () => {
58
109
  this._updateCache('edges', () =>
59
- this._graph.getEdges().filter((edge) => this.getEdgePosition(edge))
110
+ Array.from(this._graph.getEdges()).filter((edge) => {
111
+ const layout = this.getEdgePosition(edge);
112
+ return layout !== null && layout !== undefined;
113
+ })
60
114
  );
61
115
 
62
- return this._cache.get('edges') as Edge[];
116
+ return (this._cache.get('edges') as EdgeInterface[]) ?? [];
63
117
  };
64
118
 
65
- getNodePosition = (node: Node) => this._layout.getNodePosition(node);
119
+ getNodePosition = (node: NodeInterface) => {
120
+ return this._layout.getNodePosition(node) ?? null;
121
+ };
66
122
 
67
- getEdgePosition = (edge: Edge) => this._layout.getEdgePosition(edge);
123
+ getEdgePosition = (edge: EdgeInterface) => {
124
+ return this._layout.getEdgePosition(edge) ?? null;
125
+ };
68
126
 
69
127
  getGraphVersion = () => this._graph.version;
70
128
 
@@ -72,77 +130,74 @@ export class GraphEngine extends EventTarget {
72
130
 
73
131
  getLayoutState = () => this._layout.state;
74
132
 
75
- getLayoutBounds = (): Bounds2D | null => this._layout.getBounds();
133
+ getLayoutBounds = (): Bounds2D | null => this._layout.getBounds() ?? null;
76
134
 
77
135
  /** Operations on the graph */
78
136
 
79
- lockNodePosition = (node, x, y) => this._layout.lockNodePosition(node, x, y);
137
+ lockNodePosition = (node: NodeInterface, x: number, y: number) => {
138
+ this._layout.lockNodePosition(node, x, y);
139
+ };
140
+
141
+ unlockNodePosition = (node: NodeInterface) => {
142
+ this._layout.unlockNodePosition(node);
143
+ };
144
+
145
+ findNode(nodeId: string | number): NodeInterface | undefined {
146
+ return this._graph.findNode?.(nodeId) ?? this._graph.findNodeById?.(nodeId);
147
+ }
80
148
 
81
- unlockNodePosition = (node) => this._layout.unlockNodePosition(node);
149
+ createStylesheetEngine(
150
+ style: GraphStylesheet,
151
+ options: {stateUpdateTrigger?: unknown} = {}
152
+ ): GraphStylesheetEngine {
153
+ return new GraphStylesheetEngine(style, options);
154
+ }
82
155
 
83
156
  /**
84
157
  * @fires GraphEngine#onLayoutStart
85
158
  */
86
- _onLayoutStart = (event: Event) => {
159
+ _onLayoutStart = (detail?: GraphLayoutEventDetail) => {
87
160
  log.log(0, 'GraphEngine: layout start')();
88
- const detail = event instanceof CustomEvent ? (event.detail as GraphLayoutEventDetail) : undefined;
89
- /**
90
- * @event GraphEngine#onLayoutStart
91
- * @type {CustomEvent}
92
- */
93
- this.dispatchEvent(new CustomEvent('onLayoutStart', {detail}));
161
+ this._props.onLayoutStart?.(detail);
94
162
  };
95
163
 
96
164
  /**
97
165
  * @fires GraphEngine#onLayoutChange
98
166
  */
99
- _onLayoutChange = (event: Event) => {
167
+ _onLayoutChange = (detail?: GraphLayoutEventDetail) => {
100
168
  log.log(0, 'GraphEngine: layout update event')();
101
- const detail = event instanceof CustomEvent ? (event.detail as GraphLayoutEventDetail) : undefined;
102
- /**
103
- * @event GraphEngine#onLayoutChange
104
- * @type {CustomEvent}
105
- */
106
- this.dispatchEvent(new CustomEvent('onLayoutChange', {detail}));
169
+ this._props.onLayoutChange?.(detail);
107
170
  };
108
171
 
109
172
  /**
110
173
  * @fires GraphEngine#onLayoutDone
111
174
  */
112
- _onLayoutDone = (event: Event) => {
175
+ _onLayoutDone = (detail?: GraphLayoutEventDetail) => {
113
176
  log.log(0, 'GraphEngine: layout end')();
114
- const detail = event instanceof CustomEvent ? (event.detail as GraphLayoutEventDetail) : undefined;
115
- /**
116
- * @event GraphEngine#onLayoutDone
117
- * @type {CustomEvent}
118
- */
119
- this.dispatchEvent(new CustomEvent('onLayoutDone', {detail}));
177
+ this._props.onLayoutDone?.(detail);
120
178
  };
121
179
 
122
180
  /**
123
181
  * @fires GraphEngine#onLayoutError
124
182
  */
125
- _onLayoutError = (event: Event) => {
126
- const detail = event instanceof CustomEvent ? event.detail : undefined;
127
- /**
128
- * @event GraphEngine#onLayoutError
129
- * @type {CustomEvent}
130
- */
131
- this.dispatchEvent(new CustomEvent('onLayoutError', {detail}));
183
+ _onLayoutError = (error?: unknown) => {
184
+ this._props.onLayoutError?.(error);
132
185
  };
133
186
 
134
- _onGraphStructureChanged = (entity) => {
187
+ _onGraphStructureChanged = () => {
135
188
  this._layoutDirty = true;
136
189
  this._graphChanged();
137
190
  };
138
191
 
139
192
  _onTransactionStart = () => {
140
193
  this._transactionInProgress = true;
194
+ this._props.onTransactionStart?.();
141
195
  };
142
196
 
143
197
  _onTransactionEnd = () => {
144
198
  this._transactionInProgress = false;
145
199
  this._graphChanged();
200
+ this._props.onTransactionEnd?.();
146
201
  };
147
202
 
148
203
  /** Layout calculations */
@@ -151,17 +206,8 @@ export class GraphEngine extends EventTarget {
151
206
  log.log(1, 'GraphEngine: run');
152
207
  // TODO: throw if running on a cleared engine
153
208
 
154
- this._graph.addEventListener('transactionStart', this._onTransactionStart);
155
- this._graph.addEventListener('transactionEnd', this._onTransactionEnd);
156
- this._graph.addEventListener('onNodeAdded', this._onGraphStructureChanged);
157
- this._graph.addEventListener('onNodeRemoved', this._onGraphStructureChanged);
158
- this._graph.addEventListener('onEdgeAdded', this._onGraphStructureChanged);
159
- this._graph.addEventListener('onEdgeRemoved', this._onGraphStructureChanged);
160
-
161
- this._layout.addEventListener('onLayoutStart', this._onLayoutStart);
162
- this._layout.addEventListener('onLayoutChange', this._onLayoutChange);
163
- this._layout.addEventListener('onLayoutDone', this._onLayoutDone);
164
- this._layout.addEventListener('onLayoutError', this._onLayoutError);
209
+ this._attachGraphCallbacks();
210
+ this._attachLayoutCallbacks();
165
211
 
166
212
  this._layout.initializeGraph(this._graph);
167
213
  this._layout.start();
@@ -169,22 +215,17 @@ export class GraphEngine extends EventTarget {
169
215
 
170
216
  clear = () => {
171
217
  log.log(1, 'GraphEngine: end');
172
- this._graph.removeEventListener('transactionStart', this._onTransactionStart);
173
- this._graph.removeEventListener('transactionEnd', this._onTransactionEnd);
174
- this._graph.removeEventListener('onNodeAdded', this._onGraphStructureChanged);
175
- this._graph.removeEventListener('onNodeRemoved', this._onGraphStructureChanged);
176
- this._graph.removeEventListener('onEdgeAdded', this._onGraphStructureChanged);
177
- this._graph.removeEventListener('onEdgeRemoved', this._onGraphStructureChanged);
178
-
179
- this._layout.removeEventListener('onLayoutStart', this._onLayoutStart);
180
- this._layout.removeEventListener('onLayoutChange', this._onLayoutChange);
181
- this._layout.removeEventListener('onLayoutDone', this._onLayoutDone);
182
- this._layout.removeEventListener('onLayoutError', this._onLayoutError);
218
+ this._detachGraphCallbacks();
219
+ this._detachLayoutCallbacks();
183
220
  };
184
221
 
185
- resume = () => this._layout.resume();
222
+ resume = () => {
223
+ this._layout.resume();
224
+ };
186
225
 
187
- stop = () => this._layout.stop();
226
+ stop = () => {
227
+ this._layout.stop();
228
+ };
188
229
 
189
230
  _graphChanged = () => {
190
231
  if (this._layoutDirty && !this._transactionInProgress) {
@@ -200,6 +241,82 @@ export class GraphEngine extends EventTarget {
200
241
  };
201
242
 
202
243
  _updateCache(key, updateValue) {
203
- this._cache.set(key, updateValue, this._graph.version + this._layout.version);
244
+ this._cache.set(key, updateValue, this.getGraphVersion() + this.getLayoutLastUpdate());
245
+ }
246
+
247
+ private _attachGraphCallbacks() {
248
+ if (this._graphCallbacksAttached) {
249
+ return;
250
+ }
251
+ this._graph.updateProps({
252
+ onTransactionStart: this._onTransactionStart,
253
+ onTransactionEnd: this._onTransactionEnd,
254
+ onNodeAdded: (node) => {
255
+ this._onGraphStructureChanged();
256
+ this._props.onNodeAdded?.(node);
257
+ },
258
+ onNodeRemoved: (node) => {
259
+ this._onGraphStructureChanged();
260
+ this._props.onNodeRemoved?.(node);
261
+ },
262
+ onNodeUpdated: (node) => {
263
+ this._props.onNodeUpdated?.(node);
264
+ },
265
+ onEdgeAdded: (edge) => {
266
+ this._onGraphStructureChanged();
267
+ this._props.onEdgeAdded?.(edge);
268
+ },
269
+ onEdgeRemoved: (edge) => {
270
+ this._onGraphStructureChanged();
271
+ this._props.onEdgeRemoved?.(edge);
272
+ },
273
+ onEdgeUpdated: (edge) => {
274
+ this._props.onEdgeUpdated?.(edge);
275
+ }
276
+ });
277
+ this._graphCallbacksAttached = true;
278
+ }
279
+
280
+ private _detachGraphCallbacks() {
281
+ if (!this._graphCallbacksAttached) {
282
+ return;
283
+ }
284
+ this._graph.updateProps({
285
+ onTransactionStart: undefined,
286
+ onTransactionEnd: undefined,
287
+ onNodeAdded: undefined,
288
+ onNodeRemoved: undefined,
289
+ onNodeUpdated: undefined,
290
+ onEdgeAdded: undefined,
291
+ onEdgeRemoved: undefined,
292
+ onEdgeUpdated: undefined
293
+ });
294
+ this._graphCallbacksAttached = false;
295
+ }
296
+
297
+ private _attachLayoutCallbacks() {
298
+ if (this._layoutCallbacksAttached) {
299
+ return;
300
+ }
301
+ this._layout.setProps({
302
+ onLayoutStart: this._onLayoutStart,
303
+ onLayoutChange: this._onLayoutChange,
304
+ onLayoutDone: this._onLayoutDone,
305
+ onLayoutError: this._onLayoutError
306
+ });
307
+ this._layoutCallbacksAttached = true;
308
+ }
309
+
310
+ private _detachLayoutCallbacks() {
311
+ if (!this._layoutCallbacksAttached) {
312
+ return;
313
+ }
314
+ this._layout.setProps({
315
+ onLayoutStart: undefined,
316
+ onLayoutChange: undefined,
317
+ onLayoutDone: undefined,
318
+ onLayoutError: undefined
319
+ });
320
+ this._layoutCallbacksAttached = false;
204
321
  }
205
322
  }
@@ -4,9 +4,7 @@
4
4
 
5
5
  import type {Bounds2D} from '@math.gl/types';
6
6
 
7
- import type {Graph} from '../graph/graph';
8
- import type {Node} from '../graph/node';
9
- import type {Edge} from '../graph/edge';
7
+ import type {Graph, NodeInterface, EdgeInterface} from '../graph/graph';
10
8
 
11
9
  import isEqual from 'lodash.isequal';
12
10
  import {log} from '../utils/log';
@@ -18,16 +16,30 @@ export type GraphLayoutEventDetail = {
18
16
  bounds: Bounds2D | null;
19
17
  };
20
18
 
21
- export type GraphLayoutProps = {};
19
+ export type GraphLayoutProps = {
20
+ onLayoutStart?: (detail?: GraphLayoutEventDetail) => void;
21
+ onLayoutChange?: (detail?: GraphLayoutEventDetail) => void;
22
+ onLayoutDone?: (detail?: GraphLayoutEventDetail) => void;
23
+ onLayoutError?: (error?: unknown) => void;
24
+ };
25
+
22
26
 
23
- /** All the layout classes are extended from this base layout class. */
24
27
  export abstract class GraphLayout<
25
- OptionsT extends GraphLayoutProps = GraphLayoutProps
26
- > extends EventTarget {
27
- /** Name of the layout. */
28
- protected readonly _name: string = 'GraphLayout';
29
- /** Extra configuration options of the layout. */
30
- protected _options: OptionsT;
28
+ PropsT extends GraphLayoutProps = GraphLayoutProps
29
+ > {
30
+ static defaultProps: Readonly<Required<GraphLayoutProps>> = {
31
+ onLayoutStart: undefined,
32
+ onLayoutChange: undefined,
33
+ onLayoutDone: undefined,
34
+ onLayoutError: undefined
35
+ };
36
+
37
+ get [Symbol.toStringTag](): string {
38
+ return 'GraphLayout';
39
+ }
40
+
41
+ /** Extra configuration props of the layout. */
42
+ protected props: Required<PropsT>;
31
43
 
32
44
  /**
33
45
  * Last computed layout bounds in local layout coordinates.
@@ -42,11 +54,22 @@ export abstract class GraphLayout<
42
54
 
43
55
  /**
44
56
  * Constructor of GraphLayout
45
- * @param options extra configuration options of the layout
57
+ * @param props extra configuration props of the layout
46
58
  */
47
- constructor(options: OptionsT) {
48
- super();
49
- this._options = options;
59
+ constructor(props: PropsT, defaultProps?: Required<PropsT>) {
60
+ this.props = {
61
+ ...GraphLayout.defaultProps,
62
+ ...defaultProps,
63
+ ...props
64
+ };
65
+ }
66
+
67
+ getProps(): PropsT {
68
+ return {...this.props};
69
+ }
70
+
71
+ setProps(props: Partial<PropsT>): void {
72
+ this.props = {...this.props, ...props};
50
73
  }
51
74
 
52
75
  /**
@@ -58,18 +81,18 @@ export abstract class GraphLayout<
58
81
  if (!layout || !(layout instanceof GraphLayout)) {
59
82
  return false;
60
83
  }
61
- return this._name === layout._name && isEqual(this._options, layout._options);
84
+ return this instanceof layout.constructor && isEqual(this.props, layout.props);
62
85
  }
63
86
 
64
87
  // Accessors
65
88
 
66
89
  /** access the position of the node in the layout */
67
- getNodePosition(node: Node): [number, number] {
90
+ getNodePosition(node: NodeInterface): [number, number] {
68
91
  return [0, 0];
69
92
  }
70
93
 
71
94
  /** access the layout information of the edge */
72
- getEdgePosition(edge: Edge) {
95
+ getEdgePosition(edge: EdgeInterface) {
73
96
  return {
74
97
  type: 'line',
75
98
  sourcePosition: [0, 0],
@@ -84,13 +107,13 @@ export abstract class GraphLayout<
84
107
  * @param x x coordinate
85
108
  * @param y y coordinate
86
109
  */
87
- lockNodePosition(node: Node, x: number, y: number) {}
110
+ lockNodePosition(node: NodeInterface, x: number, y: number) {}
88
111
 
89
112
  /**
90
113
  * Unlock the node, the node will be able to move freely.
91
114
  * @param {Object} node Node to be unlocked
92
115
  */
93
- unlockNodePosition(node: Node) {}
116
+ unlockNodePosition(node: NodeInterface) {}
94
117
 
95
118
  /** Returns the last computed layout bounds, if available. */
96
119
  getBounds(): Bounds2D | null {
@@ -100,9 +123,9 @@ export abstract class GraphLayout<
100
123
  /** virtual functions: will be implemented in the child class */
101
124
 
102
125
  /** first time to pass the graph data into this layout */
103
- abstract initializeGraph(graph: Graph);
126
+ abstract initializeGraph(graph: Graph): void;
104
127
  /** update the existing graph */
105
- abstract updateGraph(graph: Graph);
128
+ abstract updateGraph(graph: Graph): void;
106
129
  /** start the layout calculation */
107
130
  abstract start();
108
131
  /** update the layout calculation */
@@ -194,7 +217,7 @@ export abstract class GraphLayout<
194
217
 
195
218
  /** @fires GraphLayout#onLayoutStart */
196
219
  protected _onLayoutStart = (): void => {
197
- log.log(0, `GraphLayout(${this._name}): start`)();
220
+ log.log(0, `GraphLayout(${this}): start`)();
198
221
  this._updateBounds();
199
222
  this._updateState('calculating');
200
223
 
@@ -204,12 +227,12 @@ export abstract class GraphLayout<
204
227
  * @type {CustomEvent}
205
228
  */
206
229
  const detail: GraphLayoutEventDetail = {bounds: this._bounds};
207
- this.dispatchEvent(new CustomEvent<GraphLayoutEventDetail>('onLayoutStart', {detail}));
230
+ this.props.onLayoutStart?.(detail);
208
231
  };
209
232
 
210
233
  /** @fires GraphLayout#onLayoutChange */
211
234
  protected _onLayoutChange = (): void => {
212
- log.log(0, `GraphLayout(${this._name}): update`)();
235
+ log.log(0, `GraphLayout(${this}): update`)();
213
236
  this._updateBounds();
214
237
  this._updateState('calculating');
215
238
 
@@ -219,12 +242,12 @@ export abstract class GraphLayout<
219
242
  * @type {CustomEvent}
220
243
  */
221
244
  const detail: GraphLayoutEventDetail = {bounds: this._bounds};
222
- this.dispatchEvent(new CustomEvent<GraphLayoutEventDetail>('onLayoutChange', {detail}));
245
+ this.props.onLayoutChange?.(detail);
223
246
  };
224
247
 
225
248
  /** @fires GraphLayout#onLayoutDone */
226
249
  protected _onLayoutDone = (): void => {
227
- log.log(0, `GraphLayout(${this._name}): end`)();
250
+ log.log(0, `GraphLayout(${this}): end`)();
228
251
  this._updateBounds();
229
252
  this._updateState('done');
230
253
 
@@ -234,7 +257,7 @@ export abstract class GraphLayout<
234
257
  * @type {CustomEvent}
235
258
  */
236
259
  const detail: GraphLayoutEventDetail = {bounds: this._bounds};
237
- this.dispatchEvent(new CustomEvent<GraphLayoutEventDetail>('onLayoutDone', {detail}));
260
+ this.props.onLayoutDone?.(detail);
238
261
  };
239
262
 
240
263
  /** @fires GraphLayout#onLayoutError */
@@ -246,6 +269,6 @@ export abstract class GraphLayout<
246
269
  * @event GraphLayout#onLayoutError
247
270
  * @type {CustomEvent}
248
271
  */
249
- this.dispatchEvent(new CustomEvent('onLayoutError'));
272
+ this.props.onLayoutError?.();
250
273
  };
251
274
  }