@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
@@ -8,17 +8,15 @@ import type {CompositeLayerProps} from '@deck.gl/core';
8
8
  import {COORDINATE_SYSTEM, CompositeLayer} from '@deck.gl/core';
9
9
  import {PolygonLayer} from '@deck.gl/layers';
10
10
 
11
- import {Graph} from '../graph/graph';
12
- import type {Node} from '../graph/node';
13
- import {GraphLayout} from '../core/graph-layout';
11
+ import type {Graph, NodeInterface} from '../graph/graph';
12
+ import {ClassicGraph} from '../graph/classic-graph';
13
+ import {GraphLayout, type GraphLayoutEventDetail} from '../core/graph-layout';
14
14
  import {GraphEngine} from '../core/graph-engine';
15
15
 
16
- import {GraphStyleEngine, type GraphStylesheet} from '../style/graph-style-engine';
17
- import {mixedGetPosition} from '../utils/layer-utils';
18
- import {InteractionManager} from '../core/interaction-manager';
19
- import {buildCollapsedChainLayers} from '../utils/collapsed-chains';
20
-
21
- import {warn} from '../utils/log';
16
+ import {
17
+ GraphStylesheetEngine,
18
+ type GraphStylesheet
19
+ } from '../style/graph-style-engine';
22
20
 
