@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.
- package/dist/core/graph-engine.d.ts +63 -21
- package/dist/core/graph-engine.d.ts.map +1 -1
- package/dist/core/graph-engine.js +155 -75
- package/dist/core/graph-engine.js.map +1 -1
- package/dist/core/graph-layout.d.ts +22 -18
- package/dist/core/graph-layout.d.ts.map +1 -1
- package/dist/core/graph-layout.js +33 -18
- package/dist/core/graph-layout.js.map +1 -1
- package/dist/core/interaction-manager.d.ts +2 -2
- package/dist/core/interaction-manager.d.ts.map +1 -1
- package/dist/core/interaction-manager.js +7 -5
- package/dist/core/interaction-manager.js.map +1 -1
- package/dist/graph/arrow-graph.d.ts +69 -0
- package/dist/graph/arrow-graph.d.ts.map +1 -0
- package/dist/graph/arrow-graph.js +513 -0
- package/dist/graph/arrow-graph.js.map +1 -0
- package/dist/graph/classic-graph.d.ts +169 -0
- package/dist/graph/classic-graph.d.ts.map +1 -0
- package/dist/graph/classic-graph.js +390 -0
- package/dist/graph/classic-graph.js.map +1 -0
- package/dist/graph/edge.d.ts +6 -6
- package/dist/graph/edge.d.ts.map +1 -1
- package/dist/graph/edge.js.map +1 -1
- package/dist/graph/functions/arrow-utils.d.ts +6 -0
- package/dist/graph/functions/arrow-utils.d.ts.map +1 -0
- package/dist/graph/functions/arrow-utils.js +67 -0
- package/dist/graph/functions/arrow-utils.js.map +1 -0
- package/dist/graph/functions/create-graph-from-data.d.ts +3 -0
- package/dist/graph/functions/create-graph-from-data.d.ts.map +1 -0
- package/dist/graph/functions/create-graph-from-data.js +12 -0
- package/dist/graph/functions/create-graph-from-data.js.map +1 -0
- package/dist/graph/graph-normalization.d.ts +10 -0
- package/dist/graph/graph-normalization.d.ts.map +1 -0
- package/dist/graph/graph-normalization.js +65 -0
- package/dist/graph/graph-normalization.js.map +1 -0
- package/dist/graph/graph.d.ts +62 -155
- package/dist/graph/graph.d.ts.map +1 -1
- package/dist/graph/graph.js +11 -300
- package/dist/graph/graph.js.map +1 -1
- package/dist/graph/node.d.ts +6 -6
- package/dist/graph/node.d.ts.map +1 -1
- package/dist/graph/node.js +2 -2
- package/dist/graph/node.js.map +1 -1
- package/dist/graph-data/arrow-graph-data-builder.d.ts +21 -0
- package/dist/graph-data/arrow-graph-data-builder.d.ts.map +1 -0
- package/dist/graph-data/arrow-graph-data-builder.js +105 -0
- package/dist/graph-data/arrow-graph-data-builder.js.map +1 -0
- package/dist/graph-data/graph-data-builder.d.ts +6 -0
- package/dist/graph-data/graph-data-builder.d.ts.map +1 -0
- package/dist/graph-data/graph-data-builder.js +1 -0
- package/dist/graph-data/graph-data-builder.js.map +1 -0
- package/dist/graph-data/graph-data.d.ts +40 -0
- package/dist/graph-data/graph-data.d.ts.map +1 -0
- package/dist/graph-data/graph-data.js +11 -0
- package/dist/graph-data/graph-data.js.map +1 -0
- package/dist/graph-data/plain-graph-data-builder.d.ts +20 -0
- package/dist/graph-data/plain-graph-data-builder.d.ts.map +1 -0
- package/dist/graph-data/plain-graph-data-builder.js +105 -0
- package/dist/graph-data/plain-graph-data-builder.js.map +1 -0
- package/dist/graph-style-schema.cdn.js +1 -1
- package/dist/graph-style-schema.json +1 -1
- package/dist/index.cjs +6905 -4576
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +14 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -11
- package/dist/index.js.map +1 -1
- package/dist/layers/common-layers/flow-path-layer/flow-path-layer.d.ts.map +1 -1
- package/dist/layers/common-layers/flow-path-layer/flow-path-layer.js +1 -2
- package/dist/layers/common-layers/flow-path-layer/flow-path-layer.js.map +1 -1
- package/dist/layers/common-layers/grid-layer/grid-layer.d.ts +83 -0
- package/dist/layers/common-layers/grid-layer/grid-layer.d.ts.map +1 -0
- package/dist/layers/common-layers/grid-layer/grid-layer.js +133 -0
- package/dist/layers/common-layers/grid-layer/grid-layer.js.map +1 -0
- package/dist/layers/edge-attachment-helper.d.ts.map +1 -1
- package/dist/layers/edge-attachment-helper.js +1 -2
- package/dist/layers/edge-attachment-helper.js.map +1 -1
- package/dist/layers/graph-layer.d.ts +68 -11
- package/dist/layers/graph-layer.d.ts.map +1 -1
- package/dist/layers/graph-layer.js +435 -50
- package/dist/layers/graph-layer.js.map +1 -1
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.d.ts +24 -0
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.d.ts.map +1 -0
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.js +251 -0
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.js.map +1 -0
- package/dist/layouts/d3-dag/d3-dag-layout.d.ts +46 -61
- package/dist/layouts/d3-dag/d3-dag-layout.d.ts.map +1 -1
- package/dist/layouts/d3-dag/d3-dag-layout.js +85 -270
- package/dist/layouts/d3-dag/d3-dag-layout.js.map +1 -1
- package/dist/layouts/d3-force/d3-force-layout.d.ts +20 -8
- package/dist/layouts/d3-force/d3-force-layout.d.ts.map +1 -1
- package/dist/layouts/d3-force/d3-force-layout.js +39 -20
- package/dist/layouts/d3-force/d3-force-layout.js.map +1 -1
- package/dist/layouts/experimental/force-multi-graph-layout.d.ts +19 -15
- package/dist/layouts/experimental/force-multi-graph-layout.d.ts.map +1 -1
- package/dist/layouts/experimental/force-multi-graph-layout.js +47 -38
- package/dist/layouts/experimental/force-multi-graph-layout.js.map +1 -1
- package/dist/layouts/experimental/hive-plot-layout.d.ts +18 -15
- package/dist/layouts/experimental/hive-plot-layout.d.ts.map +1 -1
- package/dist/layouts/experimental/hive-plot-layout.js +33 -34
- package/dist/layouts/experimental/hive-plot-layout.js.map +1 -1
- package/dist/layouts/experimental/radial-layout.d.ts +12 -7
- package/dist/layouts/experimental/radial-layout.d.ts.map +1 -1
- package/dist/layouts/experimental/radial-layout.js +31 -14
- package/dist/layouts/experimental/radial-layout.js.map +1 -1
- package/dist/layouts/gpu-force/gpu-force-layout.d.ts +11 -8
- package/dist/layouts/gpu-force/gpu-force-layout.d.ts.map +1 -1
- package/dist/layouts/gpu-force/gpu-force-layout.js +59 -56
- package/dist/layouts/gpu-force/gpu-force-layout.js.map +1 -1
- package/dist/layouts/simple-layout.d.ts +8 -25
- package/dist/layouts/simple-layout.d.ts.map +1 -1
- package/dist/layouts/simple-layout.js +13 -17
- package/dist/layouts/simple-layout.js.map +1 -1
- package/dist/loaders/dot-graph-loader.d.ts +25 -0
- package/dist/loaders/dot-graph-loader.d.ts.map +1 -0
- package/dist/loaders/dot-graph-loader.js +668 -0
- package/dist/loaders/dot-graph-loader.js.map +1 -0
- package/dist/loaders/json-graph-loader.d.ts +6 -0
- package/dist/loaders/json-graph-loader.d.ts.map +1 -0
- package/dist/loaders/json-graph-loader.js +31 -0
- package/dist/loaders/json-graph-loader.js.map +1 -0
- package/dist/loaders/{edge-parsers.d.ts → parsers/edge-parsers.d.ts} +1 -1
- package/dist/loaders/parsers/edge-parsers.d.ts.map +1 -0
- package/dist/loaders/{edge-parsers.js → parsers/edge-parsers.js} +1 -1
- package/dist/loaders/parsers/edge-parsers.js.map +1 -0
- package/dist/loaders/{node-parsers.d.ts → parsers/node-parsers.d.ts} +1 -1
- package/dist/loaders/parsers/node-parsers.d.ts.map +1 -0
- package/dist/loaders/{node-parsers.js → parsers/node-parsers.js} +1 -1
- package/dist/loaders/parsers/node-parsers.js.map +1 -0
- package/dist/loaders/parsers/parse-json-graph.d.ts +29 -0
- package/dist/loaders/parsers/parse-json-graph.d.ts.map +1 -0
- package/dist/loaders/parsers/parse-json-graph.js +78 -0
- package/dist/loaders/parsers/parse-json-graph.js.map +1 -0
- package/dist/style/graph-style-engine.d.ts +4 -2
- package/dist/style/graph-style-engine.d.ts.map +1 -1
- package/dist/style/graph-style-engine.js +3 -2
- package/dist/style/graph-style-engine.js.map +1 -1
- package/dist/style/{style-engine.d.ts → stylesheet-engine.d.ts} +3 -3
- package/dist/style/stylesheet-engine.d.ts.map +1 -0
- package/dist/style/{style-engine.js → stylesheet-engine.js} +1 -1
- package/dist/style/stylesheet-engine.js.map +1 -0
- package/dist/utils/collapsed-chains.d.ts +8 -8
- package/dist/utils/collapsed-chains.d.ts.map +1 -1
- package/dist/utils/collapsed-chains.js +1 -6
- package/dist/utils/collapsed-chains.js.map +1 -1
- package/dist/utils/rank-grid.d.ts +30 -0
- package/dist/utils/rank-grid.d.ts.map +1 -0
- package/dist/utils/rank-grid.js +306 -0
- package/dist/utils/rank-grid.js.map +1 -0
- package/package.json +4 -8
- package/src/_disabled/arrow-graph-data.ts.disabled +18 -0
- package/src/_disabled/columnar-graph-data-builder.ts.disabled +250 -0
- package/src/_disabled/graph-runtime-layout.ts.disabled +29 -0
- package/src/core/graph-engine.ts +201 -84
- package/src/core/graph-layout.ts +52 -29
- package/src/core/interaction-manager.ts +20 -20
- package/src/graph/arrow-graph.ts +648 -0
- package/src/graph/classic-graph.ts +447 -0
- package/src/graph/edge.ts +7 -7
- package/src/graph/functions/arrow-utils.ts +72 -0
- package/src/graph/functions/convert-arrow-graph-to-classic-graph.ts.disabled +47 -0
- package/src/graph/functions/convert-plain-graph-to-arrow-graph.ts.disabled +119 -0
- package/src/graph/functions/create-graph-from-data.ts +16 -0
- package/src/graph/functions/create-plain-graph-from-data.ts.disabled +176 -0
- package/src/graph/graph-normalization.ts +87 -0
- package/src/graph/graph.ts +68 -339
- package/src/graph/node.ts +9 -9
- package/src/graph/tabular-graph.ts.disabled +761 -0
- package/src/graph-data/arrow-graph-data-builder.ts +165 -0
- package/src/graph-data/graph-data-builder.ts +7 -0
- package/src/graph-data/graph-data.ts +57 -0
- package/src/graph-data/plain-graph-data-builder.ts +132 -0
- package/src/index.ts +53 -13
- package/src/layers/common-layers/flow-path-layer/flow-path-layer.ts +1 -2
- package/src/layers/common-layers/grid-layer/grid-layer.ts +237 -0
- package/src/layers/edge-attachment-helper.ts +22 -16
- package/src/layers/graph-layer.ts +642 -62
- package/src/layouts/d3-dag/collapsable-d3-dag-layout.ts +330 -0
- package/src/layouts/d3-dag/d3-dag-layout.ts +166 -396
- package/src/layouts/d3-force/d3-force-layout.ts +52 -30
- package/src/layouts/experimental/force-multi-graph-layout.ts +55 -49
- package/src/layouts/experimental/hive-plot-layout.ts +41 -42
- package/src/layouts/experimental/radial-layout.ts +39 -20
- package/src/layouts/gpu-force/gpu-force-layout.ts +72 -70
- package/src/layouts/simple-layout.ts +20 -44
- package/src/loaders/{create-graph.ts → deprecated/create-graph.ts.disabled} +6 -6
- package/src/loaders/deprecated/json-classic-graph-loader.ts.disabled +33 -0
- package/src/loaders/{simple-json-graph-loader.ts → deprecated/simple-json-graph-loader.ts.disabled} +3 -3
- package/src/loaders/{table-graph-loader.ts → deprecated/table-graph-loader.ts.disabled} +8 -8
- package/src/loaders/dot-graph-loader.ts +860 -0
- package/src/loaders/json-graph-loader.ts +48 -0
- package/src/loaders/parsers/create-graph-data.ts.disabled +45 -0
- package/src/loaders/{edge-parsers.ts → parsers/edge-parsers.ts} +2 -2
- package/src/loaders/{node-parsers.ts → parsers/node-parsers.ts} +2 -2
- package/src/loaders/parsers/parse-json-graph.ts +134 -0
- package/src/style/graph-style-engine.ts +5 -2
- package/src/style/{style-engine.ts → stylesheet-engine.ts} +3 -3
- package/src/utils/collapsed-chains.ts +11 -17
- package/src/utils/rank-grid.ts +426 -0
- package/dist/loaders/create-graph.d.ts +0 -12
- package/dist/loaders/create-graph.d.ts.map +0 -1
- package/dist/loaders/create-graph.js +0 -38
- package/dist/loaders/create-graph.js.map +0 -1
- package/dist/loaders/edge-parsers.d.ts.map +0 -1
- package/dist/loaders/edge-parsers.js.map +0 -1
- package/dist/loaders/json-loader.d.ts +0 -7
- package/dist/loaders/json-loader.d.ts.map +0 -1
- package/dist/loaders/json-loader.js +0 -16
- package/dist/loaders/json-loader.js.map +0 -1
- package/dist/loaders/node-parsers.d.ts.map +0 -1
- package/dist/loaders/node-parsers.js.map +0 -1
- package/dist/loaders/simple-json-graph-loader.d.ts +0 -11
- package/dist/loaders/simple-json-graph-loader.d.ts.map +0 -1
- package/dist/loaders/simple-json-graph-loader.js +0 -20
- package/dist/loaders/simple-json-graph-loader.js.map +0 -1
- package/dist/loaders/table-graph-loader.d.ts +0 -16
- package/dist/loaders/table-graph-loader.d.ts.map +0 -1
- package/dist/loaders/table-graph-loader.js +0 -91
- package/dist/loaders/table-graph-loader.js.map +0 -1
- package/dist/style/style-engine.d.ts.map +0 -1
- package/dist/style/style-engine.js.map +0 -1
- package/dist/widgets/long-press-button.d.ts +0 -12
- package/dist/widgets/long-press-button.d.ts.map +0 -1
- package/dist/widgets/long-press-button.js +0 -31
- package/dist/widgets/long-press-button.js.map +0 -1
- package/dist/widgets/view-control-widget.d.ts +0 -77
- package/dist/widgets/view-control-widget.d.ts.map +0 -1
- package/dist/widgets/view-control-widget.js +0 -197
- package/dist/widgets/view-control-widget.js.map +0 -1
- package/src/loaders/json-loader.ts +0 -19
- package/src/widgets/long-press-button.tsx +0 -50
- 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
|
|
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 {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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 {
|
|
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
|
|
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:
|
|
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:
|
|
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.
|
|
147
|
-
|
|
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
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
318
|
+
private _createStylesheetEngine(
|
|
319
|
+
style: GraphStylesheet,
|
|
320
|
+
context: string
|
|
321
|
+
): GraphStylesheetEngine | null {
|
|
220
322
|
try {
|
|
221
|
-
return new
|
|
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
|
-
|
|
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.
|
|
240
|
-
|
|
241
|
-
this.
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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:
|
|
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.
|
|
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:
|
|
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.
|
|
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
|
+
|