@unovis/ts 1.5.0-alpha.7 → 1.5.0-nikita.0
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/components/graph/config.d.ts +13 -2
- package/components/graph/config.js +3 -3
- package/components/graph/config.js.map +1 -1
- package/components/graph/index.d.ts +15 -5
- package/components/graph/index.js +199 -74
- package/components/graph/index.js.map +1 -1
- package/components/graph/modules/link/index.d.ts +2 -1
- package/components/graph/modules/link/index.js +7 -4
- package/components/graph/modules/link/index.js.map +1 -1
- package/components/graph/modules/node/index.d.ts +2 -1
- package/components/graph/modules/node/index.js +6 -5
- package/components/graph/modules/node/index.js.map +1 -1
- package/components/graph/modules/node/style.d.ts +2 -0
- package/components/graph/modules/node/style.js +34 -4
- package/components/graph/modules/node/style.js.map +1 -1
- package/components/graph/style.d.ts +1 -0
- package/components/graph/style.js +22 -1
- package/components/graph/style.js.map +1 -1
- package/components/graph/types.d.ts +6 -0
- package/components/graph/types.js +8 -2
- package/components/graph/types.js.map +1 -1
- package/components/scatter/index.d.ts +1 -0
- package/components/scatter/index.js +19 -12
- package/components/scatter/index.js.map +1 -1
- package/components/scatter/modules/point.js +1 -3
- package/components/scatter/modules/point.js.map +1 -1
- package/components/scatter/types.d.ts +2 -0
- package/data-models/graph.d.ts +2 -0
- package/data-models/graph.js +6 -0
- package/data-models/graph.js.map +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/types/graph.d.ts +2 -0
- package/types.js +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import { min, max } from 'd3-array';
|
|
3
3
|
import { select, pointer } from 'd3-selection';
|
|
4
|
+
import { brush as brush$1 } from 'd3-brush';
|
|
4
5
|
import { zoom, zoomTransform, zoomIdentity } from 'd3-zoom';
|
|
5
6
|
import { drag } from 'd3-drag';
|
|
6
7
|
import { interval } from 'd3-timer';
|
|
@@ -8,16 +9,16 @@ import { ComponentCore } from '../../core/component/index.js';
|
|
|
8
9
|
import { GraphDataModel } from '../../data-models/graph.js';
|
|
9
10
|
import { isNumber, isFunction, clamp, getBoolean, shallowDiff, isPlainObject, isEqual } from '../../utils/data.js';
|
|
10
11
|
import { smartTransition } from '../../utils/d3.js';
|
|
11
|
-
import { GraphLayoutType, GraphLinkArrowStyle } from './types.js';
|
|
12
|
+
import { GraphLayoutType, GraphNodeSelectionHighlightMode, GraphLinkArrowStyle } from './types.js';
|
|
12
13
|
import { GraphDefaultConfig } from './config.js';
|
|
13
|
-
import { background, graphGroup, root } from './style.js';
|
|
14
|
+
import { background, graphGroup, brush, root } from './style.js';
|
|
14
15
|
import * as style from './modules/node/style.js';
|
|
15
|
-
import { nodes, gNode, gNodeExit, node, nodeGauge, sideLabelGroup, label, greyedOutNode } from './modules/node/style.js';
|
|
16
|
+
import { nodes, gNode, gNodeExit, brushed, brushable, node, nodeGauge, sideLabelGroup, label, greyedOutNode } from './modules/node/style.js';
|
|
16
17
|
import { links, gLink, gLinkExit, link, greyedOutLink } from './modules/link/style.js';
|
|
17
18
|
import { panels, gPanel, panel, panelSelection, label as label$1, labelText, sideIconGroup, sideIconShape, sideIconSymbol } from './modules/panel/style.js';
|
|
18
|
-
import { createNodes, updateNodes, removeNodes,
|
|
19
|
+
import { createNodes, updateNodes, removeNodes, updateNodesPartial, zoomNodesThrottled, zoomNodes } from './modules/node/index.js';
|
|
19
20
|
import { getMaxNodeSize, getX, getY, getNodeSize } from './modules/node/helper.js';
|
|
20
|
-
import { createLinks, updateLinks, removeLinks,
|
|
21
|
+
import { createLinks, updateLinks, removeLinks, updateLinksPartial, animateLinkFlow, zoomLinksThrottled, zoomLinks } from './modules/link/index.js';
|
|
21
22
|
import { getArrowPath, getDoubleArrowPath } from './modules/link/helper.js';
|
|
22
23
|
import { removePanels, createPanels, updatePanels } from './modules/panel/index.js';
|
|
23
24
|
import { updatePanelNumNodes, updatePanelBBoxSize, initPanels, setPanelForNodes } from './modules/panel/helper.js';
|
|
@@ -53,9 +54,14 @@ class Graph extends ComponentCore {
|
|
|
53
54
|
this.setConfig(config);
|
|
54
55
|
this._backgroundRect = this.g.append('rect').attr('class', background);
|
|
55
56
|
this._graphGroup = this.g.append('g').attr('class', graphGroup);
|
|
57
|
+
this._brush = this.g.append('g').attr('class', brush);
|
|
56
58
|
this._zoomBehavior = zoom()
|
|
57
59
|
.scaleExtent(this.config.zoomScaleExtent)
|
|
58
60
|
.on('zoom', (e) => this._onZoom(e.transform, e));
|
|
61
|
+
this._brushBehavior = brush$1()
|
|
62
|
+
.on('start brush end', this._onBrush.bind(this))
|
|
63
|
+
.filter(event => event.shiftKey)
|
|
64
|
+
.keyModifiers(false);
|
|
59
65
|
this._panelsGroup = this._graphGroup.append('g').attr('class', panels);
|
|
60
66
|
this._linksGroup = this._graphGroup.append('g').attr('class', links);
|
|
61
67
|
this._nodesGroup = this._graphGroup.append('g').attr('class', nodes);
|
|
@@ -63,7 +69,11 @@ class Graph extends ComponentCore {
|
|
|
63
69
|
this._getLinkArrowDefId = this._getLinkArrowDefId.bind(this);
|
|
64
70
|
}
|
|
65
71
|
get selectedNode() {
|
|
66
|
-
|
|
72
|
+
var _a;
|
|
73
|
+
return (_a = this._selectedNodes) === null || _a === void 0 ? void 0 : _a[0];
|
|
74
|
+
}
|
|
75
|
+
get selectedNodes() {
|
|
76
|
+
return this._selectedNodes;
|
|
67
77
|
}
|
|
68
78
|
get selectedLink() {
|
|
69
79
|
return this._selectedLink;
|
|
@@ -95,7 +105,7 @@ class Graph extends ComponentCore {
|
|
|
95
105
|
return { top: extraPadding, bottom: extraPadding, left: extraPadding, right: extraPadding };
|
|
96
106
|
}
|
|
97
107
|
_render(customDuration) {
|
|
98
|
-
const { config: { disableZoom, duration, layoutAutofit, zoomEventFilter }, datamodel } = this;
|
|
108
|
+
const { config: { disableBrush, disableZoom, duration, layoutAutofit, zoomEventFilter }, datamodel } = this;
|
|
99
109
|
if (!datamodel.nodes && !datamodel.links)
|
|
100
110
|
return;
|
|
101
111
|
const animDuration = isNumber(customDuration) ? customDuration : duration;
|
|
@@ -109,6 +119,25 @@ class Graph extends ComponentCore {
|
|
|
109
119
|
this._prevWidth = this._width;
|
|
110
120
|
this._prevHeight = this._height;
|
|
111
121
|
}
|
|
122
|
+
// Handle brush behavior
|
|
123
|
+
if (!disableBrush) {
|
|
124
|
+
this._brushBehavior.extent([[0, 0], [this._width, this._height]]);
|
|
125
|
+
this._brush.call(this._brushBehavior);
|
|
126
|
+
// Activate the brush when the shift key is pressed
|
|
127
|
+
select(window)
|
|
128
|
+
.on('keydown.unovis-graph', e => e.key === 'Shift' && this._activateBrush())
|
|
129
|
+
.on('keyup.unovis-graph', e => e.key === 'Shift' && this._clearBrush());
|
|
130
|
+
this._zoomBehavior.filter(event => !event.shiftKey);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this._brush.on('.brush', null);
|
|
134
|
+
select(window)
|
|
135
|
+
.on('keydown.unovis-graph', null)
|
|
136
|
+
.on('keyup.unovis-graph', null);
|
|
137
|
+
// Clear brush in case it was disabled in an active state
|
|
138
|
+
if (this._brush.classed('active'))
|
|
139
|
+
this._clearBrush();
|
|
140
|
+
}
|
|
112
141
|
// Apply layout and render
|
|
113
142
|
if (this._shouldRecalculateLayout || !this._layoutCalculationPromise) {
|
|
114
143
|
this._layoutCalculationPromise = this._calculateLayout();
|
|
@@ -119,13 +148,14 @@ class Graph extends ComponentCore {
|
|
|
119
148
|
(_b = (_a = this.config).onLayoutCalculated) === null || _b === void 0 ? void 0 : _b.call(_a, datamodel.nodes, datamodel.links);
|
|
120
149
|
});
|
|
121
150
|
}
|
|
122
|
-
//
|
|
123
|
-
//
|
|
151
|
+
// Redefining Zoom Behavior filter to the one specified in the config,
|
|
152
|
+
// or to the default one supporting `shiftKey` for node brushing
|
|
153
|
+
// See more: https://d3js.org/d3-zoom#zoom_filter
|
|
124
154
|
this._zoomBehavior.filter(isFunction(zoomEventFilter)
|
|
125
155
|
? zoomEventFilter
|
|
126
|
-
: (e) => !e.shiftKey); // Default filter
|
|
156
|
+
: (e) => (!e.ctrlKey || e.type === 'wheel') && !e.button && !e.shiftKey); // Default filter
|
|
127
157
|
this._layoutCalculationPromise.then((isFirstRender) => {
|
|
128
|
-
var _a, _b;
|
|
158
|
+
var _a, _b, _c;
|
|
129
159
|
// If the component has been destroyed while the layout calculation
|
|
130
160
|
// was in progress, we cancel the render
|
|
131
161
|
if (this.isDestroyed())
|
|
@@ -140,19 +170,20 @@ class Graph extends ComponentCore {
|
|
|
140
170
|
this._fit(duration);
|
|
141
171
|
this._shouldFitLayout = false;
|
|
142
172
|
}
|
|
143
|
-
//
|
|
144
|
-
this.
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const selectedNode = datamodel.nodes.find(node => node.id === this.config.selectedNodeId);
|
|
150
|
-
this._selectNode(selectedNode);
|
|
173
|
+
// Update Nodes and Links Selection State
|
|
174
|
+
this._resetSelectionGreyoutState();
|
|
175
|
+
if (this.config.selectedNodeId || this.config.selectedNodeIds) {
|
|
176
|
+
const selectedIds = (_a = this.config.selectedNodeIds) !== null && _a !== void 0 ? _a : [this.config.selectedNodeId];
|
|
177
|
+
const selectedNodes = selectedIds.map(id => datamodel.getNodeFromId(id));
|
|
178
|
+
this._setNodeSelectionState(selectedNodes);
|
|
151
179
|
}
|
|
152
180
|
if (this.config.selectedLinkId) {
|
|
153
181
|
const selectedLink = datamodel.links.find(link => link.id === this.config.selectedLinkId);
|
|
154
|
-
this.
|
|
182
|
+
this._setLinkSelectionState(selectedLink);
|
|
155
183
|
}
|
|
184
|
+
// Draw
|
|
185
|
+
this._drawNodes(animDuration);
|
|
186
|
+
this._drawLinks(animDuration);
|
|
156
187
|
// Link flow animation timer
|
|
157
188
|
if (!this._timer) {
|
|
158
189
|
const refreshRateMs = 35;
|
|
@@ -180,7 +211,7 @@ class Graph extends ComponentCore {
|
|
|
180
211
|
this._setUpComponentEventsThrottled();
|
|
181
212
|
this._setCustomAttributesThrottled();
|
|
182
213
|
// On render complete callback
|
|
183
|
-
(
|
|
214
|
+
(_c = (_b = this.config).onRenderComplete) === null || _c === void 0 ? void 0 : _c.call(_b, this.g, datamodel.nodes, datamodel.links, this.config, animDuration, this._scale, this._containerWidth, this._containerHeight);
|
|
184
215
|
});
|
|
185
216
|
this._isFirstRender = false;
|
|
186
217
|
}
|
|
@@ -204,9 +235,9 @@ class Graph extends ComponentCore {
|
|
|
204
235
|
const thisRef = this;
|
|
205
236
|
if (!config.disableDrag) {
|
|
206
237
|
const dragBehaviour = drag()
|
|
207
|
-
.on('start', function (event, d) {
|
|
208
|
-
|
|
209
|
-
|
|
238
|
+
.on('start drag end', function (event, d) {
|
|
239
|
+
thisRef._handleDrag(d, event, select(this));
|
|
240
|
+
});
|
|
210
241
|
nodeGroupsMerged.call(dragBehaviour);
|
|
211
242
|
}
|
|
212
243
|
else {
|
|
@@ -348,38 +379,45 @@ class Graph extends ComponentCore {
|
|
|
348
379
|
.scale(clampedScale);
|
|
349
380
|
return transform;
|
|
350
381
|
}
|
|
351
|
-
|
|
352
|
-
const {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
this._selectedNode = node;
|
|
356
|
-
// Apply grey out
|
|
357
|
-
// Grey out all nodes
|
|
358
|
-
nodes.forEach(n => {
|
|
382
|
+
_setNodeSelectionState(nodesToSelect) {
|
|
383
|
+
const { config, datamodel } = this;
|
|
384
|
+
// Grey out all nodes and set us unselected
|
|
385
|
+
for (const n of datamodel.nodes) {
|
|
359
386
|
n._state.selected = false;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
387
|
+
if (config.nodeSelectionHighlightMode !== GraphNodeSelectionHighlightMode.None) {
|
|
388
|
+
n._state.greyout = true;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// Grey out all links and set us unselected
|
|
392
|
+
for (const l of datamodel.links) {
|
|
365
393
|
l._state.selected = false;
|
|
394
|
+
if (config.nodeSelectionHighlightMode !== GraphNodeSelectionHighlightMode.None) {
|
|
395
|
+
l._state.greyout = true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Filter out non-existing nodes
|
|
399
|
+
this._selectedNodes = nodesToSelect.filter(n => {
|
|
400
|
+
const doesNodeExist = Boolean(n);
|
|
401
|
+
if (!doesNodeExist)
|
|
402
|
+
console.warn('Unovis | Graph: Select Node: Not found');
|
|
403
|
+
return doesNodeExist;
|
|
366
404
|
});
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
405
|
+
// Set provided nodes as selected and ungreyout
|
|
406
|
+
for (const n of this._selectedNodes) {
|
|
407
|
+
n._state.selected = true;
|
|
408
|
+
n._state.greyout = false;
|
|
409
|
+
}
|
|
410
|
+
// Highlight connected links and nodes
|
|
411
|
+
if (config.nodeSelectionHighlightMode === GraphNodeSelectionHighlightMode.GreyoutNonConnected) {
|
|
412
|
+
const connectedLinks = datamodel.links.filter(l => this._selectedNodes.includes(l.source) || this._selectedNodes.includes(l.target));
|
|
372
413
|
connectedLinks.forEach(l => {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
source._state.greyout = false;
|
|
376
|
-
target._state.greyout = false;
|
|
414
|
+
l.source._state.greyout = false;
|
|
415
|
+
l.target._state.greyout = false;
|
|
377
416
|
l._state.greyout = false;
|
|
378
417
|
});
|
|
379
418
|
}
|
|
380
|
-
this._updateSelectedElements();
|
|
381
419
|
}
|
|
382
|
-
|
|
420
|
+
_setLinkSelectionState(link) {
|
|
383
421
|
const { datamodel: { nodes, links } } = this;
|
|
384
422
|
if (!link)
|
|
385
423
|
console.warn('Unovis: Graph: Select Link: Not found');
|
|
@@ -409,13 +447,12 @@ class Graph extends ComponentCore {
|
|
|
409
447
|
});
|
|
410
448
|
if (link)
|
|
411
449
|
link._state.selected = true;
|
|
412
|
-
this._updateSelectedElements();
|
|
413
450
|
}
|
|
414
|
-
|
|
451
|
+
_resetSelectionGreyoutState() {
|
|
415
452
|
const { datamodel: { nodes, links } } = this;
|
|
416
|
-
this.
|
|
453
|
+
this._selectedNodes = [];
|
|
417
454
|
this._selectedLink = undefined;
|
|
418
|
-
// Disable
|
|
455
|
+
// Disable Greyout
|
|
419
456
|
nodes.forEach(n => {
|
|
420
457
|
delete n._state.selected;
|
|
421
458
|
delete n._state.greyout;
|
|
@@ -424,18 +461,17 @@ class Graph extends ComponentCore {
|
|
|
424
461
|
delete l._state.greyout;
|
|
425
462
|
delete l._state.selected;
|
|
426
463
|
});
|
|
427
|
-
this._updateSelectedElements();
|
|
428
464
|
}
|
|
429
|
-
|
|
465
|
+
_updateNodesLinksPartial() {
|
|
430
466
|
const { config } = this;
|
|
431
467
|
const linkElements = this._linksGroup.selectAll(`.${gLink}`);
|
|
432
|
-
linkElements.call(
|
|
468
|
+
linkElements.call(updateLinksPartial, config, this._scale);
|
|
433
469
|
const nodeElements = this._nodesGroup.selectAll(`.${gNode}`);
|
|
434
|
-
nodeElements.call(
|
|
435
|
-
// this._drawPanels(nodeElements, 0)
|
|
470
|
+
nodeElements.call(updateNodesPartial, config);
|
|
436
471
|
}
|
|
437
472
|
_onBackgroundClick() {
|
|
438
|
-
this.
|
|
473
|
+
this._resetSelectionGreyoutState();
|
|
474
|
+
this._updateNodesLinksPartial();
|
|
439
475
|
}
|
|
440
476
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
441
477
|
_onNodeClick(d) {
|
|
@@ -453,13 +489,13 @@ class Graph extends ComponentCore {
|
|
|
453
489
|
if (this._isDragging)
|
|
454
490
|
return;
|
|
455
491
|
d._state.hovered = true;
|
|
456
|
-
this.
|
|
492
|
+
this._updateNodesLinksPartial();
|
|
457
493
|
}
|
|
458
494
|
_onLinkMouseOut(d) {
|
|
459
495
|
if (this._isDragging)
|
|
460
496
|
return;
|
|
461
497
|
delete d._state.hovered;
|
|
462
|
-
this.
|
|
498
|
+
this._updateNodesLinksPartial();
|
|
463
499
|
}
|
|
464
500
|
_onLinkFlowTimerFrame(elapsed = 0) {
|
|
465
501
|
const { config: { linkFlow, linkFlowAnimDuration }, datamodel: { links } } = this;
|
|
@@ -503,27 +539,17 @@ class Graph extends ComponentCore {
|
|
|
503
539
|
this._linksGroup.selectAll(`.${gLink}`)
|
|
504
540
|
.call((nodes.length > config.zoomThrottledUpdateNodeThreshold ? zoomLinksThrottled : zoomLinks), config, this._scale, this._getLinkArrowDefId);
|
|
505
541
|
}
|
|
506
|
-
|
|
507
|
-
var _a;
|
|
508
|
-
const { config } = this;
|
|
509
|
-
this._isDragging = true;
|
|
510
|
-
d._state.isDragged = true;
|
|
511
|
-
nodeSelection.call(updateNodes, config, 0, this._scale);
|
|
512
|
-
(_a = config.onNodeDragStart) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
|
|
513
|
-
}
|
|
514
|
-
_onDragged(d, event, allNodesSelection) {
|
|
515
|
-
var _a, _b, _c;
|
|
516
|
-
const { config } = this;
|
|
542
|
+
_updateNodePosition(d, x, y) {
|
|
543
|
+
var _a, _b;
|
|
517
544
|
const transform = zoomTransform(this.g.node());
|
|
518
545
|
const scale = transform.k;
|
|
519
546
|
// Prevent the node from being dragged offscreen or outside its panel
|
|
520
547
|
const panels = (_b = (_a = this._panels) === null || _a === void 0 ? void 0 : _a.filter(p => p.nodes.includes(d._id))) !== null && _b !== void 0 ? _b : [];
|
|
521
|
-
const nodeSizeValue = getNodeSize(d, config.nodeSize, d._index);
|
|
548
|
+
const nodeSizeValue = getNodeSize(d, this.config.nodeSize, d._index);
|
|
522
549
|
const maxY = min([(this._height - transform.y) / scale, ...panels.map(p => p._y + p._height)]) - nodeSizeValue / 2;
|
|
523
550
|
const maxX = min([(this._width - transform.x) / scale, ...panels.map(p => p._x + p._width)]) - nodeSizeValue / 2;
|
|
524
551
|
const minY = max([-transform.y / scale, ...panels.map(p => p._y)]) + nodeSizeValue / 2;
|
|
525
552
|
const minX = max([-transform.x / scale, ...panels.map(p => p._x)]) + nodeSizeValue / 2;
|
|
526
|
-
let [x, y] = pointer(event, this._graphGroup.node());
|
|
527
553
|
if (y < minY)
|
|
528
554
|
y = minY;
|
|
529
555
|
else if (y > maxY)
|
|
@@ -544,6 +570,62 @@ class Graph extends ComponentCore {
|
|
|
544
570
|
delete d._state.fx;
|
|
545
571
|
if (d._state.fy === d.y)
|
|
546
572
|
delete d._state.fy;
|
|
573
|
+
}
|
|
574
|
+
_onBrush(event) {
|
|
575
|
+
var _a;
|
|
576
|
+
if (!event.selection || !event.sourceEvent)
|
|
577
|
+
return;
|
|
578
|
+
const { config } = this;
|
|
579
|
+
const transform = zoomTransform(this._graphGroup.node());
|
|
580
|
+
const [xMin, yMin] = transform.invert(event.selection[0]);
|
|
581
|
+
const [xMax, yMax] = transform.invert(event.selection[1]);
|
|
582
|
+
// Update brushed nodes
|
|
583
|
+
this._nodesGroup.selectAll(`.${gNode}`)
|
|
584
|
+
.each(n => {
|
|
585
|
+
const x = getX(n);
|
|
586
|
+
const y = getY(n);
|
|
587
|
+
n._state.brushed = x >= xMin && x <= xMax && y >= yMin && y <= yMax;
|
|
588
|
+
})
|
|
589
|
+
.classed(brushed, n => n._state.brushed);
|
|
590
|
+
const brushedNodes = this._nodesGroup.selectAll(`.${brushed}`)
|
|
591
|
+
.call(updateNodesPartial, config, 0, this._scale);
|
|
592
|
+
this._brush.classed('active', event.type !== 'end');
|
|
593
|
+
(_a = config.onNodeSelectionBrush) === null || _a === void 0 ? void 0 : _a.call(config, brushedNodes.data(), event);
|
|
594
|
+
}
|
|
595
|
+
_handleDrag(d, event, nodeSelection) {
|
|
596
|
+
if (event.sourceEvent.shiftKey && d._state.brushed) {
|
|
597
|
+
this._dragSelectedNodes(event);
|
|
598
|
+
}
|
|
599
|
+
else if (!event.sourceEvent.shiftKey) {
|
|
600
|
+
switch (event.type) {
|
|
601
|
+
case 'start':
|
|
602
|
+
this._onDragStarted(d, event, nodeSelection);
|
|
603
|
+
break;
|
|
604
|
+
case 'drag':
|
|
605
|
+
this._onDragged(d, event);
|
|
606
|
+
break;
|
|
607
|
+
case 'end':
|
|
608
|
+
this._onDragEnded(d, event, nodeSelection);
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
_onDragStarted(d, event, nodeSelection) {
|
|
614
|
+
var _a;
|
|
615
|
+
const { config } = this;
|
|
616
|
+
this._isDragging = true;
|
|
617
|
+
d._state.isDragged = true;
|
|
618
|
+
nodeSelection.call(updateNodes, config, 0, this._scale);
|
|
619
|
+
(_a = config.onNodeDragStart) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
|
|
620
|
+
}
|
|
621
|
+
_onDragged(d, event) {
|
|
622
|
+
var _a;
|
|
623
|
+
const { config } = this;
|
|
624
|
+
const transform = zoomTransform(this.g.node());
|
|
625
|
+
const scale = transform.k;
|
|
626
|
+
// Update node position
|
|
627
|
+
const [x, y] = pointer(event, this._graphGroup.node());
|
|
628
|
+
this._updateNodePosition(d, x, y);
|
|
547
629
|
// Update affected DOM elements
|
|
548
630
|
const nodeSelection = this._nodesGroup.selectAll(`.${gNode}`);
|
|
549
631
|
const nodeToUpdate = nodeSelection.filter((n) => n._id === d._id);
|
|
@@ -558,7 +640,7 @@ class Graph extends ComponentCore {
|
|
|
558
640
|
const linksToAnimate = linksToUpdate.filter(d => d._state.greyout);
|
|
559
641
|
if (linksToAnimate.size())
|
|
560
642
|
animateLinkFlow(linksToAnimate, config, this._scale);
|
|
561
|
-
(
|
|
643
|
+
(_a = config.onNodeDrag) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
|
|
562
644
|
}
|
|
563
645
|
_onDragEnded(d, event, nodeSelection) {
|
|
564
646
|
var _a;
|
|
@@ -568,6 +650,49 @@ class Graph extends ComponentCore {
|
|
|
568
650
|
nodeSelection.call(updateNodes, config, 0, this._scale);
|
|
569
651
|
(_a = config.onNodeDragEnd) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
|
|
570
652
|
}
|
|
653
|
+
_dragSelectedNodes(event) {
|
|
654
|
+
var _a, _b;
|
|
655
|
+
const { config } = this;
|
|
656
|
+
const curr = pointer(event, this._graphGroup.node());
|
|
657
|
+
const selectedNodes = smartTransition(this._nodesGroup.selectAll(`.${brushed}`));
|
|
658
|
+
if (event.type === 'start') {
|
|
659
|
+
this._groupDragInit = curr;
|
|
660
|
+
this._isDragging = true;
|
|
661
|
+
selectedNodes.each(n => {
|
|
662
|
+
n.x = getX(n);
|
|
663
|
+
n.y = getY(n);
|
|
664
|
+
n._state.isDragged = true;
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
else if (event.type === 'drag') {
|
|
668
|
+
const dx = curr[0] - this._groupDragInit[0];
|
|
669
|
+
const dy = curr[1] - this._groupDragInit[1];
|
|
670
|
+
selectedNodes.each(n => this._updateNodePosition(n, n.x + dx, n.y + dy));
|
|
671
|
+
const connectedLinks = smartTransition(this._linksGroup.selectAll(`.${gLink}`)
|
|
672
|
+
.filter(l => { var _a, _b, _c, _d; return ((_b = (_a = l.source) === null || _a === void 0 ? void 0 : _a._state) === null || _b === void 0 ? void 0 : _b.isDragged) || ((_d = (_c = l.target) === null || _c === void 0 ? void 0 : _c._state) === null || _d === void 0 ? void 0 : _d.isDragged); }));
|
|
673
|
+
connectedLinks.call(updateLinks, this.config, 0, this._scale, this._getLinkArrowDefId);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
this._isDragging = false;
|
|
677
|
+
selectedNodes.each(n => { n._state.isDragged = false; });
|
|
678
|
+
}
|
|
679
|
+
selectedNodes.call(updateNodes, config, 0, this._scale);
|
|
680
|
+
(_b = (_a = this.config).onNodeSelectionDrag) === null || _b === void 0 ? void 0 : _b.call(_a, selectedNodes.data(), event);
|
|
681
|
+
}
|
|
682
|
+
_activateBrush() {
|
|
683
|
+
this._brush.classed('active', true);
|
|
684
|
+
this._nodesGroup.selectAll(`.${gNode}`)
|
|
685
|
+
.classed(brushable, true);
|
|
686
|
+
}
|
|
687
|
+
_clearBrush() {
|
|
688
|
+
var _a;
|
|
689
|
+
this._brush.classed('active', false).call((_a = this._brushBehavior) === null || _a === void 0 ? void 0 : _a.clear);
|
|
690
|
+
this._nodesGroup.selectAll(`.${gNode}`)
|
|
691
|
+
.classed(brushable, false)
|
|
692
|
+
.classed(brushed, false)
|
|
693
|
+
.each(n => { n._state.brushed = false; })
|
|
694
|
+
.call(updateNodesPartial, this.config, 0, this._scale);
|
|
695
|
+
}
|
|
571
696
|
_shouldLayoutRecalculate() {
|
|
572
697
|
const { prevConfig, config } = this;
|
|
573
698
|
if (prevConfig.layoutType !== config.layoutType)
|