23
21
  import {
24
22
  DEFAULT_GRAPH_LAYER_STYLESHEET,
@@ -44,8 +42,21 @@ import {EdgeLabelLayer} from './edge-layers/edge-label-layer';
44
42
  import {FlowLayer} from './edge-layers/flow-layer';
45
43
  import {EdgeArrowLayer} from './edge-layers/edge-arrow-layer';
46
44
  import {EdgeAttachmentHelper} from './edge-attachment-helper';
45
+ import {GridLayer, type GridLayerProps} from './common-layers/grid-layer/grid-layer';
46
+
47
+ import {JSONGraphLoader} from '../loaders/json-graph-loader';
47
48
 
48
- import {JSONLoader} from '../loaders/json-loader';
49
+ import {mixedGetPosition} from '../utils/layer-utils';
50
+ import {InteractionManager} from '../core/interaction-manager';
51
+ import {buildCollapsedChainLayers} from '../utils/collapsed-chains';
52
+ import {
53
+ mapRanksToYPositions,
54
+ selectRankLines,
55
+ type LabelAccessor,
56
+ type RankAccessor
57
+ } from '../utils/rank-grid';
58
+
59
+ import {warn} from '../utils/log';
49
60
 
50
61
  const NODE_LAYER_MAP = {
51
62
  'rectangle': RectangleLayer,
@@ -63,6 +74,17 @@ const EDGE_DECORATOR_LAYER_MAP = {
63
74
  'arrow': EdgeArrowLayer
64
75
  };
65
76
 
77
+ type GridLayerOverrides = Partial<Omit<GridLayerProps, 'id' | 'data' | 'direction'>>;
78
+
79
+ export type RankGridConfig = {
80
+ enabled?: boolean;
81
+ direction?: 'horizontal' | 'vertical';
82
+ maxLines?: number;
83
+ rankAccessor?: RankAccessor;
84
+ labelAccessor?: LabelAccessor;
85
+ gridProps?: GridLayerOverrides;
86
+ };
87
+
66
88
  const SHARED_LAYER_PROPS = {
67
89
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
68
90
  parameters: {
@@ -75,17 +97,55 @@ const NODE_STYLE_DEPRECATION_MESSAGE =
75
97
  const EDGE_STYLE_DEPRECATION_MESSAGE =
76
98
  'GraphLayer: `edgeStyle` has been replaced by `stylesheet.edges` and will be removed in a future release.';
77
99
 
100
+ const GRAPH_PROP_DEPRECATION_MESSAGE =
101
+ 'GraphLayer: `graph` prop is deprecated. Pass graphs via the `data` prop instead.';
102
+ const LAYOUT_REQUIRED_MESSAGE =
103
+ 'GraphLayer: `layout` must be provided when supplying raw graph data.';
104
+
78
105
  let NODE_STYLE_DEPRECATION_WARNED = false;
79
106
  let EDGE_STYLE_DEPRECATION_WARNED = false;
107
+ let GRAPH_PROP_DEPRECATION_WARNED = false;
108
+ let LAYOUT_REQUIRED_WARNED = false;
80
109
 
81
- export type GraphLayerProps = CompositeLayerProps & _GraphLayerProps;
110
+ export type GraphLayerRawData = {
111
+ name?: string;
112
+ nodes?: unknown[] | null;
113
+ edges?: unknown[] | null;
114
+ };
115
+
116
+ export type GraphLayerDataInput =
117
+ | GraphEngine
118
+ | Graph
119
+ | GraphLayerRawData
120
+ | unknown[]
121
+ | string
122
+ | null;
123
+
124
+ export type GraphLayerProps = CompositeLayerProps &
125
+ _GraphLayerProps & {
126
+ data?: GraphLayerDataInput | Promise<GraphLayerDataInput>;
127
+ };
128
+
129
+ type EngineResolutionFlags = {
130
+ force: boolean;
131
+ dataChanged: boolean;
132
+ layoutChanged: boolean;
133
+ graphChanged: boolean;
134
+ engineChanged: boolean;
135
+ loaderChanged: boolean;
136
+ };
82
137
 
83
138
  export type _GraphLayerProps = {
84
139
  graph?: Graph;
85
140
  layout?: GraphLayout;
86
- graphLoader?: (opts: {json: any}) => Graph;
141
+ graphLoader?: (opts: {json: unknown}) => Graph | null;
87
142
  engine?: GraphEngine;
88
143
 
144
+ onLayoutStart?: (detail?: GraphLayoutEventDetail) => void;
145
+ onLayoutChange?: (detail?: GraphLayoutEventDetail) => void;
146
+ onLayoutDone?: (detail?: GraphLayoutEventDetail) => void;
147
+ onLayoutError?: (error?: unknown) => void;
148
+
89
149
  stylesheet?: GraphLayerStylesheet;
90
150
  /** @deprecated Use `stylesheet.nodes`. */
91
151
  nodeStyle?: GraphLayerNodeStyle[];
@@ -103,19 +163,24 @@ export type _GraphLayerProps = {
103
163
  onHover: () => void;
104
164
  };
105
165
  enableDragging?: boolean;
166
+ rankGrid?: boolean | RankGridConfig;
167
+ resumeLayoutAfterDragging?: boolean;
106
168
  };
107
169
 
108
170
  /** Composite layer that renders graph nodes, edges, and decorators. */
109
171
  export class GraphLayer extends CompositeLayer<GraphLayerProps> {
110
172
  static layerName = 'GraphLayer';
111
173
 
112
- static defaultProps: Required<_GraphLayerProps> = {
174
+ static defaultProps: Required<_GraphLayerProps> & {
175
+ data: {type: string; value: null; async: true};
176
+ } = {
113
177
  // Composite layer props
114
178
  // @ts-expect-error composite layer props
115
179
  pickable: true,
180
+ data: {type: 'object', value: null, async: true},
116
181
 
117
182
  // Graph props
118
- graphLoader: JSONLoader,
183
+ graphLoader: JSONGraphLoader,
119
184
 
120
185
  stylesheet: DEFAULT_GRAPH_LAYER_STYLESHEET,
121
186
  nodeStyle: undefined as unknown as GraphLayerNodeStyle[],
@@ -131,22 +196,30 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
131
196
  onClick: () => {},
132
197
  onHover: () => {}
133
198
  },
134
- enableDragging: false
199
+ enableDragging: false,
200
+ rankGrid: false,
201
+ resumeLayoutAfterDragging: true
135
202
  };
136
203
 
137
204
  // @ts-expect-error Some typescript confusion due to override of base class state
138
205
  state!: CompositeLayer<GraphLayerProps>['state'] & {
139
206
  interactionManager: InteractionManager;
140
- graphEngine?: GraphEngine;
207
+ graphEngine?: GraphEngine | null;
208
+ layoutVersion: number;
209
+ layoutState?: string;
210
+ interactionVersion: number;
141
211
  };
142
212
 
143
213
  private readonly _edgeAttachmentHelper = new EdgeAttachmentHelper();
214
+ private _suppressNextDeckDataChange = false;
144
215
 
145
216
  forceUpdate = () => {
146
- if (this.context && this.context.layerManager) {
147
- this.setNeedsUpdate();
148
- this.setChangeFlags({dataChanged: true} as any); // TODO
217
+ if (!this.state) {
218
+ return;
149
219
  }
220
+
221
+ this.setNeedsRedraw();
222
+ this.setState({interactionVersion: this.state.interactionVersion + 1});
150
223
  };
151
224
 
152
225
  constructor(props: GraphLayerProps & CompositeLayerProps) {
@@ -154,44 +227,70 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
154
227
  }
155
228
 
156
229
  initializeState() {
230
+ const interactionManager = new InteractionManager(
231
+ {
232
+ nodeEvents: this.props.nodeEvents,
233
+ edgeEvents: this.props.edgeEvents,
234
+ engine: undefined as any,
235
+ enableDragging: Boolean(this.props.enableDragging),
236
+ resumeLayoutAfterDragging: Boolean(
237
+ this.props.resumeLayoutAfterDragging ?? GraphLayer.defaultProps.resumeLayoutAfterDragging
238
+ )
239
+ },
240
+ () => this.forceUpdate()
241
+ );
242
+
157
243
  this.state = {
158
- interactionManager: new InteractionManager(this.props as any, () => this.forceUpdate())
159
- };
160
- const engine = this.props.engine;
161
- this._setGraphEngine(engine);
244
+ interactionManager,
245
+ graphEngine: null,
246
+ layoutVersion: 0,
247
+ layoutState: undefined,
248
+ interactionVersion: 0
249
+ } as typeof this.state;
250
+
251
+ this._syncInteractionManager(this.props, null);
252
+ this._refreshEngineFromProps(this.props, {force: true});
162
253
  }
163
254
 
164
255
  shouldUpdateState({changeFlags}) {
165
- return changeFlags.dataChanged || changeFlags.propsChanged;
256
+ return changeFlags.dataChanged || changeFlags.propsChanged || changeFlags.stateChanged;
166
257
  }
167
258
 
168
259
  updateState({props, oldProps, changeFlags}) {
169
- if (
170
- changeFlags.dataChanged &&
171
- props.data &&
172
- !(Array.isArray(props.data) && props.data.length === 0)
173
- ) {
174
- // console.log(props.data);
175
- const graph = this.props.graphLoader({json: props.data});
176
- const layout = this.props.layout;
177
- const graphEngine = new GraphEngine({graph, layout});
178
- this._setGraphEngine(graphEngine);
179
- this.state.interactionManager.updateProps(props);
180
- this.forceUpdate();
181
- } else if (changeFlags.propsChanged && props.graph !== oldProps.graph) {
182
- const graphEngine = new GraphEngine({graph: props.graph, layout: props.layout});
183
- this._setGraphEngine(graphEngine);
184
- this.state.interactionManager.updateProps(props);
185
- this.forceUpdate();
186
- } else if (changeFlags.propsChanged && props.engine !== oldProps.engine) {
187
- this._setGraphEngine(props.engine);
188
- this.state.interactionManager.updateProps(props);
189
- this.forceUpdate();
260
+ const propsDataChanged = props.data !== oldProps.data;
261
+ const deckDataChanged =
262
+ changeFlags.dataChanged && !(this._suppressNextDeckDataChange && !propsDataChanged);
263
+ const dataChanged = deckDataChanged || propsDataChanged;
264
+ const layoutChanged = props.layout !== oldProps.layout;
265
+ const graphChanged = props.graph !== oldProps.graph;
266
+ const engineChanged = props.engine !== oldProps.engine;
267
+ const loaderChanged = props.graphLoader !== oldProps.graphLoader;
268
+
269
+ const engineRefreshed = this._refreshEngineFromProps(props, {
270
+ dataChanged,
271
+ layoutChanged,
272
+ graphChanged,
273
+ engineChanged,
274
+ loaderChanged
275
+ });
276
+
277
+ if (!engineRefreshed && changeFlags.propsChanged) {
278
+ const engine = this.state.graphEngine;
279
+ if (engine) {
280
+ this._applyGraphEngineCallbacks(engine);
281
+ }
190
282
  }
283
+
284
+ if (!engineRefreshed && (changeFlags.propsChanged || changeFlags.stateChanged)) {
285
+ this._syncInteractionManager(props, this.state.graphEngine ?? null);
286
+ }
287
+
288
+ this._suppressNextDeckDataChange = false;
191
289
  }
192
290
 
193
291
  finalize() {
194
292
  this._removeGraphEngine();
293
+ this._syncInteractionManager(this.props, null);
195
294
  }
196
295
 
197
296
  private _getResolvedStylesheet(): NormalizedGraphLayerStylesheet {
@@ -216,9 +315,12 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
216
315
  });
217
316
  }
218
317
 
219
- private _createStyleEngine(style: GraphStylesheet, context: string): GraphStyleEngine | null {
318
+ private _createStylesheetEngine(
319
+ style: GraphStylesheet,
320
+ context: string
321
+ ): GraphStylesheetEngine | null {
220
322
  try {
221
- return new GraphStyleEngine(style, {
323
+ return new GraphStylesheetEngine(style, {
222
324
  stateUpdateTrigger: (this.state.interactionManager as any).getLastInteraction()
223
325
  });
224
326
  } catch (error) {
@@ -228,26 +330,477 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
228
330
  }
229
331
  }
230
332
 
231
- _setGraphEngine(graphEngine: GraphEngine) {
333
+ private _refreshEngineFromProps(
334
+ props: GraphLayerProps,
335
+ {
336
+ force = false,
337
+ dataChanged = false,
338
+ layoutChanged = false,
339
+ graphChanged = false,
340
+ engineChanged = false,
341
+ loaderChanged = false
342
+ }: {
343
+ force?: boolean;
344
+ dataChanged?: boolean;
345
+ layoutChanged?: boolean;
346
+ graphChanged?: boolean;
347
+ engineChanged?: boolean;
348
+ loaderChanged?: boolean;
349
+ }
350
+ ): boolean {
351
+ const {engine: nextEngine, shouldReplace} = this._resolveEngineCandidate(props, {
352
+ force,
353
+ dataChanged,
354
+ layoutChanged,
355
+ graphChanged,
356
+ engineChanged,
357
+ loaderChanged
358
+ });
359
+
360
+ if (nextEngine === undefined) {
361
+ return false;
362
+ }
363
+
364
+ const currentEngine = this.state.graphEngine ?? null;
365
+ if (!shouldReplace && nextEngine === currentEngine) {
366
+ return false;
367
+ }
368
+
369
+ this._setGraphEngine(nextEngine);
370
+ this._syncInteractionManager(props, nextEngine);
371
+ return true;
372
+ }
373
+
374
+ private _resolveEngineCandidate(
375
+ props: GraphLayerProps,
376
+ flags: EngineResolutionFlags
377
+ ): {engine: GraphEngine | null | undefined; shouldReplace: boolean} {
378
+ const dataResult = this._getEngineFromData(props, flags);
379
+ if (dataResult) {
380
+ return dataResult;
381
+ }
382
+
383
+ const engineResult = this._getEngineFromEngineProp(props, flags);
384
+ if (engineResult) {
385
+ return engineResult;
386
+ }
387
+
388
+ const graphResult = this._getEngineFromGraphProp(props, flags);
389
+ if (graphResult) {
390
+ return graphResult;
391
+ }
392
+
393
+ if (props.data === null || props.graph === null || props.engine === null || flags.force) {
394
+ return {engine: null, shouldReplace: true};
395
+ }
396
+
397
+ return {engine: undefined, shouldReplace: flags.force};
398
+ }
399
+
400
+ private _getEngineFromData(
401
+ props: GraphLayerProps,
402
+ {force, dataChanged, layoutChanged, loaderChanged}: EngineResolutionFlags
403
+ ): {engine: GraphEngine | null | undefined; shouldReplace: boolean} | null {
404
+ const dataValue = props.data as GraphLayerDataInput | null | undefined;
405
+ if (dataValue === null || typeof dataValue === 'undefined') {
406
+ return null;
407
+ }
408
+
409
+ const shouldRebuild = force || dataChanged || layoutChanged || loaderChanged;
410
+ if (!shouldRebuild) {
411
+ return {engine: undefined, shouldReplace: false};
412
+ }
413
+
414
+ const engine = this._deriveEngineFromData(dataValue, props);
415
+ if (typeof engine === 'undefined') {
416
+ return {engine: undefined, shouldReplace: false};
417
+ }
418
+
419
+ return {
420
+ engine,
421
+ shouldReplace: true
422
+ };
423
+ }
424
+
425
+ private _getEngineFromEngineProp(
426
+ props: GraphLayerProps,
427
+ {force, engineChanged}: EngineResolutionFlags
428
+ ): {engine: GraphEngine | null | undefined; shouldReplace: boolean} | null {
429
+ if (typeof props.engine === 'undefined') {
430
+ return null;
431
+ }
432
+
433
+ if (props.engine === null) {
434
+ return {engine: null, shouldReplace: true};
435
+ }
436
+
437
+ return {
438
+ engine: props.engine,
439
+ shouldReplace: force || engineChanged
440
+ };
441
+ }
442
+
443
+ private _getEngineFromGraphProp(
444
+ props: GraphLayerProps,
445
+ {force, graphChanged, layoutChanged}: EngineResolutionFlags
446
+ ): {engine: GraphEngine | null | undefined; shouldReplace: boolean} | null {
447
+ if (typeof props.graph === 'undefined') {
448
+ return null;
449
+ }
450
+
451
+ if (props.graph === null) {
452
+ return {engine: null, shouldReplace: true};
453
+ }
454
+
455
+ this._warnGraphProp();
456
+ return {
457
+ engine: this._buildEngineFromGraph(props.graph, props.layout),
458
+ shouldReplace: force || graphChanged || layoutChanged
459
+ };
460
+ }
461
+
462
+ private _deriveEngineFromData(
463
+ data: GraphLayerDataInput,
464
+ props: GraphLayerProps
465
+ ): GraphEngine | null | undefined {
466
+ if (data === null || typeof data === 'undefined') {
467
+ return null;
468
+ }
469
+
470
+ if (typeof (data as PromiseLike<GraphLayerDataInput>)?.then === 'function') {
471
+ return undefined;
472
+ }
473
+
474
+ if (data instanceof GraphEngine) {
475
+ return data;
476
+ }
477
+
478
+ const graphCandidate = this._coerceGraph(data);
479
+ if (graphCandidate) {
480
+ return this._buildEngineFromGraph(graphCandidate, props.layout);
481
+ }
482
+
483
+ if (typeof data === 'string') {
484
+ return undefined;
485
+ }
486
+
487
+ if (Array.isArray(data) || isPlainObject(data)) {
488
+ const loader = props.graphLoader ?? JSONGraphLoader;
489
+ const graph = loader({json: data});
490
+ if (!graph) {
491
+ return null;
492
+ }
493
+ return this._buildEngineFromGraph(graph, props.layout);
494
+ }
495
+
496
+ return null;
497
+ }
498
+
499
+ private _buildEngineFromGraph(
500
+ graph: Graph | null,
501
+ layout?: GraphLayout | null
502
+ ): GraphEngine | null {
503
+ if (!graph) {
504
+ return null;
505
+ }
506
+
507
+ if (!layout) {
508
+ this._warnLayoutRequired();
509
+ return null;
510
+ }
511
+
512
+ if (graph instanceof ClassicGraph && layout instanceof GraphLayout) {
513
+ return new GraphEngine({graph, layout});
514
+ }
515
+
516
+ if (layout instanceof GraphLayout && !(graph instanceof ClassicGraph)) {
517
+ const legacyGraph = this._convertToClassicGraph(graph);
518
+ if (legacyGraph) {
519
+ return new GraphEngine({graph: legacyGraph, layout});
520
+ }
521
+ this._warnLayoutRequired();
522
+ return null;
523
+ }
524
+
525
+ if (layout) {
526
+ return new GraphEngine({graph, layout});
527
+ }
528
+
529
+ this._warnLayoutRequired();
530
+ return null;
531
+ }
532
+
533
+ private _syncInteractionManager(props: GraphLayerProps, engine: GraphEngine | null) {
534
+ const resumeLayoutAfterDragging =
535
+ props.resumeLayoutAfterDragging ?? GraphLayer.defaultProps.resumeLayoutAfterDragging;
536
+
537
+ this.state.interactionManager.updateProps({
538
+ nodeEvents: props.nodeEvents ?? GraphLayer.defaultProps.nodeEvents,
539
+ edgeEvents: props.edgeEvents ?? GraphLayer.defaultProps.edgeEvents,
540
+ engine: (engine ?? props.engine ?? null) as any,
541
+ enableDragging: Boolean(props.enableDragging),
542
+ resumeLayoutAfterDragging: Boolean(resumeLayoutAfterDragging)
543
+ });
544
+ }
545
+
546
+ private _warnGraphProp() {
547
+ if (!GRAPH_PROP_DEPRECATION_WARNED) {
548
+ warn(GRAPH_PROP_DEPRECATION_MESSAGE);
549
+ GRAPH_PROP_DEPRECATION_WARNED = true;
550
+ }
551
+ }
552
+
553
+ private _warnLayoutRequired() {
554
+ if (!LAYOUT_REQUIRED_WARNED) {
555
+ warn(LAYOUT_REQUIRED_MESSAGE);
556
+ LAYOUT_REQUIRED_WARNED = true;
557
+ }
558
+ }
559
+
560
+ private _isGraph(value: unknown): value is Graph {
561
+ if (!value || typeof value !== 'object') {
562
+ return false;
563
+ }
564
+
565
+ const candidate = value as Graph;
566
+ return (
567
+ typeof candidate.getNodes === 'function' && typeof candidate.getEdges === 'function'
568
+ );
569
+ }
570
+
571
+ private _coerceGraph(value: unknown): Graph | null {
572
+ if (value instanceof ClassicGraph) {
573
+ return value;
574
+ }
575
+
576
+ if (this._isGraph(value)) {
577
+ return value;
578
+ }
579
+
580
+ return null;
581
+ }
582
+
583
+ private _convertToClassicGraph(graph: Graph): ClassicGraph | null {
584
+ if (graph instanceof ClassicGraph) {
585
+ return graph;
586
+ }
587
+
588
+ const candidate = graph as Graph & {toClassicGraph?: () => ClassicGraph | null};
589
+ if (typeof candidate.toClassicGraph === 'function') {
590
+ try {
591
+ return candidate.toClassicGraph() ?? null;
592
+ } catch (error) {
593
+ warn('GraphLayer: failed to convert graph to ClassicGraph for layout compatibility.', error);
594
+ }
595
+ }
596
+
597
+ return null;
598
+ }
599
+
600
+ private _updateLayoutSnapshot(engine?: GraphEngine | null) {
601
+ const activeEngine = engine ?? this.state.graphEngine ?? null;
602
+
603
+ if (!activeEngine) {
604
+ if (this.state.layoutVersion !== 0 || typeof this.state.layoutState !== 'undefined') {
605
+ this._suppressNextDeckDataChange = true;
606
+ this.setState({layoutVersion: 0, layoutState: undefined});
607
+ }
608
+ this.setNeedsRedraw();
609
+ return;
610
+ }
611
+
612
+ const nextVersion = activeEngine.getLayoutLastUpdate();
613
+ const nextState = activeEngine.getLayoutState();
614
+
615
+ if (this.state.layoutVersion !== nextVersion || this.state.layoutState !== nextState) {
616
+ this._suppressNextDeckDataChange = true;
617
+ this.setState({layoutVersion: nextVersion, layoutState: nextState});
618
+ }
619
+
620
+ this.setNeedsRedraw();
621
+ }
622
+
623
+ private _handleLayoutEvent = () => {
624
+ this._updateLayoutSnapshot();
625
+ };
626
+
627
+ _setGraphEngine(graphEngine: GraphEngine | null) {
232
628
  if (graphEngine === this.state.graphEngine) {
629
+ if (graphEngine) {
630
+ this._applyGraphEngineCallbacks(graphEngine);
631
+ }
632
+ this._updateLayoutSnapshot(graphEngine);
233
633
  return;
234
634
  }
235
635
 
236
636
  this._removeGraphEngine();
637
+
237
638
  if (graphEngine) {
238
639
  this.state.graphEngine = graphEngine;
239
- this.state.graphEngine.run();
240
- // added or removed a node, or in general something layout related changed
241
- this.state.graphEngine.addEventListener('onLayoutChange', this.forceUpdate);
640
+ this._applyGraphEngineCallbacks(graphEngine);
641
+ graphEngine.run();
642
+ this._updateLayoutSnapshot(graphEngine);
643
+ } else {
644
+ this.state.graphEngine = null;
645
+ this._updateLayoutSnapshot(null);
242
646
  }
243
647
  }
244
648
 
245
649
  _removeGraphEngine() {
246
- if (this.state.graphEngine) {
247
- this.state.graphEngine.removeEventListener('onLayoutChange', this.forceUpdate);
248
- this.state.graphEngine.clear();
650
+ const engine = this.state.graphEngine;
651
+ if (engine) {
652
+ engine.setProps({
653
+ onLayoutStart: undefined,
654
+ onLayoutChange: undefined,
655
+ onLayoutDone: undefined,
656
+ onLayoutError: undefined
657
+ });
658
+ engine.clear();
249
659
  this.state.graphEngine = null;
660
+ this._updateLayoutSnapshot(null);
661
+ }
662
+ }
663
+
664
+ private _applyGraphEngineCallbacks(engine: GraphEngine) {
665
+ engine.setProps({
666
+ onLayoutStart: (detail) => {
667
+ this._handleLayoutEvent();
668
+ this.props.onLayoutStart?.(detail);
669
+ },
670
+ onLayoutChange: (detail) => {
671
+ this._handleLayoutEvent();
672
+ this.props.onLayoutChange?.(detail);
673
+ },
674
+ onLayoutDone: (detail) => {
675
+ this._handleLayoutEvent();
676
+ this.props.onLayoutDone?.(detail);
677
+ },
678
+ onLayoutError: (error) => {
679
+ this._handleLayoutEvent();
680
+ this.props.onLayoutError?.(error);
681
+ }
682
+ });
683
+ }
684
+
685
+ private _createRankGridLayer(): GridLayer | null {
686
+ const engine = this.state.graphEngine;
687
+ if (!engine) {
688
+ return null;
689
+ }
690
+
691
+ const {enabled, config} = this._normalizeRankGridConfig(this.props.rankGrid);
692
+ if (!enabled) {
693
+ return null;
694
+ }
695
+
696
+ const bounds = this._resolveRankGridBounds(engine);
697
+ if (!bounds) {
698
+ return null;
699
+ }
700
+
701
+ const data = this._buildRankGridData(engine, config, bounds);
702
+ if (!data) {
703
+ return null;
704
+ }
705
+
706
+ const direction = config?.direction ?? 'horizontal';
707
+ const gridProps = config?.gridProps ?? {};
708
+
709
+ return new GridLayer({
710
+ id: `${this.props.id}-rank-grid`,
711
+ data,
712
+ direction,
713
+ xMin: bounds.xMin,
714
+ xMax: bounds.xMax,
715
+ yMin: bounds.yMin,
716
+ yMax: bounds.yMax,
717
+ pickable: false,
718
+ ...gridProps
719
+ });
720
+ }
721
+
722
+ private _normalizeRankGridConfig(
723
+ value: GraphLayerProps['rankGrid']
724
+ ): {enabled: boolean; config?: RankGridConfig} {
725
+ if (typeof value === 'boolean') {
726
+ return {enabled: value};
727
+ }
728
+
729
+ if (value && typeof value === 'object') {
730
+ return {enabled: value.enabled ?? true, config: value};
731
+ }
732
+
733
+ return {enabled: false};
734
+ }
735
+
736
+ private _resolveRankGridBounds(engine: GraphEngine):
737
+ | {xMin: number; xMax: number; yMin: number; yMax: number}
738
+ | null {
739
+ const bounds = engine.getLayoutBounds();
740
+ if (!bounds) {
741
+ return null;
742
+ }
743
+
744
+ const [[minXRaw, minYRaw], [maxXRaw, maxYRaw]] = bounds;
745
+ const values = [minXRaw, minYRaw, maxXRaw, maxYRaw];
746
+ if (!values.every((value) => typeof value === 'number' && Number.isFinite(value))) {
747
+ return null;
748
+ }
749
+
750
+ return {
751
+ xMin: Math.min(minXRaw, maxXRaw),
752
+ xMax: Math.max(minXRaw, maxXRaw),
753
+ yMin: Math.min(minYRaw, maxYRaw),
754
+ yMax: Math.max(minYRaw, maxYRaw)
755
+ };
756
+ }
757
+
758
+ private _buildRankGridData(
759
+ engine: GraphEngine,
760
+ config: RankGridConfig | undefined,
761
+ bounds: {yMin: number; yMax: number}
762
+ ): Array<{label: string; rank: number; originalLabel?: string | number; yPosition: number}> | null {
763
+ const rankLabelPrefix = this._resolveRankFieldLabel(config?.rankAccessor);
764
+ // @ts-ignore iterator type
765
+ const rankPositions = mapRanksToYPositions(engine.getNodes(), engine.getNodePosition, {
766
+ rankAccessor: config?.rankAccessor,
767
+ labelAccessor: config?.labelAccessor,
768
+ yRange: {min: bounds.yMin, max: bounds.yMax}
769
+ });
770
+
771
+ if (rankPositions.length === 0) {
772
+ return null;
773
+ }
774
+
775
+ const selectedRanks = selectRankLines(rankPositions, {
776
+ yMin: bounds.yMin,
777
+ yMax: bounds.yMax,
778
+ maxCount: config?.maxLines ?? 8
779
+ });
780
+
781
+ if (selectedRanks.length === 0) {
782
+ return null;
783
+ }
784
+
785
+ return selectedRanks.map(({rank, label, yPosition}) => ({
786
+ label: `${rankLabelPrefix} ${rank}`,
787
+ rank,
788
+ originalLabel: label === undefined ? undefined : label,
789
+ yPosition
790
+ }));
791
+ }
792
+
793
+ private _resolveRankFieldLabel(rankAccessor: RankAccessor | undefined): string {
794
+ if (!rankAccessor) {
795
+ return 'srank';
796
+ }
797
+ if (typeof rankAccessor === 'string' && rankAccessor.length > 0) {
798
+ return rankAccessor;
799
+ }
800
+ if (typeof rankAccessor === 'function' && rankAccessor.name) {
801
+ return rankAccessor.name;
250
802
  }
803
+ return 'rank';
251
804
  }
252
805
 
253
806
  createNodeLayers() {
@@ -267,7 +820,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
267
820
  warn(`GraphLayer: Invalid node type "${style.type}".`);
268
821
  return null;
269
822
  }
270
- const stylesheet = this._createStyleEngine(
823
+ const stylesheet = this._createStylesheetEngine(
271
824
  restStyle as unknown as GraphStylesheet,
272
825
  `node stylesheet "${style.type}"`
273
826
  );
@@ -321,7 +874,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
321
874
  .filter(Boolean)
322
875
  .flatMap((style, idx) => {
323
876
  const {decorators, data = (edges) => edges, visible = true, ...restEdgeStyle} = style;
324
- const stylesheet = this._createStyleEngine(
877
+ const stylesheet = this._createStylesheetEngine(
325
878
  {
326
879
  type: 'edge',
327
880
  ...restEdgeStyle
@@ -349,13 +902,14 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
349
902
 
350
903
  const decoratorLayers = decorators
351
904
  .filter(Boolean)
905
+ // @ts-ignore eslint-disable-next-line @typescript-eslint/no-unused-vars
352
906
  .map((decoratorStyle, idx2) => {
353
907
  const DecoratorLayer = EDGE_DECORATOR_LAYER_MAP[decoratorStyle.type];
354
908
  if (!DecoratorLayer) {
355
909
  warn(`GraphLayer: Invalid edge decorator type "${decoratorStyle.type}".`);
356
910
  return null;
357
911
  }
358
- const decoratorStylesheet = this._createStyleEngine(
912
+ const decoratorStylesheet = this._createStylesheetEngine(
359
913
  decoratorStyle as unknown as GraphStylesheet,
360
914
  `edge decorator stylesheet "${decoratorStyle.type}"`
361
915
  );
@@ -399,7 +953,23 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
399
953
  }
400
954
 
401
955
  renderLayers() {
402
- return [this.createEdgeLayers(), this.createNodeLayers()];
956
+ const layers: any[] = [];
957
+ const gridLayer = this._createRankGridLayer();
958
+ if (gridLayer) {
959
+ layers.push(gridLayer);
960
+ }
961
+
962
+ const edgeLayers = this.createEdgeLayers();
963
+ if (Array.isArray(edgeLayers) && edgeLayers.length > 0) {
964
+ layers.push(...edgeLayers);
965
+ }
966
+
967
+ const nodeLayers = this.createNodeLayers();
968
+ if (Array.isArray(nodeLayers) && nodeLayers.length > 0) {
969
+ layers.push(...nodeLayers);
970
+ }
971
+
972
+ return layers;
403
973
  }
404
974
 
405
975
  private _createChainOverlayLayers(engine: GraphEngine) {
@@ -425,7 +995,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
425
995
  ...SHARED_LAYER_PROPS,
426
996
  id: 'collapsed-chain-outlines',
427
997
  data: collapsedOutlineNodes,
428
- getPolygon: (node: Node) => getChainOutlinePolygon(node),
998
+ getPolygon: (node: NodeInterface) => getChainOutlinePolygon(node),
429
999
  stroked: true,
430
1000
  filled: false,
431
1001
  getLineColor: [220, 64, 64, 220],
@@ -440,7 +1010,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
440
1010
  );
441
1011
  }
442
1012
 
443
- const collapsedMarkerStylesheet = this._createStyleEngine(
1013
+ const collapsedMarkerStylesheet = this._createStylesheetEngine(
444
1014
  {
445
1015
  type: 'marker',
446
1016
  fill: [64, 96, 192, 255],
@@ -478,7 +1048,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
478
1048
  ...SHARED_LAYER_PROPS,
479
1049
  id: 'expanded-chain-outlines',
480
1050
  data: expandedOutlineNodes,
481
- getPolygon: (node: Node) => getChainOutlinePolygon(node),
1051
+ getPolygon: (node: NodeInterface) => getChainOutlinePolygon(node),
482
1052
  stroked: true,
483
1053
  filled: false,
484
1054
  getLineColor: [64, 96, 192, 200],
@@ -493,7 +1063,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
493
1063
  );
494
1064
  }
495
1065
 
496
- const expandedMarkerStylesheet = this._createStyleEngine(
1066
+ const expandedMarkerStylesheet = this._createStylesheetEngine(
497
1067
  {
498
1068
  type: 'marker',
499
1069
  fill: [64, 96, 192, 255],
@@ -528,3 +1098,13 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
528
1098
  return layers;
529
1099
  }
530
1100
  }
1101
+
1102
+ function isPlainObject(value: unknown): value is Record<string | number | symbol, unknown> {
1103
+ if (!value || typeof value !== 'object') {
1104
+ return false;
1105
+ }
1106
+
1107
+ const prototype = Object.getPrototypeOf(value);
1108
+ return prototype === Object.prototype || prototype === null;
1109
+ }
1110
+