@deck.gl-community/graph-layers 9.2.0-beta.6 → 9.2.5
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/_deprecated/old-constants.d.ts.map +1 -1
- package/dist/_deprecated/old-constants.js.map +1 -1
- package/dist/core/graph-engine.d.ts +3 -2
- package/dist/core/graph-engine.d.ts.map +1 -1
- package/dist/core/graph-engine.js +1 -0
- package/dist/core/graph-engine.js.map +1 -1
- package/dist/core/graph-layout.d.ts.map +1 -1
- package/dist/core/graph-layout.js.map +1 -1
- package/dist/core/interaction-manager.d.ts.map +1 -1
- package/dist/core/interaction-manager.js.map +1 -1
- package/dist/graph/arrow-graph.d.ts.map +1 -1
- package/dist/graph/arrow-graph.js.map +1 -1
- package/dist/graph/classic-graph.d.ts.map +1 -1
- package/dist/graph/classic-graph.js +1 -3
- package/dist/graph/classic-graph.js.map +1 -1
- package/dist/graph/functions/arrow-utils.d.ts.map +1 -1
- package/dist/graph/functions/arrow-utils.js +5 -3
- package/dist/graph/functions/arrow-utils.js.map +1 -1
- package/dist/graph/functions/create-graph-from-data.d.ts.map +1 -1
- package/dist/graph/functions/create-graph-from-data.js.map +1 -1
- package/dist/graph/graph-normalization.d.ts.map +1 -1
- package/dist/graph/graph-normalization.js.map +1 -1
- package/dist/graph-data/arrow-graph-data-builder.d.ts.map +1 -1
- package/dist/graph-data/arrow-graph-data-builder.js.map +1 -1
- package/dist/graph-data/graph-data-builder.d.ts.map +1 -1
- package/dist/graph-data/plain-graph-data-builder.d.ts.map +1 -1
- package/dist/graph-style-schema.cdn.js +1 -1
- package/dist/graph-style-schema.json +1 -1
- package/dist/index.cjs +332 -224
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layers/common-layers/grid-layer/grid-layer.d.ts.map +1 -1
- package/dist/layers/common-layers/grid-layer/grid-layer.js +6 -16
- package/dist/layers/common-layers/grid-layer/grid-layer.js.map +1 -1
- package/dist/layers/edge-attachment-helper.d.ts.map +1 -1
- package/dist/layers/edge-attachment-helper.js +1 -3
- package/dist/layers/edge-attachment-helper.js.map +1 -1
- package/dist/layers/edge-layer.js +4 -4
- package/dist/layers/edge-layer.js.map +1 -1
- package/dist/layers/edge-layers/arrow-2d-geometry.js +1 -8
- package/dist/layers/edge-layers/arrow-2d-geometry.js.map +1 -1
- package/dist/layers/graph-layer.d.ts +4 -3
- package/dist/layers/graph-layer.d.ts.map +1 -1
- package/dist/layers/graph-layer.js +20 -17
- package/dist/layers/graph-layer.js.map +1 -1
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.d.ts.map +1 -1
- package/dist/layouts/d3-dag/collapsable-d3-dag-layout.js.map +1 -1
- package/dist/layouts/d3-dag/d3-dag-layout.d.ts.map +1 -1
- package/dist/layouts/d3-dag/d3-dag-layout.js +9 -2
- package/dist/layouts/d3-dag/d3-dag-layout.js.map +1 -1
- package/dist/layouts/experimental/radial-layout.d.ts.map +1 -1
- package/dist/layouts/experimental/radial-layout.js.map +1 -1
- package/dist/layouts/simple-layout.d.ts.map +1 -1
- package/dist/layouts/simple-layout.js +4 -1
- package/dist/layouts/simple-layout.js.map +1 -1
- package/dist/loaders/dot-graph-loader.d.ts.map +1 -1
- package/dist/loaders/dot-graph-loader.js +10 -3
- package/dist/loaders/dot-graph-loader.js.map +1 -1
- package/dist/loaders/json-graph-loader.d.ts.map +1 -1
- package/dist/loaders/json-graph-loader.js +2 -2
- package/dist/loaders/json-graph-loader.js.map +1 -1
- package/dist/loaders/parsers/parse-json-graph.js +2 -1
- package/dist/loaders/parsers/parse-json-graph.js.map +1 -1
- package/dist/style/graph-layer-stylesheet.d.ts +14 -5
- package/dist/style/graph-layer-stylesheet.d.ts.map +1 -1
- package/dist/style/graph-layer-stylesheet.js +14 -8
- package/dist/style/graph-layer-stylesheet.js.map +1 -1
- package/dist/style/graph-style-engine.d.ts +4 -4
- package/dist/style/graph-style-engine.d.ts.map +1 -1
- package/dist/style/graph-style-engine.js +7 -5
- package/dist/style/graph-style-engine.js.map +1 -1
- package/dist/style/graph-stylesheet-schema.d.ts +13211 -0
- package/dist/style/graph-stylesheet-schema.d.ts.map +1 -0
- package/dist/style/graph-stylesheet-schema.js +346 -0
- package/dist/style/graph-stylesheet-schema.js.map +1 -0
- package/dist/style/style-property.d.ts.map +1 -1
- package/dist/style/style-property.js +17 -5
- package/dist/style/style-property.js.map +1 -1
- package/dist/style/stylesheet-engine.d.ts.map +1 -1
- package/dist/style/stylesheet-engine.js +1 -1
- package/dist/style/stylesheet-engine.js.map +1 -1
- package/dist/utils/collapsed-chains.d.ts.map +1 -1
- package/dist/utils/collapsed-chains.js.map +1 -1
- package/dist/utils/node-boundary.d.ts.map +1 -1
- package/dist/utils/node-boundary.js +1 -1
- package/dist/utils/node-boundary.js.map +1 -1
- package/dist/utils/rank-grid.d.ts.map +1 -1
- package/dist/utils/rank-grid.js +5 -2
- package/dist/utils/rank-grid.js.map +1 -1
- package/package.json +8 -8
- package/src/_deprecated/old-constants.ts +12 -6
- package/src/core/graph-engine.ts +7 -2
- package/src/core/graph-layout.ts +2 -6
- package/src/core/interaction-manager.ts +2 -1
- package/src/graph/arrow-graph.ts +17 -10
- package/src/graph/classic-graph.ts +8 -5
- package/src/graph/functions/arrow-utils.ts +8 -4
- package/src/graph/functions/create-graph-from-data.ts +2 -2
- package/src/graph/graph-normalization.ts +8 -2
- package/src/graph-data/arrow-graph-data-builder.ts +6 -3
- package/src/graph-data/graph-data-builder.ts +1 -1
- package/src/graph-data/plain-graph-data-builder.ts +1 -1
- package/src/index.ts +35 -17
- package/src/layers/common-layers/grid-layer/grid-layer.ts +26 -19
- package/src/layers/edge-attachment-helper.ts +54 -45
- package/src/layers/edge-layer.ts +4 -4
- package/src/layers/edge-layers/arrow-2d-geometry.ts +1 -8
- package/src/layers/graph-layer.ts +109 -99
- package/src/layouts/d3-dag/collapsable-d3-dag-layout.ts +14 -7
- package/src/layouts/d3-dag/d3-dag-layout.ts +31 -19
- package/src/layouts/experimental/radial-layout.ts +4 -1
- package/src/layouts/simple-layout.ts +6 -4
- package/src/loaders/dot-graph-loader.ts +19 -7
- package/src/loaders/json-graph-loader.ts +3 -5
- package/src/loaders/parsers/parse-json-graph.ts +2 -1
- package/src/style/graph-layer-stylesheet.ts +26 -19
- package/src/style/graph-style-engine.ts +30 -17
- package/src/style/graph-stylesheet-schema.ts +490 -0
- package/src/style/style-property.ts +26 -11
- package/src/style/stylesheet-engine.ts +44 -29
- package/src/utils/collapsed-chains.ts +6 -2
- package/src/utils/node-boundary.ts +2 -3
- package/src/utils/rank-grid.ts +31 -17
- package/dist/style/graph-stylesheet.schema.d.ts +0 -311
- package/dist/style/graph-stylesheet.schema.d.ts.map +0 -1
- package/dist/style/graph-stylesheet.schema.js +0 -238
- package/dist/style/graph-stylesheet.schema.js.map +0 -1
- package/src/style/graph-stylesheet.schema.ts +0 -344
|
@@ -15,15 +15,15 @@ import {GraphEngine} from '../core/graph-engine';
|
|
|
15
15
|
|
|
16
16
|
import {
|
|
17
17
|
GraphStylesheetEngine,
|
|
18
|
-
type GraphStylesheet
|
|
18
|
+
type GraphStylesheet,
|
|
19
|
+
type GraphStyleRule
|
|
19
20
|
} from '../style/graph-style-engine';
|
|
20
21
|
|
|
21
22
|
import {
|
|
22
|
-
|
|
23
|
+
DEFAULT_GRAPH_LAYER_STYLESHEET_INPUT,
|
|
23
24
|
normalizeGraphLayerStylesheet,
|
|
24
25
|
type GraphLayerEdgeStyle,
|
|
25
26
|
type GraphLayerNodeStyle,
|
|
26
|
-
type GraphLayerStylesheet,
|
|
27
27
|
type NormalizedGraphLayerStylesheet
|
|
28
28
|
} from '../style/graph-layer-stylesheet';
|
|
29
29
|
|
|
@@ -44,8 +44,6 @@ import {EdgeArrowLayer} from './edge-layers/edge-arrow-layer';
|
|
|
44
44
|
import {EdgeAttachmentHelper} from './edge-attachment-helper';
|
|
45
45
|
import {GridLayer, type GridLayerProps} from './common-layers/grid-layer/grid-layer';
|
|
46
46
|
|
|
47
|
-
import {JSONGraphLoader} from '../loaders/json-graph-loader';
|
|
48
|
-
|
|
49
47
|
import {mixedGetPosition} from '../utils/layer-utils';
|
|
50
48
|
import {InteractionManager} from '../core/interaction-manager';
|
|
51
49
|
import {buildCollapsedChainLayers} from '../utils/collapsed-chains';
|
|
@@ -55,23 +53,24 @@ import {
|
|
|
55
53
|
type LabelAccessor,
|
|
56
54
|
type RankAccessor
|
|
57
55
|
} from '../utils/rank-grid';
|
|
56
|
+
import {createGraphFromData} from '../graph/functions/create-graph-from-data';
|
|
58
57
|
|
|
59
58
|
import {warn} from '../utils/log';
|
|
60
59
|
|
|
61
60
|
const NODE_LAYER_MAP = {
|
|
62
|
-
|
|
61
|
+
rectangle: RectangleLayer,
|
|
63
62
|
'rounded-rectangle': RoundedRectangleLayer,
|
|
64
63
|
'path-rounded-rectangle': PathBasedRoundedRectangleLayer,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
icon: ImageLayer,
|
|
65
|
+
circle: CircleLayer,
|
|
66
|
+
label: LabelLayer,
|
|
67
|
+
marker: ZoomableMarkerLayer
|
|
69
68
|
};
|
|
70
69
|
|
|
71
70
|
const EDGE_DECORATOR_LAYER_MAP = {
|
|
72
71
|
'edge-label': EdgeLabelLayer,
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
flow: FlowLayer,
|
|
73
|
+
arrow: EdgeArrowLayer
|
|
75
74
|
};
|
|
76
75
|
|
|
77
76
|
type GridLayerOverrides = Partial<Omit<GridLayerProps, 'id' | 'data' | 'direction'>>;
|
|
@@ -106,6 +105,13 @@ let NODE_STYLE_DEPRECATION_WARNED = false;
|
|
|
106
105
|
let EDGE_STYLE_DEPRECATION_WARNED = false;
|
|
107
106
|
let GRAPH_PROP_DEPRECATION_WARNED = false;
|
|
108
107
|
let LAYOUT_REQUIRED_WARNED = false;
|
|
108
|
+
const DEFAULT_GRAPH_LOADER = ({json}: {json: unknown}) => {
|
|
109
|
+
if (!json || typeof json !== 'object') {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return createGraphFromData(json as any);
|
|
114
|
+
};
|
|
109
115
|
|
|
110
116
|
export type GraphLayerRawData = {
|
|
111
117
|
name?: string;
|
|
@@ -146,7 +152,7 @@ export type _GraphLayerProps = {
|
|
|
146
152
|
onLayoutDone?: (detail?: GraphLayoutEventDetail) => void;
|
|
147
153
|
onLayoutError?: (error?: unknown) => void;
|
|
148
154
|
|
|
149
|
-
stylesheet?:
|
|
155
|
+
stylesheet?: GraphStylesheet;
|
|
150
156
|
/** @deprecated Use `stylesheet.nodes`. */
|
|
151
157
|
nodeStyle?: GraphLayerNodeStyle[];
|
|
152
158
|
/** @deprecated Use `stylesheet.edges`. */
|
|
@@ -171,18 +177,18 @@ export type _GraphLayerProps = {
|
|
|
171
177
|
export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
172
178
|
static layerName = 'GraphLayer';
|
|
173
179
|
|
|
174
|
-
static defaultProps:
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
static defaultProps: _GraphLayerProps &
|
|
181
|
+
Pick<CompositeLayerProps, 'pickable'> & {
|
|
182
|
+
data: {type: string; value: null; async: true};
|
|
183
|
+
} = {
|
|
177
184
|
// Composite layer props
|
|
178
|
-
// @ts-expect-error composite layer props
|
|
179
185
|
pickable: true,
|
|
180
186
|
data: {type: 'object', value: null, async: true},
|
|
181
187
|
|
|
182
188
|
// Graph props
|
|
183
|
-
graphLoader:
|
|
189
|
+
graphLoader: DEFAULT_GRAPH_LOADER,
|
|
184
190
|
|
|
185
|
-
stylesheet:
|
|
191
|
+
stylesheet: DEFAULT_GRAPH_LAYER_STYLESHEET_INPUT,
|
|
186
192
|
nodeStyle: undefined as unknown as GraphLayerNodeStyle[],
|
|
187
193
|
nodeEvents: {
|
|
188
194
|
onMouseLeave: () => {},
|
|
@@ -316,7 +322,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
316
322
|
}
|
|
317
323
|
|
|
318
324
|
private _createStylesheetEngine(
|
|
319
|
-
style:
|
|
325
|
+
style: GraphStyleRule,
|
|
320
326
|
context: string
|
|
321
327
|
): GraphStylesheetEngine | null {
|
|
322
328
|
try {
|
|
@@ -485,7 +491,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
if (Array.isArray(data) || isPlainObject(data)) {
|
|
488
|
-
const loader = props.graphLoader ??
|
|
494
|
+
const loader = props.graphLoader ?? DEFAULT_GRAPH_LOADER;
|
|
489
495
|
const graph = loader({json: data});
|
|
490
496
|
if (!graph) {
|
|
491
497
|
return null;
|
|
@@ -563,9 +569,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
563
569
|
}
|
|
564
570
|
|
|
565
571
|
const candidate = value as Graph;
|
|
566
|
-
return
|
|
567
|
-
typeof candidate.getNodes === 'function' && typeof candidate.getEdges === 'function'
|
|
568
|
-
);
|
|
572
|
+
return typeof candidate.getNodes === 'function' && typeof candidate.getEdges === 'function';
|
|
569
573
|
}
|
|
570
574
|
|
|
571
575
|
private _coerceGraph(value: unknown): Graph | null {
|
|
@@ -590,7 +594,10 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
590
594
|
try {
|
|
591
595
|
return candidate.toClassicGraph() ?? null;
|
|
592
596
|
} catch (error) {
|
|
593
|
-
warn(
|
|
597
|
+
warn(
|
|
598
|
+
'GraphLayer: failed to convert graph to ClassicGraph for layout compatibility.',
|
|
599
|
+
error
|
|
600
|
+
);
|
|
594
601
|
}
|
|
595
602
|
}
|
|
596
603
|
|
|
@@ -719,9 +726,10 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
719
726
|
});
|
|
720
727
|
}
|
|
721
728
|
|
|
722
|
-
private _normalizeRankGridConfig(
|
|
723
|
-
|
|
724
|
-
|
|
729
|
+
private _normalizeRankGridConfig(value: GraphLayerProps['rankGrid']): {
|
|
730
|
+
enabled: boolean;
|
|
731
|
+
config?: RankGridConfig;
|
|
732
|
+
} {
|
|
725
733
|
if (typeof value === 'boolean') {
|
|
726
734
|
return {enabled: value};
|
|
727
735
|
}
|
|
@@ -733,9 +741,9 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
733
741
|
return {enabled: false};
|
|
734
742
|
}
|
|
735
743
|
|
|
736
|
-
private _resolveRankGridBounds(
|
|
737
|
-
|
|
738
|
-
|
|
744
|
+
private _resolveRankGridBounds(
|
|
745
|
+
engine: GraphEngine
|
|
746
|
+
): {xMin: number; xMax: number; yMin: number; yMax: number} | null {
|
|
739
747
|
const bounds = engine.getLayoutBounds();
|
|
740
748
|
if (!bounds) {
|
|
741
749
|
return null;
|
|
@@ -759,7 +767,12 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
759
767
|
engine: GraphEngine,
|
|
760
768
|
config: RankGridConfig | undefined,
|
|
761
769
|
bounds: {yMin: number; yMax: number}
|
|
762
|
-
): Array<{
|
|
770
|
+
): Array<{
|
|
771
|
+
label: string;
|
|
772
|
+
rank: number;
|
|
773
|
+
originalLabel?: string | number;
|
|
774
|
+
yPosition: number;
|
|
775
|
+
}> | null {
|
|
763
776
|
const rankLabelPrefix = this._resolveRankFieldLabel(config?.rankAccessor);
|
|
764
777
|
// @ts-ignore iterator type
|
|
765
778
|
const rankPositions = mapRanksToYPositions(engine.getNodes(), engine.getNodePosition, {
|
|
@@ -821,7 +834,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
821
834
|
return null;
|
|
822
835
|
}
|
|
823
836
|
const stylesheet = this._createStylesheetEngine(
|
|
824
|
-
restStyle as unknown as
|
|
837
|
+
restStyle as unknown as GraphStyleRule,
|
|
825
838
|
`node stylesheet "${style.type}"`
|
|
826
839
|
);
|
|
827
840
|
if (!stylesheet) {
|
|
@@ -870,66 +883,64 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
870
883
|
nodeStyle: nodeStyles
|
|
871
884
|
});
|
|
872
885
|
|
|
873
|
-
return edgeStyleArray
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
return [];
|
|
886
|
-
}
|
|
886
|
+
return edgeStyleArray.filter(Boolean).flatMap((style, idx) => {
|
|
887
|
+
const {decorators, data = (edges) => edges, visible = true, ...restEdgeStyle} = style;
|
|
888
|
+
const stylesheet = this._createStylesheetEngine(
|
|
889
|
+
{
|
|
890
|
+
type: 'edge',
|
|
891
|
+
...restEdgeStyle
|
|
892
|
+
} as GraphStyleRule,
|
|
893
|
+
'edge stylesheet'
|
|
894
|
+
);
|
|
895
|
+
if (!stylesheet) {
|
|
896
|
+
return [];
|
|
897
|
+
}
|
|
887
898
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
899
|
+
const edgeLayer = new EdgeLayer({
|
|
900
|
+
...SHARED_LAYER_PROPS,
|
|
901
|
+
id: `edge-layer-${idx}`,
|
|
902
|
+
data: data(engine.getEdges()),
|
|
903
|
+
getLayoutInfo,
|
|
904
|
+
pickable: true,
|
|
905
|
+
positionUpdateTrigger: [engine.getLayoutLastUpdate(), engine.getLayoutState()].join(),
|
|
906
|
+
stylesheet,
|
|
907
|
+
visible
|
|
908
|
+
} as any);
|
|
909
|
+
|
|
910
|
+
if (!decorators || !Array.isArray(decorators) || decorators.length === 0) {
|
|
911
|
+
return [edgeLayer];
|
|
912
|
+
}
|
|
898
913
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
914
|
+
const decoratorLayers = decorators
|
|
915
|
+
.filter(Boolean)
|
|
916
|
+
// @ts-ignore eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
917
|
+
.map((decoratorStyle, idx2) => {
|
|
918
|
+
const DecoratorLayer = EDGE_DECORATOR_LAYER_MAP[decoratorStyle.type];
|
|
919
|
+
if (!DecoratorLayer) {
|
|
920
|
+
warn(`GraphLayer: Invalid edge decorator type "${decoratorStyle.type}".`);
|
|
921
|
+
return null;
|
|
922
|
+
}
|
|
923
|
+
const decoratorStylesheet = this._createStylesheetEngine(
|
|
924
|
+
decoratorStyle as unknown as GraphStyleRule,
|
|
925
|
+
`edge decorator stylesheet "${decoratorStyle.type}"`
|
|
926
|
+
);
|
|
927
|
+
if (!decoratorStylesheet) {
|
|
928
|
+
return null;
|
|
929
|
+
}
|
|
930
|
+
return new DecoratorLayer({
|
|
931
|
+
...SHARED_LAYER_PROPS,
|
|
932
|
+
id: `edge-decorator-${idx2}`,
|
|
933
|
+
data: data(engine.getEdges()),
|
|
934
|
+
getLayoutInfo,
|
|
935
|
+
pickable: true,
|
|
936
|
+
positionUpdateTrigger: [engine.getLayoutLastUpdate(), engine.getLayoutState()].join(),
|
|
937
|
+
stylesheet: decoratorStylesheet
|
|
938
|
+
} as any);
|
|
939
|
+
})
|
|
940
|
+
.filter(Boolean);
|
|
902
941
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
// @ts-ignore eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
906
|
-
.map((decoratorStyle, idx2) => {
|
|
907
|
-
const DecoratorLayer = EDGE_DECORATOR_LAYER_MAP[decoratorStyle.type];
|
|
908
|
-
if (!DecoratorLayer) {
|
|
909
|
-
warn(`GraphLayer: Invalid edge decorator type "${decoratorStyle.type}".`);
|
|
910
|
-
return null;
|
|
911
|
-
}
|
|
912
|
-
const decoratorStylesheet = this._createStylesheetEngine(
|
|
913
|
-
decoratorStyle as unknown as GraphStylesheet,
|
|
914
|
-
`edge decorator stylesheet "${decoratorStyle.type}"`
|
|
915
|
-
);
|
|
916
|
-
if (!decoratorStylesheet) {
|
|
917
|
-
return null;
|
|
918
|
-
}
|
|
919
|
-
return new DecoratorLayer({
|
|
920
|
-
...SHARED_LAYER_PROPS,
|
|
921
|
-
id: `edge-decorator-${idx2}`,
|
|
922
|
-
data: data(engine.getEdges()),
|
|
923
|
-
getLayoutInfo,
|
|
924
|
-
pickable: true,
|
|
925
|
-
positionUpdateTrigger: [engine.getLayoutLastUpdate(), engine.getLayoutState()].join(),
|
|
926
|
-
stylesheet: decoratorStylesheet
|
|
927
|
-
} as any);
|
|
928
|
-
})
|
|
929
|
-
.filter(Boolean);
|
|
930
|
-
|
|
931
|
-
return [edgeLayer, ...decoratorLayers];
|
|
932
|
-
});
|
|
942
|
+
return [edgeLayer, ...decoratorLayers];
|
|
943
|
+
});
|
|
933
944
|
}
|
|
934
945
|
|
|
935
946
|
onClick(info, event): boolean {
|
|
@@ -1018,7 +1029,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
1018
1029
|
marker: 'circle-plus-filled',
|
|
1019
1030
|
offset: [24, -24],
|
|
1020
1031
|
scaleWithZoom: false
|
|
1021
|
-
} as
|
|
1032
|
+
} as GraphStyleRule,
|
|
1022
1033
|
'collapsed chain marker stylesheet'
|
|
1023
1034
|
);
|
|
1024
1035
|
|
|
@@ -1071,7 +1082,7 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
1071
1082
|
marker: 'circle-minus-filled',
|
|
1072
1083
|
offset: [24, -24],
|
|
1073
1084
|
scaleWithZoom: false
|
|
1074
|
-
} as
|
|
1085
|
+
} as GraphStyleRule,
|
|
1075
1086
|
'expanded chain marker stylesheet'
|
|
1076
1087
|
);
|
|
1077
1088
|
|
|
@@ -1099,12 +1110,11 @@ export class GraphLayer extends CompositeLayer<GraphLayerProps> {
|
|
|
1099
1110
|
}
|
|
1100
1111
|
}
|
|
1101
1112
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
const prototype = Object.getPrototypeOf(value);
|
|
1108
|
-
return prototype === Object.prototype || prototype === null;
|
|
1113
|
+
function isPlainObject(value: unknown): value is Record<string | number | symbol, unknown> {
|
|
1114
|
+
if (!value || typeof value !== 'object') {
|
|
1115
|
+
return false;
|
|
1109
1116
|
}
|
|
1110
1117
|
|
|
1118
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1119
|
+
return prototype === Object.prototype || prototype === null;
|
|
1120
|
+
}
|
|
@@ -19,13 +19,13 @@ type CollapsedChainDescriptor = {
|
|
|
19
19
|
export type CollapsableD3DagLayoutProps = D3DagLayoutProps & {
|
|
20
20
|
/** Whether to collapse linear chains of nodes into a single representative. */
|
|
21
21
|
collapseLinearChains?: boolean;
|
|
22
|
-
}
|
|
22
|
+
};
|
|
23
23
|
|
|
24
24
|
export class CollapsableD3DagLayout extends D3DagLayout<CollapsableD3DagLayoutProps> {
|
|
25
25
|
static override defaultProps: Required<CollapsableD3DagLayoutProps> = {
|
|
26
26
|
...D3DagLayout.defaultProps,
|
|
27
27
|
collapseLinearChains: false
|
|
28
|
-
}
|
|
28
|
+
};
|
|
29
29
|
|
|
30
30
|
private _chainDescriptors = new Map<string, CollapsedChainDescriptor>();
|
|
31
31
|
private _nodeToChainId = new Map<string | number, string>();
|
|
@@ -61,7 +61,10 @@ export class CollapsableD3DagLayout extends D3DagLayout<CollapsableD3DagLayoutPr
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
if (!this._chainDescriptors.has(chainId)) {
|
|
64
|
-
log.log(
|
|
64
|
+
log.log(
|
|
65
|
+
1,
|
|
66
|
+
`CollapsableD3DagLayout: toggleCollapsedChain(${chainId}) skipped (unknown chain)`
|
|
67
|
+
);
|
|
65
68
|
return;
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -102,9 +105,14 @@ export class CollapsableD3DagLayout extends D3DagLayout<CollapsableD3DagLayoutPr
|
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
if (changed) {
|
|
105
|
-
log.log(
|
|
108
|
+
log.log(
|
|
109
|
+
0,
|
|
110
|
+
'CollapsableD3DagLayout: setCollapsedChains -> changes detected, rerunning layout'
|
|
111
|
+
);
|
|
106
112
|
// eslint-disable-next-line no-console
|
|
107
|
-
console.log(
|
|
113
|
+
console.log(
|
|
114
|
+
'CollapsableD3DagLayout: setCollapsedChains -> changes detected, rerunning layout'
|
|
115
|
+
);
|
|
108
116
|
this._runLayout();
|
|
109
117
|
} else {
|
|
110
118
|
log.log(1, 'CollapsableD3DagLayout: setCollapsedChains -> no changes');
|
|
@@ -138,8 +146,7 @@ export class CollapsableD3DagLayout extends D3DagLayout<CollapsableD3DagLayoutPr
|
|
|
138
146
|
`CollapsableD3DagLayout: refreshing collapsed chains (previous=${previousChainCount})`
|
|
139
147
|
);
|
|
140
148
|
|
|
141
|
-
const collapseDefault =
|
|
142
|
-
this.props.collapseLinearChains;
|
|
149
|
+
const collapseDefault = this.props.collapseLinearChains;
|
|
143
150
|
|
|
144
151
|
const previousStates = new Map(this._collapsedChainState);
|
|
145
152
|
|
|
@@ -153,7 +153,9 @@ function isEdgeInterface(value: unknown): value is EdgeInterface {
|
|
|
153
153
|
/**
|
|
154
154
|
* Layout that orchestrates d3-dag operators from declarative options.
|
|
155
155
|
*/
|
|
156
|
-
export class D3DagLayout<
|
|
156
|
+
export class D3DagLayout<
|
|
157
|
+
PropsT extends D3DagLayoutProps = D3DagLayoutProps
|
|
158
|
+
> extends GraphLayout<PropsT> {
|
|
157
159
|
static defaultProps: Readonly<Required<D3DagLayoutProps>> = {
|
|
158
160
|
...GraphLayout.defaultProps,
|
|
159
161
|
layout: 'sugiyama',
|
|
@@ -213,7 +215,6 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
213
215
|
}
|
|
214
216
|
}
|
|
215
217
|
|
|
216
|
-
|
|
217
218
|
initializeGraph(graph: Graph): void {
|
|
218
219
|
this.updateGraph(graph);
|
|
219
220
|
}
|
|
@@ -277,14 +278,12 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
277
278
|
return this._nodePositions.get(mappedId) || null;
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
getEdgePosition(edge: EdgeInterface):
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
| null {
|
|
281
|
+
getEdgePosition(edge: EdgeInterface): {
|
|
282
|
+
type: string;
|
|
283
|
+
sourcePosition: [number, number];
|
|
284
|
+
targetPosition: [number, number];
|
|
285
|
+
controlPoints: [number, number][];
|
|
286
|
+
} | null {
|
|
288
287
|
const mappedSourceId = this._mapNodeId(edge.getSourceNodeId());
|
|
289
288
|
const mappedTargetId = this._mapNodeId(edge.getTargetNodeId());
|
|
290
289
|
if (mappedSourceId === mappedTargetId) {
|
|
@@ -407,7 +406,9 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
407
406
|
const connect = graphConnect()
|
|
408
407
|
.sourceId(({source}: ConnectDatum): string => source)
|
|
409
408
|
.targetId(({target}: ConnectDatum): string => target)
|
|
410
|
-
.nodeDatum(
|
|
409
|
+
.nodeDatum(
|
|
410
|
+
(id: string): NodeInterface => this._nodeLookup.get(this._fromDagId(id)) ?? new Node({id})
|
|
411
|
+
)
|
|
411
412
|
.single(true);
|
|
412
413
|
|
|
413
414
|
const edges = Array.from(this._graph.getEdges());
|
|
@@ -508,7 +509,9 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
508
509
|
.filter((edge) => edge.isDirected() && edge.getSourceNodeId() === nodeId);
|
|
509
510
|
}
|
|
510
511
|
|
|
511
|
-
private _ensureEdgeData<T>(
|
|
512
|
+
private _ensureEdgeData<T>(
|
|
513
|
+
dag: MutGraph<NodeInterface, T>
|
|
514
|
+
): MutGraph<NodeInterface, EdgeInterface> {
|
|
512
515
|
for (const link of dag.links()) {
|
|
513
516
|
if (isEdgeInterface(link.data)) {
|
|
514
517
|
continue;
|
|
@@ -551,7 +554,10 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
551
554
|
// @ts-expect-error TS2345 - Argument of type '(dagNode: MutGraphNode<NodeInterface, EdgeInterface>) => number | undefined' is not assignable to parameter of type '(dagNode: MutGraphNode<NodeInterface, EdgeInterface>) => number'.
|
|
552
555
|
layeringOperator = layeringOperator.rank((dagNode) => {
|
|
553
556
|
const node = dagNode.data as NodeInterface;
|
|
554
|
-
const rank =
|
|
557
|
+
const rank =
|
|
558
|
+
typeof nodeRank === 'function'
|
|
559
|
+
? nodeRank?.(node)
|
|
560
|
+
: node?.getPropertyValue(nodeRank) || undefined;
|
|
555
561
|
// if (rank !== undefined) {
|
|
556
562
|
// console.log(`Node ${node.getId()} assigned to rank ${rank}`);
|
|
557
563
|
// }
|
|
@@ -644,8 +650,17 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
644
650
|
if (!edge) {
|
|
645
651
|
continue;
|
|
646
652
|
}
|
|
647
|
-
const points =
|
|
648
|
-
|
|
653
|
+
const points =
|
|
654
|
+
link.points && link.points.length
|
|
655
|
+
? link.points
|
|
656
|
+
: [
|
|
657
|
+
[link.source.x ?? 0, link.source.y ?? 0],
|
|
658
|
+
[link.target.x ?? 0, link.target.y ?? 0]
|
|
659
|
+
];
|
|
660
|
+
this._rawEdgePoints.set(
|
|
661
|
+
edge.getId(),
|
|
662
|
+
points.map((point) => [...point] as [number, number])
|
|
663
|
+
);
|
|
649
664
|
}
|
|
650
665
|
|
|
651
666
|
this._updateTransformedGeometry();
|
|
@@ -687,10 +702,7 @@ export class D3DagLayout<PropsT extends D3DagLayoutProps = D3DagLayoutProps> ext
|
|
|
687
702
|
for (const [edgeId, points] of this._rawEdgePoints) {
|
|
688
703
|
const transformed = points.map(([x, y]) => transform(x, y));
|
|
689
704
|
this._edgePoints.set(edgeId, transformed);
|
|
690
|
-
this._edgeControlPoints.set(
|
|
691
|
-
edgeId,
|
|
692
|
-
transformed.length > 2 ? transformed.slice(1, -1) : []
|
|
693
|
-
);
|
|
705
|
+
this._edgeControlPoints.set(edgeId, transformed.length > 2 ? transformed.slice(1, -1) : []);
|
|
694
706
|
}
|
|
695
707
|
|
|
696
708
|
for (const [id, position] of this._lockedNodePositions) {
|
|
@@ -10,7 +10,10 @@ export type RadialLayoutProps = GraphLayoutProps & {
|
|
|
10
10
|
tree?: any;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
const getTreeNode = (
|
|
13
|
+
const getTreeNode = (
|
|
14
|
+
nodeId: string,
|
|
15
|
+
nodeMap: Record<string, {children?: string[]; isLeaf?: boolean}>
|
|
16
|
+
) => {
|
|
14
17
|
const node = nodeMap[nodeId];
|
|
15
18
|
if (node) {
|
|
16
19
|
return node;
|
|
@@ -35,7 +35,7 @@ export class SimpleLayout extends GraphLayout<SimpleLayoutProps> {
|
|
|
35
35
|
this._notifyLayoutComplete();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
stop()
|
|
38
|
+
stop(): void {}
|
|
39
39
|
|
|
40
40
|
update(): void {
|
|
41
41
|
this._notifyLayoutComplete();
|
|
@@ -50,7 +50,10 @@ export class SimpleLayout extends GraphLayout<SimpleLayoutProps> {
|
|
|
50
50
|
const nodes = Array.from(graph.getNodes());
|
|
51
51
|
this._nodeMap = new Map(nodes.map((node) => [node.getId(), node]));
|
|
52
52
|
this._nodePositionMap = new Map(
|
|
53
|
-
nodes.map((node) => [
|
|
53
|
+
nodes.map((node) => [
|
|
54
|
+
node.getId(),
|
|
55
|
+
this._normalizePosition(this.props.nodePositionAccessor(node))
|
|
56
|
+
])
|
|
54
57
|
);
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -63,7 +66,7 @@ export class SimpleLayout extends GraphLayout<SimpleLayoutProps> {
|
|
|
63
66
|
return [0, 0] as [number, number];
|
|
64
67
|
}
|
|
65
68
|
const position = this._nodePositionMap.get(node.getId());
|
|
66
|
-
return position ?? [0, 0] as [number, number];
|
|
69
|
+
return position ?? ([0, 0] as [number, number]);
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
getEdgePosition = (edge: EdgeInterface) => {
|
|
@@ -91,7 +94,6 @@ export class SimpleLayout extends GraphLayout<SimpleLayoutProps> {
|
|
|
91
94
|
this._onLayoutDone();
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
|
|
95
97
|
protected override _updateBounds(): void {
|
|
96
98
|
const positions = Array.from(this._nodePositionMap.values(), (position) =>
|
|
97
99
|
this._normalizePosition(position)
|
|
@@ -55,13 +55,12 @@ export type DOTGraphLoaderMetadata = {
|
|
|
55
55
|
|
|
56
56
|
export type DOTGraphLoaderOptions = LoaderOptions & {
|
|
57
57
|
dot?: {
|
|
58
|
-
|
|
58
|
+
version?: number;
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
export type DOTGraphParserOptions = NonNullable<DOTGraphLoaderOptions['dot']>;
|
|
63
63
|
|
|
64
|
-
|
|
65
64
|
export const DOTGraphLoader = {
|
|
66
65
|
dataType: null as unknown as ArrowGraphData,
|
|
67
66
|
batchType: null as never,
|
|
@@ -89,7 +88,6 @@ export const DOTGraphLoader = {
|
|
|
89
88
|
}
|
|
90
89
|
} as const satisfies LoaderWithParser<ArrowGraphData, never, DOTGraphLoaderOptions>;
|
|
91
90
|
|
|
92
|
-
|
|
93
91
|
export function loadDOTGraph(dot: string, options: DOTGraphParserOptions = {}): ArrowGraphData {
|
|
94
92
|
const parsed = parseDOT(dot);
|
|
95
93
|
return buildArrowGraphData(parsed, options);
|
|
@@ -121,7 +119,9 @@ function buildArrowGraphData(
|
|
|
121
119
|
for (const node of parsed.nodes.values()) {
|
|
122
120
|
const attributes: DOTAttributeMap = {...node.attributes};
|
|
123
121
|
if (node.subgraphs.size > 0) {
|
|
124
|
-
attributes.subgraphs = Array.from(node.subgraphs, (id) =>
|
|
122
|
+
attributes.subgraphs = Array.from(node.subgraphs, (id) =>
|
|
123
|
+
describeSubgraph(id, subgraphDescriptors)
|
|
124
|
+
);
|
|
125
125
|
}
|
|
126
126
|
builder.addNode({
|
|
127
127
|
id: node.id,
|
|
@@ -428,7 +428,11 @@ class DOTParser {
|
|
|
428
428
|
graphAttributes: {}
|
|
429
429
|
};
|
|
430
430
|
this.scopes.push(context);
|
|
431
|
-
this.result.subgraphs.set(subgraphId, {
|
|
431
|
+
this.result.subgraphs.set(subgraphId, {
|
|
432
|
+
id: subgraphId,
|
|
433
|
+
attributes: context.graphAttributes,
|
|
434
|
+
parentId
|
|
435
|
+
});
|
|
432
436
|
|
|
433
437
|
let shouldContinue = true;
|
|
434
438
|
while (shouldContinue) {
|
|
@@ -702,7 +706,10 @@ function readQuotedString(input: string, startIndex: number): {value: string; ne
|
|
|
702
706
|
throw new Error('Unterminated string literal in DOT source.');
|
|
703
707
|
}
|
|
704
708
|
|
|
705
|
-
function readEscapedCharacter(
|
|
709
|
+
function readEscapedCharacter(
|
|
710
|
+
input: string,
|
|
711
|
+
startIndex: number
|
|
712
|
+
): {value: string; nextIndex: number} {
|
|
706
713
|
const next = input[startIndex];
|
|
707
714
|
switch (next) {
|
|
708
715
|
case 'n':
|
|
@@ -807,7 +814,12 @@ function isIdentifierLike(token: Token): boolean {
|
|
|
807
814
|
}
|
|
808
815
|
|
|
809
816
|
function isStructuralToken(token: Token): boolean {
|
|
810
|
-
return
|
|
817
|
+
return (
|
|
818
|
+
token.type === 'lbrace' ||
|
|
819
|
+
token.type === 'rbrace' ||
|
|
820
|
+
token.type === 'lbrack' ||
|
|
821
|
+
token.type === 'rbrack'
|
|
822
|
+
);
|
|
811
823
|
}
|
|
812
824
|
|
|
813
825
|
function parseIdentifierValue(token: Token): string {
|
|
@@ -12,8 +12,7 @@ import type {PlainGraphData} from '../graph-data/graph-data';
|
|
|
12
12
|
const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';
|
|
13
13
|
|
|
14
14
|
export type JSONGraphLoaderOptions = LoaderOptions & {
|
|
15
|
-
jsongraph?: {
|
|
16
|
-
};
|
|
15
|
+
jsongraph?: {};
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
export type JSONGraphParserOptions = NonNullable<JSONGraphLoaderOptions['jsongraph']>;
|
|
@@ -31,15 +30,14 @@ export const JSONGraphLoader = {
|
|
|
31
30
|
mimeTypes: ['application/json'],
|
|
32
31
|
text: true,
|
|
33
32
|
options: {
|
|
34
|
-
|
|
35
|
-
}
|
|
33
|
+
jsongraph: {}
|
|
36
34
|
},
|
|
37
35
|
|
|
38
36
|
parse: async (arrayBuffer: ArrayBuffer, options?: JSONGraphLoaderOptions) => {
|
|
39
37
|
const text = new TextDecoder().decode(arrayBuffer);
|
|
40
38
|
return Promise.resolve(JSONGraphLoader.parseTextSync(text, options));
|
|
41
39
|
},
|
|
42
|
-
|
|
40
|
+
|
|
43
41
|
parseTextSync: (text: string, options?: JSONGraphLoaderOptions) => {
|
|
44
42
|
// const parseOptions = {...JSONGraphLoader.options.jsongraph, ...options?.jsongraph};
|
|
45
43
|
throw new Error('JSONGraphLoader.parseTextSync not implemented');
|
|
@@ -84,7 +84,8 @@ function parseNodes(
|
|
|
84
84
|
state: parsed.state ?? (attributes.state as NodeState | undefined),
|
|
85
85
|
selectable: parsed.selectable ?? (attributes.selectable as boolean | undefined),
|
|
86
86
|
highlightConnectedEdges:
|
|
87
|
-
parsed.highlightConnectedEdges ??
|
|
87
|
+
parsed.highlightConnectedEdges ??
|
|
88
|
+
(attributes.highlightConnectedEdges as boolean | undefined),
|
|
88
89
|
label: parsed.label ?? (attributes.label as string | undefined),
|
|
89
90
|
weight: parsed.weight ?? (attributes.weight as number | undefined),
|
|
90
91
|
attributes
|